prepare_items(); $add_new_url = admin_url( 'post-new.php?post_type=' . Custom_Code::POST_TYPE ); $rebuild_nonce = wp_create_nonce( 'ao_cc_rebuild_cache' ); // phpcs:ignore WordPress.Security.NonceVerification -- read-only display flags $just_rebuilt = isset( $_GET['ao-cc-rebuilt'] ); // phpcs:ignore WordPress.Security.NonceVerification $just_toggled = isset( $_GET['ao-cc-toggled'] ); ?>


views(); ?>
search_box( __( 'Search Code', 'admin-optimizer' ), 'ao-custom-code' ); $list_table->display(); ?>
is_pro_active(); $presets = Custom_Code_Presets::get_presets(); $show_create_form = true; require Custom_Code::MODULE_PATH . 'settings/views/preset-modal.php'; } /** * Process list table bulk actions before the admin page outputs headers. * * @return void */ public function maybe_handle_bulk_actions(): void { // phpcs:ignore WordPress.Security.NonceVerification.Missing -- nonce is verified before any state change in handle_bulk_actions(). $page = isset( $_POST['page'] ) ? sanitize_key( wp_unslash( $_POST['page'] ) ) : ''; if ( 'ao-custom-code' !== $page ) { return; } if ( ! current_user_can( Custom_Code::CAPABILITY ) ) { wp_die( esc_html__( 'You do not have permission to access this page.', 'admin-optimizer' ) ); } $this->handle_bulk_actions(); } /** * Process bulk actions submitted from the list table. * * @return void */ private function handle_bulk_actions(): void { $action = isset( $_POST['action'] ) && '-1' !== $_POST['action'] ? sanitize_key( wp_unslash( $_POST['action'] ) ) : ( isset( $_POST['action2'] ) && '-1' !== $_POST['action2'] ? sanitize_key( wp_unslash( $_POST['action2'] ) ) : '' ); if ( empty( $action ) || ! in_array( $action, [ 'trash', 'restore', 'delete', 'activate', 'deactivate' ], true ) ) { return; } check_admin_referer( 'ao_cc_bulk_action', 'ao_cc_bulk_nonce' ); $post_ids = isset( $_POST['post'] ) ? array_map( 'absint', (array) $_POST['post'] ) : []; foreach ( $post_ids as $post_id ) { if ( 'trash' === $action && current_user_can( 'delete_post', $post_id ) ) { wp_trash_post( $post_id ); } elseif ( 'restore' === $action && current_user_can( 'delete_post', $post_id ) ) { wp_untrash_post( $post_id ); } elseif ( 'delete' === $action && current_user_can( 'delete_post', $post_id ) ) { wp_delete_post( $post_id, true ); } elseif ( 'activate' === $action && current_user_can( 'edit_post', $post_id ) ) { wp_update_post( [ 'ID' => $post_id, 'post_status' => 'publish', ] ); } elseif ( 'deactivate' === $action && current_user_can( 'edit_post', $post_id ) ) { wp_update_post( [ 'ID' => $post_id, 'post_status' => 'draft', ] ); } } // Status mutations bypass the edit-form save path, so rebuild all affected // option caches. The Pro engine also refreshes currently-published targets. $this->get_cache()->rebuild_all(); $redirect_args = []; if ( 'restore' === $action ) { $redirect_args['restored'] = count( $post_ids ); } elseif ( 'delete' === $action ) { $redirect_args['deleted'] = count( $post_ids ); } elseif ( 'activate' === $action ) { $redirect_args['activated'] = count( $post_ids ); } elseif ( 'deactivate' === $action ) { $redirect_args['deactivated'] = count( $post_ids ); } else { $redirect_args['trashed'] = count( $post_ids ); } // phpcs:ignore WordPress.Security.NonceVerification.Missing -- nonce was verified above. if ( ! empty( $_REQUEST['post_status'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing -- nonce was verified above. $redirect_args['post_status'] = sanitize_key( wp_unslash( $_REQUEST['post_status'] ) ); } // phpcs:ignore WordPress.Security.NonceVerification.Missing -- nonce was verified above. if ( ! empty( $_REQUEST['ao_cc_type_filter'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing -- nonce was verified above. $redirect_args['ao_cc_type_filter'] = sanitize_key( wp_unslash( $_REQUEST['ao_cc_type_filter'] ) ); } // phpcs:ignore WordPress.Security.NonceVerification.Missing -- nonce was verified above. if ( ! empty( $_REQUEST['s'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing -- nonce was verified above. $redirect_args['s'] = sanitize_text_field( wp_unslash( $_REQUEST['s'] ) ); } wp_safe_redirect( Custom_Code::get_module_admin_url( $redirect_args ) ); exit; } /** * Permanently delete a single custom code item from the Trash. * * @return void */ public function handle_force_delete_post(): void { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- checked below with the post-specific action. $post_id = isset( $_GET['post'] ) ? absint( wp_unslash( $_GET['post'] ) ) : 0; if ( ! $post_id || ! current_user_can( 'delete_post', $post_id ) ) { wp_die( esc_html__( 'You do not have permission to delete this item.', 'admin-optimizer' ) ); } check_admin_referer( 'ao_cc_delete_code_' . $post_id ); $post = get_post( $post_id ); if ( ! $post || Custom_Code::POST_TYPE !== $post->post_type ) { wp_die( esc_html__( 'Invalid custom code item.', 'admin-optimizer' ) ); } wp_delete_post( $post_id, true ); wp_safe_redirect( Custom_Code::get_module_admin_url( [ 'post_status' => 'trash', 'deleted' => 1, ] ) ); exit; } /** * Restore a single custom code item from the Trash. * * @return void */ public function handle_restore_post(): void { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- checked below with the post-specific action. $post_id = isset( $_GET['post'] ) ? absint( wp_unslash( $_GET['post'] ) ) : 0; if ( ! $post_id || ! current_user_can( 'delete_post', $post_id ) ) { wp_die( esc_html__( 'You do not have permission to restore this item.', 'admin-optimizer' ) ); } check_admin_referer( 'ao_cc_restore_code_' . $post_id ); $post = get_post( $post_id ); if ( ! $post || Custom_Code::POST_TYPE !== $post->post_type ) { wp_die( esc_html__( 'Invalid custom code item.', 'admin-optimizer' ) ); } wp_untrash_post( $post_id ); wp_safe_redirect( Custom_Code::get_module_admin_url( [ 'post_status' => 'trash', 'restored' => 1, ] ) ); exit; } /** * Register metaboxes on the ao_custom_code edit screen. * * @return void */ public function register_metaboxes(): void { add_meta_box( 'ao-cc-content', __( 'Code', 'admin-optimizer' ), [ $this, 'render_content_metabox' ], Custom_Code::POST_TYPE, 'normal', 'high' ); add_meta_box( 'ao-cc-notes', __( 'Internal Notes', 'admin-optimizer' ), [ $this, 'render_notes_metabox' ], Custom_Code::POST_TYPE, 'normal' ); add_meta_box( 'ao-cc-rules', __( 'Display Rules', 'admin-optimizer' ), [ $this, 'render_display_rules_metabox' ], Custom_Code::POST_TYPE, 'side' ); add_meta_box( 'ao-cc-display-settings', __( 'Display Settings', 'admin-optimizer' ), [ $this, 'render_display_settings_metabox' ], Custom_Code::POST_TYPE, 'side' ); remove_meta_box( 'slugdiv', Custom_Code::POST_TYPE, 'normal' ); } /** * Render the code content metabox. * Type selector shown on new posts; locked to read-only on existing posts. * * @param \WP_Post $post The post being edited. * @return void */ public function render_content_metabox( $post ): void { wp_nonce_field( Custom_Code::NONCE_ACTION, Custom_Code::NONCE_FIELD ); $type_meta = get_post_meta( $post->ID, '_ao_cc_type', true ); $type = $type_meta ? $type_meta : 'css'; $is_pro = $this->is_pro_active(); // JS and HTML snippets require unfiltered_html; save_post() rejects them otherwise. $can_unfiltered = current_user_can( 'unfiltered_html' ); $shortcode_label = $is_pro ? __( 'Shortcode', 'admin-optimizer' ) : __( 'Shortcode (Pro)', 'admin-optimizer' ); ?>

<script> tag. Example: <script src="https://example.com/script.js" defer></script>', 'admin-optimizer' ), [ 'code' => [] ] ); ?>

<script> tag. Example: <script src="https://example.com/script.js" defer></script>', 'admin-optimizer' ), [ 'code' => [] ] ); ?>

is_pro_active() ) { /** * Lets Pro render its own built-in shortcode reference panel * instead of Free's default. */ do_action( 'ao_cc_render_builtin_shortcodes_panel' ); } else { $this->render_builtin_shortcodes_panel(); } ?> is_pro_active(); $presets = Custom_Code_Presets::get_presets(); $show_create_form = false; require Custom_Code::MODULE_PATH . 'settings/views/preset-modal.php'; } /** * Render the collapsible "Built-in shortcodes" reference panel. * * @return void */ private function render_builtin_shortcodes_panel(): void { $lib = [ [ 'ao_copyright', __( 'Copyright symbol', 'admin-optimizer' ) ], [ 'ao_year', __( 'Current year', 'admin-optimizer' ) ], [ 'ao_sitename', __( 'Site name', 'admin-optimizer' ) ], [ 'ao_tagline', __( 'Site tagline', 'admin-optimizer' ) ], [ 'ao_home_url', __( 'Site home URL', 'admin-optimizer' ) ], [ 'ao_post_title', __( 'Current post/page title', 'admin-optimizer' ) ], [ 'ao_post_date', __( 'Post published date', 'admin-optimizer' ) ], [ 'ao_post_modified', __( 'Post last modified date', 'admin-optimizer' ) ], [ 'ao_user_name', __( "Logged-in user's display name", 'admin-optimizer' ) ], [ 'ao_user_email', __( "Logged-in user's email address", 'admin-optimizer' ) ], [ 'ao_login_url', __( 'Login page URL', 'admin-optimizer' ) ], [ 'ao_logout_url', __( 'Logout URL', 'admin-optimizer' ) ], [ 'ao_privacy_page', __( 'Privacy Policy page URL', 'admin-optimizer' ) ], ]; ?>

', esc_html( $tag ), esc_html( $desc ) ); } ?>
[%s]%s
ID ) ? (string) get_post_meta( $post->ID, '_ao_cc_notes', true ) : ''; ?>

ID, '_ao_cc_type', true ); $type = $type_meta ? $type_meta : 'css'; $display_meta = get_post_meta( $post->ID, '_ao_cc_display', true ); $display = $display_meta ? $display_meta : 'inline'; $position_meta = get_post_meta( $post->ID, '_ao_cc_position', true ); $position = $position_meta ? $position_meta : 'wp_head'; $locations = get_post_meta( $post->ID, '_ao_cc_locations', true ); $locations = is_array( $locations ) ? $locations : []; if ( 'shortcode' === $type ) { echo '

' . esc_html__( 'Shortcodes have no location targeting — use the shortcode tag wherever you need it.', 'admin-optimizer' ) . '

'; return; } ?>




$label ) : ?>
is_pro_active() ) : ?>

', '' ); ?>

render_load_priority( $post ); $this->render_specific_posts_fields( $post ); $this->render_post_types_fields( $post ); $this->render_tax_slugs_fields( $post ); } /** * Render the load priority radio buttons. * Free: disabled placeholder. Pro: fires ao_cc_render_load_priority. * * @param \WP_Post $post The post being edited. * @return void */ private function render_load_priority( $post ) { if ( $this->is_pro_active() ) { /** * Fires the Load Priority section's real radios. * * @param \WP_Post $post The post being edited. */ do_action( 'ao_cc_render_load_priority', $post ); return; } ?>



is_pro_active() ) { /** * Fires the Custom Post Types targeting section's real checkboxes. * * @param \WP_Post $post The post being edited. */ do_action( 'ao_cc_render_post_types_fields', $post ); return; } $wrap_style = 'color:#aaa;pointer-events:none;'; $public_types = get_post_types( [ 'public' => true, '_builtin' => false, ], 'objects' ); unset( $public_types[ Custom_Code::POST_TYPE ] ); ?>


is_pro_active() ) { /** * Fires the Custom Taxonomy Archives targeting section's real checkboxes. * * @param \WP_Post $post The post being edited. */ do_action( 'ao_cc_render_tax_slugs_fields', $post ); return; } $wrap_style = 'color:#aaa;pointer-events:none;'; $public_taxes = array_filter( get_taxonomies( [ 'public' => true, '_builtin' => false, ], 'objects' ), static fn( $tax ) => ! empty( $tax->rewrite ) ); ?>


is_pro_active() ) { /** * Fires the Specific Posts targeting section's real fields. * * @param \WP_Post $post The post being edited. */ do_action( 'ao_cc_render_specific_posts_fields', $post ); return; } $wrap_style = 'color:#aaa;pointer-events:none;'; ?>

is_pro_active() ) { /** * Fires the Display Settings metabox's real controls (minify * checkbox, user-condition radios, role/user pickers). * * @param \WP_Post $post The post being edited. */ do_action( 'ao_cc_render_display_settings', $post ); return; } $wrap_style = 'color: #aaa;pointer-events:none;'; ?>

', '' ); ?>




id, 'ao-custom-code' ) ) { return; } add_screen_option( 'per_page', [ 'label' => __( 'Snippets per page', 'admin-optimizer' ), 'default' => 20, 'option' => 'ao_cc_per_page', ] ); } /** * Save the per-page Screen Option value. * * @param mixed $status Existing status (false to skip saving). * @param string $option Option name. * @param mixed $value Submitted value. * @return int */ public function save_screen_option( $_status, string $_option, $value ): int { return (int) $value; } /** * Handle the "Rebuild Cache" admin-post action. * * @return void */ /** * Resolve the cache engine to use for a rebuild. * * Free always gets its own Custom_Code_Cache. When Pro is active, the * `ao_cc_cache_engine` filter lets Custom_Code_Pro swap in * Custom_Code_Cache_Pro instead — mirrors DB_Cleaner_Pro's * `adminoptim_db_cleaner_query_engine` filter for the same purpose. * * @return Custom_Code_Cache */ private function get_cache(): Custom_Code_Cache { $cache = new Custom_Code_Cache(); if ( ! $this->is_pro_active() ) { return $cache; } /** * Filters the cache engine used to rebuild Custom Code's frontend output. * * @param Custom_Code_Cache $cache Free's default cache engine. */ return apply_filters( 'ao_cc_cache_engine', $cache ); } /** * Handle the admin-page "Rebuild Cache" request (nonce-verified form submission, not AJAX). * * @return void */ public function handle_rebuild_cache(): void { if ( ! current_user_can( Custom_Code::CAPABILITY ) ) { wp_die( -1 ); } check_admin_referer( 'ao_cc_rebuild_cache' ); $this->get_cache()->rebuild_all(); wp_safe_redirect( Custom_Code::get_module_admin_url( [ 'ao-cc-rebuilt' => '1' ] ) ); exit; } /** * Handle the AJAX "Rebuild Cache" request. * * @return void */ public function ajax_rebuild_cache(): void { if ( ! current_user_can( Custom_Code::CAPABILITY ) ) { wp_send_json_error( 'forbidden', 403 ); } check_ajax_referer( 'ao_cc_rebuild_cache' ); $this->get_cache()->rebuild_all(); wp_send_json_success( [ 'message' => __( 'Cache rebuilt successfully.', 'admin-optimizer' ) ] ); } /** * Toggle a snippet between published and draft. * * @return void */ public function handle_toggle_status(): void { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- checked below. $post_id = isset( $_GET['post'] ) ? absint( $_GET['post'] ) : 0; if ( ! $post_id ) { wp_die( -1 ); } check_admin_referer( 'ao_cc_toggle_status_' . $post_id ); if ( ! current_user_can( Custom_Code::CAPABILITY ) || ! current_user_can( 'edit_post', $post_id ) ) { wp_die( -1 ); } $post = get_post( $post_id ); if ( ! $post || Custom_Code::POST_TYPE !== $post->post_type ) { wp_die( -1 ); } $new_status = 'publish' === $post->post_status ? 'draft' : 'publish'; remove_action( 'save_post_' . Custom_Code::POST_TYPE, [ $this, 'save_post' ] ); wp_update_post( [ 'ID' => $post_id, 'post_status' => $new_status, ] ); add_action( 'save_post_' . Custom_Code::POST_TYPE, [ $this, 'save_post' ], 10, 3 ); // Rebuild so the change is immediately reflected on the frontend. $old_locations = get_post_meta( $post_id, '_ao_cc_locations', true ); $old_display_raw = (string) get_post_meta( $post_id, '_ao_cc_display', true ); $old_display = $old_display_raw ? $old_display_raw : 'inline'; $old_position_raw = (string) get_post_meta( $post_id, '_ao_cc_position', true ); $old_position = $old_position_raw ? $old_position_raw : ''; $old_priority_raw = (string) get_post_meta( $post_id, '_ao_cc_load_priority', true ); $old_priority = in_array( $old_priority_raw, Custom_Code::VALID_PRIORITIES, true ) ? $old_priority_raw : 'default'; $cache = $this->get_cache(); $cache->rebuild( $post_id, is_array( $old_locations ) ? $old_locations : [], $old_display, $old_position, $old_priority ); if ( $this->is_pro_active() ) { $post_ids = get_post_meta( $post_id, '_ao_cc_post_ids', true ); $post_ids = is_array( $post_ids ) ? $post_ids : []; $cache->rebuild_post_meta( $post_ids, $post_ids ); } // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- nonce was verified above. $redirect_args = [ 'ao-cc-toggled' => '1', ]; if ( ! empty( $_REQUEST['post_status'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended $redirect_args['post_status'] = sanitize_key( wp_unslash( $_REQUEST['post_status'] ) ); } wp_safe_redirect( Custom_Code::get_module_admin_url( $redirect_args ) ); exit; } /** * Rebuild the cache when a post is unpublished or trashed without going through save_post. * * @param string $new_status New status. * @param string $old_status Old status. * @param \WP_Post $post Post object. * @return void */ public function on_status_transition( string $new_status, string $old_status, \WP_Post $post ): void { if ( Custom_Code::POST_TYPE !== $post->post_type ) { return; } // Only activation/deactivation can change frontend output. if ( $old_status === $new_status || ( 'publish' !== $old_status && 'publish' !== $new_status ) ) { return; } // The save_post handler (with nonce) will rebuild as well when this transition // comes from an edit-screen form submission, so avoid a redundant double rebuild. if ( isset( $_POST[ Custom_Code::NONCE_FIELD ] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing return; } $old_locations = get_post_meta( $post->ID, '_ao_cc_locations', true ); $old_locations = is_array( $old_locations ) ? $old_locations : []; $old_display_raw = (string) get_post_meta( $post->ID, '_ao_cc_display', true ); $old_display = $old_display_raw !== '' ? $old_display_raw : 'inline'; $old_position = (string) get_post_meta( $post->ID, '_ao_cc_position', true ); $old_priority_raw = (string) get_post_meta( $post->ID, '_ao_cc_load_priority', true ); $old_priority = in_array( $old_priority_raw, Custom_Code::VALID_PRIORITIES, true ) ? $old_priority_raw : 'default'; $cache = $this->get_cache(); $cache->rebuild( $post->ID, $old_locations, $old_display, $old_position, $old_priority ); if ( $this->is_pro_active() ) { $post_ids = get_post_meta( $post->ID, '_ao_cc_post_ids', true ); $post_ids = is_array( $post_ids ) ? $post_ids : []; $cache->rebuild_post_meta( $post_ids, $post_ids ); } } /** * Save post data and rebuild the frontend cache. * * @param int $post_id The ID of the post being saved. * @param \WP_Post $post The post object being saved. Unused directly, * but required in the signature so $update is * reachable — save_post_{post_type} always * passes all three positionally. * @param bool $update Whether this is an update to an existing * post (true) or a genuinely new post's first * save (false), as WordPress itself resolves it. * @return void */ public function save_post( int $post_id, \WP_Post $post, bool $update = true ): void { if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) { return; } if ( ! current_user_can( Custom_Code::CAPABILITY ) || ! current_user_can( 'edit_post', $post_id ) ) { return; } // No nonce field present — not a form submission (e.g. programmatic save). if ( ! isset( $_POST[ Custom_Code::NONCE_FIELD ] ) ) { return; } $nonce = sanitize_key( wp_unslash( $_POST[ Custom_Code::NONCE_FIELD ] ) ); if ( ! wp_verify_nonce( $nonce, Custom_Code::NONCE_ACTION ) ) { wp_die( -1 ); } // Read pre-save meta for cache diff. $old_loc_meta = get_post_meta( $post_id, '_ao_cc_locations', true ); $old_locations = $old_loc_meta ? $old_loc_meta : []; $old_disp_meta = get_post_meta( $post_id, '_ao_cc_display', true ); $old_display = $old_disp_meta ? $old_disp_meta : 'inline'; $old_pos_meta = get_post_meta( $post_id, '_ao_cc_position', true ); $old_position = $old_pos_meta ? $old_pos_meta : ''; $old_priority_meta = get_post_meta( $post_id, '_ao_cc_load_priority', true ); $old_priority = in_array( $old_priority_meta, Custom_Code::VALID_PRIORITIES, true ) ? $old_priority_meta : 'default'; $old_post_ids_meta = get_post_meta( $post_id, '_ao_cc_post_ids', true ); $old_post_ids = is_array( $old_post_ids_meta ) ? $old_post_ids_meta : []; // --- Type --- $existing_type = get_post_meta( $post_id, '_ao_cc_type', true ); if ( isset( $_POST['_ao_cc_type'] ) ) { $raw_type = sanitize_key( wp_unslash( $_POST['_ao_cc_type'] ) ); if ( 'shortcode' === $raw_type && ! $this->is_pro_active() ) { return; } $type = in_array( $raw_type, Custom_Code::TYPES, true ) ? $raw_type : 'css'; } else { $type = $existing_type ? $existing_type : 'css'; } if ( 'shortcode' === $type && ! $this->is_pro_active() ) { return; } $type_changed = '' !== $existing_type && $existing_type !== $type; if ( 'shortcode' === $type && $this->is_pro_active() ) { $shortcode_error = apply_filters( 'ao_cc_shortcode_validation_error', '', $post_id ); if ( is_string( $shortcode_error ) && '' !== $shortcode_error ) { set_transient( 'ao_cc_error_' . get_current_user_id() . '_' . $post_id, $shortcode_error, 45 ); return; } } // --- Validate and save post content --- $post_data = [ 'ID' => $post_id ]; $validation_error = null; if ( isset( $_POST['_ao_cc_content'] ) ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- sanitized below based on capability $raw_content = wp_unslash( $_POST['_ao_cc_content'] ); $raw_content = $this->normalize_line_endings( $raw_content ); // Strip accidental wrapping \s*$#i', '', $raw_content ); } if ( 'shortcode' === $type ) { // Free stores shortcode content as text. Pro may safely widen this through its gated filter. $shortcode_content = sanitize_textarea_field( $raw_content ); if ( $this->is_pro_active() ) { $shortcode_content = apply_filters( 'ao_cc_shortcode_content', $shortcode_content, $raw_content, $post_id ); } $post_data['post_content'] = is_string( $shortcode_content ) ? $shortcode_content : ''; } else { // JS and HTML snippets require unfiltered_html — wp_kses_post strips