has_limitations()) { add_filter('stylesheet', array($this, 'force_active_theme_stylesheet')); add_filter('template', array($this, 'force_active_theme_template')); add_filter('allowed_themes', array($this, 'add_extra_available_themes')); add_filter('site_allowed_themes', array($this, 'add_extra_available_themes')); add_filter('wp_prepare_themes_for_js', array($this, 'maybe_remove_activate_button')); add_action('admin_enqueue_scripts', array($this, 'hacky_remove_activate_button')); add_action('admin_footer-themes.php', array($this, 'modify_backbone_template')); add_action('customize_changeset_save_data', array($this, 'prevent_theme_activation_on_customizer'), 99, 2); } // end if; } // end load_limitations; /** * Prevents sub-site admins from switching to locked themes inside the customizer. * * @since 2.0.10 * * @param array $data The changeset array being saved. * @param array $context The context array with tons of info about the current customizer session. * @return array|void */ public function prevent_theme_activation_on_customizer($data, $context) { if (wu_get_current_site()->has_limitations() === false) { return $data; } // end if; $pending_theme_switch = $context['manager']->is_theme_active() === false; if ($pending_theme_switch === false) { return $data; } // end if; $new_theme = $context['manager']->theme()->stylesheet; $theme_limitations = wu_get_current_site()->get_limitations()->themes; if ($theme_limitations->allowed($new_theme, 'not_available')) { $response = array( 'code' => 'not-available', 'message' => __('This theme is not available on your current plan.', 'wp-ultimo'), ); wp_send_json($response, 'not-available'); exit; } // end if; return $data; } // end prevent_theme_activation_on_customizer; /** * Removes the activate button from not available themes. * * This uses a very hack-y approach due to a bug on WordPress * Core. The problem is that the WP code assumes that no one * with the capability of activating themes would be unable * to activate a theme (in cases of external factors for example). * * @todo Send patch to WordPress core. * @since 2.0.0 * @return void */ public function hacky_remove_activate_button() { global $pagenow; if (!function_exists('wu_generate_upgrade_to_unlock_url')) { return; } // end if; if ($pagenow !== 'themes.php') { return; } // end if; $membership = wu_get_current_site()->get_membership(); if (!$membership) { return; } // end if; $upgrade_button = wu_generate_upgrade_to_unlock_button(__('Upgrade to unlock', 'wp-ultimo'), array( 'module' => 'themes', 'type' => 'EXTENSION', 'classes' => 'button', )); wp_localize_script('theme', 'wu_theme_settings', array( 'themes_not_available' => $this->themes_not_available, 'replacement_message' => $upgrade_button, )); } // end hacky_remove_activate_button; /** * Modifies the default WordPress theme page template. * * @since 2.0.0 * @return void */ public function modify_backbone_template() { // phpcs:disable ?> get_limitations()->themes; foreach ($themes as $stylesheet => &$data) { $data['notAvailable'] = false; if ($theme_limitations->allowed($stylesheet, 'not_available')) { $data['actions']['activate'] = ''; /* * Hack solution due to core WP * not allowing us to filter out the button. */ $data['notAvailable'] = true; /* * Adds to the not available list * for our hack-y solution. */ $this->themes_not_available[] = $stylesheet; } // end if; } // end foreach; return $themes; } // end maybe_remove_activate_button; /** * Force the activation of one particularly selected theme. * * @since 2.0.0 * * @param string $stylesheet The default theme being used. * @return string */ public function force_active_theme_stylesheet($stylesheet) { if (is_main_site()) { return $stylesheet; } // end if; $forced_stylesheet = $this->get_forced_theme_stylesheet(); return $forced_stylesheet ? $forced_stylesheet : $stylesheet; } // end force_active_theme_stylesheet; /** * Force the activation of one particularly selected theme. * * @since 2.1.2 * * @param string $template The default theme being used. * @return string */ public function force_active_theme_template($template) { if (is_main_site()) { return $template; } // end if; $forced_template = $this->get_forced_theme_template(); return $forced_template ? $forced_template : $template; } // end force_active_theme_template; /** * Deactivates the plugins that people are not allowed to use. * * @since 2.0.0 * * @param array $themes Array with the plugins activated. * @return array */ public function add_extra_available_themes($themes) { /* * Bail on network admin =) */ if (is_network_admin()) { return $themes; } // end if; $theme_limitations = wu_get_current_site()->get_limitations()->themes; $_themes = $theme_limitations->get_all_themes(); foreach ($_themes as $theme_stylesheet) { $should_appear = $theme_limitations->allowed($theme_stylesheet, 'visible'); if (!$should_appear && isset($themes[$theme_stylesheet])) { unset($themes[$theme_stylesheet]); } elseif ($should_appear && !isset($themes[$theme_stylesheet])) { $themes[] = $theme_stylesheet; } // end if; } // end foreach; return $themes; } // end add_extra_available_themes; /** * Get the stylesheet of the theme that is forced to be active. * * @since 2.1.2 * * @return string|bool The stylesheet of the theme that is forced to be active or false. */ protected function get_forced_theme_stylesheet() { if ($this->forced_theme_stylesheet === null) { $this->forced_theme_stylesheet = wu_get_current_site()->get_limitations()->themes->get_forced_active_theme(); } // end if; return $this->forced_theme_stylesheet; } // end get_forced_theme_stylesheet; /** * Get the template of the theme that is forced to be active. * * @since 2.1.2 * * @return string|bool The template of the theme that is forced to be active or false. */ protected function get_forced_theme_template() { if ($this->forced_theme_template === null) { $stylesheet = $this->get_forced_theme_stylesheet(); $this->forced_theme_template = $stylesheet ? wp_get_theme($stylesheet)->get_template() : false; } // end if; return $this->forced_theme_template; } // end get_forced_theme_template; } // end class Theme_Limits;