urn true; } } //By default, all tweaks are disabled. return false; } /** * @param WP_Screen $screen */ public function processPostponedTweaks($screen = null) { if ( empty($screen) && function_exists('get_current_screen') ) { $screen = get_current_screen(); } $screenId = isset($screen, $screen->id) ? $screen->id : null; foreach ($this->postponedTweaks as $id => $tweak) { if ( !$tweak->isEnabledForScreen($screenId) ) { continue; } $tweak->apply(); } $this->postponedTweaks = array(); } public function processSidebarWidgets() { global $wp_widget_factory; global $pagenow; if ( !isset($wp_widget_factory, $wp_widget_factory->widgets) || !is_array($wp_widget_factory->widgets) ) { return; } $widgetTweaks = array(); foreach ($wp_widget_factory->widgets as $id => $widget) { $tweak = new ameHideSidebarWidgetTweak($widget); $widgetTweaks[$tweak->getId()] = $tweak; } //Sort the tweaks in alphabetic order. uasort( $widgetTweaks, /** * @param ameBaseTweak $a * @param ameBaseTweak $b * @return int */ function ($a, $b) { return strnatcasecmp($a->getLabel(), $b->getLabel()); } ); foreach ($widgetTweaks as $tweak) { $this->addTweak($tweak, self::APPLY_TWEAK_MANUALLY); } if ( is_admin() && ($pagenow === 'widgets.php') ) { $this->processTweaks($widgetTweaks); } } public function processSidebars() { global $wp_registered_sidebars; global $pagenow; if ( !isset($wp_registered_sidebars) || !is_array($wp_registered_sidebars) ) { return; } $sidebarTweaks = array(); foreach ($wp_registered_sidebars as $id => $sidebar) { $tweak = new ameHideSidebarTweak($sidebar); $this->addTweak($tweak, self::APPLY_TWEAK_MANUALLY); $sidebarTweaks[$tweak->getId()] = $tweak; } if ( is_admin() && ($pagenow === 'widgets.php') ) { $this->processTweaks($sidebarTweaks); } } public function addSection($id, $label, $priority = null) { $section = new ameTweakSection($id, $label); if ( $priority !== null ) { $section->setPriority($priority); } $this->sections[$section->getId()] = $section; } protected function getTemplateVariables($templateName) { $variables = parent::getTemplateVariables($templateName); $variables['tweaks'] = $this->tweaks; return $variables; } public function enqueueTabScripts() { $codeEditorSettings = null; if ( function_exists('wp_enqueue_code_editor') ) { $codeEditorSettings = wp_enqueue_code_editor(array('type' => 'text/html')); } wp_register_auto_versioned_script( 'ame-tweak-manager', plugins_url('tweak-manager.js', __FILE__), array( 'ame-lodash', 'knockout', 'ame-actor-selector', 'jquery-json', 'ame-jquery-cookie', 'ame-ko-extensions', ) ); wp_enqueue_script('ame-tweak-manager'); //Reselect the same actor. $query = $this->menuEditor->get_query_params(); $selectedActor = null; if ( isset($query['selected_actor']) ) { $selectedActor = strval($query['selected_actor']); } $scriptData = $this->getScriptData(); $scriptData['selectedActor'] = $selectedActor; $scriptData['defaultCodeEditorSettings'] = $codeEditorSettings; wp_localize_script('ame-tweak-manager', 'wsTweakManagerData', $scriptData); } protected function getScriptData() { $settings = $this->loadSettings(); $tweakSettings = ameUtils::get($settings, 'tweaks', array()); $tweakData = array(); foreach ($this->tweaks as $id => $tweak) { $item = $tweak->toArray(); $item = array_merge(ameUtils::get($tweakSettings, $id, array()), $item); $tweakData[] = $item; } $sectionData = array(); foreach ($this->sections as $section) { $sectionData[] = array( 'id' => $section->getId(), 'label' => $section->getLabel(), 'priority' => $section->getPriority(), ); } return array( 'tweaks' => $tweakData, 'sections' => $sectionData, 'isProVersion' => $this->menuEditor->is_pro_version(), 'lastUserTweakSuffix' => ameUtils::get($settings, 'lastUserTweakSuffix', 0), ); } public function enqueueTabStyles() { parent::enqueueTabStyles(); wp_enqueue_auto_versioned_style( 'ame-tweak-manager-css', plugins_url('tweaks.css', __FILE__) ); } public function handleSettingsForm($post = array()) { parent::handleSettingsForm($post); $submittedSettings = json_decode($post['settings'], true); //To save space, filter out tweaks that are not enabled for anyone and have no other settings. //Most tweaks only have "id" and "enabledForActor" properties. $basicProperties = array('id' => true, 'enabledForActor' => true); $submittedSettings['tweaks'] = array_filter( $submittedSettings['tweaks'], function ($settings) use ($basicProperties) { if ( !empty($settings['enabledForActor']) ) { return true; } $additionalProperties = array_diff_key($settings, $basicProperties); return !empty($additionalProperties); } ); //User-defined tweaks must have a type. $submittedSettings['tweaks'] = array_filter( $submittedSettings['tweaks'], function ($settings) { return empty($settings['isUserDefined']) || !empty($settings['typeId']); } ); //TODO: Give other components an opportunity to validate and sanitize tweak settings. E.g. a filter. //Sanitize CSS with FILTER_SANITIZE_FULL_SPECIAL_CHARS if unfiltered_html is not enabled. Always strip . //Build a lookup array of user-defined tweaks so that we can register them later //without iterating through the entire list. $userDefinedTweakIds = array(); foreach ($submittedSettings['tweaks'] as $properties) { if ( !empty($properties['isUserDefined']) && !empty($properties['id']) ) { $userDefinedTweakIds[$properties['id']] = true; } } //We use an incrementing suffix to ensure each user-defined tweak gets a unique ID. $lastUserTweakSuffix = ameUtils::get($this->loadSettings(), 'lastUserTweakSuffix', 0); $newSuffix = ameUtils::get($submittedSettings, 'lastUserTweakSuffix', 0); if ( is_scalar($newSuffix) && is_numeric($newSuffix) ) { $newSuffix = max(intval($newSuffix), 0); if ( $newSuffix < 10000000 ) { $lastUserTweakSuffix = $newSuffix; } } $this->settings['tweaks'] = $submittedSettings['tweaks']; $this->settings['userDefinedTweaks'] = $userDefinedTweakIds; $this->settings['lastUserTweakSuffix'] = $lastUserTweakSuffix; $this->saveSettings(); $params = array('updated' => 1); if ( !empty($post['selected_actor']) ) { $params['selected_actor'] = strval($post['selected_actor']); } wp_redirect($this->getTabUrl($params)); exit; } } class ameTweakSection { private $id; private $label; private $priority = 0; public function __construct($id, $label) { $this->id = $id; $this->label = $label; } public function getId() { return $this->id; } public function getLabel() { return $this->label; } public function getPriority() { return $this->priority; } public function setPriority($priority) { $this->priority = $priority; return $this; } }