'', // Name of the menu item
// 'parent' => null, // slug of parent, if blank, then this is a top level menu
'id' => '', // Unique ID of the menu item
'panel' => '', // The Name of the panel to create
'panel_desc' => '', // The description to display on the panel
'panel_id' => '', // The panel ID to create / add to. If this is blank & `panel` is given, this will be generated
'capability' => 'edit_theme_options', // User role
// 'icon' => 'dashicons-admin-generic', // Menu icon for top level menus only
'desc' => '', // Description
'position' => 30,// Menu position for top level menus only
);
public $settings;
public $options = array();
public $owner;
// Makes sure we only load live previewing CSS only once
private static $namespacesWithPrintedPreviewCSS = array();
function __construct( $settings, $owner ) {
$this->owner = $owner;
$this->settings = array_merge( $this->defaultSettings, $settings );
if ( empty( $this->settings['name'] ) ) {
$this->settings['name'] = __( 'More Options', TF_I18NDOMAIN );
}
if ( empty( $this->settings['id'] ) ) {
$this->settings['id'] = $this->owner->optionNamespace . '_' . str_replace( ' ', '-', trim( strtolower( $this->settings['name'] ) ) );
}
if ( empty( $this->settings['panel_id'] ) ) {
$this->settings['panel_id'] = $this->owner->optionNamespace . '_' . str_replace( ' ', '-', trim( strtolower( $this->settings['panel'] ) ) );
}
// Register the customizer control.
add_action( 'customize_register', array( $this, 'register' ) );
// Enqueue required customizer styles & scripts.
tf_add_action_once( 'customize_controls_enqueue_scripts', array( $this, 'loadUploaderScript' ) );
// Clear local storage, we use it for remembering modified customizer values.
tf_add_action_once( 'customize_controls_print_footer_scripts', array( $this, 'initLocalStorage' ) );
// Generate the custom CSS for live previews.
tf_add_action_once( 'wp_ajax_tf_generate_customizer_css', array( $this, 'ajaxGenerateCustomizerCSS' ) );
// Modify the values of the options for the generation of CSS with the values from the customizer $_POST.
global $wp_customize;
if ( isset( $wp_customize ) ) {
tf_add_filter_once( 'tf_pre_get_value_' . $this->owner->optionNamespace, array( $this, 'useCustomizerModifiedValue' ), 10, 3 );
}
}
public function loadUploaderScript() {
wp_enqueue_media();
wp_enqueue_script( 'tf-theme-customizer-serialize', TitanFramework::getURL( '../js/min/serialize-min.js', __FILE__ ) );
wp_enqueue_style( 'tf-admin-theme-customizer-styles', TitanFramework::getURL( '../css/admin-theme-customizer-styles.css', __FILE__ ) );
}
public function getID() {
return $this->settings['id'];
}
/**
* Ajax handler for generating CSS based on the existing options with values changed to
* match the customizer modified values.
*
* @since 1.9.2
*
* @return void
*/
public function ajaxGenerateCustomizerCSS() {
// This value is passed back to the live preview ajax handler in $this->livePreviewMainScript()
$generated = array(
'css' => '',
);
foreach ( TitanFramework::getAllInstances() as $framework ) {
// Modify the values of the options for the generation of CSS with the values from the customizer $_POST.
$namespace = $framework->optionNamespace;
add_filter( "tf_pre_get_value_{$namespace}", array( $this, 'useCustomizerModifiedValue' ), 10, 3 );
// Generate our new CSS based on the customizer values
$css = $framework->cssInstance->generateCSS();
$generated['css'] .= $css;
/**
* Allow options to add customizer live preview parameters. The tf_generate_customizer_preview_js hook allows for manipulating these values.
*
* @since 1.9.2
*
* @see tf_generate_customizer_preview_js
*/
$generated = apply_filters( "tf_generate_customizer_preview_css_{$namespace}", $generated );
}
wp_send_json_success( $generated );
}
/**
* Override the getOption value with the customizer value which comes from the $_POST array
*
* @since 1.9.2
*
* @param mixed $value The value of the option.
* @param int $postID The post ID if there is one (always null in this case).
* @param TitanFrameworkOption $option The option being parsed.
*
* @return mixed The new value
*
* @see tf_pre_get_value_{namespace}
*/
public function useCustomizerModifiedValue( $value, $postID, $option ) {
if ( empty( $_POST ) ) {
return $value;
}
if ( ! is_array( $_POST ) ) {
return $value;
}
if ( array_key_exists( $option->getID(), $_POST ) ) {
return $_POST[ $option->getID() ];
}
if ( ! empty( $_POST['customized'] ) ) {
$customizedSettings = (array) json_decode( stripslashes( $_POST['customized'] ) );
if ( is_array( $customizedSettings ) && ! empty( $customizedSettings ) ) {
if ( array_key_exists( $option->getID(), $customizedSettings ) ) {
return $customizedSettings[ $option->getID() ];
}
}
}
return $value;
}
/**
* Prints the script that clears the JS local storage when customizer loads, this ensures we start fresh.
* Use localStorage so we can still use values when the customizer refreshes.
*
* @since 1.9.2
*
* @return void
*/
public function initLocalStorage() {
?>
options as $option ) {
if ( empty( $option->settings['css'] ) && empty( $option->settings['livepreview'] ) ) {
continue;
}
// Print the starting script tag.
if ( ! $printStart ) {
$printStart = true;
?>
owner->optionNamespace, self::$namespacesWithPrintedPreviewCSS ) ) {
self::$namespacesWithPrintedPreviewCSS[] = $this->owner->optionNamespace;
echo '';
}
}
public function register( $wp_customize ) {
add_action( 'wp_head', array( $this, 'printPreviewCSS' ), 1000 );
// Create the panel
if ( ! empty( $this->settings['panel_id'] ) ) {
$existingPanels = $wp_customize->panels();
if ( ! array_key_exists( $this->settings['panel_id'], $existingPanels ) ) {
$wp_customize->add_panel( $this->settings['panel_id'], array(
'title' => $this->settings['panel'],
'priority' => $this->settings['position'],
'capability' => $this->settings['capability'],
'description' => ! empty( $this->settings['panel_desc'] ) ? $this->settings['panel_desc'] : '',
) );
}
}
// Create the section
$existingSections = $wp_customize->sections();
if ( ! array_key_exists( $this->settings['id'], $existingSections ) ) {
$wp_customize->add_section( $this->settings['id'], array(
'title' => $this->settings['name'],
'priority' => $this->settings['position'],
'description' => $this->settings['desc'],
'capability' => $this->settings['capability'],
'panel' => empty( $this->settings['panel_id'] ) ? '' : $this->settings['panel_id'],
) );
}
// Unfortunately we have to call each option's register from here
foreach ( $this->options as $index => $option ) {
if ( ! empty( $option->settings['id'] ) ) {
$namespace = $this->owner->optionNamespace;
$option_type = $option->settings['type'];
$transport = empty( $option->settings['livepreview'] ) && empty( $option->settings['css'] ) ? 'refresh' : 'postMessage';
/**
* Allow options to override the transport mode of an option in the customizer
*
* @since 1.9.2
*/
$transport = apply_filters( "tf_customizer_transport_{$option_type}_{$namespace}", $transport, $option );
$wp_customize->add_setting( $option->getID(), array(
'default' => $option->settings['default'],
'transport' => $transport,
) );
}
// We add the index here, this will be used to order the controls because of this minor bug:
// https://core.trac.wordpress.org/ticket/20733
$option->registerCustomizerControl( $wp_customize, $this, $index + 100 );
}
add_action( 'wp_footer', array( $this, 'livePreview' ) );
tf_add_action_once( 'wp_footer', array( $this, 'livePreviewMainScript' ) );
}
public function createOption( $settings ) {
if ( ! apply_filters( 'tf_create_option_continue_' . $this->owner->optionNamespace, true, $settings ) ) {
return null;
}
$obj = TitanFrameworkOption::factory( $settings, $this );
$this->options[] = $obj;
do_action( 'tf_create_option_' . $this->owner->optionNamespace, $obj );
return $obj;
}
}