Completed
Push — master ( 6b2386...2bf093 )
by Ahmad
04:44
created

TitanFramework::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 20
Code Lines 11

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 20
rs 9.4286
cc 1
eloc 11
nc 1
nop 1
1
<?php
0 ignored issues
show
Coding Style Compatibility introduced by
For compatibility and reusability of your code, PSR1 recommends that a file should introduce either new symbols (like classes, functions, etc.) or have side-effects (like outputting something, or including other files), but not both at the same time. The first symbol is defined on line 16 and the first side effect is on line 8.

The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.

The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.

To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.

Loading history...
2
/**
3
 * Titan Framework class
4
 *
5
 * @package Titan Framework
6
 */
7
8
if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly.
9
}
10
11
/**
12
 * TitanFramework class
13
 *
14
 * @since 1.0
15
 */
16
class TitanFramework {
17
18
	/**
19
	 * All TitanFramework instances
20
	 * @var array
21
	 */
22
	private static $instances = array();
23
24
	/**
25
	 * The current option namespace.
26
	 * Options will be prefixed with this in the database
27
	 * @var string
28
	 */
29
	public $optionNamespace;
30
31
	/**
32
	 * All main containers (admin pages, meta boxes, customizer section)
33
	 * @var array of TitanFrameworkAdminPage, TitanFrameworkMetaBox, & TitanFrameworkCustomizer
34
	 */
35
	private $mainContainers = array();
36
37
	/**
38
	 * All Google Font options used. This is for enqueuing Google Fonts for the frontend
39
	 * TODO Move this to the TitanFrameworkOptionSelectGooglefont class and let it enqueue from there
40
	 * @var array TitanFrameworkOptionSelectGooglefont
41
	 */
42
	private $googleFontsOptions = array();
0 ignored issues
show
Unused Code introduced by
The property $googleFontsOptions is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
43
44
	/**
45
	 * We store option ids which should not be created here
46
	 * @var array
47
	 * @see removeOption()
48
	 */
49
	private $optionsToRemove = array();
50
51
	/**
52
	 * Holds the values of all admin (page & tab) options. We need this since
53
	 * @var array of TitanFrameworkOption
54
	 */
55
	private $adminOptions;
56
57
	/**
58
	 * The CSS class instance used
59
	 * @var TitanFrameworkCSS
60
	 */
61
	public $cssInstance;
62
63
	/**
64
	 * We store the options (with IDs) here, used for ensuring our serialized option
65
	 * value doesn't get cluttered with unused options
66
	 * @var array
67
	 */
68
	public $optionsUsed = array();
69
70
	/**
71
	 * The current list of settings
72
	 * @var array
73
	 */
74
	public $settings = array();
75
76
	/**
77
	 * Default settings
78
	 * @var array
79
	 */
80
	private $defaultSettings = array(
81
		'css' => 'generate', 	// If 'generate', Titan will try and generate a cacheable
82
		                        // CSS file (or inline if it can't).
83
			 					// If 'inline', CSS will be printed out in the head tag,
84
								// If false, CSS will not be generated nor printed.
85
	);
86
87
88
	/**
89
	 * Gets an instance of the framework for the namespace
90
	 *
91
	 * @since 1.0
92
	 *
93
	 * @param string $optionNamespace The namespace to get options from.
94
	 *
95
	 * @return TitanFramework
96
	 */
97
	public static function getInstance( $optionNamespace ) {
98
99
		// Clean namespace.
100
		$optionNamespace = str_replace( ' ', '-', trim( strtolower( $optionNamespace ) ) );
101
102
		foreach ( self::$instances as $instance ) {
103
			if ( $instance->optionNamespace == $optionNamespace ) {
104
				return $instance;
105
			}
106
		}
107
108
		$newInstance = new TitanFramework( $optionNamespace );
109
		self::$instances[] = $newInstance;
110
		return $newInstance;
111
	}
112
113
114
	/**
115
	 * Gets all active instances of Titan Framework
116
	 *
117
	 * @since 1.9.2
118
	 *
119
	 * @return array An array of TitanFramework objects
120
	 */
121
	public static function getAllInstances() {
122
		return self::$instances;
123
	}
124
125
126
	/**
127
	 * Creates a new TitanFramework object
128
	 *
129
	 * @since 1.0
130
	 *
131
	 * @param string $optionNamespace The namespace to get options from.
132
	 */
133
	function __construct( $optionNamespace ) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
134
135
		// Clean namespace.
136
		$optionNamespace = str_replace( ' ', '-', trim( strtolower( $optionNamespace ) ) );
137
138
		$this->optionNamespace = $optionNamespace;
139
		$this->settings = $this->defaultSettings;
140
141
		do_action( 'tf_init', $this );
142
		do_action( 'tf_init_' . $this->optionNamespace, $this );
143
144
		$this->cssInstance = new TitanFrameworkCSS( $this );
145
146
		add_action( 'admin_enqueue_scripts', array( $this, 'loadAdminScripts' ) );
147
		add_action( 'tf_create_option_' . $this->optionNamespace, array( $this, 'rememberAllOptions' ) );
148
		add_filter( 'tf_create_option_continue_' . $this->optionNamespace, array( $this, 'removeChildThemeOptions' ), 10, 2 );
149
150
		// Create a save option filter for customizer options.
151
		add_filter( 'pre_update_option', array( $this, 'addCustomizerSaveFilter' ), 10, 3 );
152
	}
153
154
155
	/**
156
	 * Action hook on tf_create_option to remember all the options, used to ensure that our
157
	 * serialized option does not get cluttered with unused options
158
	 *
159
	 * @since 1.2.1
160
	 *
161
	 * @param TitanFrameworkOption $option The option that was just created.
162
	 *
163
	 * @return void
164
	 */
165
	public function rememberAllOptions( $option ) {
166
		if ( ! empty( $option->settings['id'] ) ) {
167
168
			if ( is_admin() && isset( $this->optionsUsed[ $option->settings['id'] ] ) ) {
169
				self::displayFrameworkError(
170
					sprintf( __( 'All option IDs per namespace must be unique. The id %s has been used multiple times.', TF_I18NDOMAIN ),
171
						'<code>' . $option->settings['id'] . '</code>'
172
					)
173
				);
174
			}
175
176
			$this->optionsUsed[ $option->settings['id'] ] = $option;
177
		}
178
	}
179
180
181
	/**
182
	 * Loads all the admin scripts used by Titan Framework
183
	 *
184
	 * @since 1.0
185
	 *
186
	 * @param string $hook The slug of admin page that called the enqueue.
187
	 *
188
	 * @return void
189
	 */
190
	public function loadAdminScripts( $hook ) {
191
192
		// Get all options panel IDs.
193
		$panel_ids = array();
194
		if ( ! empty( $this->mainContainers['admin-page'] ) ) {
195
			foreach ( $this->mainContainers['admin-page'] as $admin_panel ) {
196
				$panel_ids[] = $admin_panel->panelID;
197
			}
198
		}
199
200
		// Only enqueue scripts if we're on a Titan options page.
201
		if ( in_array( $hook, $panel_ids ) || ! empty( $this->mainContainers['meta-box'] ) ) {
202
			wp_enqueue_media();
203
			wp_enqueue_script( 'tf-serialize', TitanFramework::getURL( '../js/min/serialize-min.js', __FILE__ ) );
204
			wp_enqueue_script( 'tf-styling', TitanFramework::getURL( '../js/min/admin-styling-min.js', __FILE__ ) );
205
			wp_enqueue_style( 'tf-admin-styles', TitanFramework::getURL( '../css/admin-styles.css', __FILE__ ) );
206
		}
207
	}
208
209
210
	/**
211
	 * Gets all the admin page options (not meta & customizer) and loads them from the database into
212
	 * a class variable. This is needed because all our admin page options are contained in a single entry.
213
	 *
214
	 * @since 1.9
215
	 *
216
	 * @return array All admin options currently in the instance
217
	 */
218
	protected function getInternalAdminOptions() {
219
		if ( empty( $this->adminOptions ) ) {
220
			$this->adminOptions = array();
221
		}
222
223
		if ( ! empty( $this->adminOptions ) ) {
224
			return $this->adminOptions;
225
		}
226
227
		// Check if we have options saved already.
228
		$currentOptions = get_option( $this->optionNamespace . '_options' );
229
230
		// First time run, this action hook can be used to trigger something.
231
		if ( false === $currentOptions ) {
232
			do_action( 'tf_init_no_options_' . $this->optionNamespace );
233
		}
234
235
		// Put all the available options in our global variable for future checking.
236
		if ( ! empty( $currentOptions ) && ! count( $this->adminOptions ) ) {
237
			$this->adminOptions = unserialize( $currentOptions );
238
		}
239
240
		if ( empty( $this->adminOptions ) ) {
241
			$this->adminOptions = array();
242
		}
243
244
		return $this->adminOptions;
245
	}
246
247
248
	/**
249
	 * Gets the admin page option that's loaded into the instance, used by the option class
250
	 *
251
	 * @since 1.9
252
	 *
253
	 * @param string $optionName The ID of the option (not namespaced).
254
	 * @param mixed  $defaultValue The default value to return if the option isn't available yet.
255
	 *
256
	 * @return mixed The option value
257
	 *
258
	 * @see TitanFrameworkOption->getValue()
259
	 */
260
	public function getInternalAdminPageOption( $optionName, $defaultValue = false ) {
261
262
		// Run this first to ensure that adminOptions carries all our admin page options.
263
		$this->getInternalAdminOptions();
264
265
		if ( array_key_exists( $optionName, $this->adminOptions ) ) {
266
			return $this->adminOptions[ $optionName ];
267
		} else {
268
			return $defaultValue;
269
		}
270
	}
271
272
273
	/**
274
	 * Sets the admin page option that's loaded into the instance, used by the option class.
275
	 * Doesn't perform a save, only sets the value in the class variable.
276
	 *
277
	 * @since 1.9
278
	 *
279
	 * @param string $optionName The ID of the option (not namespaced).
280
	 * @param mixed  $value The value to set.
281
	 *
282
	 * @return bool Always returns true
283
	 *
284
	 * @see TitanFrameworkOption->setValue()
285
	 */
286
	public function setInternalAdminPageOption( $optionName, $value ) {
287
288
		// Run this first to ensure that adminOptions carries all our admin page options.
289
		$this->getInternalAdminOptions();
290
291
		$this->adminOptions[ $optionName ] = $value;
292
		return true;
293
	}
294
295
296
	/**
297
	 * Saves all the admin (not meta & customizer) options which are currently loaded into this instance
298
	 *
299
	 * @since 1.0
300
	 *
301
	 * @return array All admin options currently in the instance
302
	 */
303
	public function saveInternalAdminPageOptions() {
304
305
		// Run this first to ensure that adminOptions carries all our admin page options.
306
		$this->getInternalAdminOptions();
307
308
		update_option( $this->optionNamespace . '_options', serialize( $this->adminOptions ) );
309
		do_action( 'tf_save_options_' . $this->optionNamespace );
310
		return $this->adminOptions;
311
	}
312
313
314
	/**
315
	 * Create a admin page
316
	 *
317
	 * @deprecated 1.9 Use createContainer() with 'type' => 'admin-page' or createAdminPanel() instead.
318
	 * @since 1.0
319
	 *
320
	 * @param array $settings The arguments for creating the admin page.
321
	 *
322
	 * @return TitanFrameworkAdminPage The created admin page
323
	 */
324
	public function createAdminPanel( $settings ) {
325
		// _deprecated_function( __FUNCTION__, '1.9', 'createAdminPage' );
0 ignored issues
show
Unused Code Comprehensibility introduced by
58% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
326
		return $this->createAdminPage( $settings );
327
	}
328
329
330
	/**
331
	 * Create a admin page
332
	 *
333
	 * @since 1.0
334
	 *
335
	 * @param array $settings The arguments for creating the admin page.
336
	 *
337
	 * @return TitanFrameworkAdminPage The created admin page
338
	 */
339
	public function createAdminPage( $settings ) {
340
		$settings['type'] = 'admin-page';
341
		$container = $this->createContainer( $settings );
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->createContainer($settings); of type null|object adds the type object to the return on line 343 which is incompatible with the return type documented by TitanFramework::createAdminPage of type TitanFrameworkAdminPage|null.
Loading history...
342
		do_action( 'tf_admin_panel_created_' . $this->optionNamespace, $container );
343
		return $container;
344
	}
345
346
347
	/**
348
	 * Create a meta box
349
	 *
350
	 * @since 1.0
351
	 *
352
	 * @param array $settings The arguments for creating the meta box.
353
	 *
354
	 * @return TitanFrameworkMetaBox The created meta box
355
	 */
356
	public function createMetaBox( $settings ) {
357
		$settings['type'] = 'meta-box';
358
		return $this->createContainer( $settings );
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->createContainer($settings); of type null|object adds the type object to the return on line 358 which is incompatible with the return type documented by TitanFramework::createMetaBox of type TitanFrameworkMetaBox|null.
Loading history...
359
	}
360
361
362
	/**
363
	 * Create a customizer section
364
	 *
365
	 * @deprecated 1.9 Use createContainer() with 'type' => 'customizer' or createCustomizer instead.
366
	 * @since 1.0
367
	 *
368
	 * @param array $settings The arguments for creating a customizer section.
369
	 *
370
	 * @return TitanFrameworkCustomizer The created section
371
	 */
372
	public function createThemeCustomizerSection( $settings ) {
373
		// _deprecated_function( __FUNCTION__, '1.9', 'createContainer' );
0 ignored issues
show
Unused Code Comprehensibility introduced by
58% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
374
		return $this->createCustomizer( $settings );
375
	}
376
377
378
	/**
379
	 * Create a customizer section
380
	 *
381
	 * @since 1.9
382
	 *
383
	 * @param array $settings The arguments for creating a customizer section.
384
	 *
385
	 * @return TitanFrameworkCustomizer The created section
386
	 */
387
	public function createCustomizer( $settings ) {
388
		$settings['type'] = 'customizer';
389
		$container = $this->createContainer( $settings );
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->createContainer($settings); of type null|object adds the type object to the return on line 391 which is incompatible with the return type documented by TitanFramework::createCustomizer of type TitanFrameworkCustomizer|null.
Loading history...
390
		do_action( 'tf_theme_customizer_created_' . $this->optionNamespace, $container );
391
		return $container;
392
	}
393
394
395
	/**
396
	 * Creates a container (e.g. admin page, meta box, customizer section) depending
397
	 * on the `type` parameter given in $settings
398
	 *
399
	 * @since 1.9
400
	 *
401
	 * @param array $settings The arguments for creating the container.
402
	 *
403
	 * @return TitanFrameworkCustomizer|TitanFrameworkAdminPage|TitanFrameworkMetaBox The created container
404
	 */
405
	public function createContainer( $settings ) {
406
		if ( empty( $settings['type'] ) ) {
407
			self::displayFrameworkError( sprintf( __( '%s needs a %s parameter.', TF_I18NDOMAIN ), '<code>' . __FUNCTION__ . '</code>', '<code>type</code>' ) );
408
			return;
409
		}
410
411
		$type = strtolower( $settings['type'] );
412
		$class = 'TitanFramework' . str_replace( ' ', '', ucfirst( str_replace( '-', ' ', $settings['type'] ) ) );
413
		$action = str_replace( '-', '_', $type );
414
		$container = false;
415
416
		if ( ! class_exists( $class ) ) {
417
			self::displayFrameworkError( sprintf( __( 'Container of type %s, does not exist.', TF_I18NDOMAIN ), '<code>' . $settings['type'] . '</code>' ) );
418
			return;
419
		}
420
421
		// Create the container object.
422
		$container = new $class( $settings, $this );
423
		if ( empty( $this->mainContainers[ $type ] ) ) {
424
			$this->mainContainers[ $type ] = array();
425
		}
426
427
		$this->mainContainers[ $type ][] = $container;
428
429
		do_action( 'tf_' . $action . '_created_' . $this->optionNamespace, $container );
430
431
		return $container;
432
	}
433
434
435
	/**
436
	 * A function available ONLY to CHILD themes to stop the creation of options
437
	 * created by the PARENT theme.
438
	 *
439
	 * @since 1.2.1
440
	 * @access public
441
	 *
442
	 * @param string $optionName The id of the option to remove / stop from being created.
443
	 *
444
	 * @return void
445
	 */
446
	public function removeOption( $optionName ) {
447
		$this->optionsToRemove[] = $optionName;
448
	}
449
450
451
	/**
452
	 * Hook to the tf_create_option_continue filter, to check whether or not to continue
453
	 * adding an option (if the option id was used in $titan->removeOption).
454
	 *
455
	 * @since 1.2.1
456
	 * @access public
457
	 *
458
	 * @param boolean $continueCreating If true, the option will be created.
459
	 * @param array   $optionSettings The settings for the option to be created.
460
	 *
461
	 * @return boolean If true, continue with creating the option. False to stop it..
462
	 */
463
	public function removeChildThemeOptions( $continueCreating, $optionSettings ) {
464
		if ( ! count( $this->optionsToRemove ) ) {
465
			return $continueCreating;
466
		}
467
		if ( empty( $optionSettings['id'] ) ) {
468
			return $continueCreating;
469
		}
470
		if ( in_array( $optionSettings['id'], $this->optionsToRemove ) ) {
471
			return false;
472
		}
473
		return $continueCreating;
474
	}
475
476
477
	/**
478
	 * Get an option
479
	 *
480
	 * @since 1.0
481
	 *
482
	 * @param string $optionName The name of the option.
483
	 * @param int    $postID The post ID if this is a meta option.
484
	 *
485
	 * @return mixed The option value
486
	 */
487
	public function getOption( $optionName, $postID = null ) {
488
		$value = false;
489
490
		// Get the option value.
491
		if ( array_key_exists( $optionName, $this->optionsUsed ) ) {
492
			$option = $this->optionsUsed[ $optionName ];
493
			$value = $option->getValue( $postID );
494
		}
495
496
		return apply_filters( 'tf_get_option_' . $this->optionNamespace, $value, $optionName, $postID );
497
	}
498
499
500
	/**
501
	 * Gets a set of options. Pass an associative array containing the option names as keys and
502
	 * the values you want to be retained if the option names are not implemented.
503
	 *
504
	 * @since 1.9
505
	 *
506
	 * @param array $optionArray An associative array containing option names as keys.
507
	 * @param int   $postID The post ID if this is a meta option.
508
	 *
509
	 * @return array An array containing the values saved.
510
	 *
511
	 * @see $this->getOption()
512
	 */
513
	public function getOptions( $optionArray, $postID = null ) {
514
		foreach ( $optionArray as $optionName => $originalValue ) {
515
			if ( array_key_exists( $optionName, $this->optionsUsed ) ) {
516
				$optionArray[ $optionName ] = $this->getOption( $optionName, $postID );
517
			}
518
		}
519
		return apply_filters( 'tf_get_options_' . $this->optionNamespace, $optionArray, $postID );
520
	}
521
522
523
	/**
524
	 * Sets an option
525
	 *
526
	 * @since 1.0
527
	 *
528
	 * @param string $optionName The name of the option to save.
529
	 * @param mixed  $value The value of the option.
530
	 * @param int    $postID The ID of the parent post if this is a meta box option.
531
	 *
532
	 * @return boolean Always returns true
533
	 */
534
	public function setOption( $optionName, $value, $postID = null ) {
535
536
		// Get the option value.
537
		if ( array_key_exists( $optionName, $this->optionsUsed ) ) {
538
			$option = $this->optionsUsed[ $optionName ];
539
			$option->setValue( $value, $postID );
540
		}
541
542
		do_action( 'tf_set_option_' . $this->optionNamespace, $optionName, $value, $postID );
543
544
		return true;
545
	}
546
547
548
	/**
549
	 * Deletes ALL the options for the namespace. Even deletes all meta found in all posts.
550
	 * Mainly used for unit tests
551
	 *
552
	 * @since 1.9
553
	 *
554
	 * @return void
555
	 */
556
	public function deleteAllOptions() {
557
558
		// Delete all admin options.
559
		delete_option( $this->optionNamespace . '_options' );
560
		$this->adminOptions = array();
561
562
		// Delete all meta options.
563
		global $wpdb;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
564
		$allPosts = $wpdb->get_results( 'SELECT ID FROM ' . $wpdb->posts, ARRAY_A );
565
		if ( ! empty( $allPosts ) ) {
566
			foreach ( $allPosts as $row ) {
567
				$allMeta = get_post_meta( $row['ID'] );
568
569
				// Only remove meta data that the framework created.
570
				foreach ( $allMeta as $metaName => $dummy ) {
571
					if ( stripos( $metaName, $this->optionNamespace . '_' ) === 0 ) {
572
						delete_post_meta( $row['ID'], $metaName );
573
					}
574
				}
575
			}
576
		}
577
578
		// Delete all theme mods.
579
		$allThemeMods = get_theme_mods();
580
		if ( ! empty( $allThemeMods ) && is_array( $allThemeMods ) ) {
581
			foreach ( $allThemeMods as $optionName => $dummy ) {
582
583
				// Only remove theme mods that the framework created.
584
				if ( stripos( $optionName, $this->optionNamespace . '_' ) === 0 ) {
585
					remove_theme_mod( $optionName );
586
				}
587
			}
588
		}
589
	}
590
591
592
	/**
593
	 * Generates style rules which can use options as their values
594
	 *
595
	 * @since 1.0
596
	 *
597
	 * @param string $CSSString The styles to render.
598
	 *
599
	 * @return void
600
	 */
601
	public function createCSS( $CSSString ) {
602
		$this->cssInstance->addCSS( $CSSString );
603
	}
604
605
606
	/**
607
	 * Displays an error notice
608
	 *
609
	 * @since 1.0
610
	 *
611
	 * @param string       $message The error message to display.
612
	 * @param array|object $errorObject The object to dump inside the error message.
613
	 *
614
	 * @return void
615
	 */
616
	public static function displayFrameworkError( $message, $errorObject = null ) {
617
		// Clean up the debug object for display. e.g. If this is a setting, we can have lots of blank values.
618
		if ( is_array( $errorObject ) ) {
619
			foreach ( $errorObject as $key => $val ) {
620
				if ( '' === $val ) {
621
					unset( $errorObject[ $key ] );
622
				}
623
			}
624
		}
625
626
		// Display an error message.
627
		?>
628
		<div style='margin: 20px; text-align: center;'><strong><?php echo TF_NAME ?> Error:</strong>
629
			<?php echo $message ?>
630
			<?php
631
			if ( ! empty( $errorObject ) ) :
632
				?>
633
				<pre><code style="display: inline-block; padding: 10px"><?php echo print_r( $errorObject, true ) ?></code></pre>
634
				<?php
635
			endif;
636
			?>
637
		</div>
638
		<?php
639
	}
640
641
642
	/**
643
	 * Acts the same way as plugins_url( 'script', __FILE__ ) but returns then correct url
644
	 * when called from inside a theme.
645
	 *
646
	 * @since 1.1.2
647
	 *
648
	 * @param string $script the script to get the url to, relative to $file.
649
	 * @param string $file the current file, should be __FILE__.
650
	 *
651
	 * @return string the url to $script
652
	 */
653
	public static function getURL( $script, $file ) {
654
		$parentTheme = trailingslashit( get_template_directory() );
655
		$childTheme = trailingslashit( get_stylesheet_directory() );
656
		$plugin = trailingslashit( dirname( $file ) );
657
658
		// Windows sometimes mixes up forward and back slashes, ensure forward slash for correct URL output.
659
		$parentTheme = str_replace( '\\', '/', $parentTheme );
660
		$childTheme = str_replace( '\\', '/', $childTheme );
661
		$file = str_replace( '\\', '/', $file );
662
663
		$url = '';
664
665
		// Framework is in a parent theme.
666
		if ( stripos( $file, $parentTheme ) !== false ) {
667
			$dir = trailingslashit( dirname( str_replace( $parentTheme, '', $file ) ) );
668
			if ( './' == $dir ) {
669
				$dir = '';
670
			}
671
			$url = trailingslashit( get_template_directory_uri() ) . $dir . $script;
672
673
		} else if ( stripos( $file, $childTheme ) !== false ) {
674
			// Framework is in a child theme.
675
			$dir = trailingslashit( dirname( str_replace( $childTheme, '', $file ) ) );
676
			if ( './' == $dir ) {
677
				$dir = '';
678
			}
679
			$url = trailingslashit( get_stylesheet_directory_uri() ) . $dir . $script;
680
681
		} else {
682
			// Framework is a or in a plugin.
683
			$url = plugins_url( $script, $file );
684
		}
685
686
		// Replace /foo/../ with '/'.
687
		$url = preg_replace( '/\/(?!\.\.)[^\/]+\/\.\.\//', '/', $url );
688
689
		return $url;
690
	}
691
692
693
	/**
694
	 * Sets a value in the $setting class variable
695
	 *
696
	 * @since 1.6
697
	 *
698
	 * @param string $setting The name of the setting.
699
	 * @param string $value The value to set.
700
	 *
701
	 * @return void
702
	 */
703
	public function set( $setting, $value ) {
704
		$oldValue = $this->settings[ $setting ];
705
		$this->settings[ $setting ] = $value;
706
707
		do_action( 'tf_setting_' . $setting . '_changed_' . $this->optionNamespace, $value, $oldValue );
708
	}
709
710
711
	/**
712
	 * Gets the CSS generated
713
	 *
714
	 * @since 1.6
715
	 *
716
	 * @return string The generated CSS
717
	 */
718
	public function generateCSS() {
719
		return $this->cssInstance->generateCSS();
720
	}
721
722
723
724
	/**
725
	 * Adds a 'tf_save_option_{namespace}_{optionID}' filter to all Customizer options
726
	 * which are just about to be saved
727
	 *
728
	 * This uses the `pre_update_option` filter to check all the options being saved if it's
729
	 * a theme_mod option. It further checks whether these are Titan customizer options,
730
	 * then attaches the new hook into those.
731
	 *
732
	 * @since 1.8
733
	 *
734
	 * @param mixed  $value The value to be saved in the options.
735
	 * @param string $optionName The option name.
736
	 * @param mixed  $oldValue The previously stored value.
737
	 *
738
	 * @return mixed The modified value to save
739
	 *
740
	 * @see pre_update_option filter
741
	 */
742
	public function addCustomizerSaveFilter( $value, $optionName, $oldValue ) {
0 ignored issues
show
Unused Code introduced by
The parameter $oldValue is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
743
744
		$theme = get_option( 'stylesheet' );
745
746
		// Intercept theme mods only.
747
		if ( strpos( $optionName, 'theme_mods_' . $theme ) !== 0 ) {
748
			return $value;
749
		}
750
751
		// We expect theme mods to be an array.
752
		if ( ! is_array( $value ) ) {
753
			return $value;
754
		}
755
756
		// Checks whether a Titan customizer is in place.
757
		$customizerUsed = false;
758
759
		// Go through all our customizer options and filter them for saving.
760
		$optionIDs = array();
761
		if ( ! empty( $this->mainContainers['customizer'] ) ) {
762
			foreach ( $this->mainContainers['customizer'] as $customizer ) {
763
				foreach ( $customizer->options as $option ) {
764
					if ( ! empty( $option->settings['id'] ) ) {
765
						$optionID = $option->settings['id'];
766
						$themeModName = $this->optionNamespace . '_' . $option->settings['id'];
767
768
						if ( ! array_key_exists( $themeModName, $value ) ) {
769
							continue;
770
						}
771
772
						$customizerUsed = true;
773
774
						// Try and unserialize if possible.
775
						$tempValue = $value[ $themeModName ];
776
						if ( is_serialized( $tempValue ) ) {
777
							$tempValue = unserialize( $tempValue );
778
						}
779
780
						// Hook 'tf_save_option_{namespace}'.
781
						$newValue = apply_filters( 'tf_save_option_' . $this->optionNamespace, $tempValue, $option->settings['id'] );
782
783
						// Hook 'tf_save_option_{namespace}_{optionID}'.
784
						$newValue = apply_filters( 'tf_save_option_' . $themeModName, $tempValue );
785
786
						// We mainly check for equality here so that we won't have to serialize IF the value wasn't touched anyway.
787
						if ( $newValue != $tempValue ) {
788
							if ( is_array( $newValue ) ) {
789
								$newValue = serialize( $newValue );
790
							}
791
792
							$value[ $themeModName ] = $newValue;
793
						}
794
					}
795
				}
796
			}
797
		}
798
799
		if ( $customizerUsed ) {
800
			/** This action is documented in class-admin-page.php */
801
			$namespace = $this->optionNamespace;
802
			do_action( "tf_pre_save_options_{$namespace}", $this->mainContainers['customizer'] );
803
		}
804
805
		return $value;
806
	}
807
}
808