401 lines
9.0 KiB
PHP
401 lines
9.0 KiB
PHP
<?php
|
|
/**
|
|
* Handles limitations to post types, uploads and more.
|
|
*
|
|
* @package WP_Ultimo
|
|
* @subpackage Limits
|
|
* @since 2.0.0
|
|
*/
|
|
|
|
namespace WP_Ultimo\Limits;
|
|
|
|
// Exit if accessed directly
|
|
defined('ABSPATH') || exit;
|
|
|
|
/**
|
|
* Handles limitations to post types, uploads and more.
|
|
*
|
|
* @since 2.0.0
|
|
*/
|
|
class Theme_Limits {
|
|
|
|
use \WP_Ultimo\Traits\Singleton;
|
|
|
|
/**
|
|
* List of themes that are not available.
|
|
*
|
|
* @since 2.0.0
|
|
* @var array
|
|
*/
|
|
protected $themes_not_available = array();
|
|
|
|
/**
|
|
* Keep a cache of the results as the check is costly.
|
|
*
|
|
* @since 2.1.2
|
|
* @var null|false|string
|
|
*/
|
|
protected $forced_theme_stylesheet = null;
|
|
|
|
/**
|
|
* Keep a cache of the template results as the check is costly.
|
|
*
|
|
* @since 2.1.2
|
|
* @var null|false|string
|
|
*/
|
|
protected $forced_theme_template = null;
|
|
|
|
/**
|
|
* Runs on the first and only instantiation.
|
|
*
|
|
* @since 2.0.0
|
|
* @return void
|
|
*/
|
|
public function init() {
|
|
|
|
/**
|
|
* We need to bail if we're inside the WP CLI context and the
|
|
* `skip-plugins` flag is present.
|
|
*
|
|
* This is due to the fact that without WP Ultimo being loaded,
|
|
* the functions and classes we'll need to perform any kind of proper
|
|
* checks won't be available. To validate if we're being loaded or not,
|
|
* we check for the function `wu_get_product`.
|
|
*
|
|
* @since 2.1.0
|
|
*/
|
|
if (wu_cli_is_plugin_skipped('wp-ultimo')) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
add_action('wu_sunrise_loaded', array($this, 'load_limitations'));
|
|
|
|
} // end init;
|
|
|
|
/**
|
|
* Apply limitations if they are available.
|
|
*
|
|
* @since 2.0.0
|
|
* @return void
|
|
*/
|
|
public function load_limitations() {
|
|
|
|
if (wu_get_current_site()->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 ?>
|
|
|
|
<script type="text/javascript">
|
|
|
|
if (typeof wu_theme_settings !== 'undefined') {
|
|
|
|
let content = document.getElementById("tmpl-theme").innerHTML;
|
|
|
|
content = content.replace(new RegExp('(<a class="button activate".*<\/a>)', 'g'), '<# if ( !wu_theme_settings.themes_not_available.includes(data.id) ) { #>$1<# } else { #> {{{ wu_theme_settings.replacement_message.replace("EXTENSION", data.id) }}} <# } #>');
|
|
|
|
document.getElementById("tmpl-theme").innerHTML = content;
|
|
|
|
} // end if;
|
|
|
|
</script>
|
|
|
|
<?php // phpcs:enable
|
|
|
|
} // end modify_backbone_template;
|
|
|
|
/**
|
|
* Checks if a theme needs to have the activate button removed.
|
|
*
|
|
* @since 2.0.0
|
|
*
|
|
* @param array $themes The list of themes available.
|
|
* @return array
|
|
*/
|
|
public function maybe_remove_activate_button($themes) {
|
|
|
|
if (is_main_site()) {
|
|
|
|
return $themes;
|
|
|
|
} // end if;
|
|
|
|
$theme_limitations = wu_get_current_site()->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;
|