page_hook = add_menu_page( __( 'MarqueeAll — Widget Manager', 'marqueeall' ), __( 'MarqueeAll', 'marqueeall' ), 'manage_options', 'marqueeall', [ $this, 'render_page' ], 'https://ps.w.org/marqueeall/assets/icon-128x128.gif', 58 ); } /** * Enqueue admin-page assets — only on our own page. * * @param string $hook_suffix Current admin page hook. * @return void */ public function enqueue_assets( $hook_suffix ) { if ( $hook_suffix !== $this->page_hook ) { return; } wp_enqueue_style( 'marqueeall-admin', MASSCIE_URL . 'assets/css/marqueeall-admin.css', [], MASSCIE_VERSION ); wp_enqueue_script( 'marqueeall-admin', MASSCIE_URL . 'assets/js/marqueeall-admin.js', [ 'jquery' ], MASSCIE_VERSION, true ); wp_localize_script( 'marqueeall-admin', 'MARQUEEALL_ADMIN', [ 'ajax_url' => admin_url( 'admin-ajax.php' ), 'nonce' => wp_create_nonce( 'marqueeall_save_widget_status' ), 'i18n' => [ 'saving' => __( 'Saving…', 'marqueeall' ), 'saved' => __( 'Settings saved!', 'marqueeall' ), 'save_error' => __( 'Could not save settings. Please try again.', 'marqueeall' ), /* translators: 1: Number of enabled widgets, 2: Total available widgets. */ 'enabled_count' => __( '%1$d of %2$d available widgets enabled', 'marqueeall' ), ], ] ); } /** * Render the Widget Manager admin page. * * @return void */ public function render_page() { if ( ! current_user_can( 'manage_options' ) ) { wp_die( esc_html__( 'You do not have permission to access this page.', 'marqueeall' ) ); } $registry = Widget_Registry::instance()->get_all(); $total = Widget_Registry::instance()->count(); $widget_manager = Widget_Manager::instance(); $status = $widget_manager->get_status(); $enabled_count = $widget_manager->get_enabled_count(); ?>

', '' ); ?>

1|0 for every widget * * @return void Sends JSON response and exits. */ public function ajax_save_widget_status() { // Nonce verification. check_ajax_referer( 'marqueeall_save_widget_status', 'nonce' ); // Capability check. if ( ! current_user_can( 'manage_options' ) ) { wp_send_json_error( [ 'message' => __( 'You do not have permission to perform this action.', 'marqueeall' ) ], 403 ); return; } // Read and sanitize the incoming status map. // The JS sends a complete object with 1 or 0 for every slug, // so unchecked (disabled) widgets are explicitly included as 0. // phpcs:ignore WordPress.Security.NonceVerification.Missing -- already verified above. $raw_status = isset( $_POST['widget_status'] ) && is_array( $_POST['widget_status'] ) ? wp_unslash( $_POST['widget_status'] ) // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized : []; $incoming = []; foreach ( $raw_status as $slug => $value ) { $incoming[ sanitize_key( $slug ) ] = absint( $value ); } // Pass to the manager, which builds the full canonical map. $result = Widget_Manager::instance()->save_status( $incoming ); $enabled_count = Widget_Manager::instance()->get_enabled_count(); $total = Widget_Registry::instance()->count(); if ( 'error' === $result ) { wp_send_json_error( [ 'message' => __( 'Could not save settings. Please try again.', 'marqueeall' ) ] ); return; } // Both 'saved' and 'unchanged' are reported as success to the user. $message = 'saved' === $result ? __( 'Settings saved!', 'marqueeall' ) : __( 'Settings saved!', 'marqueeall' ); wp_send_json_success( [ 'message' => $message, 'enabled_count' => $enabled_count, 'total' => $total, ] ); } }