Changeset 3357461
- Timestamp:
- 09/07/2025 05:02:02 PM (5 months ago)
- Location:
- advanced-settings
- Files:
-
- 4 added
- 1 deleted
- 10 edited
- 15 copied
-
tags/3.2.0 (copied) (copied from advanced-settings/trunk)
-
tags/3.2.0/admin-ui/admin-ui.css (copied) (copied from advanced-settings/trunk/admin-ui/admin-ui.css) (3 diffs)
-
tags/3.2.0/admin-ui/admin-ui.php (copied) (copied from advanced-settings/trunk/admin-ui/admin-ui.php) (1 diff)
-
tags/3.2.0/admin-ui/images/wppeak.com-logo-vectorized-white.svg (added)
-
tags/3.2.0/admin-ui/react/app.css (copied) (copied from advanced-settings/trunk/admin-ui/react/app.css)
-
tags/3.2.0/admin-ui/react/app.js (copied) (copied from advanced-settings/trunk/admin-ui/react/app.js)
-
tags/3.2.0/advanced-settings.php (copied) (copied from advanced-settings/trunk/advanced-settings.php) (1 diff)
-
tags/3.2.0/feature-setup/categories.php (copied) (copied from advanced-settings/trunk/feature-setup/categories.php)
-
tags/3.2.0/feature-setup/features/adminarea.php (copied) (copied from advanced-settings/trunk/feature-setup/features/adminarea.php)
-
tags/3.2.0/feature-setup/features/advset.php (copied) (copied from advanced-settings/trunk/feature-setup/features/advset.php)
-
tags/3.2.0/feature-setup/features/dashboard.php (deleted)
-
tags/3.2.0/feature-setup/features/developer.php (copied) (copied from advanced-settings/trunk/feature-setup/features/developer.php) (3 diffs)
-
tags/3.2.0/feature-setup/features/editing.php (copied) (copied from advanced-settings/trunk/feature-setup/features/editing.php) (1 diff)
-
tags/3.2.0/feature-setup/features/frontend.php (copied) (copied from advanced-settings/trunk/feature-setup/features/frontend.php)
-
tags/3.2.0/feature-setup/features/includes/developer.settings_pages.post_types--admin-post-types.php (modified) (2 diffs)
-
tags/3.2.0/feature-setup/features/includes/developer.settings_pages.post_types--init.php (added)
-
tags/3.2.0/feature-setup/features/includes/frontend.auto_thumbs.php (modified) (1 diff)
-
tags/3.2.0/feature-setup/features/system.php (copied) (copied from advanced-settings/trunk/feature-setup/features/system.php)
-
tags/3.2.0/migrations/3.x.x.php (copied) (copied from advanced-settings/trunk/migrations/3.x.x.php)
-
tags/3.2.0/readme.txt (copied) (copied from advanced-settings/trunk/readme.txt) (7 diffs)
-
trunk/admin-ui/admin-ui.css (modified) (3 diffs)
-
trunk/admin-ui/admin-ui.php (modified) (1 diff)
-
trunk/admin-ui/images/wppeak.com-logo-vectorized-white.svg (added)
-
trunk/advanced-settings.php (modified) (1 diff)
-
trunk/feature-setup/features/developer.php (modified) (3 diffs)
-
trunk/feature-setup/features/editing.php (modified) (1 diff)
-
trunk/feature-setup/features/includes/developer.settings_pages.post_types--admin-post-types.php (modified) (2 diffs)
-
trunk/feature-setup/features/includes/developer.settings_pages.post_types--init.php (added)
-
trunk/feature-setup/features/includes/frontend.auto_thumbs.php (modified) (1 diff)
-
trunk/readme.txt (modified) (7 diffs)
Legend:
- Unmodified
- Added
- Removed
-
advanced-settings/tags/3.2.0/admin-ui/admin-ui.css
r3323103 r3357461 128 128 height: 80vh; 129 129 background-color: #fff; 130 overflow: hidden;130 overflow: visible; 131 131 } 132 132 … … 149 149 flex-direction: column; 150 150 height: 100%; 151 border-radius: .5em; 152 overflow: hidden; 151 153 } 152 154 … … 248 250 flex-direction: column; 249 251 height: 100%; 252 } 253 254 .advset-modal-madeby { 255 padding: 0; 256 display: flex; 257 gap: 1em; 258 position: absolute; 259 top: 100%; 260 right: 0px; 261 left: 0px; 262 color: #fff; 263 opacity: .8; 264 justify-content: center; 265 margin: 0 auto; 266 width: fit-content; 267 } 268 269 .advset-modal-madeby img { 270 flex-shrink: 0; 271 flex-grow: 0; 272 width: 50px; 273 height: auto; 274 } 275 276 .advset-modal-madeby p { 277 font-size: var(--advset-font-size-small); 278 } 279 280 .advset-modal-madeby a { 281 color: inherit !important; 250 282 } 251 283 -
advanced-settings/tags/3.2.0/admin-ui/admin-ui.php
r3323109 r3357461 207 207 </div> 208 208 </div> 209 <div class="advset-modal-madeby"> 210 <img src="<?php echo plugins_url('', ADVSET_FILE); ?>/admin-ui/images/wppeak.com-logo-vectorized-white.svg" alt="Advanced Settings"> 211 <p> 212 Advanced Settings is made by <a href="https://www.wppeak.com/" target="_blank" rel="noopener noreferrer">wppeak.com</a>.<br /> 213 We make plugins and other useful WordPress tools. 214 </p> 215 </div> 209 216 </dialog> 210 217 <?php -
advanced-settings/tags/3.2.0/advanced-settings.php
r3323109 r3357461 6 6 Author: Helmut Wandl 7 7 Author URI: https://ehtmlu.com/ 8 Version: 3. 1.18 Version: 3.2.0 9 9 Requires at least: 5.0.0 10 10 Requires PHP: 7.4 -
advanced-settings/tags/3.2.0/feature-setup/features/developer.php
r3323103 r3357461 135 135 'id' => 'developer.settings_pages.post_types', 136 136 'category' => 'developer', 137 'experimental' => true,138 137 'ui_config' => fn() => [ 139 138 'tags' => [ … … 145 144 'enable' => [ 146 145 'type' => 'toggle', 147 'label' => __('Post types settings', 'advanced-settings'), 148 'description' => __('These post types settings are currently under review and may be changed or removed in the future.', 'advanced-settings'), 146 'label' => __('Custom post types', 'advanced-settings'), 149 147 ], 150 148 'info' => [ … … 157 155 'execution_handler' => function() { 158 156 require_once ADVSET_DIR.'/feature-setup/features/includes/developer.settings_pages.php'; 159 160 add_action('init', function() { 161 162 $post_types = (array) get_option( 'advset_post_types', array() ); 163 164 if( is_admin() && current_user_can('manage_options') && isset($_GET['delete_posttype']) ) { 165 unset($post_types[$_GET['delete_posttype']]); 166 update_option( 'advset_post_types', $post_types ); 167 } 168 169 if( is_admin() && current_user_can('manage_options') && isset($_POST['advset_action_posttype']) ) { 170 171 extract($_POST); 172 173 $labels = array( 174 'name' => $label, 175 #'singular_name' => @$singular_name, 176 #'add_new' => @$add_new, 177 #'add_new_item' => @$add_new_item, 178 #'edit_item' => @$edit_item, 179 #'new_item' => @$new_item, 180 #'all_items' => @$all_items, 181 #'view_item' => @$view_item, 182 #'search_items' => @$search_items, 183 #'not_found' => @$not_found, 184 #'not_found_in_trash' => @$not_found_in_trash, 185 #'parent_item_colon' => @$parent_item_colon, 186 #'menu_name' => @$menu_name 187 ); 188 189 $typename = sanitize_key( $type ); 190 191 $post_types[$type] = array( 192 'labels' => $labels, 193 'public' => (bool) (isset($public) ? $public : false), 194 'publicly_queryable' => (bool) (isset($publicly_queryable) ? $publicly_queryable : false), 195 'show_ui' => (bool) (isset($show_ui) ? $show_ui : false), 196 'show_in_menu' => (bool) (isset($show_in_menu) ? $show_in_menu : false), 197 'query_var' => (bool) (isset($query_var) ? $query_var : false), 198 #'rewrite' => array( 'slug' => 'book' ), 199 #'capability_type' => 'post', 200 'has_archive' => (bool) (isset($has_archive) ? $has_archive : false), 201 'hierarchical' => (bool) (isset($hierarchical) ? $hierarchical : false), 202 #'menu_position' => (int)@$menu_position, 203 'supports' => (array) (empty($supports) ? [] : $supports), 204 'taxonomies' => (array) (empty($taxonomies) ? [] : $taxonomies), 205 ); 206 207 update_option( 'advset_post_types', $post_types ); 208 209 } 210 #print_r($post_types); 211 if( sizeof($post_types)>0 ) 212 foreach( $post_types as $post_type=>$args ) { 213 register_post_type( $post_type, $args ); 214 if( in_array( 'thumbnail', $args['supports'] ) ) { 215 add_theme_support( 'post-thumbnails', array( $post_type, 'post' ) ); 216 } 217 } 218 219 }); 220 221 add_action('admin_menu', function() { 222 add_options_page( 223 __('Post Types', 'advanced-settings'), 224 __('Post Types', 'advanced-settings'), 225 'manage_options', 226 'advanced-settings-post-types', 227 function() { 228 include ADVSET_DIR.'/feature-setup/features/includes/developer.settings_pages.post_types--admin-post-types.php'; 229 } 230 ); 231 }); 157 require_once ADVSET_DIR.'/feature-setup/features/includes/developer.settings_pages.post_types--init.php'; 158 Advset__Feature__Post_Types::init(); 232 159 }, 233 160 'priority' => 10, -
advanced-settings/tags/3.2.0/feature-setup/features/editing.php
r3323103 r3357461 355 355 ], 356 356 'execution_handler' => function() { 357 require_once ADVSET_DIR . '/feature-setup/features/includes/frontend.auto_thumbs.php'; 358 add_action('transition_post_status', 'advset__feature__auto_thumbs', 10, 3); 357 add_action('transition_post_status', function($new_status, $old_status, $post) { 358 if ($new_status !== 'publish') { 359 return; 360 } 361 require_once ADVSET_DIR . '/feature-setup/features/includes/frontend.auto_thumbs.php'; 362 Advset__Feature__Auto_Thumbs::init()->transition_post_status($new_status, $old_status, $post); 363 }, 10, 3); 359 364 }, 360 365 'priority' => 70, -
advanced-settings/tags/3.2.0/feature-setup/features/includes/developer.settings_pages.post_types--admin-post-types.php
r3286786 r3357461 1 <?php defined('ABSPATH') or exit; 2 3 global $_wp_post_type_features; 4 5 $post_types = get_post_types( '', 'objects' ); 6 7 unset( $post_types['attachment'], $post_types['revision'], $post_types['nav_menu_item'] ); 8 9 $advset_post_types = (array) get_option( 'advset_post_types', array() ); 10 11 ?> 12 <script> 13 <?php echo 'posttype_data='.json_encode($post_types).';'; ?> 14 <?php echo 'supports='.json_encode($_wp_post_type_features).';'; ?> 15 show_form=function(type) { 16 17 $=jQuery; 18 19 if( type ) { 20 21 data = posttype_data[type]; 22 23 data.type=type; 24 populate( '#posttype_form', data ); 25 26 var checks = $('[name=supports\\[\\]]', '#posttype_form'); 27 for( i=0; i<checks.length;i++ ) 28 if( supports[type][$(checks[i]).attr('value')] ) 29 $(checks[i]).attr("checked", "checked"); 30 else 31 $(checks[i]).attr("checked", null); 32 33 var checks = $('[name=taxonomies\\[\\]]', '#posttype_form'); 34 for( i=0; i<checks.length;i++ ) 35 if( data['taxonomies'].join(',').indexOf($(checks[i]).attr('value'))>-1 ) 36 $(checks[i]).attr("checked", "checked"); 37 else 38 $(checks[i]).attr("checked", null); 39 40 } 41 42 $('#post_type_list').hide(); 43 $('#post_type_form').fadeIn(); 44 //$('#post_type_form').reset(); // dont works 45 $('#namefield').focus(); 1 <?php 2 3 if (!defined('ABSPATH')) exit; 4 5 6 $advset_posttype_nonce = wp_create_nonce('advset_posttype_nonce'); 7 8 $advset_posttypes_data = get_option('advset_post_types', []); 9 10 $advset_posttypes_data_default = [ 11 'supports' => [ 12 'title', 13 'editor', 14 ], 15 'public' => true, 16 'publicly_queryable' => true, 17 'show_ui' => true, 18 'show_in_menu' => true, 19 'query_var' => true, 20 'has_archive' => false, 21 'hierarchical' => false, 22 'taxonomies' => [ 23 'category', 24 'post_tag', 25 ], 26 ]; 27 28 29 30 31 ?> 32 <script> 33 34 document.addEventListener('DOMContentLoaded', function() { 35 const formContainerElement = document.getElementById('advset_posttype_form_container'); 36 const listContainerElement = document.getElementById('advset_posttype_list_container'); 37 const formElement = formContainerElement?.querySelector('#advset_posttype_form'); 38 const labelInputElement = formContainerElement?.querySelector('[name="label"]'); 39 const typeInputElement = formContainerElement?.querySelector('[name="type"]'); 40 const typeStoredInputElement = formContainerElement?.querySelector('[name="type_stored"]'); 41 const typeAvailableIndicatorElement = formContainerElement?.querySelector('#advset_type_available_indicator'); 42 const submitButtonElement = formContainerElement?.querySelector('[type="submit"]'); 43 44 const posttypes_data = <?php echo json_encode($advset_posttypes_data); ?>; 45 const posttypes_data_default = <?php echo json_encode($advset_posttypes_data_default); ?>; 46 47 document.addEventListener('click', function(event) { 48 if (event.target.closest('.advset-posttype-edit-link')) { 49 event.preventDefault(); 50 showForm(event.target.getAttribute('data-type')); 51 } 52 if (event.target.closest('.advset-posttype-cancel-link')) { 53 event.preventDefault(); 54 showList(); 55 } 56 if (event.target.closest('.advset-posttype-delete-link')) { 57 event.preventDefault(); 58 if (confirm('<?php _e('Are you sure you want to delete this post type?') ?>')) { 59 advset_submit_delete_posttype(event.target.getAttribute('data-type')); 60 } 61 } 62 }); 63 64 labelInputElement.addEventListener('blur', function() { 65 if (typeInputElement.value === '') { 66 checkType(true); 67 } 68 }); 69 70 typeInputElement.addEventListener('input', function() { 71 checkType(); 72 }); 73 74 function checkType(generate_from_label = false) { 75 setTypeValidity(null); 76 if (!generate_from_label && typeInputElement.value === '') { 77 return; 78 } 79 fetch('<?php echo rest_url('advset_posttypes/v1/check-type'); ?>', { 80 method: 'POST', 81 body: JSON.stringify({ 82 label_input: labelInputElement.value, 83 type_input: typeInputElement.value, 84 type_stored: typeStoredInputElement.value, 85 generate_from_label, 86 }), 87 headers: { 88 'Content-Type': 'application/json', 89 'X-WP-Nonce': '<?php echo wp_create_nonce('wp_rest'); ?>', 90 }, 91 }) 92 .then(response => response.json()) 93 .then(data => { 94 if (generate_from_label && data.type_available) { 95 typeInputElement.value = data.type_available; 96 setTypeValidity(true); 97 } 98 else if (data.is_taken) { 99 setTypeValidity(false); 100 } 101 else if (data.is_valid) { 102 setTypeValidity(true); 103 } 104 }); 105 } 106 107 function setTypeValidity(validity) { 108 let color, icon, text; 109 switch (validity) { 110 case true: 111 color = 'green'; 112 icon = '✅'; 113 text = 'Type is available'; 114 break; 115 case false: 116 color = 'red'; 117 icon = '❌'; 118 text = 'Type already exists'; 119 break; 120 default: 121 color = 'gray'; 122 icon = ''; 123 text = ''; 124 break; 125 } 126 typeInputElement.setCustomValidity(validity === false ? text : ''); 127 typeAvailableIndicatorElement.textContent = icon + ' ' + text; 128 typeAvailableIndicatorElement.style.color = color; 129 } 130 131 function showForm(type) { 132 133 const data = type ? posttypes_data[type] : posttypes_data_default; 134 data.label = data?.labels?.name ?? type; 135 data.type = type ?? ''; 136 data.type_stored = type ?? ''; 137 138 formElement.querySelectorAll('[name]').forEach(element => { 139 if (element.name.slice(0, 1) === '_') { 140 return; 141 } 142 143 if (element.type === 'checkbox') { 144 if (element.name.slice(-2) === '[]') { 145 element.checked = data[element.name.slice(0, -2)]?.includes(element.value) ?? element.defaultChecked; 146 } else { 147 element.checked = data[element.name] ?? element.defaultChecked; 148 } 149 } else if (['text', 'hidden', 'textarea'].includes(element.type)) { 150 element.value = data[element.name] ?? element.defaultValue; 151 } 152 }); 153 154 submitButtonElement.value = type ? submitButtonElement.dataset.saveChanges : submitButtonElement.dataset.create; 155 156 setTypeValidity(null); 157 158 listContainerElement.style.display = 'none'; 159 formContainerElement.style.display = ''; 160 labelInputElement.focus(); 161 } 162 163 function showList() { 164 formContainerElement.style.display = 'none'; 165 listContainerElement.style.display = ''; 166 }; 167 168 // Submit delete via hidden POST form 169 function advset_submit_delete_posttype(slug) { 170 const form = document.getElementById('advset_delete_posttype_form'); 171 const input = document.getElementById('advset_delete_posttype_slug'); 172 if (!slug || !form || !input) return false; 173 input.value = slug; 174 form.submit(); 46 175 return false; 47 176 }; 48 populate=function (frm, data) { 49 $=jQuery; 50 $.each(data, function(key, value){ 51 var $ctrl = $('[name='+key+']', frm); 52 switch($ctrl.attr("type")) { 53 case "text" : 54 case "hidden": 55 case "textarea": 56 $ctrl.val(value); 57 break; 58 case "radio" : case "checkbox": 59 $ctrl.each(function(){ 60 if( $(this).attr('value') == value 61 || $(this).attr('name')=='query_var' && $(this).attr('value')!='' ) 62 $(this).attr("checked",value); 63 else 64 $(this).attr("checked",null); 65 }); 66 break; 67 } 68 }); 69 }; 70 show_list=function() { 71 $('#post_type_form').hide(); 72 $('#post_type_list').fadeIn(); 73 }; 74 str2slug=function(str) { 75 var new_str = ''; 76 str=str.toLowerCase(); 77 str=str.replace(/[aáàãâä]/g,'a'); 78 str=str.replace(/[éèêë]/g,'e'); 79 str=str.replace(/[íìîï]/g,'i'); 80 str=str.replace(/[óòõôö]/g,'o'); 81 str=str.replace(/[úùûü]/g,'u'); 82 str=str.replace('ç','c'); 83 str=str.replace(/[^a-z0-9_\-]/g,''); 84 str=str.substring(0, 20); 85 return str; 86 }; 87 function in_array(needle, haystack) { 88 var length = haystack.length; 89 for(var i = 0; i < length; i++) { 90 if(haystack[i] == needle) return true; 91 } 92 return false; 93 } 94 </script> 95 96 <div class="wrap"> 97 <?php advset_page_header() ?> 98 <br /> 99 <?php echo advset_page_experimental(); ?> 100 <br /> 101 <br /> 102 103 104 <div style="padding: 1rem; background: #fff; border: #f00 solid 2px; border-radius: .5rem; "> 105 <h3 style="margin: 0; ">WARNING</h3> 106 <p style="margin: 0; "><?php _e('Be careful, changing a post type can significantly impact the functionality of the website.') ?></p> 107 </div> 108 <br /> 109 <a href="#" onclick="return show_form();" class="add-new-h2">Add New Post Type</a> 110 <br /> 111 <br /> 112 113 <div id="post_type_form" style="display:none"> 114 115 <h3>Add New Post Type</h3> 116 117 <form id="posttype_form" action="" method="post"> 118 <?php #settings_fields( 'advanced-settings-post-types' ); ?> 119 120 <input type="hidden" name="advset_action_posttype" value="1" /> 121 122 <table class="form-table"> 123 <tr valign="top"> 124 <th scope="row"><?php _e('Label'); ?></th> 125 <td> 126 <input id="namefield" name="label" type="text" value="" onblur=" 127 const input = document.getElementById('typefield'); 128 if( input.value === '' ) 129 input.value = str2slug(this.value); 130 " /> 131 132 <!--p><a href="#">+ show more labels</a></p--> 133 134 </td> 135 </tr> 136 137 <tr valign="top"> 138 <th scope="row"><?php _e('Type Name'); ?></th> 139 <td> 140 <input id="typefield" name="type" type="text" value="" pattern="^[a-z0-9_\-]{1,20}$" required /><br /> 141 <i style="color:#999">Post type names must be between 1 and 20 characters in length. Lowercase alphanumeric characters, dashes, and underscores are allowed. </i> 142 </td> 143 </tr> 144 145 <tr valign="top"> 146 <th scope="row"><?php _e('Supports'); ?></th> 147 <td> 148 <input name="supports[]" id="posttype-support-title" value="title" type="checkbox" checked="checked"> 149 <label for="posttype-support-title">title</label><br /> 150 <input name="supports[]" id="posttype-support-editor" value="editor" type="checkbox" checked="checked"> 151 <label for="posttype-support-editor">editor</label><br /> 152 <input name="supports[]" id="posttype-support-author" value="author" type="checkbox"> 153 <label for="posttype-support-author">author</label><br /> 154 <input name="supports[]" id="posttype-support-thumbnail" value="thumbnail" type="checkbox"> 155 <label for="posttype-support-thumbnail">thumbnail</label><br /> 156 <input name="supports[]" id="posttype-support-excerpt" value="excerpt" type="checkbox"> 157 <label for="posttype-support-excerpt">excerpt</label><br /> 158 <input name="supports[]" id="posttype-support-trackbacks" value="trackbacks" type="checkbox"> 159 <label for="posttype-support-trackbacks">trackbacks</label><br /> 160 <input name="supports[]" id="posttype-support-custom-fields" value="custom-fields" type="checkbox"> 161 <label for="posttype-support-custom-fields">custom fields</label><br /> 162 <input name="supports[]" id="posttype-support-comments" value="comments" type="checkbox"> 163 <label for="posttype-support-comments">comments</label><br /> 164 <input name="supports[]" id="posttype-support-revisions" value="revisions" type="checkbox"> 165 <label for="posttype-support-revisions">revisions</label> <br /> 166 <input name="supports[]" id="posttype-support-page-attributes" value="page-attributes" type="checkbox"> 167 <label for="posttype-support-page-attributes">page attributes</label> 168 </td> 169 </tr> 170 171 <tr valign="top"> 172 <th scope="row"><?php _e('Settings'); ?></th> 173 <td> 174 <label><input name="public" value="1" type="checkbox" checked="checked"> 175 public</label><br /> 176 <label><input name="publicly_queryable" value="1" type="checkbox" checked="checked"> 177 publicly_queryable</label><br /> 178 <label><input name="show_ui" value="1" type="checkbox" checked="checked"> 179 show_ui</label><br /> 180 <label><input name="show_in_menu" value="1" type="checkbox" checked="checked"> 181 show_in_menu</label><br /> 182 <label><input name="query_var" value="1" type="checkbox" checked="checked"> 183 query_var</label><br /> 184 <!--label><input name="rewrite" value="1" type="checkbox"> 185 rewrite</label><br /--> 186 <!--label><input name="capability_type" value="1" type="checkbox"> 187 capability_type</label><br /--> 188 <label><input name="has_archive" value="1" type="checkbox"> 189 has_archive</label><br /> 190 <label><input name="hierarchical" value="1" type="checkbox"> 191 hierarchical</label> <br /> 192 <!--label><input name="menu_position" value="1" type="checkbox"> 193 menu_position</label--> 194 </td> 195 </tr> 196 197 <tr valign="top"> 198 <th scope="row"><?php _e('Taxonomies'); ?></th> 199 <td> 200 <label><input name="taxonomies[]" value="category" type="checkbox" checked="checked"> 201 category</label><br /> 202 <label><input name="taxonomies[]" value="post_tag" type="checkbox" checked="checked"> 203 post_tag</label> 204 </td> 205 </tr> 206 207 </table> 208 <p class="submit"> 209 <input type="submit" name="submit" id="submit" class="button button-primary" value="<?php _e('Save Changes') ?>" /> 210 <input type="button" onclick="show_list();" class="button" value="<?php _e('Cancel') ?>" /> 211 </p> 212 </form> 213 </div> 214 215 <form id="post_type_list" action="options.php" method="post"> 216 217 <table class="widefat fixed" cellspacing="0"> 177 }); 178 </script> 179 180 <div class="wrap"> 181 <?php advset_page_header() ?> 182 <br /> 183 <!-- <?php echo advset_page_experimental(); ?> 184 <br /> 185 <br /> --> 186 187 188 <!-- <div style="padding: 1rem; background: #fff; border: #f00 solid 2px; border-radius: .5rem; "> 189 <h3 style="margin: 0; ">WARNING</h3> 190 <p style="margin: 0; "><?php _e('Be careful, changing a post type can significantly impact the functionality of the website.') ?></p> 191 </div> 192 <br /> --> 193 <a class="advset-posttype-edit-link add-new-h2" href="#" data-type=""><?php _e('Add') ?></a> 194 <br /> 195 <br /> 196 197 <div id="advset_posttype_form_container" style="display:none"> 198 199 <h3><?php _e('Add') ?></h3> 200 201 <form id="advset_posttype_form" action="" method="post"> 202 <?php #settings_fields( 'advanced-settings-post-types' ); ?> 203 204 <input type="hidden" name="_advset_posttype_nonce" value="<?php echo $advset_posttype_nonce; ?>" /> 205 206 <input type="hidden" name="_advset_posttype_action_save" value="1" /> 207 208 <input type="hidden" name="type_stored" value="" /> 209 210 <table class="form-table"> 211 <tr valign="top"> 212 <th scope="row"><?php _e('Label'); ?></th> 213 <td> 214 <input name="label" type="text" value="" /> 215 216 <!--p><a href="#">+ show more labels</a></p--> 217 218 </td> 219 </tr> 220 221 <tr valign="top"> 222 <th scope="row"><?php _e('Type Name'); ?></th> 223 <td> 224 <input name="type" type="text" value="" pattern="^[a-z0-9_\-]{1,20}$" required /> <span id="advset_type_available_indicator"></span><br /> 225 <i style="color:#999">Post type names must be between 1 and 20 characters in length. Lowercase alphanumeric characters, dashes, and underscores are allowed. </i> 226 </td> 227 </tr> 228 229 <tr valign="top"> 230 <th scope="row"><?php _e('Description'); ?></th> 231 <td> 232 <!-- <textarea name="description" rows="3" style="width: 100%;"></textarea> --> 233 <input name="description" type="text" value="" /> 234 </td> 235 </tr> 236 237 <tr valign="top"> 238 <th scope="row"><?php _e('Supports'); ?></th> 239 <td> 240 <input name="supports[]" id="posttype-support-title" value="title" type="checkbox"> 241 <label for="posttype-support-title">title</label><br /> 242 <input name="supports[]" id="posttype-support-editor" value="editor" type="checkbox"> 243 <label for="posttype-support-editor">editor</label><br /> 244 <input name="supports[]" id="posttype-support-author" value="author" type="checkbox"> 245 <label for="posttype-support-author">author</label><br /> 246 <input name="supports[]" id="posttype-support-thumbnail" value="thumbnail" type="checkbox"> 247 <label for="posttype-support-thumbnail">thumbnail</label><br /> 248 <input name="supports[]" id="posttype-support-excerpt" value="excerpt" type="checkbox"> 249 <label for="posttype-support-excerpt">excerpt</label><br /> 250 <input name="supports[]" id="posttype-support-trackbacks" value="trackbacks" type="checkbox"> 251 <label for="posttype-support-trackbacks">trackbacks</label><br /> 252 <input name="supports[]" id="posttype-support-custom-fields" value="custom-fields" type="checkbox"> 253 <label for="posttype-support-custom-fields">custom fields</label><br /> 254 <input name="supports[]" id="posttype-support-comments" value="comments" type="checkbox"> 255 <label for="posttype-support-comments">comments</label><br /> 256 <input name="supports[]" id="posttype-support-revisions" value="revisions" type="checkbox"> 257 <label for="posttype-support-revisions">revisions</label> <br /> 258 <input name="supports[]" id="posttype-support-page-attributes" value="page-attributes" type="checkbox"> 259 <label for="posttype-support-page-attributes">page attributes</label> 260 </td> 261 </tr> 262 263 <tr valign="top"> 264 <th scope="row"><?php _e('Settings'); ?></th> 265 <td> 266 <label><input name="public" value="1" type="checkbox"> 267 public</label><br /> 268 <label><input name="publicly_queryable" value="1" type="checkbox"> 269 publicly_queryable</label><br /> 270 <label><input name="show_ui" value="1" type="checkbox"> 271 show_ui</label><br /> 272 <label><input name="show_in_menu" value="1" type="checkbox"> 273 show_in_menu</label><br /> 274 <label><input name="query_var" value="1" type="checkbox"> 275 query_var</label><br /> 276 <!--label><input name="rewrite" value="1" type="checkbox"> 277 rewrite</label><br /--> 278 <!--label><input name="capability_type" value="1" type="checkbox"> 279 capability_type</label><br /--> 280 <label><input name="has_archive" value="1" type="checkbox"> 281 has_archive</label><br /> 282 <label><input name="hierarchical" value="1" type="checkbox"> 283 hierarchical</label> <br /> 284 <!--label><input name="menu_position" value="1" type="checkbox"> 285 menu_position</label--> 286 </td> 287 </tr> 288 289 <tr valign="top"> 290 <th scope="row"><?php _e('Taxonomies'); ?></th> 291 <td> 292 <label><input name="taxonomies[]" value="category" type="checkbox"> 293 category</label><br /> 294 <label><input name="taxonomies[]" value="post_tag" type="checkbox"> 295 post_tag</label> 296 </td> 297 </tr> 298 299 </table> 300 <p class="submit"> 301 <input type="submit" id="submit" class="button button-primary" value="<?php _e('Save Changes') ?>" data-save-changes="<?php _e('Save Changes') ?>" data-create="<?php _e('Create') ?>" /> 302 <input type="button" class="button advset-posttype-cancel-link" value="<?php _e('Cancel') ?>" /> 303 </p> 304 </form> 305 </div> 306 307 <div id="advset_posttype_list_container"> 308 <?php if (!empty($advset_posttypes_data)) { ?> 309 <form id="advset_posttype_list" action="options.php" method="post"> 310 311 <table class="widefat fixed striped" cellspacing="0"> 218 312 <thead> 219 313 <tr> 220 <th scope="col" id="cb" class="manage-column column-cb check-column" style=""><label class="screen-reader-text" for="cb-select-all-1">Selecionar Tudo</label><input id="cb-select-all-1" type="checkbox"></th> 221 <th scope="col" id="title" class="manage-column column-title" width="40%">Label <small>(Menu name)</small></th> 222 <th scope="col" id="type_name" class="manage-column column-title" width="30%">Type</th> 223 <th scope="col" id="type_desc" class="manage-column column-title" width="30%">Description</th> 314 <th scope="col" id="title" class="manage-column column-title" width="40%"><?php _e('Label') ?></th> 315 <th scope="col" id="type_name" class="manage-column column-title" width="30%"><?php _e('Type') ?></th> 316 <th scope="col" id="type_desc" class="manage-column column-title" width="30%"><?php _e('Description') ?></th> 224 317 </tr> 225 318 </thead> 226 <?php foreach($ post_types as $typename=>$post_type) { ?>319 <?php foreach($advset_posttypes_data as $typename => $post_type) { ?> 227 320 <tr class=" iedit"> 228 <th scope="row" class="check-column"> 229 230 <input id="cb-select-1" type="checkbox" name="post[]" value="1"> 231 <div class="locked-indicator"></div> 232 </th> 233 <td> 234 <strong><?php echo $post_type->label ?></strong> 321 <td> 322 <strong><?php echo $post_type['labels']['name'] ?></strong> 235 323 <div class="row-actions"> 236 <?php if( !in_array( $post_type->name, array('post', 'page') ) ) { ?>237 324 <span class="edit"> 238 <a href="#" onclick="show_form('<?php echo $post_type->name ?>');">Edit</a> 325 <a class="advset-posttype-edit-link" href="#" data-type="<?php echo esc_attr($typename) ?>"><?php _e('Edit') ?></a> 326 | 239 327 </span> 240 | <a href="options-general.php?page=advanced-settings-post-types&delete_posttype=<?php echo $post_type->name ?>" title="default categories">delete</a>241 < ?php } else echo ' '; ?>242 328 <span class="trash"> 329 <a class="advset-posttype-delete-link" href="#" data-type="<?php echo esc_attr($typename) ?>"><?php _e('Delete') ?></a> 330 </span> 243 331 </div> 244 332 </td> 245 <td><?php echo $ post_type->name ?></td>246 <td>< /td>333 <td><?php echo $typename ?></td> 334 <td><?php echo str_replace("\n", '<br />', strip_tags($post_type['description'] ?? '')) ?></td> 247 335 </tr> 248 336 <?php } ?> … … 250 338 <tfoot> 251 339 <tr> 252 <th scope="col" class="manage-column column-cb check-column" style=""><label class="screen-reader-text" for="cb-select-all-2">Selecionar Tudo</label><input id="cb-select-all-2" type="checkbox"></th> 253 <th scope="col" id="title" class="manage-column column-title" width="40%">Label <small>(Menu name)</small></th> 254 <th scope="col" id="type_name" class="manage-column column-title" width="30%">Type</th> 255 <th scope="col" id="type_desc" class="manage-column column-title" width="30%">Description</th> 340 <th scope="col" id="title" class="manage-column column-title" width="40%"><?php _e('Label') ?></th> 341 <th scope="col" id="type_name" class="manage-column column-title" width="30%"><?php _e('Type') ?></th> 342 <th scope="col" id="type_desc" class="manage-column column-title" width="30%"><?php _e('Description') ?></th> 256 343 </tr> 257 344 </tfoot> 258 345 259 346 </table> 260 261 <!--p class="submit"><input type="submit" name="submit" id="submit" class="button-primary" value="<?php _e('Save changes') ?>"></p--> 347 </form> 348 <?php } else { ?> 349 <div> 350 <p><?php _e('No custom post types found.') ?></p> 351 </div> 352 <?php } ?> 353 354 <form id="advset_delete_posttype_form" action="<?php echo esc_url( admin_url('options-general.php?page=advanced-settings-post-types') ); ?>" method="post" style="display: none;"> 355 <input type="hidden" name="_advset_posttype_nonce" value="<?php echo esc_attr($advset_posttype_nonce); ?>" /> 356 <input type="hidden" name="_advset_posttype_action_delete" id="advset_delete_posttype_slug" value="" /> 262 357 </form> 263 358 </div> 359 </div> -
advanced-settings/tags/3.2.0/feature-setup/features/includes/frontend.auto_thumbs.php
r3281733 r3357461 1 1 <?php 2 2 3 if ( !defined('ABSPATH')) exit;3 if (!defined('ABSPATH')) exit; 4 4 5 5 6 function advset__feature__auto_thumbs( $new_status, $old_status, $post ) { 7 if ('publish' == $new_status) { 8 advset__feature__auto_thumbs__publish_post($post); 6 /** 7 * Auto Thumbs feature class. 8 */ 9 class Advset__Feature__Auto_Thumbs { 10 11 private static $instance = null; 12 13 private function __construct() {} 14 15 /** 16 * Initialize the feature. 17 * 18 * @return Advset__Feature__Auto_Thumbs The instance of the feature. 19 */ 20 public static function init() { 21 if (self::$instance === null) { 22 self::$instance = new self(); 23 } 24 return self::$instance; 9 25 } 10 } 26 27 /** 28 * Transition the post status. 29 * 30 * @param string $new_status The new status of the post. 31 * @param string $old_status The old status of the post. 32 * @param object $post The post object. 33 * @return bool True if the post thumbnail was generated, false otherwise. 34 */ 35 public function transition_post_status( string $new_status, string $old_status, object $post ) { 36 global $wpdb; 37 38 // If the post is not published, return 39 if ($new_status !== 'publish') { 40 return false; 41 } 11 42 12 // 13 function advset__feature__auto_thumbs__publish_post( $post ) { 14 global $wpdb; 15 16 // First check whether Post Thumbnail is already set for this post. 17 if (get_post_meta($post->ID, '_thumbnail_id', true) || get_post_meta($post->ID, 'skip_post_thumb', true)) 18 return; 19 20 // Initialize variable used to store list of matched images as per provided regular expression 21 $matches = array(); 22 23 // Get all images from post's body 24 preg_match_all('/<\s*img [^\>]*src\s*=\s*[\""\']?([^\""\'>]*)[^\>]*/i', empty($post->post_content) ? '' : $post->post_content, $matches); 25 26 if (count($matches)) { 27 foreach ($matches[0] as $key => $image) { 28 /** 29 * If the image is from wordpress's own media gallery, then it appends the thumbmail id to a css class. 30 * Look for this id in the IMG tag. 31 */ 32 preg_match('/wp-image-([\d]*)/i', $image, $thumb_id); 33 $thumb_id = empty($thumb_id[1]) ? null : $thumb_id[1]; 34 43 // First check whether Post Thumbnail is already set for this post. 44 if (get_post_meta($post->ID, '_thumbnail_id', true) || get_post_meta($post->ID, 'skip_post_thumb', true)) 45 return false; 46 47 // Initialize variable used to store the thumbnail id 48 $thumb_id = null; 49 50 // Initialize variable used to store list of matched images as per provided regular expression 51 $images = []; 52 53 // Get all images from post's body 54 preg_match_all('/<\s*img [^\>]*src\s*=\s*[\""\']?([^\""\'>]*)[^\>]*/i', $post->post_content ?? '', $images, PREG_SET_ORDER); 55 56 // If no images are found, return 57 if (empty($images)) { 58 return false; 59 } 60 61 // Loop through all images 62 foreach ($images as $image) { 63 $img_html = $image[0]; 64 $image_url = $image[1]; 65 66 // If the image is from wordpress's own media gallery, then it appends the thumbmail id to a css class. 67 preg_match('/\s+class\s*=\s*[\""\']?([^\""\'>]*)/i', $img_html, $matches_class); 68 preg_match('/(?:^|\s+)wp-image-([\d]*)(?:\s+|$)/i', $matches_class[1] ?? '', $matches_thumb_id); 69 if (!empty($matches_thumb_id[1]) && (int) $matches_thumb_id[1] > 0) { 70 $thumb_id = (int) $matches_thumb_id[1]; 71 break; 72 } 73 74 // Get the image URL 75 if (!wp_http_validate_url($image_url)) { 76 continue; 77 } 78 35 79 // If thumb id is not found, try to look for the image in DB. Thanks to "Erwin Vrolijk" for providing this code. 36 if (!$thumb_id) {37 $image = $matches[1][$key];38 $ result = $wpdb->get_results($wpdb->prepare("SELECT ID FROM {$wpdb->posts} WHERE guid = %s", $image));39 $thumb_id = empty($result[0]->ID) ? null : $result[0]->ID;80 $attachment = $wpdb->get_results($wpdb->prepare("SELECT ID FROM {$wpdb->posts} WHERE guid = %s", $image_url)); 81 if (!empty($attachment[0]->ID) && (int) $attachment[0]->ID > 0) { 82 $thumb_id = (int) $attachment[0]->ID; 83 break; 40 84 } 41 85 42 86 // Ok. Still no id found. Some other way used to insert the image in post. Now we must fetch the image from URL and do the needful. 43 if (!$thumb_id) { 44 $thumb_id = advset__feature__auto_thumbs__generate_post_thumbnail($matches, $key, $post); 45 } 46 47 // If we succeed in generating thumg, let's update post meta 48 if ($thumb_id) { 49 update_post_meta( $post->ID, '_thumbnail_id', $thumb_id ); 87 preg_match('/\s+alt\s*=\s*[\""\']?([^\""\'>]*)/i', $img_html, $matches_alt); 88 preg_match('/\s+title\s*=\s*[\""\']?([^\""\'>]*)/i', $img_html, $matches_title); 89 $imported_thumb_id = $this->import_image_from_url($image_url, $post->ID, [ 90 'alt' => $matches_alt[1] ?? '', 91 'title' => $matches_title[1] ?? '', 92 ]); 93 if (!is_wp_error($imported_thumb_id) && (int) $imported_thumb_id > 0) { 94 $thumb_id = (int) $imported_thumb_id; 50 95 break; 51 96 } 52 97 } 98 99 // If we succeed in generating thumg, let's update post meta 100 if ($thumb_id) { 101 update_post_meta( $post->ID, '_thumbnail_id', $thumb_id ); 102 return true; 103 } 104 105 return false; 106 } 107 108 /** 109 * Imports an image from an external URL into the media library. 110 * 111 * @param string $url The URL of the image to import. 112 * @param int $post_id The ID of the post to import the image to. 113 * @param array $opts Optional arguments for the import. 114 * @return int|\WP_Error Attachment-ID oder Fehler 115 */ 116 private function import_image_from_url( string $url, int $post_id = 0, array $opts = [] ) { 117 118 // Validate the URL 119 if (!wp_http_validate_url($url)) { 120 return new WP_Error('invalid_url', __('Invalid image URL.')); 121 } 122 123 // Parse the options 124 $opts = wp_parse_args($opts, [ 125 'alt' => '', 126 'title' => '', 127 ]); 128 129 // Require the necessary files 130 require_once ABSPATH.'wp-admin/includes/file.php'; 131 require_once ABSPATH.'wp-admin/includes/image.php'; 132 require_once ABSPATH.'wp-admin/includes/media.php'; 133 134 // Download the image 135 $tmp = download_url($url); 136 if ( is_wp_error($tmp) ) { 137 return $tmp; 138 } 139 140 // Get the name and mime type of the image 141 $name = wp_basename(parse_url($url, PHP_URL_PATH) ?: 'image'); 142 $wp_filetype = wp_check_filetype_and_ext( $tmp, $name ); 143 144 // Check if the image is a valid image 145 if (empty($wp_filetype['type']) || !wp_match_mime_types('image', $wp_filetype['type'])) { 146 return new WP_Error('invalid_image', __('The uploaded file is not a valid image. Please try again.')); 147 } 148 149 // Create the file array 150 $file_array = [ 151 'name' => $name, 152 'tmp_name' => $tmp, 153 'type' => $wp_filetype['type'], 154 ]; 155 156 // Create the post data 157 $post_data = []; 158 if (!empty($opts['title'])) { 159 $post_data['post_title'] = $opts['title']; 160 } 161 162 // Create the description 163 $desc = null; 164 165 // Sideload the image 166 $attachment_id = media_handle_sideload($file_array, $post_id, $desc, $post_data); 167 168 // Unlink the temporary file if it exists 169 @unlink($tmp); 170 171 // If there is an error, return the error 172 if ( is_wp_error($attachment_id) ) { 173 return $attachment_id; 174 } 175 176 // Update the attachment meta if the alt text is provided 177 if (!empty($opts['alt'])) { 178 update_post_meta($attachment_id, '_wp_attachment_image_alt', $opts['alt']); 179 } 180 181 // Return the attachment ID (as integer) 182 return (int) $attachment_id; 53 183 } 54 184 } 55 56 57 function advset__feature__auto_thumbs__generate_post_thumbnail( $matches, $key, $post ) {58 // Make sure to assign correct title to the image. Extract it from img tag59 $imageTitle = '';60 preg_match_all('/<\s*img [^\>]*title\s*=\s*[\""\']?([^\""\'>]*)/i', empty($post->post_content) ? '' : $post->post_content, $matchesTitle);61 62 if (count($matchesTitle) && isset($matchesTitle[1])) {63 $imageTitle = empty($matchesTitle[1][$key]) ? '' : $matchesTitle[1][$key];64 }65 66 // Get the URL now for further processing67 $imageUrl = $matches[1][$key];68 69 // Get the file name70 $filename = substr($imageUrl, (strrpos($imageUrl, '/'))+1);71 72 if ( !(($uploads = wp_upload_dir(current_time('mysql')) ) && false === $uploads['error']) )73 return null;74 75 // Generate unique file name76 $filename = wp_unique_filename( $uploads['path'], $filename );77 78 // Move the file to the uploads dir79 $new_file = $uploads['path'] . "/$filename";80 81 if (!ini_get('allow_url_fopen'))82 $file_data = advset__feature__auto_thumbs__curl_get_file_contents($imageUrl);83 else84 $file_data = @file_get_contents($imageUrl);85 86 if (!$file_data) {87 return null;88 }89 90 file_put_contents($new_file, $file_data);91 92 // Set correct file permissions93 $stat = stat( dirname( $new_file ));94 $perms = $stat['mode'] & 0000666;95 @ chmod( $new_file, $perms );96 97 // Get the file type. Must to use it as a post thumbnail.98 $wp_filetype = wp_check_filetype( $filename );99 100 extract( $wp_filetype );101 102 // No file type! No point to proceed further103 if ( ( !$type || !$ext ) && !current_user_can( 'unfiltered_upload' ) ) {104 return null;105 }106 107 // Compute the URL108 $url = $uploads['url'] . "/$filename";109 110 // Construct the attachment array111 $attachment = array(112 'post_mime_type' => $type,113 'guid' => $url,114 'post_parent' => null,115 'post_title' => $imageTitle,116 'post_content' => '',117 );118 119 $thumb_id = wp_insert_attachment($attachment, false, $post->ID);120 if ( !is_wp_error($thumb_id) ) {121 require_once(ABSPATH . '/wp-admin/includes/image.php');122 123 // Added fix by misthero as suggested124 wp_update_attachment_metadata( $thumb_id, wp_generate_attachment_metadata( $thumb_id, $new_file ) );125 update_attached_file( $thumb_id, $new_file );126 127 return $thumb_id;128 }129 130 return null;131 }132 133 function advset__feature__auto_thumbs__curl_get_file_contents($URL) {134 $c = curl_init();135 curl_setopt($c, CURLOPT_RETURNTRANSFER, 1);136 curl_setopt($c, CURLOPT_URL, $URL);137 $contents = curl_exec($c);138 curl_close($c);139 140 if ($contents) {141 return $contents;142 }143 144 return FALSE;145 } -
advanced-settings/tags/3.2.0/readme.txt
r3323109 r3357461 8 8 Requires at least: 5.0.0 9 9 Tested up to: 6.8 10 Stable tag: 3. 1.110 Stable tag: 3.2.0 11 11 License: GPLv3 or later 12 12 License URI: http://www.gnu.org/licenses/gpl-3.0.html … … 22 22 [→ details in FAQ](https://wordpress.org/plugins/advanced-settings#will%20the%20plugin%20become%20slower%20with%20more%20features%3F) 23 23 24 **🪶 LIGHTWEIGHT** 25 Advanced Settings 3 is lightweight (only about 0.5 MB) and discreet (no dashboard hijacking). 26 [→ details in FAQ](https://wordpress.org/plugins/advanced-settings#how%20can%20the%20plugin%20be%20lightweight%20despite%20so%20many%20features%3F) 27 24 28 **🔒 SECURITY** 25 29 Advanced Settings 3 has been independently reviewed for security vulnerabilities via Patchstack. … … 27 31 28 32 **✳️ INFO ABOUT THE 2 BAD RATINGS** 29 2 bad ratings occurred in 2017 because outdated PHP versions were used, but can't happen again.33 Bad ratings occurred in 2017 because users used outdated PHP versions, but can't happen again. 30 34 [→ details in FAQ](https://wordpress.org/plugins/advanced-settings#what%20caused%20the%20two%20bad%20ratings%3F) 31 35 … … 90 94 91 95 * Display SQL queries and page load time 96 * Create custom post types 💥 renewed 92 97 93 98 = Configuration = … … 118 123 Advanced Settings 3 works as follows: Only when you open the plugin's settings window does the plugin recognise which settings are actually available. When saving, only the activated settings are written to a separate cache file. Only this cache file is then taken into account during operation. This means that slowdowns can only occur due to **active** features. However, as some features deactivate WordPress functions, the plugin can actually make WordPress even faster than in the standard configuration. 119 124 125 = How can the plugin be lightweight despite so many features? = 126 127 **Short answer:** 128 Typically, graphical user interfaces represent the largest chunk of data. Since we have largely standardized the user interface for all features, additional features are of little importance. 129 130 **Detailed answer:** 131 The plugin is currently only 0.5 MB in size. Only about a third of that is used for the actual functionality of the features. The rest is used for the graphical user interface, backward compatibility, performance optimization, and the like. So if we doubled the number of features, the plugin would still be smaller than 0.7 MB. Theoretically, we could quadruple the number of features and still stay under 1 MB. So the number of features isn't crucial. The trick is to standardize everything around the features so that each additional feature has minimal impact. 132 133 We are passionate about lightweight plugins that remain politely in the background while you work, so we can assure you that this will continue to be the case. 134 120 135 = How is the security of the plugin ensured? = 121 136 … … 152 167 == Changelog == 153 168 169 = 3.2.0 - 2025-09-07 = 170 * Fixed a medium priority security issue which appeared on activated feature "Automatically generate the Post Thumbnail" 171 * Thoroughly revised feature "Automatically generate the Post Thumbnail" 172 * Fixed a low priority security issue which appeared on activated experimental feature "Post types settings" (now "Custom post types") 173 * Thoroughly revised feature "Post types settings", renamed it to "Custom post types" and removed the "experimental" flag 174 154 175 = 3.1.1 - 2025-07-06 = 155 176 * Fixed minor cache problem … … 161 182 = 3.0.2 - 2025-06-04 = 162 183 * Fixed order of features 163 * Fixed a minor security issue in old code (rated as low priority by [Patchstack](https://patchstack.com/))184 * Fixed a low priority security issue which appeared on activated experimental feature "Filters and actions settings" 164 185 165 186 = 3.0.1 - 2025-05-03 = -
advanced-settings/trunk/admin-ui/admin-ui.css
r3323103 r3357461 128 128 height: 80vh; 129 129 background-color: #fff; 130 overflow: hidden;130 overflow: visible; 131 131 } 132 132 … … 149 149 flex-direction: column; 150 150 height: 100%; 151 border-radius: .5em; 152 overflow: hidden; 151 153 } 152 154 … … 248 250 flex-direction: column; 249 251 height: 100%; 252 } 253 254 .advset-modal-madeby { 255 padding: 0; 256 display: flex; 257 gap: 1em; 258 position: absolute; 259 top: 100%; 260 right: 0px; 261 left: 0px; 262 color: #fff; 263 opacity: .8; 264 justify-content: center; 265 margin: 0 auto; 266 width: fit-content; 267 } 268 269 .advset-modal-madeby img { 270 flex-shrink: 0; 271 flex-grow: 0; 272 width: 50px; 273 height: auto; 274 } 275 276 .advset-modal-madeby p { 277 font-size: var(--advset-font-size-small); 278 } 279 280 .advset-modal-madeby a { 281 color: inherit !important; 250 282 } 251 283 -
advanced-settings/trunk/admin-ui/admin-ui.php
r3323109 r3357461 207 207 </div> 208 208 </div> 209 <div class="advset-modal-madeby"> 210 <img src="<?php echo plugins_url('', ADVSET_FILE); ?>/admin-ui/images/wppeak.com-logo-vectorized-white.svg" alt="Advanced Settings"> 211 <p> 212 Advanced Settings is made by <a href="https://www.wppeak.com/" target="_blank" rel="noopener noreferrer">wppeak.com</a>.<br /> 213 We make plugins and other useful WordPress tools. 214 </p> 215 </div> 209 216 </dialog> 210 217 <?php -
advanced-settings/trunk/advanced-settings.php
r3323109 r3357461 6 6 Author: Helmut Wandl 7 7 Author URI: https://ehtmlu.com/ 8 Version: 3. 1.18 Version: 3.2.0 9 9 Requires at least: 5.0.0 10 10 Requires PHP: 7.4 -
advanced-settings/trunk/feature-setup/features/developer.php
r3323103 r3357461 135 135 'id' => 'developer.settings_pages.post_types', 136 136 'category' => 'developer', 137 'experimental' => true,138 137 'ui_config' => fn() => [ 139 138 'tags' => [ … … 145 144 'enable' => [ 146 145 'type' => 'toggle', 147 'label' => __('Post types settings', 'advanced-settings'), 148 'description' => __('These post types settings are currently under review and may be changed or removed in the future.', 'advanced-settings'), 146 'label' => __('Custom post types', 'advanced-settings'), 149 147 ], 150 148 'info' => [ … … 157 155 'execution_handler' => function() { 158 156 require_once ADVSET_DIR.'/feature-setup/features/includes/developer.settings_pages.php'; 159 160 add_action('init', function() { 161 162 $post_types = (array) get_option( 'advset_post_types', array() ); 163 164 if( is_admin() && current_user_can('manage_options') && isset($_GET['delete_posttype']) ) { 165 unset($post_types[$_GET['delete_posttype']]); 166 update_option( 'advset_post_types', $post_types ); 167 } 168 169 if( is_admin() && current_user_can('manage_options') && isset($_POST['advset_action_posttype']) ) { 170 171 extract($_POST); 172 173 $labels = array( 174 'name' => $label, 175 #'singular_name' => @$singular_name, 176 #'add_new' => @$add_new, 177 #'add_new_item' => @$add_new_item, 178 #'edit_item' => @$edit_item, 179 #'new_item' => @$new_item, 180 #'all_items' => @$all_items, 181 #'view_item' => @$view_item, 182 #'search_items' => @$search_items, 183 #'not_found' => @$not_found, 184 #'not_found_in_trash' => @$not_found_in_trash, 185 #'parent_item_colon' => @$parent_item_colon, 186 #'menu_name' => @$menu_name 187 ); 188 189 $typename = sanitize_key( $type ); 190 191 $post_types[$type] = array( 192 'labels' => $labels, 193 'public' => (bool) (isset($public) ? $public : false), 194 'publicly_queryable' => (bool) (isset($publicly_queryable) ? $publicly_queryable : false), 195 'show_ui' => (bool) (isset($show_ui) ? $show_ui : false), 196 'show_in_menu' => (bool) (isset($show_in_menu) ? $show_in_menu : false), 197 'query_var' => (bool) (isset($query_var) ? $query_var : false), 198 #'rewrite' => array( 'slug' => 'book' ), 199 #'capability_type' => 'post', 200 'has_archive' => (bool) (isset($has_archive) ? $has_archive : false), 201 'hierarchical' => (bool) (isset($hierarchical) ? $hierarchical : false), 202 #'menu_position' => (int)@$menu_position, 203 'supports' => (array) (empty($supports) ? [] : $supports), 204 'taxonomies' => (array) (empty($taxonomies) ? [] : $taxonomies), 205 ); 206 207 update_option( 'advset_post_types', $post_types ); 208 209 } 210 #print_r($post_types); 211 if( sizeof($post_types)>0 ) 212 foreach( $post_types as $post_type=>$args ) { 213 register_post_type( $post_type, $args ); 214 if( in_array( 'thumbnail', $args['supports'] ) ) { 215 add_theme_support( 'post-thumbnails', array( $post_type, 'post' ) ); 216 } 217 } 218 219 }); 220 221 add_action('admin_menu', function() { 222 add_options_page( 223 __('Post Types', 'advanced-settings'), 224 __('Post Types', 'advanced-settings'), 225 'manage_options', 226 'advanced-settings-post-types', 227 function() { 228 include ADVSET_DIR.'/feature-setup/features/includes/developer.settings_pages.post_types--admin-post-types.php'; 229 } 230 ); 231 }); 157 require_once ADVSET_DIR.'/feature-setup/features/includes/developer.settings_pages.post_types--init.php'; 158 Advset__Feature__Post_Types::init(); 232 159 }, 233 160 'priority' => 10, -
advanced-settings/trunk/feature-setup/features/editing.php
r3323103 r3357461 355 355 ], 356 356 'execution_handler' => function() { 357 require_once ADVSET_DIR . '/feature-setup/features/includes/frontend.auto_thumbs.php'; 358 add_action('transition_post_status', 'advset__feature__auto_thumbs', 10, 3); 357 add_action('transition_post_status', function($new_status, $old_status, $post) { 358 if ($new_status !== 'publish') { 359 return; 360 } 361 require_once ADVSET_DIR . '/feature-setup/features/includes/frontend.auto_thumbs.php'; 362 Advset__Feature__Auto_Thumbs::init()->transition_post_status($new_status, $old_status, $post); 363 }, 10, 3); 359 364 }, 360 365 'priority' => 70, -
advanced-settings/trunk/feature-setup/features/includes/developer.settings_pages.post_types--admin-post-types.php
r3286786 r3357461 1 <?php defined('ABSPATH') or exit; 2 3 global $_wp_post_type_features; 4 5 $post_types = get_post_types( '', 'objects' ); 6 7 unset( $post_types['attachment'], $post_types['revision'], $post_types['nav_menu_item'] ); 8 9 $advset_post_types = (array) get_option( 'advset_post_types', array() ); 10 11 ?> 12 <script> 13 <?php echo 'posttype_data='.json_encode($post_types).';'; ?> 14 <?php echo 'supports='.json_encode($_wp_post_type_features).';'; ?> 15 show_form=function(type) { 16 17 $=jQuery; 18 19 if( type ) { 20 21 data = posttype_data[type]; 22 23 data.type=type; 24 populate( '#posttype_form', data ); 25 26 var checks = $('[name=supports\\[\\]]', '#posttype_form'); 27 for( i=0; i<checks.length;i++ ) 28 if( supports[type][$(checks[i]).attr('value')] ) 29 $(checks[i]).attr("checked", "checked"); 30 else 31 $(checks[i]).attr("checked", null); 32 33 var checks = $('[name=taxonomies\\[\\]]', '#posttype_form'); 34 for( i=0; i<checks.length;i++ ) 35 if( data['taxonomies'].join(',').indexOf($(checks[i]).attr('value'))>-1 ) 36 $(checks[i]).attr("checked", "checked"); 37 else 38 $(checks[i]).attr("checked", null); 39 40 } 41 42 $('#post_type_list').hide(); 43 $('#post_type_form').fadeIn(); 44 //$('#post_type_form').reset(); // dont works 45 $('#namefield').focus(); 1 <?php 2 3 if (!defined('ABSPATH')) exit; 4 5 6 $advset_posttype_nonce = wp_create_nonce('advset_posttype_nonce'); 7 8 $advset_posttypes_data = get_option('advset_post_types', []); 9 10 $advset_posttypes_data_default = [ 11 'supports' => [ 12 'title', 13 'editor', 14 ], 15 'public' => true, 16 'publicly_queryable' => true, 17 'show_ui' => true, 18 'show_in_menu' => true, 19 'query_var' => true, 20 'has_archive' => false, 21 'hierarchical' => false, 22 'taxonomies' => [ 23 'category', 24 'post_tag', 25 ], 26 ]; 27 28 29 30 31 ?> 32 <script> 33 34 document.addEventListener('DOMContentLoaded', function() { 35 const formContainerElement = document.getElementById('advset_posttype_form_container'); 36 const listContainerElement = document.getElementById('advset_posttype_list_container'); 37 const formElement = formContainerElement?.querySelector('#advset_posttype_form'); 38 const labelInputElement = formContainerElement?.querySelector('[name="label"]'); 39 const typeInputElement = formContainerElement?.querySelector('[name="type"]'); 40 const typeStoredInputElement = formContainerElement?.querySelector('[name="type_stored"]'); 41 const typeAvailableIndicatorElement = formContainerElement?.querySelector('#advset_type_available_indicator'); 42 const submitButtonElement = formContainerElement?.querySelector('[type="submit"]'); 43 44 const posttypes_data = <?php echo json_encode($advset_posttypes_data); ?>; 45 const posttypes_data_default = <?php echo json_encode($advset_posttypes_data_default); ?>; 46 47 document.addEventListener('click', function(event) { 48 if (event.target.closest('.advset-posttype-edit-link')) { 49 event.preventDefault(); 50 showForm(event.target.getAttribute('data-type')); 51 } 52 if (event.target.closest('.advset-posttype-cancel-link')) { 53 event.preventDefault(); 54 showList(); 55 } 56 if (event.target.closest('.advset-posttype-delete-link')) { 57 event.preventDefault(); 58 if (confirm('<?php _e('Are you sure you want to delete this post type?') ?>')) { 59 advset_submit_delete_posttype(event.target.getAttribute('data-type')); 60 } 61 } 62 }); 63 64 labelInputElement.addEventListener('blur', function() { 65 if (typeInputElement.value === '') { 66 checkType(true); 67 } 68 }); 69 70 typeInputElement.addEventListener('input', function() { 71 checkType(); 72 }); 73 74 function checkType(generate_from_label = false) { 75 setTypeValidity(null); 76 if (!generate_from_label && typeInputElement.value === '') { 77 return; 78 } 79 fetch('<?php echo rest_url('advset_posttypes/v1/check-type'); ?>', { 80 method: 'POST', 81 body: JSON.stringify({ 82 label_input: labelInputElement.value, 83 type_input: typeInputElement.value, 84 type_stored: typeStoredInputElement.value, 85 generate_from_label, 86 }), 87 headers: { 88 'Content-Type': 'application/json', 89 'X-WP-Nonce': '<?php echo wp_create_nonce('wp_rest'); ?>', 90 }, 91 }) 92 .then(response => response.json()) 93 .then(data => { 94 if (generate_from_label && data.type_available) { 95 typeInputElement.value = data.type_available; 96 setTypeValidity(true); 97 } 98 else if (data.is_taken) { 99 setTypeValidity(false); 100 } 101 else if (data.is_valid) { 102 setTypeValidity(true); 103 } 104 }); 105 } 106 107 function setTypeValidity(validity) { 108 let color, icon, text; 109 switch (validity) { 110 case true: 111 color = 'green'; 112 icon = '✅'; 113 text = 'Type is available'; 114 break; 115 case false: 116 color = 'red'; 117 icon = '❌'; 118 text = 'Type already exists'; 119 break; 120 default: 121 color = 'gray'; 122 icon = ''; 123 text = ''; 124 break; 125 } 126 typeInputElement.setCustomValidity(validity === false ? text : ''); 127 typeAvailableIndicatorElement.textContent = icon + ' ' + text; 128 typeAvailableIndicatorElement.style.color = color; 129 } 130 131 function showForm(type) { 132 133 const data = type ? posttypes_data[type] : posttypes_data_default; 134 data.label = data?.labels?.name ?? type; 135 data.type = type ?? ''; 136 data.type_stored = type ?? ''; 137 138 formElement.querySelectorAll('[name]').forEach(element => { 139 if (element.name.slice(0, 1) === '_') { 140 return; 141 } 142 143 if (element.type === 'checkbox') { 144 if (element.name.slice(-2) === '[]') { 145 element.checked = data[element.name.slice(0, -2)]?.includes(element.value) ?? element.defaultChecked; 146 } else { 147 element.checked = data[element.name] ?? element.defaultChecked; 148 } 149 } else if (['text', 'hidden', 'textarea'].includes(element.type)) { 150 element.value = data[element.name] ?? element.defaultValue; 151 } 152 }); 153 154 submitButtonElement.value = type ? submitButtonElement.dataset.saveChanges : submitButtonElement.dataset.create; 155 156 setTypeValidity(null); 157 158 listContainerElement.style.display = 'none'; 159 formContainerElement.style.display = ''; 160 labelInputElement.focus(); 161 } 162 163 function showList() { 164 formContainerElement.style.display = 'none'; 165 listContainerElement.style.display = ''; 166 }; 167 168 // Submit delete via hidden POST form 169 function advset_submit_delete_posttype(slug) { 170 const form = document.getElementById('advset_delete_posttype_form'); 171 const input = document.getElementById('advset_delete_posttype_slug'); 172 if (!slug || !form || !input) return false; 173 input.value = slug; 174 form.submit(); 46 175 return false; 47 176 }; 48 populate=function (frm, data) { 49 $=jQuery; 50 $.each(data, function(key, value){ 51 var $ctrl = $('[name='+key+']', frm); 52 switch($ctrl.attr("type")) { 53 case "text" : 54 case "hidden": 55 case "textarea": 56 $ctrl.val(value); 57 break; 58 case "radio" : case "checkbox": 59 $ctrl.each(function(){ 60 if( $(this).attr('value') == value 61 || $(this).attr('name')=='query_var' && $(this).attr('value')!='' ) 62 $(this).attr("checked",value); 63 else 64 $(this).attr("checked",null); 65 }); 66 break; 67 } 68 }); 69 }; 70 show_list=function() { 71 $('#post_type_form').hide(); 72 $('#post_type_list').fadeIn(); 73 }; 74 str2slug=function(str) { 75 var new_str = ''; 76 str=str.toLowerCase(); 77 str=str.replace(/[aáàãâä]/g,'a'); 78 str=str.replace(/[éèêë]/g,'e'); 79 str=str.replace(/[íìîï]/g,'i'); 80 str=str.replace(/[óòõôö]/g,'o'); 81 str=str.replace(/[úùûü]/g,'u'); 82 str=str.replace('ç','c'); 83 str=str.replace(/[^a-z0-9_\-]/g,''); 84 str=str.substring(0, 20); 85 return str; 86 }; 87 function in_array(needle, haystack) { 88 var length = haystack.length; 89 for(var i = 0; i < length; i++) { 90 if(haystack[i] == needle) return true; 91 } 92 return false; 93 } 94 </script> 95 96 <div class="wrap"> 97 <?php advset_page_header() ?> 98 <br /> 99 <?php echo advset_page_experimental(); ?> 100 <br /> 101 <br /> 102 103 104 <div style="padding: 1rem; background: #fff; border: #f00 solid 2px; border-radius: .5rem; "> 105 <h3 style="margin: 0; ">WARNING</h3> 106 <p style="margin: 0; "><?php _e('Be careful, changing a post type can significantly impact the functionality of the website.') ?></p> 107 </div> 108 <br /> 109 <a href="#" onclick="return show_form();" class="add-new-h2">Add New Post Type</a> 110 <br /> 111 <br /> 112 113 <div id="post_type_form" style="display:none"> 114 115 <h3>Add New Post Type</h3> 116 117 <form id="posttype_form" action="" method="post"> 118 <?php #settings_fields( 'advanced-settings-post-types' ); ?> 119 120 <input type="hidden" name="advset_action_posttype" value="1" /> 121 122 <table class="form-table"> 123 <tr valign="top"> 124 <th scope="row"><?php _e('Label'); ?></th> 125 <td> 126 <input id="namefield" name="label" type="text" value="" onblur=" 127 const input = document.getElementById('typefield'); 128 if( input.value === '' ) 129 input.value = str2slug(this.value); 130 " /> 131 132 <!--p><a href="#">+ show more labels</a></p--> 133 134 </td> 135 </tr> 136 137 <tr valign="top"> 138 <th scope="row"><?php _e('Type Name'); ?></th> 139 <td> 140 <input id="typefield" name="type" type="text" value="" pattern="^[a-z0-9_\-]{1,20}$" required /><br /> 141 <i style="color:#999">Post type names must be between 1 and 20 characters in length. Lowercase alphanumeric characters, dashes, and underscores are allowed. </i> 142 </td> 143 </tr> 144 145 <tr valign="top"> 146 <th scope="row"><?php _e('Supports'); ?></th> 147 <td> 148 <input name="supports[]" id="posttype-support-title" value="title" type="checkbox" checked="checked"> 149 <label for="posttype-support-title">title</label><br /> 150 <input name="supports[]" id="posttype-support-editor" value="editor" type="checkbox" checked="checked"> 151 <label for="posttype-support-editor">editor</label><br /> 152 <input name="supports[]" id="posttype-support-author" value="author" type="checkbox"> 153 <label for="posttype-support-author">author</label><br /> 154 <input name="supports[]" id="posttype-support-thumbnail" value="thumbnail" type="checkbox"> 155 <label for="posttype-support-thumbnail">thumbnail</label><br /> 156 <input name="supports[]" id="posttype-support-excerpt" value="excerpt" type="checkbox"> 157 <label for="posttype-support-excerpt">excerpt</label><br /> 158 <input name="supports[]" id="posttype-support-trackbacks" value="trackbacks" type="checkbox"> 159 <label for="posttype-support-trackbacks">trackbacks</label><br /> 160 <input name="supports[]" id="posttype-support-custom-fields" value="custom-fields" type="checkbox"> 161 <label for="posttype-support-custom-fields">custom fields</label><br /> 162 <input name="supports[]" id="posttype-support-comments" value="comments" type="checkbox"> 163 <label for="posttype-support-comments">comments</label><br /> 164 <input name="supports[]" id="posttype-support-revisions" value="revisions" type="checkbox"> 165 <label for="posttype-support-revisions">revisions</label> <br /> 166 <input name="supports[]" id="posttype-support-page-attributes" value="page-attributes" type="checkbox"> 167 <label for="posttype-support-page-attributes">page attributes</label> 168 </td> 169 </tr> 170 171 <tr valign="top"> 172 <th scope="row"><?php _e('Settings'); ?></th> 173 <td> 174 <label><input name="public" value="1" type="checkbox" checked="checked"> 175 public</label><br /> 176 <label><input name="publicly_queryable" value="1" type="checkbox" checked="checked"> 177 publicly_queryable</label><br /> 178 <label><input name="show_ui" value="1" type="checkbox" checked="checked"> 179 show_ui</label><br /> 180 <label><input name="show_in_menu" value="1" type="checkbox" checked="checked"> 181 show_in_menu</label><br /> 182 <label><input name="query_var" value="1" type="checkbox" checked="checked"> 183 query_var</label><br /> 184 <!--label><input name="rewrite" value="1" type="checkbox"> 185 rewrite</label><br /--> 186 <!--label><input name="capability_type" value="1" type="checkbox"> 187 capability_type</label><br /--> 188 <label><input name="has_archive" value="1" type="checkbox"> 189 has_archive</label><br /> 190 <label><input name="hierarchical" value="1" type="checkbox"> 191 hierarchical</label> <br /> 192 <!--label><input name="menu_position" value="1" type="checkbox"> 193 menu_position</label--> 194 </td> 195 </tr> 196 197 <tr valign="top"> 198 <th scope="row"><?php _e('Taxonomies'); ?></th> 199 <td> 200 <label><input name="taxonomies[]" value="category" type="checkbox" checked="checked"> 201 category</label><br /> 202 <label><input name="taxonomies[]" value="post_tag" type="checkbox" checked="checked"> 203 post_tag</label> 204 </td> 205 </tr> 206 207 </table> 208 <p class="submit"> 209 <input type="submit" name="submit" id="submit" class="button button-primary" value="<?php _e('Save Changes') ?>" /> 210 <input type="button" onclick="show_list();" class="button" value="<?php _e('Cancel') ?>" /> 211 </p> 212 </form> 213 </div> 214 215 <form id="post_type_list" action="options.php" method="post"> 216 217 <table class="widefat fixed" cellspacing="0"> 177 }); 178 </script> 179 180 <div class="wrap"> 181 <?php advset_page_header() ?> 182 <br /> 183 <!-- <?php echo advset_page_experimental(); ?> 184 <br /> 185 <br /> --> 186 187 188 <!-- <div style="padding: 1rem; background: #fff; border: #f00 solid 2px; border-radius: .5rem; "> 189 <h3 style="margin: 0; ">WARNING</h3> 190 <p style="margin: 0; "><?php _e('Be careful, changing a post type can significantly impact the functionality of the website.') ?></p> 191 </div> 192 <br /> --> 193 <a class="advset-posttype-edit-link add-new-h2" href="#" data-type=""><?php _e('Add') ?></a> 194 <br /> 195 <br /> 196 197 <div id="advset_posttype_form_container" style="display:none"> 198 199 <h3><?php _e('Add') ?></h3> 200 201 <form id="advset_posttype_form" action="" method="post"> 202 <?php #settings_fields( 'advanced-settings-post-types' ); ?> 203 204 <input type="hidden" name="_advset_posttype_nonce" value="<?php echo $advset_posttype_nonce; ?>" /> 205 206 <input type="hidden" name="_advset_posttype_action_save" value="1" /> 207 208 <input type="hidden" name="type_stored" value="" /> 209 210 <table class="form-table"> 211 <tr valign="top"> 212 <th scope="row"><?php _e('Label'); ?></th> 213 <td> 214 <input name="label" type="text" value="" /> 215 216 <!--p><a href="#">+ show more labels</a></p--> 217 218 </td> 219 </tr> 220 221 <tr valign="top"> 222 <th scope="row"><?php _e('Type Name'); ?></th> 223 <td> 224 <input name="type" type="text" value="" pattern="^[a-z0-9_\-]{1,20}$" required /> <span id="advset_type_available_indicator"></span><br /> 225 <i style="color:#999">Post type names must be between 1 and 20 characters in length. Lowercase alphanumeric characters, dashes, and underscores are allowed. </i> 226 </td> 227 </tr> 228 229 <tr valign="top"> 230 <th scope="row"><?php _e('Description'); ?></th> 231 <td> 232 <!-- <textarea name="description" rows="3" style="width: 100%;"></textarea> --> 233 <input name="description" type="text" value="" /> 234 </td> 235 </tr> 236 237 <tr valign="top"> 238 <th scope="row"><?php _e('Supports'); ?></th> 239 <td> 240 <input name="supports[]" id="posttype-support-title" value="title" type="checkbox"> 241 <label for="posttype-support-title">title</label><br /> 242 <input name="supports[]" id="posttype-support-editor" value="editor" type="checkbox"> 243 <label for="posttype-support-editor">editor</label><br /> 244 <input name="supports[]" id="posttype-support-author" value="author" type="checkbox"> 245 <label for="posttype-support-author">author</label><br /> 246 <input name="supports[]" id="posttype-support-thumbnail" value="thumbnail" type="checkbox"> 247 <label for="posttype-support-thumbnail">thumbnail</label><br /> 248 <input name="supports[]" id="posttype-support-excerpt" value="excerpt" type="checkbox"> 249 <label for="posttype-support-excerpt">excerpt</label><br /> 250 <input name="supports[]" id="posttype-support-trackbacks" value="trackbacks" type="checkbox"> 251 <label for="posttype-support-trackbacks">trackbacks</label><br /> 252 <input name="supports[]" id="posttype-support-custom-fields" value="custom-fields" type="checkbox"> 253 <label for="posttype-support-custom-fields">custom fields</label><br /> 254 <input name="supports[]" id="posttype-support-comments" value="comments" type="checkbox"> 255 <label for="posttype-support-comments">comments</label><br /> 256 <input name="supports[]" id="posttype-support-revisions" value="revisions" type="checkbox"> 257 <label for="posttype-support-revisions">revisions</label> <br /> 258 <input name="supports[]" id="posttype-support-page-attributes" value="page-attributes" type="checkbox"> 259 <label for="posttype-support-page-attributes">page attributes</label> 260 </td> 261 </tr> 262 263 <tr valign="top"> 264 <th scope="row"><?php _e('Settings'); ?></th> 265 <td> 266 <label><input name="public" value="1" type="checkbox"> 267 public</label><br /> 268 <label><input name="publicly_queryable" value="1" type="checkbox"> 269 publicly_queryable</label><br /> 270 <label><input name="show_ui" value="1" type="checkbox"> 271 show_ui</label><br /> 272 <label><input name="show_in_menu" value="1" type="checkbox"> 273 show_in_menu</label><br /> 274 <label><input name="query_var" value="1" type="checkbox"> 275 query_var</label><br /> 276 <!--label><input name="rewrite" value="1" type="checkbox"> 277 rewrite</label><br /--> 278 <!--label><input name="capability_type" value="1" type="checkbox"> 279 capability_type</label><br /--> 280 <label><input name="has_archive" value="1" type="checkbox"> 281 has_archive</label><br /> 282 <label><input name="hierarchical" value="1" type="checkbox"> 283 hierarchical</label> <br /> 284 <!--label><input name="menu_position" value="1" type="checkbox"> 285 menu_position</label--> 286 </td> 287 </tr> 288 289 <tr valign="top"> 290 <th scope="row"><?php _e('Taxonomies'); ?></th> 291 <td> 292 <label><input name="taxonomies[]" value="category" type="checkbox"> 293 category</label><br /> 294 <label><input name="taxonomies[]" value="post_tag" type="checkbox"> 295 post_tag</label> 296 </td> 297 </tr> 298 299 </table> 300 <p class="submit"> 301 <input type="submit" id="submit" class="button button-primary" value="<?php _e('Save Changes') ?>" data-save-changes="<?php _e('Save Changes') ?>" data-create="<?php _e('Create') ?>" /> 302 <input type="button" class="button advset-posttype-cancel-link" value="<?php _e('Cancel') ?>" /> 303 </p> 304 </form> 305 </div> 306 307 <div id="advset_posttype_list_container"> 308 <?php if (!empty($advset_posttypes_data)) { ?> 309 <form id="advset_posttype_list" action="options.php" method="post"> 310 311 <table class="widefat fixed striped" cellspacing="0"> 218 312 <thead> 219 313 <tr> 220 <th scope="col" id="cb" class="manage-column column-cb check-column" style=""><label class="screen-reader-text" for="cb-select-all-1">Selecionar Tudo</label><input id="cb-select-all-1" type="checkbox"></th> 221 <th scope="col" id="title" class="manage-column column-title" width="40%">Label <small>(Menu name)</small></th> 222 <th scope="col" id="type_name" class="manage-column column-title" width="30%">Type</th> 223 <th scope="col" id="type_desc" class="manage-column column-title" width="30%">Description</th> 314 <th scope="col" id="title" class="manage-column column-title" width="40%"><?php _e('Label') ?></th> 315 <th scope="col" id="type_name" class="manage-column column-title" width="30%"><?php _e('Type') ?></th> 316 <th scope="col" id="type_desc" class="manage-column column-title" width="30%"><?php _e('Description') ?></th> 224 317 </tr> 225 318 </thead> 226 <?php foreach($ post_types as $typename=>$post_type) { ?>319 <?php foreach($advset_posttypes_data as $typename => $post_type) { ?> 227 320 <tr class=" iedit"> 228 <th scope="row" class="check-column"> 229 230 <input id="cb-select-1" type="checkbox" name="post[]" value="1"> 231 <div class="locked-indicator"></div> 232 </th> 233 <td> 234 <strong><?php echo $post_type->label ?></strong> 321 <td> 322 <strong><?php echo $post_type['labels']['name'] ?></strong> 235 323 <div class="row-actions"> 236 <?php if( !in_array( $post_type->name, array('post', 'page') ) ) { ?>237 324 <span class="edit"> 238 <a href="#" onclick="show_form('<?php echo $post_type->name ?>');">Edit</a> 325 <a class="advset-posttype-edit-link" href="#" data-type="<?php echo esc_attr($typename) ?>"><?php _e('Edit') ?></a> 326 | 239 327 </span> 240 | <a href="options-general.php?page=advanced-settings-post-types&delete_posttype=<?php echo $post_type->name ?>" title="default categories">delete</a>241 < ?php } else echo ' '; ?>242 328 <span class="trash"> 329 <a class="advset-posttype-delete-link" href="#" data-type="<?php echo esc_attr($typename) ?>"><?php _e('Delete') ?></a> 330 </span> 243 331 </div> 244 332 </td> 245 <td><?php echo $ post_type->name ?></td>246 <td>< /td>333 <td><?php echo $typename ?></td> 334 <td><?php echo str_replace("\n", '<br />', strip_tags($post_type['description'] ?? '')) ?></td> 247 335 </tr> 248 336 <?php } ?> … … 250 338 <tfoot> 251 339 <tr> 252 <th scope="col" class="manage-column column-cb check-column" style=""><label class="screen-reader-text" for="cb-select-all-2">Selecionar Tudo</label><input id="cb-select-all-2" type="checkbox"></th> 253 <th scope="col" id="title" class="manage-column column-title" width="40%">Label <small>(Menu name)</small></th> 254 <th scope="col" id="type_name" class="manage-column column-title" width="30%">Type</th> 255 <th scope="col" id="type_desc" class="manage-column column-title" width="30%">Description</th> 340 <th scope="col" id="title" class="manage-column column-title" width="40%"><?php _e('Label') ?></th> 341 <th scope="col" id="type_name" class="manage-column column-title" width="30%"><?php _e('Type') ?></th> 342 <th scope="col" id="type_desc" class="manage-column column-title" width="30%"><?php _e('Description') ?></th> 256 343 </tr> 257 344 </tfoot> 258 345 259 346 </table> 260 261 <!--p class="submit"><input type="submit" name="submit" id="submit" class="button-primary" value="<?php _e('Save changes') ?>"></p--> 347 </form> 348 <?php } else { ?> 349 <div> 350 <p><?php _e('No custom post types found.') ?></p> 351 </div> 352 <?php } ?> 353 354 <form id="advset_delete_posttype_form" action="<?php echo esc_url( admin_url('options-general.php?page=advanced-settings-post-types') ); ?>" method="post" style="display: none;"> 355 <input type="hidden" name="_advset_posttype_nonce" value="<?php echo esc_attr($advset_posttype_nonce); ?>" /> 356 <input type="hidden" name="_advset_posttype_action_delete" id="advset_delete_posttype_slug" value="" /> 262 357 </form> 263 358 </div> 359 </div> -
advanced-settings/trunk/feature-setup/features/includes/frontend.auto_thumbs.php
r3281733 r3357461 1 1 <?php 2 2 3 if ( !defined('ABSPATH')) exit;3 if (!defined('ABSPATH')) exit; 4 4 5 5 6 function advset__feature__auto_thumbs( $new_status, $old_status, $post ) { 7 if ('publish' == $new_status) { 8 advset__feature__auto_thumbs__publish_post($post); 6 /** 7 * Auto Thumbs feature class. 8 */ 9 class Advset__Feature__Auto_Thumbs { 10 11 private static $instance = null; 12 13 private function __construct() {} 14 15 /** 16 * Initialize the feature. 17 * 18 * @return Advset__Feature__Auto_Thumbs The instance of the feature. 19 */ 20 public static function init() { 21 if (self::$instance === null) { 22 self::$instance = new self(); 23 } 24 return self::$instance; 9 25 } 10 } 26 27 /** 28 * Transition the post status. 29 * 30 * @param string $new_status The new status of the post. 31 * @param string $old_status The old status of the post. 32 * @param object $post The post object. 33 * @return bool True if the post thumbnail was generated, false otherwise. 34 */ 35 public function transition_post_status( string $new_status, string $old_status, object $post ) { 36 global $wpdb; 37 38 // If the post is not published, return 39 if ($new_status !== 'publish') { 40 return false; 41 } 11 42 12 // 13 function advset__feature__auto_thumbs__publish_post( $post ) { 14 global $wpdb; 15 16 // First check whether Post Thumbnail is already set for this post. 17 if (get_post_meta($post->ID, '_thumbnail_id', true) || get_post_meta($post->ID, 'skip_post_thumb', true)) 18 return; 19 20 // Initialize variable used to store list of matched images as per provided regular expression 21 $matches = array(); 22 23 // Get all images from post's body 24 preg_match_all('/<\s*img [^\>]*src\s*=\s*[\""\']?([^\""\'>]*)[^\>]*/i', empty($post->post_content) ? '' : $post->post_content, $matches); 25 26 if (count($matches)) { 27 foreach ($matches[0] as $key => $image) { 28 /** 29 * If the image is from wordpress's own media gallery, then it appends the thumbmail id to a css class. 30 * Look for this id in the IMG tag. 31 */ 32 preg_match('/wp-image-([\d]*)/i', $image, $thumb_id); 33 $thumb_id = empty($thumb_id[1]) ? null : $thumb_id[1]; 34 43 // First check whether Post Thumbnail is already set for this post. 44 if (get_post_meta($post->ID, '_thumbnail_id', true) || get_post_meta($post->ID, 'skip_post_thumb', true)) 45 return false; 46 47 // Initialize variable used to store the thumbnail id 48 $thumb_id = null; 49 50 // Initialize variable used to store list of matched images as per provided regular expression 51 $images = []; 52 53 // Get all images from post's body 54 preg_match_all('/<\s*img [^\>]*src\s*=\s*[\""\']?([^\""\'>]*)[^\>]*/i', $post->post_content ?? '', $images, PREG_SET_ORDER); 55 56 // If no images are found, return 57 if (empty($images)) { 58 return false; 59 } 60 61 // Loop through all images 62 foreach ($images as $image) { 63 $img_html = $image[0]; 64 $image_url = $image[1]; 65 66 // If the image is from wordpress's own media gallery, then it appends the thumbmail id to a css class. 67 preg_match('/\s+class\s*=\s*[\""\']?([^\""\'>]*)/i', $img_html, $matches_class); 68 preg_match('/(?:^|\s+)wp-image-([\d]*)(?:\s+|$)/i', $matches_class[1] ?? '', $matches_thumb_id); 69 if (!empty($matches_thumb_id[1]) && (int) $matches_thumb_id[1] > 0) { 70 $thumb_id = (int) $matches_thumb_id[1]; 71 break; 72 } 73 74 // Get the image URL 75 if (!wp_http_validate_url($image_url)) { 76 continue; 77 } 78 35 79 // If thumb id is not found, try to look for the image in DB. Thanks to "Erwin Vrolijk" for providing this code. 36 if (!$thumb_id) {37 $image = $matches[1][$key];38 $ result = $wpdb->get_results($wpdb->prepare("SELECT ID FROM {$wpdb->posts} WHERE guid = %s", $image));39 $thumb_id = empty($result[0]->ID) ? null : $result[0]->ID;80 $attachment = $wpdb->get_results($wpdb->prepare("SELECT ID FROM {$wpdb->posts} WHERE guid = %s", $image_url)); 81 if (!empty($attachment[0]->ID) && (int) $attachment[0]->ID > 0) { 82 $thumb_id = (int) $attachment[0]->ID; 83 break; 40 84 } 41 85 42 86 // Ok. Still no id found. Some other way used to insert the image in post. Now we must fetch the image from URL and do the needful. 43 if (!$thumb_id) { 44 $thumb_id = advset__feature__auto_thumbs__generate_post_thumbnail($matches, $key, $post); 45 } 46 47 // If we succeed in generating thumg, let's update post meta 48 if ($thumb_id) { 49 update_post_meta( $post->ID, '_thumbnail_id', $thumb_id ); 87 preg_match('/\s+alt\s*=\s*[\""\']?([^\""\'>]*)/i', $img_html, $matches_alt); 88 preg_match('/\s+title\s*=\s*[\""\']?([^\""\'>]*)/i', $img_html, $matches_title); 89 $imported_thumb_id = $this->import_image_from_url($image_url, $post->ID, [ 90 'alt' => $matches_alt[1] ?? '', 91 'title' => $matches_title[1] ?? '', 92 ]); 93 if (!is_wp_error($imported_thumb_id) && (int) $imported_thumb_id > 0) { 94 $thumb_id = (int) $imported_thumb_id; 50 95 break; 51 96 } 52 97 } 98 99 // If we succeed in generating thumg, let's update post meta 100 if ($thumb_id) { 101 update_post_meta( $post->ID, '_thumbnail_id', $thumb_id ); 102 return true; 103 } 104 105 return false; 106 } 107 108 /** 109 * Imports an image from an external URL into the media library. 110 * 111 * @param string $url The URL of the image to import. 112 * @param int $post_id The ID of the post to import the image to. 113 * @param array $opts Optional arguments for the import. 114 * @return int|\WP_Error Attachment-ID oder Fehler 115 */ 116 private function import_image_from_url( string $url, int $post_id = 0, array $opts = [] ) { 117 118 // Validate the URL 119 if (!wp_http_validate_url($url)) { 120 return new WP_Error('invalid_url', __('Invalid image URL.')); 121 } 122 123 // Parse the options 124 $opts = wp_parse_args($opts, [ 125 'alt' => '', 126 'title' => '', 127 ]); 128 129 // Require the necessary files 130 require_once ABSPATH.'wp-admin/includes/file.php'; 131 require_once ABSPATH.'wp-admin/includes/image.php'; 132 require_once ABSPATH.'wp-admin/includes/media.php'; 133 134 // Download the image 135 $tmp = download_url($url); 136 if ( is_wp_error($tmp) ) { 137 return $tmp; 138 } 139 140 // Get the name and mime type of the image 141 $name = wp_basename(parse_url($url, PHP_URL_PATH) ?: 'image'); 142 $wp_filetype = wp_check_filetype_and_ext( $tmp, $name ); 143 144 // Check if the image is a valid image 145 if (empty($wp_filetype['type']) || !wp_match_mime_types('image', $wp_filetype['type'])) { 146 return new WP_Error('invalid_image', __('The uploaded file is not a valid image. Please try again.')); 147 } 148 149 // Create the file array 150 $file_array = [ 151 'name' => $name, 152 'tmp_name' => $tmp, 153 'type' => $wp_filetype['type'], 154 ]; 155 156 // Create the post data 157 $post_data = []; 158 if (!empty($opts['title'])) { 159 $post_data['post_title'] = $opts['title']; 160 } 161 162 // Create the description 163 $desc = null; 164 165 // Sideload the image 166 $attachment_id = media_handle_sideload($file_array, $post_id, $desc, $post_data); 167 168 // Unlink the temporary file if it exists 169 @unlink($tmp); 170 171 // If there is an error, return the error 172 if ( is_wp_error($attachment_id) ) { 173 return $attachment_id; 174 } 175 176 // Update the attachment meta if the alt text is provided 177 if (!empty($opts['alt'])) { 178 update_post_meta($attachment_id, '_wp_attachment_image_alt', $opts['alt']); 179 } 180 181 // Return the attachment ID (as integer) 182 return (int) $attachment_id; 53 183 } 54 184 } 55 56 57 function advset__feature__auto_thumbs__generate_post_thumbnail( $matches, $key, $post ) {58 // Make sure to assign correct title to the image. Extract it from img tag59 $imageTitle = '';60 preg_match_all('/<\s*img [^\>]*title\s*=\s*[\""\']?([^\""\'>]*)/i', empty($post->post_content) ? '' : $post->post_content, $matchesTitle);61 62 if (count($matchesTitle) && isset($matchesTitle[1])) {63 $imageTitle = empty($matchesTitle[1][$key]) ? '' : $matchesTitle[1][$key];64 }65 66 // Get the URL now for further processing67 $imageUrl = $matches[1][$key];68 69 // Get the file name70 $filename = substr($imageUrl, (strrpos($imageUrl, '/'))+1);71 72 if ( !(($uploads = wp_upload_dir(current_time('mysql')) ) && false === $uploads['error']) )73 return null;74 75 // Generate unique file name76 $filename = wp_unique_filename( $uploads['path'], $filename );77 78 // Move the file to the uploads dir79 $new_file = $uploads['path'] . "/$filename";80 81 if (!ini_get('allow_url_fopen'))82 $file_data = advset__feature__auto_thumbs__curl_get_file_contents($imageUrl);83 else84 $file_data = @file_get_contents($imageUrl);85 86 if (!$file_data) {87 return null;88 }89 90 file_put_contents($new_file, $file_data);91 92 // Set correct file permissions93 $stat = stat( dirname( $new_file ));94 $perms = $stat['mode'] & 0000666;95 @ chmod( $new_file, $perms );96 97 // Get the file type. Must to use it as a post thumbnail.98 $wp_filetype = wp_check_filetype( $filename );99 100 extract( $wp_filetype );101 102 // No file type! No point to proceed further103 if ( ( !$type || !$ext ) && !current_user_can( 'unfiltered_upload' ) ) {104 return null;105 }106 107 // Compute the URL108 $url = $uploads['url'] . "/$filename";109 110 // Construct the attachment array111 $attachment = array(112 'post_mime_type' => $type,113 'guid' => $url,114 'post_parent' => null,115 'post_title' => $imageTitle,116 'post_content' => '',117 );118 119 $thumb_id = wp_insert_attachment($attachment, false, $post->ID);120 if ( !is_wp_error($thumb_id) ) {121 require_once(ABSPATH . '/wp-admin/includes/image.php');122 123 // Added fix by misthero as suggested124 wp_update_attachment_metadata( $thumb_id, wp_generate_attachment_metadata( $thumb_id, $new_file ) );125 update_attached_file( $thumb_id, $new_file );126 127 return $thumb_id;128 }129 130 return null;131 }132 133 function advset__feature__auto_thumbs__curl_get_file_contents($URL) {134 $c = curl_init();135 curl_setopt($c, CURLOPT_RETURNTRANSFER, 1);136 curl_setopt($c, CURLOPT_URL, $URL);137 $contents = curl_exec($c);138 curl_close($c);139 140 if ($contents) {141 return $contents;142 }143 144 return FALSE;145 } -
advanced-settings/trunk/readme.txt
r3323109 r3357461 8 8 Requires at least: 5.0.0 9 9 Tested up to: 6.8 10 Stable tag: 3. 1.110 Stable tag: 3.2.0 11 11 License: GPLv3 or later 12 12 License URI: http://www.gnu.org/licenses/gpl-3.0.html … … 22 22 [→ details in FAQ](https://wordpress.org/plugins/advanced-settings#will%20the%20plugin%20become%20slower%20with%20more%20features%3F) 23 23 24 **🪶 LIGHTWEIGHT** 25 Advanced Settings 3 is lightweight (only about 0.5 MB) and discreet (no dashboard hijacking). 26 [→ details in FAQ](https://wordpress.org/plugins/advanced-settings#how%20can%20the%20plugin%20be%20lightweight%20despite%20so%20many%20features%3F) 27 24 28 **🔒 SECURITY** 25 29 Advanced Settings 3 has been independently reviewed for security vulnerabilities via Patchstack. … … 27 31 28 32 **✳️ INFO ABOUT THE 2 BAD RATINGS** 29 2 bad ratings occurred in 2017 because outdated PHP versions were used, but can't happen again.33 Bad ratings occurred in 2017 because users used outdated PHP versions, but can't happen again. 30 34 [→ details in FAQ](https://wordpress.org/plugins/advanced-settings#what%20caused%20the%20two%20bad%20ratings%3F) 31 35 … … 90 94 91 95 * Display SQL queries and page load time 96 * Create custom post types 💥 renewed 92 97 93 98 = Configuration = … … 118 123 Advanced Settings 3 works as follows: Only when you open the plugin's settings window does the plugin recognise which settings are actually available. When saving, only the activated settings are written to a separate cache file. Only this cache file is then taken into account during operation. This means that slowdowns can only occur due to **active** features. However, as some features deactivate WordPress functions, the plugin can actually make WordPress even faster than in the standard configuration. 119 124 125 = How can the plugin be lightweight despite so many features? = 126 127 **Short answer:** 128 Typically, graphical user interfaces represent the largest chunk of data. Since we have largely standardized the user interface for all features, additional features are of little importance. 129 130 **Detailed answer:** 131 The plugin is currently only 0.5 MB in size. Only about a third of that is used for the actual functionality of the features. The rest is used for the graphical user interface, backward compatibility, performance optimization, and the like. So if we doubled the number of features, the plugin would still be smaller than 0.7 MB. Theoretically, we could quadruple the number of features and still stay under 1 MB. So the number of features isn't crucial. The trick is to standardize everything around the features so that each additional feature has minimal impact. 132 133 We are passionate about lightweight plugins that remain politely in the background while you work, so we can assure you that this will continue to be the case. 134 120 135 = How is the security of the plugin ensured? = 121 136 … … 152 167 == Changelog == 153 168 169 = 3.2.0 - 2025-09-07 = 170 * Fixed a medium priority security issue which appeared on activated feature "Automatically generate the Post Thumbnail" 171 * Thoroughly revised feature "Automatically generate the Post Thumbnail" 172 * Fixed a low priority security issue which appeared on activated experimental feature "Post types settings" (now "Custom post types") 173 * Thoroughly revised feature "Post types settings", renamed it to "Custom post types" and removed the "experimental" flag 174 154 175 = 3.1.1 - 2025-07-06 = 155 176 * Fixed minor cache problem … … 161 182 = 3.0.2 - 2025-06-04 = 162 183 * Fixed order of features 163 * Fixed a minor security issue in old code (rated as low priority by [Patchstack](https://patchstack.com/))184 * Fixed a low priority security issue which appeared on activated experimental feature "Filters and actions settings" 164 185 165 186 = 3.0.1 - 2025-05-03 =
Note: See TracChangeset
for help on using the changeset viewer.