__('Metaboxes & Widgets', AAM_KEY), 'description' => __('Manage visibility for the classic (not Gutenberg blocks) backend metaboxes, dashboard and frontend widgets for any role, user or visitors. The service ONLY removes unwanted metaboxes and widgets and does not prevent from direct data spoofing.', AAM_KEY), 'setting' => self::FEATURE_FLAG ); return $services; }, 30); } if (AAM_Core_Config::get(self::FEATURE_FLAG, true)) { if (is_admin()) { // Hook that initialize the AAM UI part of the service add_action('aam_init_ui_action', function () { AAM_Backend_Feature_Main_Metabox::register(); }, 10); } $this->initializeHooks(); } } /** * Initialize Metaboxes & Widgets hooks * * @return void * * @access protected * @version 6.0.0 */ protected function initializeHooks() { if (is_admin()) { // Manager WordPress metaboxes add_action("in_admin_header", function () { global $post; if (AAM_Core_Request::get('init') === 'metabox') { //make sure that nobody is playing with screen options if (is_a($post, 'WP_Post')) { $id = $post->post_type; } else { $screen = get_current_screen(); $id = ($screen ? $screen->id : ''); } $model = new AAM_Backend_Feature_Main_Metabox; $model->initialize($id); } }, 999); // Manage Navigation Menu page to support // https://forum.aamplugin.com/d/61-restrict-role-from-updating-or-deleting-specific-navigation-menus add_filter('nav_menu_meta_box_object', function ($postType) { $postType->_default_query['suppress_filters'] = false; return $postType; }); // Manager WordPress metaboxes - Classic Editor add_action("in_admin_header", array($this, 'filterMetaboxes'), 999); // Manage Dashboard widgets add_action("widgets_admin_page", array($this, 'filterMetaboxes'), 999); } else { // Widget filters add_filter('sidebars_widgets', array($this, 'filterWidgets'), 999); } } /** * Handle metabox initialization process * * @return void * * @access public * @version 6.0.0 */ public function filterMetaboxes() { global $post; // Make sure that nobody is playing with screen options if (is_a($post, 'WP_Post')) { $id = $post->post_type; } else { $screen = get_current_screen(); $id = ($screen ? $screen->id : null); } if (filter_input(INPUT_GET, 'init') !== 'metabox') { if ($id !== 'widgets') { $this->filterBackend($id); } else { $this->filterAppearanceWidgets(); } } } /** * Filter backend metaboxes and widgets * * @param string $screen * * @access public * @global array $wp_meta_boxes * @version 6.0.0 */ public function filterBackend($screen) { global $wp_meta_boxes; if (is_array($wp_meta_boxes)) { foreach ($wp_meta_boxes as $screen_id => $zones) { if ($screen === $screen_id) { $this->filterZones($zones, $screen_id); } } } } /** * Filter of widgets on the Appearance->Widgets screen * * @access public * * @return void * @global array $wp_registered_widgets * @version 6.0.0 */ public function filterAppearanceWidgets() { global $wp_registered_widgets; $object = AAM::getUser()->getObject('metabox'); foreach ($wp_registered_widgets as $id => $widget) { $callback = $this->getWidgetCallback($widget); if ($object->isHidden('widgets', $callback)) { unregister_widget($callback); unset($wp_registered_widgets[$id]); } } } /** * Filter frontend widgets * * @param array $widgets * * @return array * * @access public * @version 6.0.0 */ public function filterWidgets($widgets) { global $wp_registered_widgets; $object = AAM::getUser()->getObject('metabox'); if (is_array($wp_registered_widgets)) { foreach ($wp_registered_widgets as $id => $widget) { $callback = $this->getWidgetCallback($widget); if ($object->isHidden('widgets', $callback)) { unregister_widget($callback); // Remove it from registered widget global var!! // INFORM: Why Unregister Widget does not clear global var? unset($wp_registered_widgets[$id]); } } } return $widgets; } /** * Filter metaboxes based on screen * * @param array $zones * @param string $screen_id * * @return void * * @access protected * @version 6.0.0 */ protected function filterZones($zones, $screen_id) { foreach ($zones as $zone => $priorities) { foreach ($priorities as $metaboxes) { $this->removeMetaboxes($zone, $metaboxes, $screen_id); } } } /** * Filter list of metaboxes on the screen * * @param string $zone * @param array $metaboxes * @param string $screen_id * * @return void * * @access protected * @version 6.0.0 */ protected function removeMetaboxes($zone, $metaboxes, $screen_id) { $object = AAM::getUser()->getObject('metabox'); foreach (array_keys($metaboxes) as $id) { if ($object->isHidden($screen_id, $id)) { remove_meta_box($id, $screen_id, $zone); } } } /** * Get widget's callback * * The callback is used as unique widget identifier * * @param mixed $widget * * @return string * * @access protected * @version 6.0.0 */ protected function getWidgetCallback($widget) { if (is_array($widget['callback'])) { if (is_object($widget['callback'][0])) { $callback = get_class($widget['callback'][0]); } elseif (is_string($widget['callback'][0])) { $callback = $widget['callback'][0]; } } if (empty($callback)) { $callback = isset($widget['classname']) ? $widget['classname'] : null; } return $callback; } } if (defined('AAM_KEY')) { AAM_Service_Metabox::bootstrap(); }