PluginProbe
Customify / 2.10.9
Customify v2.10.9
2.10.9 1.2.3 1.2.4 1.2.5 1.2.6 1.2.7 1.2.7.1 1.3.0 1.3.1 1.4.0 1.4.1 1.4.2 1.5.0 1.5.1 1.5.2 1.5.3 1.5.4 1.5.5 1.5.6 1.5.7 1.6.0 1.6.0.1 1.6.5 1.7.0 1.7.1 All 77 releases
customify / includes / class-customify-theme-configs.php

class-customify-theme-configs.php in Customify 2.10.9, at includes/class-customify-theme-configs.php

383 lines 12.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 // phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped,WordPress.Security.EscapeOutput.ExceptionNotEscaped,WordPress.Security.EscapeOutput.UnsafePrintingFunction -- Legacy Customify view output contains trusted config HTML, dynamic CSS/JS, or WordPress Customizer binding attributes.
3 /**
4 * This is the class that handles the overall logic for the theme configs.
5 *
6 * @see https://pixelgrade.com
7 * @author Pixelgrade
8 * @since 1.7.4
9 */
10
11 if ( ! defined( 'ABSPATH' ) ) {
12 exit; // Exit if accessed directly
13 }
14
15 if ( ! class_exists( 'Customify_Theme_Configs' ) ) {
16
17 class Customify_Theme_Configs {
18
19 /**
20 * Holds the only instance of this class.
21 * @var null|Customify_Theme_Configs
22 * @access protected
23 * @since 1.7.4
24 */
25 protected static $_instance = null;
26
27 /**
28 * The external theme config for the current active theme.
29 * @var array
30 * @access public
31 * @since 1.7.4
32 */
33 public $external_theme_config = null;
34
35 /**
36 * Constructor.
37 *
38 * @since 1.7.4
39 */
40 protected function __construct() {
41 $this->init();
42 }
43
44 /**
45 * Initialize this module.
46 *
47 * @since 1.7.4
48 */
49 public function init() {
50 // Hook up.
51 $this->add_hooks();
52 }
53
54 /**
55 * Initiate our hooks
56 *
57 * @since 1.7.4
58 */
59 public function add_hooks() {
60 /*
61 * Handle the external theme configuration logic. We use a late priority to be able to overwrite if we have to.
62 */
63 add_filter( 'customify_filter_fields', array( $this, 'maybe_activate_external_theme_config' ), 10, 1 );
64 add_filter( 'customify_filter_fields', array( $this, 'maybe_apply_external_theme_config' ), 100, 1 );
65 // Maybe the theme has instructed us to do things like removing sections or controls.
66 add_action( 'customize_register', array( $this, 'maybe_process_external_theme_config_extras' ), 11 );
67
68 /*
69 * Scripts enqueued in the Customizer.
70 */
71 add_action( 'customize_controls_init', array( $this, 'register_admin_customizer_scripts' ), 10 );
72 add_action( 'customize_controls_enqueue_scripts', array( $this, 'enqueue_admin_customizer_scripts' ), 10 );
73
74 /**
75 * Determine if we should output the theme root JSON in the Customizer for easier copy&paste to cloud.
76 */
77 if ( defined( 'CUSTOMIFY_SM_LOAD_THEME_ROOT_CONFIG' ) && true === CUSTOMIFY_SM_LOAD_THEME_ROOT_CONFIG ) {
78 add_filter( 'customize_controls_print_styles', array( $this, 'maybe_output_json_external_config' ), 0 );
79 }
80 }
81
82 /**
83 * Register Customizer admin scripts.
84 */
85 function register_admin_customizer_scripts() {
86
87 }
88
89 /**
90 * Enqueue Customizer admin scripts
91 */
92 function enqueue_admin_customizer_scripts() {
93 // If there is no style manager support, bail early.
94 if ( ! $this->is_supported() ) {
95 return;
96 }
97
98 // Enqueue the needed scripts, already registered.
99 }
100
101 /**
102 * Determine if Style Manager is supported.
103 *
104 * @return bool
105 * @since 1.7.4
106 *
107 */
108 public function is_supported() {
109 // For now we will only use the fact that Style Manager is supported.
110 return apply_filters( 'customify_theme_configs_are_supported', Customify_Style_Manager::instance()->is_supported() );
111 }
112
113 /**
114 * Get the themes configuration.
115 *
116 * @param bool $skip_cache Optional. Whether to use the cached config or fetch a new one.
117 *
118 * @return array
119 * @since 1.7.4
120 *
121 */
122 public function get_theme_configs( $skip_cache = false ) {
123 $theme_configs = array();
124
125 // Make sure that the Design Assets class is loaded.
126 require_once 'lib/class-customify-design-assets.php';
127
128 // Get the design assets data.
129 $design_assets = Customify_Design_Assets::instance()->get( $skip_cache );
130 if ( false !== $design_assets && ! empty( $design_assets['theme_configs'] ) ) {
131 $theme_configs = $design_assets['theme_configs'];
132 }
133
134 return apply_filters( 'customify_get_theme_configs', $theme_configs );
135 }
136
137 /**
138 * Maybe activate an external theme config.
139 *
140 * If the conditions are met, activate an external theme config by declaring support for the style manager and saving the config.
141 *
142 * @param array $config This holds required keys for the plugin config like 'opt-name', 'panels', 'settings'
143 *
144 * @return array
145 * @since 1.7.4
146 *
147 */
148 public function maybe_activate_external_theme_config( $config ) {
149 // If somebody else already declared support for the Style Manager, we stop and let them have it.
150 if ( $this->is_supported() ) {
151 return $config;
152 }
153
154 // First gather details about the current (parent) theme.
155 $theme = wp_get_theme( get_template() );
156 // Bail if for some strange reason we couldn't find the theme.
157 if ( ! $theme->exists() ) {
158 return $config;
159 }
160
161 // Now determine if we have a theme config for the current theme.
162 $theme_configs = $this->get_theme_configs();
163
164 // We will go through every theme config and determine it's match score
165 foreach ( $theme_configs as $hashid => $theme_config ) {
166 // Loose matching means that the theme doesn't have to match all the conditions.
167 $loose_match = false;
168 if ( ! empty( $theme_config['loose_match'] ) ) {
169 $loose_match = true;
170 }
171
172 $matches = 0;
173 $total = 0;
174 if ( ! empty( $theme_config['name'] ) && $theme_config['name'] == $theme->get( 'Name' ) ) {
175 $matches ++;
176 $total ++;
177 }
178 if ( ! empty( $theme_config['slug'] ) && $theme_config['slug'] == $theme->get_stylesheet() ) {
179 $matches ++;
180 $total ++;
181 }
182 if ( ! empty( $theme_config['txtd'] ) && $theme_config['txtd'] == $theme->get( 'TextDomain' ) ) {
183 $matches ++;
184 $total ++;
185 }
186
187 $theme_configs[ $hashid ]['match_score'] = 0;
188 if ( true === $loose_match ) {
189 $theme_configs[ $hashid ]['match_score'] = $matches;
190 } elseif ( $matches === $total ) {
191 $theme_configs[ $hashid ]['match_score'] = $matches;
192 }
193 }
194
195 // Now we will order the theme configs by match scores, descending and get the highest matching candidate, if any.
196 $theme_configs = Customify_Array::array_orderby( $theme_configs, 'match_score', SORT_DESC );
197 $external_theme_config = array_shift( $theme_configs );
198 // If we've ended up with a theme config with a zero match score, bail.
199 if ( empty( $external_theme_config['match_score'] ) || empty( $external_theme_config['config']['sections'] ) ) {
200 return $config;
201 }
202
203 // Now we have a theme config to work with. Save it for later use.
204 $this->external_theme_config = $external_theme_config;
205
206 // Declare support for the Style Manager if there is such a section in the config
207 if ( isset( $external_theme_config['config']['sections']['style_manager_section'] ) ) {
208 add_theme_support( 'customizer_style_manager' );
209 }
210
211 return $config;
212 }
213
214 /**
215 * Maybe apply an external theme config.
216 *
217 * If the conditions are met, apply an external theme config. Right now we are only handling sections and their controls.
218 *
219 * @param array $config This holds required keys for the plugin config like 'opt-name', 'panels', 'settings'
220 *
221 * @return array
222 * @since 1.7.4
223 *
224 */
225 public function maybe_apply_external_theme_config( $config ) {
226 // Bail if we have no external theme config data.
227 if ( empty( $this->external_theme_config ) ) {
228 return $config;
229 }
230
231 // Apply the theme config.
232 // If we are dealing with the Customify default config, we need a clean slate, sort of.
233 if ( 'customify_defaults' === $config['opt-name'] ) {
234 // We will save the Style Manager config so we can merge with it. But the rest goes away.
235 $style_manager_section = array();
236 if ( isset( $config['sections']['style_manager_section'] ) ) {
237 $style_manager_section = $config['sections']['style_manager_section'];
238 }
239
240 $config['opt-name'] = get_template() . '_options';
241 if ( ! empty( $this->external_theme_config['config']['opt-name'] ) ) {
242 $config['opt-name'] = $this->external_theme_config['config']['opt-name'];
243 }
244
245 $config['sections'] = array(
246 'style_manager_section' => $style_manager_section,
247 );
248 }
249
250 // Now merge things.
251 $config['sections'] = Customify_Array::array_merge_recursive_distinct( $config['sections'], $this->external_theme_config['config']['sections'] );
252
253 return $config;
254 }
255
256 /**
257 * Maybe process certain "commands" from the external theme config.
258 *
259 * Mainly things like removing sections, controls, etc.
260 *
261 * @param WP_Customize_Manager $wp_customize
262 *
263 * @since 1.7.4
264 *
265 */
266 public function maybe_process_external_theme_config_extras( $wp_customize ) {
267 // Bail if we have no external theme config data.
268 if ( empty( $this->external_theme_config ) ) {
269 return;
270 }
271
272 // Maybe remove panels
273 if ( ! empty( $this->external_theme_config['config']['remove_panels'] ) ) {
274 // Standardize it.
275 if ( is_string( $this->external_theme_config['config']['remove_panels'] ) ) {
276 $this->external_theme_config['config']['remove_panels'] = array( $this->external_theme_config['config']['remove_panels'] );
277 }
278
279 foreach ( $this->external_theme_config['config']['remove_panels'] as $panel_id ) {
280 $wp_customize->remove_panel( $panel_id );
281 }
282 }
283
284 // Maybe remove sections
285 if ( ! empty( $this->external_theme_config['config']['remove_sections'] ) ) {
286 // Standardize it.
287 if ( is_string( $this->external_theme_config['config']['remove_sections'] ) ) {
288 $this->external_theme_config['config']['remove_sections'] = array( $this->external_theme_config['config']['remove_sections'] );
289 }
290
291 foreach ( $this->external_theme_config['config']['remove_sections'] as $section_id ) {
292
293 if ( 'widgets' === $section_id ) {
294 global $wp_registered_sidebars;
295
296 foreach ( $wp_registered_sidebars as $widget => $settings ) {
297 $wp_customize->remove_section( 'sidebar-widgets-' . $widget );
298 }
299 continue;
300 }
301
302 $wp_customize->remove_section( $section_id );
303 }
304 }
305
306 // Maybe remove settings
307 if ( ! empty( $this->external_theme_config['config']['remove_settings'] ) ) {
308 // Standardize it.
309 if ( is_string( $this->external_theme_config['config']['remove_settings'] ) ) {
310 $this->external_theme_config['config']['remove_settings'] = array( $this->external_theme_config['config']['remove_settings'] );
311 }
312
313 foreach ( $this->external_theme_config['config']['remove_settings'] as $setting_id ) {
314 $wp_customize->remove_setting( $setting_id );
315 }
316 }
317
318 // Maybe remove controls
319 if ( ! empty( $this->external_theme_config['config']['remove_controls'] ) ) {
320 // Standardize it.
321 if ( is_string( $this->external_theme_config['config']['remove_controls'] ) ) {
322 $this->external_theme_config['config']['remove_controls'] = array( $this->external_theme_config['config']['remove_controls'] );
323 }
324
325 foreach ( $this->external_theme_config['config']['remove_controls'] as $control_id ) {
326 $wp_customize->remove_control( $control_id );
327 }
328 }
329 }
330
331 /**
332 * Output the JSON in the Customizer page source.
333 */
334 public function maybe_output_json_external_config() {
335 if ( ! empty( $this->external_theme_config['config'] ) ) {
336 // Also output the JSON in a special hidden div for easy copy pasting.
337 // Also remove any multiple tabs.
338 echo "\n" . '<!--' . "\n" . 'Just copy&paste this:' . "\n" . "\n" . trim( str_replace( '\t\t', '', json_encode( $this->external_theme_config['config'] ) ) ) . "\n" . "\n" . '-->' . "\n";
339 }
340 }
341
342 /**
343 * Main Customify_Theme_Configs Instance
344 *
345 * Ensures only one instance of Customify_Theme_Configs is loaded or can be loaded.
346 *
347 * @return Customify_Theme_Configs Main Customify_Theme_Configs instance
348 * @since 1.7.4
349 * @static
350 *
351 */
352 public static function instance() {
353
354 if ( is_null( self::$_instance ) ) {
355 self::$_instance = new self();
356 }
357
358 return self::$_instance;
359 }
360
361 /**
362 * Cloning is forbidden.
363 *
364 * @since 1.7.4
365 */
366 public function __clone() {
367
368 _doing_it_wrong( __FUNCTION__, esc_html__( 'You should not do that!', 'customify' ), null );
369 }
370
371 /**
372 * Unserializing instances of this class is forbidden.
373 *
374 * @since 1.7.4
375 */
376 public function __wakeup() {
377
378 _doing_it_wrong( __FUNCTION__, esc_html__( 'You should not do that!', 'customify' ), null );
379 }
380 }
381
382 }
383