first commit

This commit is contained in:
CHIEFSOFT\ameye
2023-12-28 16:20:07 -05:00
commit b114fdf4fa
5377 changed files with 1850677 additions and 0 deletions
@@ -0,0 +1,556 @@
<?php
namespace Nimble;
if ( did_action('nimble_skope_loaded') ) {
if ( ( defined( 'CZR_DEV' ) && CZR_DEV ) || ( defined( 'NIMBLE_DEV' ) && NIMBLE_DEV ) ) {
error_log( __FILE__ . ' => The skope has already been loaded' );
}
return;
}
// Set the namsepace as a global so we can use it when fired from another theme/plugin using the fmk
global $czr_skope_namespace;
$czr_skope_namespace = __NAMESPACE__ . '\\';
do_action( 'nimble_skope_loaded' );
//Creates a new instance
function Flat_Skop_Base( $params = array() ) {
return Flat_Skop_Base::skp_get_instance( $params );
}
/////////////////////////////////////////////////////////////////
// <DEFINITIONS>
// THE SKOPE MODEL
function skp_get_default_skope_model() {
return array(
'title' => '',
'long_title' => '',
'ctx_title' => '',
'id' => '',
'skope' => '',
//'level' => '',
'obj_id' => '',
'skope_id' => '',
'values' => ''
);
}
// those contexts have no group
function skp_get_no_group_skope_list() {
return array( 'home', 'search', '404', 'date' );
}
/////////////////////////////////////////////////////////////////
// </DEFINITIONS>
/////////////////////////////////////////////////////////////////
// HELPERS
function skp_trim_text( $text, $text_length, $more ) {
if ( !$text )
return '';
$text = trim( strip_tags( $text ) );
if ( !$text_length )
return $text;
$end_substr = $_text_length = strlen( $text );
if ( $_text_length > $text_length ){
$end_substr = strpos( $text, ' ' , $text_length);
$end_substr = ( $end_substr !== FALSE ) ? $end_substr : $text_length;
$text = substr( $text , 0 , $end_substr );
}
return ( ( $end_substr < $text_length ) && $more ) ? $text : $text . ' ' .$more ;
}
/////////////////////////////////////////////////////////////////
// SKOPE HELPERS
/**
* Return the current skope
* Front / Back agnostic.
* @param $_requesting_wot is a string with the following possible values : 'meta_type' (like post) , 'type' (like page), 'id' (like page id)
* @param $_return_string string param stating if the return value should be a string or an array
* @param $requested_parts is an array of parts looking like
* Array
* (
* [meta_type] => post
* [type] => page
* [obj_id] => 9
* )
* USE CASE when $requested_parts is passed : when a post gets deleted, we need to clean any skope posts associated. That's when we invoke skp_get_skope( null, true, $requested_parts )
* @return a string of all concatenated ctx parts (default) 0R an array of the ctx parts
*/
function skp_get_skope( $_requesting_wot = null, $_return_string = true, $requested_parts = array() ) {
//skope builder from the wp $query
//=> returns :
// the meta_type : post, tax, user
// the type : post_type, taxonomy name, author
// the id : post id, term id, user id
// if $parts are provided, use them.
// Note that the value of skp_get_query_skope() is cached when get the first time for better performance
$parts = ( is_array( $requested_parts ) && !empty( $requested_parts ) ) ? $requested_parts : skp_get_query_skope();
// error_log( '<SKOPE PARTS>' );
// error_log( print_r( $parts, true ) );
// error_log( '</SKOPE PARTS>' );
$_return = array();
$meta_type = $type = $obj_id = false;
if ( is_array( $parts ) && !empty( $parts ) ) {
$meta_type = isset( $parts['meta_type'] ) ? $parts['meta_type'] : false;
$type = isset( $parts['type'] ) ? $parts['type'] : false;
$obj_id = isset( $parts['obj_id'] ) ? $parts['obj_id'] : false;
}
switch ( $_requesting_wot ) {
case 'meta_type':
if ( false !== $meta_type ) {
$_return = array( "meta_type" => "{$meta_type}" );
}
break;
case 'type':
if ( false !== $type ) {
$_return = array( "type" => "{$type}" );
}
break;
case 'id':
if ( false !== $obj_id ) {
$_return = array( "id" => "{$obj_id}" );
}
break;
default:
//LOCAL
//here we don't check if there's a type this is the case where there must be one when a meta type (post, tax, user) is defined.
//typically the skope will look like post_page_25
if ( false !== $meta_type && false !== $obj_id ) {
$_return = array( "meta_type" => "{$meta_type}" , "type" => "{$type}", "id" => "{$obj_id}" );
}
//GROUP
else if ( false !== $meta_type && !$obj_id ) {
$_return = array( "meta_type" => "{$meta_type}", "type" => "{$type}" );
}
//LOCAL WITH NO GROUP : home ( when home displays "Your latests posts" ) , 404, search, date, post type archive
else if ( false !== $obj_id ) {
$_return = array( "id" => "{$obj_id}" );
}
else {
// don't print the skope error log if not in dev mode
// fixes : https://github.com/presscustomizr/czr-skope/issues/1
if ( defined( 'NIMBLE_DEV' ) && NIMBLE_DEV ) {
// the favicon request break skope building, so skip this case
// see https://github.com/presscustomizr/nimble-builder/issues/658
if ( '/favicon.ico' !== $_SERVER['REQUEST_URI'] ) {
error_log( __FUNCTION__ . ' error when building the local skope, no object_id provided.');
error_log( print_r( $parts, true) );
}
}
}
break;
}
//return the parts array if not a string requested
if ( !$_return_string ) {
return $_return;
}
//don't go further if not an array or empty
if ( !is_array( $_return ) || ( is_array( $_return ) && empty( $_return ) ) ) {
return '';
}
//if a specific part of the ctx is requested, don't concatenate
//return the part if exists
if ( !is_null( $_requesting_wot ) ) {
return isset( $_return[ $_requesting_wot ] ) ? $_return[ $_requesting_wot ] : '';
}
//generate the ctx string from the array of ctx_parts
$_concat = "";
foreach ( $_return as $_key => $_part ) {
if ( empty( $_concat) ) {
$_concat .= $_part;
} else {
$_concat .= '_'. $_part;
}
}
return $_concat;
}
/**
* skope builder from the wp $query
* !!has to be fired after 'template_redirect'
* Used on front ( not customizing preview ? => @todo make sure of this )
* @return array of ctx parts
*/
function skp_get_query_skope() {
//don't call get_queried_object if the $query is not defined yet
global $wp_the_query;
if ( !isset( $wp_the_query ) || empty( $wp_the_query ) ) {
return array();
}
// is it cached already ?
if ( !empty( Flat_Skop_Base()->query_skope ) ) {
return Flat_Skop_Base()->query_skope;
}
$queried_object = get_queried_object();
// error_log( '<GET QUERIED OBJECT>' . gettype( $queried_object ) );
// error_log( print_r( $wp_the_query , true ) );
// error_log( '</GET QUERIED OBJECT>' );
$meta_type = $type = $obj_id = false;
// The queried object is NULL on
// - home when displaying the latest posts
// - date archives
// - 404 page
// - search page
if ( !is_null( $queried_object ) && is_object( $queried_object ) ) {
//post, custom post types, page
if ( isset($queried_object->post_type) ) {
$meta_type = 'post';
$type = $queried_object->post_type;
$obj_id = $queried_object->ID;
}
//taxinomies : tags, categories, custom tax type
if ( isset($queried_object->taxonomy) && isset($queried_object->term_id) ) {
$meta_type = 'tax';
$type = $queried_object->taxonomy;
$obj_id = $queried_object->term_id;
}
}
//author archive page
if ( is_author() ) {
$meta_type = 'user';
$type = 'author';
$obj_id = $wp_the_query->get( 'author' );
}
//SKOPES WITH NO GROUPS
//post type archive object
if ( is_post_type_archive() ) {
$obj_id = 'post_type_archive' . '_'. $wp_the_query->get( 'post_type' );
}
if ( is_404() ) {
$obj_id = '404';
}
if ( is_search() ) {
$obj_id = 'search';
}
if ( is_date() ) {
$obj_id = 'date';
}
if ( skp_is_real_home() ) {
$obj_id = 'home';
// December 2018
// when the home page is a page, the skope now includes the page id, instead of being generic as it was since then : skp__post_page_home
// This has been introduced to facilitate the compatibility of Nimble Builder with multilanguage plugins like polylang
// => Allows user to create a different home page for each languages
//
// To summarize,
// Before dec 2018 :
// - home page is blog page => skope_id = skp___home
// - home page is page => skope_id = skp__post_page_home
//
// After Dec 2018
// - hope page is blog page => skope_id is unchanged = skp__home
// - home page is a page => skope_id is changed to = skp__post_page_{$static_home_page_id}
//
// This means that if Nimble sections, or any other contextualizations had been made on home when 'page' === get_option( 'show_on_front' ),
// for which the corresponding skope_id was skp__post_page_home,
// those settings have to be copied in the skp__post_page_{$static_home_page_id} skope settings
// If we are on the real home page, but displaying a static page then set the static page id as obj_id
if ( !is_home() && 'page' === get_option( 'show_on_front' ) ) {
$home_page_id = get_option( 'page_on_front' );
if ( 0 < $home_page_id ) {
$obj_id = $home_page_id;
}
}
}
// cache now
if ( did_action( 'wp' ) ) {
Flat_Skop_Base()->query_skope = apply_filters( 'skp_get_query_skope' , array( 'meta_type' => $meta_type , 'type' => $type , 'obj_id' => $obj_id ), $queried_object );
}
return Flat_Skop_Base()->query_skope;
}
//@return the skope prefix used both when customizing and on front
function skp_get_skope_id( $level = 'local' ) {
// CACHE THE SKOPE WHEN 'wp' DONE
// the skope id is used when filtering the options, called hundreds of times.
// We get higher performances with a cached value instead of using the skp_get_skope_id() function on each call.
$new_skope_ids = array( 'local' => '_skope_not_set_', 'group' => '_skope_not_set_' );
if ( did_action( 'wp' ) ) {
if ( empty( Flat_Skop_Base()->current_skope_ids ) ) {
$new_skope_ids['local'] = skp_build_skope_id( array( 'skope_string' => skp_get_skope(), 'skope_level' => 'local' ) );
$new_skope_ids['group'] = skp_build_skope_id( array( 'skope_level' => 'group' ) );
Flat_Skop_Base()->current_skope_ids = $new_skope_ids;
$skope_id_to_return = $new_skope_ids[ $level ];
// error_log('<SKOPE ID cached in skp_get_skope_id>');
// error_log( print_r( $new_skope_ids, true ) );
// error_log('</SKOPE ID cached in skp_get_skope_id>');
} else {
$new_skope_ids = Flat_Skop_Base()->current_skope_ids;
$skope_id_to_return = $new_skope_ids[ $level ];
}
} else {
$skope_id_to_return = array_key_exists( $level, $new_skope_ids ) ? $new_skope_ids[ $level ] : '_skope_not_set_';
}
// if ( !(bool)did_action( 'wp' ) ) {
// sek_error_log('ACTION WP NOT FIRED', did_action('wp'));
// }
// Jan 2021, while working on https://github.com/presscustomizr/nimble-builder-pro/issues/81
// when customizing and firing this function during ajax calls, the check for did_action('wp') will return 0.
// => which will lead to skope_id set to '_skope_not_set_'
// in order to prevent this, let's get the skope_id value from the customizer posted value when available.
if ( skp_is_customizing() && '_skope_not_set_' === $skope_id_to_return && 'local' === $level && !empty($_POST['local_skope_id']) ) {
$skope_id_to_return = sanitize_text_field($_POST['local_skope_id']);
}
// Feb 2021 => added for https://github.com/presscustomizr/nimble-builder/issues/478
if ( skp_is_customizing() && '_skope_not_set_' === $skope_id_to_return && 'group' === $level && !empty($_POST['group_skope_id']) ) {
$skope_id_to_return = sanitize_text_field($_POST['group_skope_id']);
}
$skope_id_to_return = apply_filters( 'skp_get_skope_id', $skope_id_to_return, $level );
// At this point, the skope_id should be set
if ( '_skope_not_set_' === $skope_id_to_return ) {
//error_log( __FUNCTION__ . ' error => skope_id not set for level ' . $level );
}
// error_log('$skope_id_to_return => ' . $level . ' ' . $skope_id_to_return );
// error_log( print_r( Flat_Skop_Base()->current_skope_ids , true ) );
return $skope_id_to_return;
}
//@param args = array(
// 'skope_string' => skp_get_skope(),
// 'skope_type' => $skp_type,
// 'skope_level' => 'local'
//)
//@return string
function skp_build_skope_id( $args = array() ) {
$skope_id = '_skope_not_set_';
// normalizes
$args = is_array( $args ) ? $args : array();
$args = wp_parse_args(
$args,
array( 'skope_string' => '', 'skope_type' => '', 'skope_level' => '' )
);
// set params if not provided
$args['skope_level'] = empty( $args['skope_level'] ) ? 'local' : $args['skope_level'];
$args['skope_string'] = ( 'local' == $args['skope_level'] && empty( $args['skope_string'] ) ) ? skp_get_skope() : $args['skope_string'];
$args['skope_type'] = ( 'group' == $args['skope_level'] && empty( $args['skope_type'] ) ) ? skp_get_skope( 'type' ) : $args['skope_type'];
// generate skope_id for two cases : local or group
switch( $args[ 'skope_level'] ) {
case 'local' :
$skope_id = strtolower( NIMBLE_SKOPE_ID_PREFIX . $args[ 'skope_string' ] );
break;
case 'group' :
if ( !empty( $args[ 'skope_type' ] ) ) {
$skope_id = strtolower( NIMBLE_SKOPE_ID_PREFIX . 'all_' . $args[ 'skope_type' ] );
}
break;
}
return $skope_id;
}
/**
* Used when localizing the customizer js params
* Can be a post ( post, pages, CPT) , tax(tag, cats, custom taxs), author, date, search page, 404.
* @param $args : array(
* 'level' => string,
* 'meta_type' => string
* 'long' => bool
* 'is_prefixed' => bool //<= indicated if we should add the "Options for" prefix
* )
* @return string title of the current ctx if exists. If not => false.
*/
function skp_get_skope_title( $args = array() ) {
$defaults = array(
'level' => '',
'meta_type' => null,
'long' => false,
'is_prefixed' => true
);
$args = wp_parse_args( $args, $defaults );
$level = $args['level'];
$meta_type = $args['meta_type'];
$long = $args['long'];
$is_prefixed = $args['is_prefixed'];
$_dyn_type = ( skp_is_customize_preview_frame() && isset( $_POST['dyn_type']) ) ? sanitize_text_field($_POST['dyn_type']) : '';
$type = skp_get_skope('type');
$skope = skp_get_skope();
$title = '';
if( 'local' == $level ) {
$type = skp_get_skope( 'type' );
$title = $is_prefixed ? __( 'Options for', 'text_doma') . ' ' : $title;
if ( skp_skope_has_a_group( $meta_type ) ) {
$_id = skp_get_skope('id');
switch ($meta_type) {
case 'post':
$type_obj = get_post_type_object( $type );
$title .= sprintf( '%1$s "%3$s" (id : %2$s)', strtolower( $type_obj->labels->singular_name ), $_id, get_the_title( $_id ) );
break;
case 'tax':
$type_obj = get_taxonomy( $type );
$term = get_term( $_id, $type );
$title .= sprintf( '%1$s "%3$s" (id : %2$s)', strtolower( $type_obj->labels->singular_name ), $_id, $term->name );
break;
case 'user':
$author = get_userdata( $_id );
$title .= sprintf( '%1$s "%3$s" (id : %2$s)', __('user', 'text_doma'), $_id, $author->user_login );
break;
}
} else if ( ( 'trans' == $_dyn_type || skp_skope_has_no_group( $skope ) ) ) {
if ( is_post_type_archive() ) {
global $wp_the_query;
$title .= sprintf( __( '%1$s archive page', 'text_doma'), $wp_the_query->get( 'post_type' ) );
} else {
$title .= strtolower( $skope );
}
} else {
$title .= __( 'Undefined', 'text_doma');
}
}
if ( 'group' == $level || 'special_group' == $level ) {
$title = $is_prefixed ? __( 'Options for all', 'text_doma') . ' ' : __( 'All' , 'text_doma' ) . ' ';
switch( $meta_type ) {
case 'post' :
$type_obj = get_post_type_object( $type );
$title .= strtolower( $type_obj->labels->name );
break;
case 'tax' :
$type_obj = get_taxonomy( $type );
$title .= strtolower( $type_obj->labels->name );
break;
case 'user' :
$title .= __('users', 'text_doma');
break;
}
}
if ( 'global' == $level ) {
$title = __( 'Sitewide options', 'text_doma');
}
$title = ucfirst( $title );
return skp_trim_text( $title, $long ? 45 : 28, '...');
}
//@return bool
//=> tells if the current skope is part of the ones without group
function skp_skope_has_no_group( $meta_type ) {
return in_array(
$meta_type,
skp_get_no_group_skope_list()
) || is_post_type_archive();
}
//@return bool
//Tells if the current skope has a group level
function skp_skope_has_a_group( $meta_type ) {
return in_array(
$meta_type,
array('post', 'tax', 'user')
);
}
//@return bool
function skp_is_real_home() {
// Warning : when show_on_front is a page, but no page_on_front has been picked yet, is_home() is true
// beware of https://github.com/presscustomizr/nimble-builder/issues/349
return ( is_home() && ( 'posts' == get_option( 'show_on_front' ) || '__nothing__' == get_option( 'show_on_front' ) ) )
|| ( is_home() && 0 == get_option( 'page_on_front' ) && 'page' == get_option( 'show_on_front' ) )//<= this is the case when the user want to display a page on home but did not pick a page yet
|| is_front_page();
}
/**
* Returns a boolean
*/
function skp_is_customizing() {
//checks if is customizing : two contexts, admin and front (preview frame)
global $pagenow;
$_is_ajaxing_from_customizer = isset( $_POST['customized'] ) || isset( $_POST['wp_customize'] );
$is_customizing = false;
// the check on $pagenow does NOT work on multisite install @see https://github.com/presscustomizr/nimble-builder/issues/240
// That's why we also check with other global vars
// @see wp-includes/theme.php, _wp_customize_include()
$is_customize_php_page = ( is_admin() && 'customize.php' == basename( $_SERVER['PHP_SELF'] ) );
$is_customize_admin_page_one = (
$is_customize_php_page
||
( isset( $_REQUEST['wp_customize'] ) && 'on' == sanitize_text_field($_REQUEST['wp_customize']) )
||
( !empty( $_GET['customize_changeset_uuid'] ) || !empty( $_POST['customize_changeset_uuid'] ) )
);
$is_customize_admin_page_two = is_admin() && isset( $pagenow ) && 'customize.php' == $pagenow;
if ( $is_customize_admin_page_one || $is_customize_admin_page_two ) {
$is_customizing = true;
//hu_is_customize_preview_frame() ?
// Note : is_customize_preview() is not able to differentiate when previewing in the customizer and when previewing a changeset draft.
// @todo => change this
} else if ( is_customize_preview() || ( !is_admin() && isset($_REQUEST['customize_messenger_channel']) ) ) {
$is_customizing = true;
// hu_doing_customizer_ajax()
} else if ( $_is_ajaxing_from_customizer && ( defined( 'DOING_AJAX' ) && DOING_AJAX ) ) {
$is_customizing = true;
}
return $is_customizing;
}
/**
* Is the customizer preview panel being displayed ?
* @return boolean
*/
function skp_is_customize_preview_frame() {
return is_customize_preview() || ( !is_admin() && isset($_REQUEST['customize_messenger_channel']) );
}
/**
* @return boolean
*/
function skp_is_previewing_live_changeset() {
return !isset( $_POST['customize_messenger_channel']) && is_customize_preview();
}
?>
@@ -0,0 +1,30 @@
<?php
////////////////////////////////////////////////////////////////
// FLAT SKOPE BASE
if ( !class_exists( 'Flat_Skop_Base' ) ) :
class Flat_Skop_Base {
static $instance;
public $query_skope = array();//<= will cache the query skope ( otherwise called multiple times ) on the first invokation of skp_get_query_skope() IF 'wp' done
public $current_skope_ids = array();// will cache the skope ids on the first invokation of skp_get_skope_id, if 'wp' done
public static function skp_get_instance( $params ) {
if ( !isset( self::$instance ) && !( self::$instance instanceof Flat_Skop_Base ) )
self::$instance = new Flat_Skope_Clean_Final( $params );
return self::$instance;
}
function __construct( $params = array() ) {
$defaults = array(
'base_url_path' => ''//NIMBLE_BASE_URL . '/inc/czr-skope/'
);
$params = wp_parse_args( $params, $defaults );
if ( !defined( 'NIMBLE_SKOPE_BASE_URL' ) ) { define( 'NIMBLE_SKOPE_BASE_URL' , $params['base_url_path'] ); }
if ( !defined( 'NIMBLE_SKOPE_ID_PREFIX' ) ) { define( 'NIMBLE_SKOPE_ID_PREFIX' , "skp__" ); }
$this->skp_register_and_load_control_assets();
$this->skp_export_skope_data_and_schedule_sending_to_panel();
$this->skp_schedule_cleaning_on_object_delete();
}//__construct
}
endif;
?>
@@ -0,0 +1,45 @@
<?php
/////////////////////////////////////////////////////////////////
// PRINT CUSTOMIZER JAVASCRIPT + LOCALIZED DATA
if ( !class_exists( 'Flat_Skop_Register_And_Load_Control_Assets' ) ) :
class Flat_Skop_Register_And_Load_Control_Assets extends Flat_Skop_Base {
// Fired in Flat_Skop_Base::__construct()
public function skp_register_and_load_control_assets() {
add_action( 'customize_controls_enqueue_scripts', array( $this, 'skp_enqueue_controls_js_css' ), 20 );
}
public function skp_enqueue_controls_js_css() {
$_use_unminified = defined('CZR_DEV')
&& true === CZR_DEV
// && false === strpos( dirname( dirname( dirname (__FILE__) ) ) , 'inc/wfc' )
&& file_exists( sprintf( '%s/assets/czr/js/czr-skope-base.js' , dirname( __FILE__ ) ) );
$_prod_script_path = sprintf(
'%1$s/assets/czr/js/%2$s' ,
NIMBLE_SKOPE_BASE_URL,
$_use_unminified ? 'czr-skope-base.js' : 'czr-skope-base.min.js'
);
wp_enqueue_script(
'czr-skope-base',
//dev / debug mode mode?
$_prod_script_path,
array('customize-controls' , 'jquery', 'underscore'),
( defined('WP_DEBUG') && true === WP_DEBUG ) ? time() : wp_get_theme()->version,
$in_footer = true
);
wp_localize_script(
'czr-skope-base',
'FlatSkopeLocalizedData',
array(
'noGroupSkopeList' => skp_get_no_group_skope_list(),
'defaultSkopeModel' => skp_get_default_skope_model(),
'i18n' => array()
)
);
}
}//class
endif;
?>
@@ -0,0 +1,192 @@
<?php
/* ------------------------------------------------------------------------- *
* CUSTOMIZE PREVIEW : export skope data and send skope to the panel
/* ------------------------------------------------------------------------- */
if ( !class_exists( 'Flat_Export_Skope_Data_And_Send_To_Panel' ) ) :
class Flat_Export_Skope_Data_And_Send_To_Panel extends Flat_Skop_Register_And_Load_Control_Assets {
// Fired in Flat_Skop_Base::__construct()
public function skp_export_skope_data_and_schedule_sending_to_panel() {
add_action( 'wp_head', array( $this, 'skp_print_server_skope_data') , 30 );
}
//hook : 'wp_footer'
public function skp_print_server_skope_data() {
if ( !skp_is_customize_preview_frame() )
return;
global $wp_query, $wp_customize;
$_meta_type = skp_get_skope( 'meta_type', true );
// $_czr_scopes = array( );
$_czr_skopes = $this->_skp_get_json_export_ready_skopes();
$_czr_query_data = $this->_skp_get_json_export_ready_query_data();
ob_start();
?>
var _doSend = function() {
// December 2020 : it may happen that the 'sync' event was already sent and that we missed it
// Typically when the site is slow.
// So we need to check if the "sync" event has fired already ( see customize-base.js, ::bind method )
// For more security, let's introduce a marker and attempt to re-sent after a moment if needed
window.czr_skopes_sent = false;
var _send = function() {
wp.customize.preview.send( 'czr-new-skopes-synced', {
czr_new_skopes : _wpCustomizeSettings.czr_new_skopes || [],
czr_stylesheet : _wpCustomizeSettings.czr_stylesheet || '',
isChangesetDirty : _wpCustomizeSettings.isChangesetDirty || false,
skopeGlobalDBOpt : _wpCustomizeSettings.skopeGlobalDBOpt || [],
} );
window.czr_skopes_sent = true;
};
jQuery( function() {
if ( wp.customize.preview.topics && wp.customize.preview.topics.sync && wp.customize.preview.topics.sync.fired() ) {
_send();
} else {
wp.customize.preview.bind( 'sync', function( events ) {
_send();
});
}
setTimeout( function() {
if ( !window.czr_skopes_sent ) {
_send();
}
}, 2500 );
});
};
// recursively try to load jquery every 200ms during 6s ( max 30 times )
var _doWhenCustomizeSettingsReady = function( attempts ) {
attempts = attempts || 0;
if ( typeof undefined !== typeof window._wpCustomizeSettings ) {
_wpCustomizeSettings.czr_new_skopes = <?php echo wp_json_encode( $_czr_skopes ); ?>;
_wpCustomizeSettings.czr_stylesheet = '<?php echo get_stylesheet(); ?>';
_wpCustomizeSettings.czr_query_params = <?php echo wp_json_encode($_czr_query_data); ?>;
_doSend();
} else if ( attempts < 30 ) {
setTimeout( function() {
attempts++;
_doWhenCustomizeSettingsReady( attempts );
}, 20 );
} else {
if ( window.console && window.console.log ) {
console.log('Nimble Builder problem : _wpCustomizeSettings is not defined');
}
}
};
_doWhenCustomizeSettingsReady();
<?php
$script = ob_get_clean();
wp_register_script( 'nb_print_skope_data_js', '');
wp_enqueue_script( 'nb_print_skope_data_js' );
wp_add_inline_script( 'nb_print_skope_data_js', $script );
}
// introduced in october 2019 for https://github.com/presscustomizr/nimble-builder/issues/401
private function _skp_get_json_export_ready_query_data() {
global $wp_query;
global $authordata;
add_filter('get_the_archive_title_prefix', '__return_false');
$archive_title = get_the_archive_title();
remove_filter('get_the_archive_title_prefix', '__return_false');
return [
'is_singular' => $wp_query->is_singular,
'is_archive' => $wp_query->is_archive,
'is_search' => $wp_query->is_search,
'is_attachment' => $wp_query->is_attachment,
'is_front_page' => is_front_page(),
'the_archive_title' => $archive_title,
'the_archive_description' => get_the_archive_description(),
'the_previous_post_link' => is_singular() ? get_previous_post_link( $format = '%link' ) : '',
'the_next_post_link' => is_singular() ? get_next_post_link( $format = '%link' ) : '',
'the_search_query' => get_search_query(),
'the_search_results_nb' => (int) $wp_query->found_posts,
'the_author_id' => isset( $authordata->ID ) ? $authordata->ID : 0,
'post_id' => get_the_ID(),
'query_vars' => $wp_query->query_vars
];
}
/* ------------------------------------------------------------------------- *
* CUSTOMIZE PREVIEW : BUILD SKOPES JSON
/* ------------------------------------------------------------------------- */
//generates the array of available scopes for a given context
//ex for a single post tagged #tag1 and #tag2 and categroized #cat1 :
//global
//all posts
//local
//posts tagged #tag1
//posts tagged #tag2
//posts categorized #cat1
//@return array()
//
//skp_get_skope_title() takes the following default args
//array(
// 'level' => '',
// 'meta_type' => null,
// 'long' => false,
// 'is_prefixed' => true
//)
private function _skp_get_json_export_ready_skopes() {
$skopes = array();
$_meta_type = skp_get_skope( 'meta_type', true );
//default properties of the scope object
$defaults = skp_get_default_skope_model();
//global and local and always sent
$skopes[] = wp_parse_args(
array(
'title' => skp_get_skope_title( array( 'level' => 'global' ) ),
'long_title' => skp_get_skope_title( array( 'level' => 'global', 'meta_type' => null, 'long' => true ) ),
'ctx_title' => skp_get_skope_title( array( 'level' => 'global', 'meta_type' => null, 'long' => true, 'is_prefixed' => false ) ),
'skope' => 'global',
'level' => '_all_'
),
$defaults
);
//SPECIAL GROUPS
//@todo
//GROUP
//Do we have a group ? => if yes, then there must be a meta type
if ( skp_get_skope('meta_type') ) {
$skopes[] = wp_parse_args(
array(
'title' => skp_get_skope_title( array( 'level' => 'group', 'meta_type' => $_meta_type ) ),
'long_title' => skp_get_skope_title( array( 'level' => 'group', 'meta_type' => $_meta_type, 'long' => true ) ),
'ctx_title' => skp_get_skope_title( array( 'level' => 'group', 'meta_type' => $_meta_type, 'long' => true, 'is_prefixed' => false ) ),
'skope' => 'group',
'level' => 'all_' . skp_get_skope('type'),
'skope_id' => skp_get_skope_id( 'group' )
),
$defaults
);
}
//LOCAL
$skopes[] = wp_parse_args(
array(
'title' => skp_get_skope_title( array( 'level' => 'local', 'meta_type' => $_meta_type ) ),
'long_title' => skp_get_skope_title( array( 'level' => 'local', 'meta_type' => $_meta_type, 'long' => true ) ),
'ctx_title' => skp_get_skope_title( array( 'level' => 'local', 'meta_type' => $_meta_type, 'long' => true, 'is_prefixed' => false ) ),
'skope' => 'local',
'level' => skp_get_skope(),
'obj_id' => skp_get_skope('id'),
'skope_id' => skp_get_skope_id( 'local' )
),
$defaults
);
return apply_filters( 'skp_json_export_ready_skopes', $skopes );
}
}//class
endif;
?>
@@ -0,0 +1,105 @@
<?php
if ( !class_exists( 'Flat_Skope_Clean_Final' ) ) :
final class Flat_Skope_Clean_Final extends Flat_Export_Skope_Data_And_Send_To_Panel {
// Fired in Flat_Skop_Base::__construct()
public function skp_schedule_cleaning_on_object_delete() {
add_action( 'delete_post', array( $this, 'skp_clean_skopified_posts' ) );
add_action( 'delete_term_taxonomy', array( $this, 'skp_clean_skopified_taxonomies' ) );
add_action( 'delete_user', array( $this, 'skp_clean_skopified_users' ) );
}
// Clean any associated skope post for all public post types : post, page, public cpt
// 'delete_post' Fires immediately before a post is deleted from the database.
// @see wp-includes/post.php
// don't have to return anything
public function skp_clean_skopified_posts( $postid ) {
$deletion_candidate = get_post( $postid );
if ( !$deletion_candidate || !is_object( $deletion_candidate ) )
return;
// Stop here if the post type is not considered "viewable".
// For built-in post types such as posts and pages, the 'public' value will be evaluated.
// For all others, the 'publicly_queryable' value will be used.
// For example, the 'revision' post type, which is purely internal and not skopable, won't pass this test.
if ( !is_post_type_viewable( $deletion_candidate->post_type ) )
return;
// Force the skope parts normally retrieved with skp_get_query_skope()
$skope_string = skp_get_skope( null, true, array(
'meta_type' => 'post',
'type' => $deletion_candidate->post_type,
'obj_id' => $postid
) );
// build a skope_id with the normalized function
$skope_id = skp_build_skope_id( array( 'skope_string' => $skope_string, 'skope_level' => 'local' ) );
// fetch the skope post id which, if exists, is set as a theme mod
$skope_post_id_candidate = get_theme_mod( $skope_id );
if ( $skope_post_id_candidate > 0 && get_post( $skope_post_id_candidate ) ) {
// permanently delete the skope post from db
wp_delete_post( $skope_post_id_candidate );
// remove the theme_mod
remove_theme_mod( $skope_id );
}
}
// 'delete_term_taxonomy' Fires immediately before a term taxonomy ID is deleted.
public function skp_clean_skopified_taxonomies( $term_id ) {
$deletion_candidate = get_term( $term_id );
if ( !$deletion_candidate || !is_object( $deletion_candidate ) )
return;
//error_log( print_r( $deletion_candidate, true ) );
// Force the skope parts normally retrieved with skp_get_query_skope()
$skope_string = skp_get_skope( null, true, array(
'meta_type' => 'tax',
'type' => $deletion_candidate->taxonomy,
'obj_id' => $term_id
) );
// build a skope_id with the normalized function
$skope_id = skp_build_skope_id( array( 'skope_string' => $skope_string, 'skope_level' => 'local' ) );
// fetch the skope post id which, if exists, is set as a theme mod
$skope_post_id_candidate = get_theme_mod( $skope_id );
if ( $skope_post_id_candidate > 0 && get_post( $skope_post_id_candidate ) ) {
// permanently delete the skope post from db
wp_delete_post( $skope_post_id_candidate );
// remove the theme_mod
remove_theme_mod( $skope_id );
//error_log( 'SUCCESSFULLY REMOVED SKOPE POST ID ' . $skope_post_id_candidate . ' AND THEME MOD ' . $skope_id );
}
}
// 'delete_user' Fires immediately before a user is deleted from the database.
public function skp_clean_skopified_users( $user_id ) {
// Force the skope parts normally retrieved with skp_get_query_skope()
$skope_string = skp_get_skope( null, true, array(
'meta_type' => 'user',
'type' => 'author',
'obj_id' => $user_id
) );
// build a skope_id with the normalized function
$skope_id = skp_build_skope_id( array( 'skope_string' => $skope_string, 'skope_level' => 'local' ) );
// fetch the skope post id which, if exists, is set as a theme mod
$skope_post_id_candidate = get_theme_mod( $skope_id );
if ( $skope_post_id_candidate > 0 && get_post( $skope_post_id_candidate ) ) {
// permanently delete the skope post from db
wp_delete_post( $skope_post_id_candidate );
// remove the theme_mod
remove_theme_mod( $skope_id );
//error_log( 'SUCCESSFULLY REMOVED SKOPE POST ID ' . $skope_post_id_candidate . ' AND THEME MOD ' . $skope_id );
}
}
}//class
endif;
?>
@@ -0,0 +1,272 @@
module.exports = {
"env": {
"browser": true
},
"extends": "eslint:recommended",
"rules": {
"accessor-pairs": "error",
"array-bracket-newline": "off",
"array-bracket-spacing": "off",
"array-callback-return": "off",
"array-element-newline": "off",
"arrow-body-style": "error",
"arrow-parens": "error",
"arrow-spacing": "error",
"block-scoped-var": "off",
"block-spacing": "off",
"brace-style": "off",
"callback-return": "error",
"camelcase": "off",
"capitalized-comments": "off",
"class-methods-use-this": "error",
"comma-dangle": "off",
"comma-spacing": "off",
"comma-style": [
"error",
"last"
],
"complexity": "off",
"computed-property-spacing": "off",
"consistent-return": "off",
"consistent-this": "off",
"curly": "off",
"default-case": "off",
"dot-location": "off",
"dot-notation": "off",
"eol-last": "off",
"eqeqeq": "off",
"for-direction": "off",
"func-call-spacing": "off",
"func-name-matching": "error",
"func-names": [
"error",
"never"
],
"func-style": "off",
"function-paren-newline": "off",
"generator-star-spacing": "error",
"getter-return": "error",
"global-require": "off",
"guard-for-in": "off",
"handle-callback-err": "error",
"id-blacklist": "error",
"id-length": "off",
"id-match": "error",
"implicit-arrow-linebreak": "error",
"indent": "off",
"indent-legacy": "off",
"init-declarations": "off",
"jsx-quotes": "error",
"key-spacing": "off",
"keyword-spacing": "off",
"line-comment-position": "off",
"linebreak-style": "off",
"lines-around-comment": "off",
"lines-around-directive": "off",
"lines-between-class-members": "error",
"max-depth": "off",
"max-len": "off",
"max-lines": "off",
"max-nested-callbacks": "error",
"max-params": "off",
"max-statements": "off",
"max-statements-per-line": "off",
"multiline-comment-style": "off",
"multiline-ternary": "off",
"new-parens": "off",
"newline-after-var": "off",
"newline-before-return": "off",
"newline-per-chained-call": "off",
"no-alert": "error",
"no-array-constructor": "error",
"no-await-in-loop": "error",
"no-bitwise": "off",
"no-buffer-constructor": "error",
"no-caller": "error",
"no-catch-shadow": "off",
"no-confusing-arrow": "error",
"no-continue": "off",
"no-div-regex": "error",
"no-duplicate-imports": "error",
"no-else-return": "off",
"no-empty-function": "off",
"no-eq-null": "off",
"no-eval": "error",
"no-extend-native": "off",
"no-extra-bind": "error",
"no-extra-label": "error",
"no-extra-parens": "off",
"no-floating-decimal": "off",
"no-implicit-coercion": [
"error",
{
"boolean": false,
"number": false,
"string": false
}
],
"no-implicit-globals": "off",
"no-implied-eval": "error",
"no-inline-comments": "off",
"no-inner-declarations": [
"error",
"functions"
],
"no-invalid-this": "off",
"no-iterator": "error",
"no-label-var": "off",
"no-labels": "off",
"no-lone-blocks": "off",
"no-lonely-if": "off",
"no-loop-func": "error",
"no-magic-numbers": "off",
"no-mixed-operators": "off",
"no-mixed-requires": "error",
"no-multi-assign": "off",
"no-multi-spaces": "off",
"no-multi-str": "error",
"no-multiple-empty-lines": "off",
"no-native-reassign": "error",
"no-negated-condition": "off",
"no-negated-in-lhs": "error",
"no-nested-ternary": "off",
"no-new": "off",
"no-new-func": "error",
"no-new-object": "error",
"no-new-require": "error",
"no-new-wrappers": "error",
"no-octal-escape": "error",
"no-param-reassign": "off",
"no-path-concat": "error",
"no-plusplus": "off",
"no-process-env": "error",
"no-process-exit": "error",
"no-proto": "error",
"no-prototype-builtins": "off",
"no-restricted-globals": "error",
"no-restricted-imports": "error",
"no-restricted-modules": "error",
"no-restricted-properties": "error",
"no-restricted-syntax": "error",
"no-return-assign": "off",
"no-return-await": "error",
"no-script-url": "error",
"no-self-assign": [
"error",
{
"props": false
}
],
"no-self-compare": "off",
"no-sequences": "off",
"no-shadow": "off",
"no-shadow-restricted-names": "error",
"no-spaced-func": "off",
"no-sync": "error",
"no-tabs": "off",
"no-template-curly-in-string": "error",
"no-ternary": "off",
"no-throw-literal": "off",
"no-undef-init": "error",
"no-undefined": "error",
"no-underscore-dangle": "off",
"no-unmodified-loop-condition": "error",
"no-unneeded-ternary": [
"error",
{
"defaultAssignment": true
}
],
"no-unused-expressions": "off",
"no-use-before-define": "off",
"no-useless-call": "off",
"no-useless-computed-key": "error",
"no-useless-concat": "off",
"no-useless-constructor": "error",
"no-useless-rename": "error",
"no-useless-return": "off",
"no-var": "off",
"no-void": "off",
"no-warning-comments": "off",
"no-whitespace-before-property": "error",
"no-with": "error",
"nonblock-statement-body-position": [
"error",
"any"
],
"object-curly-newline": "off",
"object-curly-spacing": "off",
"object-property-newline": "off",
"object-shorthand": "off",
"one-var": "off",
"one-var-declaration-per-line": "off",
"operator-assignment": "off",
"operator-linebreak": [
"error",
"after"
],
"padded-blocks": "off",
"padding-line-between-statements": "error",
"prefer-arrow-callback": "off",
"prefer-const": "error",
"prefer-destructuring": "off",
"prefer-numeric-literals": "error",
"prefer-promise-reject-errors": "error",
"prefer-reflect": "off",
"prefer-rest-params": "off",
"prefer-spread": "off",
"prefer-template": "off",
"quote-props": "off",
"quotes": "off",
"radix": [
"error",
"always"
],
"require-await": "error",
"require-jsdoc": "off",
"rest-spread-spacing": "error",
"semi": "off",
"semi-spacing": "off",
"semi-style": [
"error",
"last"
],
"sort-imports": "error",
"sort-keys": "off",
"sort-vars": "off",
"space-before-blocks": "off",
"space-before-function-paren": "off",
"space-in-parens": "off",
"space-infix-ops": "off",
"space-unary-ops": "off",
"spaced-comment": "off",
"strict": "off",
"switch-colon-spacing": "off",
"symbol-description": "error",
"template-curly-spacing": "error",
"template-tag-spacing": "error",
"unicode-bom": [
"error",
"never"
],
"valid-jsdoc": "off",
"valid-typeof": [
"error",
{
"requireStringLiterals": false
}
],
"vars-on-top": "off",
"wrap-iife": "off",
"wrap-regex": "off",
"yield-star-spacing": "error",
"yoda": "off"
},
"globals": {
"wp": true,
"jQuery": true,
"_":true,
'FlatSkopeLocalizedData' : true,
'serverControlParams' : true
}
};
@@ -0,0 +1,136 @@
var CZRFlatSkopeModuleMths = CZRFlatSkopeModuleMths || {};
( function ( api, $, _ ) {
$.extend( CZRFlatSkopeModuleMths, {
// fired in module::initialize
scheduleSkopeReactions : function() {
var module = this;
// @params looks like :
// {
// newSkopes : newSkopes,
// previousSkopes : previousSkopes
// }
api.bind( 'active-skopes-updated', function( params ) {
console.log( 'active-skopes-updated', params, module.SKOPE_LEVEL );
params = _.extend( { newSkopes : {}, previousSkopes : {} }, params );
if ( ! _.has( params.newSkopes, module.SKOPE_LEVEL ) ) {
api.errorLog( 'active-skopes-updated => ' + module.SKOPE_LEVEL + ' was not found in the skope list' );
return;
} else {
module.isReady.then( function() {
// Always update the local skope-id in the pre-item
if ( module.preItem && ! _.isEmpty( module.preItem.czr_Input ) && module.preItem.czr_Input.has('skope-id') ) {
module.preItem.czr_Input( 'skope-id' )( params.newSkopes[ module.SKOPE_LEVEL ] );
}
// Print the contextual items only
//module.refreshContextualItems();
// Display the parent control when relevant
module.control.active( '_skope_not_set_' != params.newSkopes[ module.SKOPE_LEVEL ] );
});
// Print a bottom notification in all controls wrapper
//module.printSkopeInfoInControls();
}
});
},
//This method react to the skope change
// => reinstantiates all items based on the current collection
// refreshContextualItems : function() {
// var module = this;
// //Remove item views and instances
// module.czr_Item.each( function( _itm ) {
// if ( ! _.isEmpty( _itm.container ) && 0 < _itm.container.length ) {
// $.when( _itm.container.remove() ).done( function() {
// //Remove item instances
// module.czr_Item.remove( _itm.id );
// });
// } else {
// //Remove item instances
// module.czr_Item.remove( _itm.id );
// }
// });
// // Reset the item collection
// // => the collection listeners will be setup after populate, on 'items-collection-populated'
// var _collection_ = $.extend( true, [], module.itemCollection() );
// // reset the collection
// module.itemCollection = new api.Value( [] );
// module.populateSavedItemCollection( _collection_ );
// },
// // invoked when module.ready() and api.czr_activeSkopes updated
// printSkopeInfoInControls : function() {
// var module = this,
// _css_class_ = 'skp-note-for-' + module.SKOPE_LEVEL;
// //This = _ctrl_
// var mayBePrintAndSetupCtrlBottomNote = function() {
// var _ctrl_ = this,
// _skope_title_ = FlatSkopeLocalizedData.i18n[ 'this page' ];
// if ( 0 < _ctrl_.container.find( '.' + _css_class_ ).length )
// return;
// var currentSkopeObj = _.findWhere( api.czr_currentSkopesCollection(), { skope : module.SKOPE_LEVEL } );
// if ( ! _.isEmpty( currentSkopeObj ) ) {
// _skope_title_ = currentSkopeObj.ctx_title;
// }
// _ctrl_.container.append(
// $('<div>', {
// class: [ _css_class_ , 'skp-ctrl-bottom-note', 'czr-notice' ].join(' '),
// html : [
// FlatSkopeLocalizedData.i18n[ 'Can be customized for' ],
// '<span class="skp-focus-link"><u>' + _skope_title_ + '</u><span>'
// ].join(' ')
// })
// );
// api.CZR_Helpers.setupDOMListeners(
// [//toggles remove view alert
// {
// trigger : 'click keydown',
// selector : ['.' + _css_class_, '.skp-focus-link'].join(' '),
// name : _css_class_,
// //data = {
// // dom_el,
// // dom_event,
// // event,
// // model
// // }
// actions : function( data ) {
// data.dom_event.preventDefault();
// module.control.focus();
// }
// }//actions to execute
// ],
// { model: {}, dom_el:_ctrl_.container },//model + dom scope
// null //instance where to look for the cb methods
// );//api.CZR_Helpers.setupDOMListeners
// };//mayBePrintAndSetupCtrlBottomNote
// _.each( api.czr_skopeBase.getSkopableSettings(), function( settingData ) {
// //console.log('settingDATA', settingData );
// api.control.when( settingData.apiCtrlId, function( _ctrl_ ) {
// _ctrl_.deferred.embedded.then( function() {
// $.when( _ctrl_.container.find('.' + _css_class_ ).remove() ).done( function() {
// if ( module.weHaveASkope() ) {
// mayBePrintAndSetupCtrlBottomNote.call( _ctrl_ );
// }
// });
// });
// } );
// });
// }//printSkopeInfoInControls
});//extend
})( wp.customize , jQuery, _ );
@@ -0,0 +1,132 @@
//@global serverControlParams
var CZRSkopeBaseMths = CZRSkopeBaseMths || {};
(function ( api, $, _ ) {
$.extend( CZRSkopeBaseMths, {
initialize: function() {
var self = this;
///////////////////// DEFINITIONS /////////////////////
//Store the state of the first skope collection state
api.czr_initialSkopeCollectionPopulated = $.Deferred();
//the czr_skopeCollection stores all skopes instantiated by the user
//this collection is not updated directly
//=> it's updated on skope() instance change
api.czr_skopeCollection = new api.Value([]);//all available skope, including the current skopes
//the current skopes collection get updated each time the 'czr-new-skopes-synced' event is triggered on the api by the preview
api.czr_currentSkopesCollection = new api.Value([]);
//the currently active skopes
api.czr_activeSkopes = new api.Value( { local : '', group : ''} );
///////////////////// SKOPE COLLECTIONS SYNCHRONISATION AND LISTENERS /////////////////////
//LISTEN TO SKOPE SYNC => UPDATE SKOPE COLLECTION ON START AND ON EACH REFRESH
//the sent data look like :
//{
// czr_new_skopes : _wpCustomizeSettings.czr_new_skopes || [],
// isChangesetDirty : boolean
// }
api.bind( 'ready' , function() {
api.previewer.bind( 'czr-new-skopes-synced', function( skope_server_data ) {
if ( serverControlParams.isDevMode ) {
api.infoLog( 'API SKOPE SYNCED', skope_server_data );
}
// set the currently active stylesheet
if ( ! _.has( skope_server_data, 'czr_stylesheet') ) {
api.errorLog( "On 'czr-new-skopes-synced' : missing stylesheet in the server data" );
return;
}
api.czr_skopeBase.stylesheet = api.czr_skopeBase.stylesheet || new api.Value( api.settings.theme.stylesheet );
api.czr_skopeBase.stylesheet( skope_server_data.czr_stylesheet );
//api.consoleLog('czr-skopes-ready DATA', skope_server_data );
var preview = this,
previousSkopeCollection = api.czr_currentSkopesCollection();
//initialize skopes with the server sent skope_server_data
//if skope has not been initialized yet and the server sent wrong skope_server_data, then reject the skope ready promise()
if ( ! _.has( skope_server_data, 'czr_new_skopes') ) {
api.errorLog( "On 'czr-new-skopes-synced' : missing skopes in the server data" );
return;
}
// If no "group" skope has been sent, check if we should have one
// array( 'home', 'search', '404', 'date' ) <= have no group
if ( _.isEmpty( _.findWhere( skope_server_data.czr_new_skopes, { skope : 'group' } ) ) ){
var _local_ = _.findWhere( skope_server_data.czr_new_skopes, { skope : 'local' } );
if ( ! _.isEmpty( _local_ ) && ! _.contains( FlatSkopeLocalizedData.noGroupSkopeList, _local_.level ) ) {
api.errorLog( 'No group level skope sent while there should be one' );
}
}
//1) Updated the collection with normalized skopes => prepareSkopeForAPI + api.czr_currentSkopesCollection( collection )
//2) When the api.czr_currentSkopesCollection() Value is set => instantiates the missing skope
//3) Set the skope layout view when the skope embedded promise is resolved
if ( serverControlParams.isDevMode ) {
api.czr_skopeBase.updateSkopeCollection( skope_server_data.czr_new_skopes , preview.channel() );
} else {
try {
api.czr_skopeBase.updateSkopeCollection( skope_server_data.czr_new_skopes , preview.channel() );
} catch ( er ) {
console.log('UPDATE SKOPE COLLECTION ERROR', er);
return;
}
}
//@return void()
// => refresh skope notice below the skope switcher title
// => refresh bottom skope infos in the preview
// var _refreshSkopeInfosNotices = function() {
// console.log('REFRESH SKOPE TITLE IF NEEDED ?');
// //WRITE THE CURRENT SKOPE TITLE
// //self._writeCurrentSkopeTitle();
// };
//Always wait for the initial collection to be populated
api.czr_initialSkopeCollectionPopulated.then( function() {
//console.log('INITIAL SKOPE COLLECTION POPULATED');
if ( ! _.has( skope_server_data, 'czr_new_skopes' ) || _.isEmpty( skope_server_data.czr_new_skopes ) ) {
api.errorLog( 'Missing skope data after refresh', skope_server_data );
}
// set the local and group skope id
api.czr_activeSkopes( {
'local' : self.getSkopeProperty( 'skope_id', 'local' ),
'group' : self.getSkopeProperty( 'skope_id', 'group' )
});
// if ( ! _.isEmpty( previousSkopeCollection ) ) { //Rewrite the title when the local skope has changed
// var _prevLoc = _.findWhere( previousSkopeCollection , { skope : 'local' } ).opt_name,
// _newLoc =_.findWhere( skope_server_data.czr_new_skopes, { skope : 'local' } ).opt_name;
// if ( _newLoc !== _prevLoc ) {
// //REFRESH SKOPE INFOS IN TITLE AND PREVIEW FRAME
// _refreshSkopeInfosNotices();
// }
// }
});
});//api.previewer.bind
});//api.bind( 'ready'
//CURRENT SKOPE COLLECTION LISTENER
//The skope collection is set on 'czr-new-skopes-synced' triggered by the preview
//setup the callbacks of the skope collection update
//on init and on preview change : the collection of skopes is populated with new skopes
//=> instanciate the relevant skope object + render them
api.czr_currentSkopesCollection.bind( function( to, from ) {
return self.currentSkopesCollectionReact( to, from );
}, { deferred : true });
///////////////////// VARIOUS /////////////////////
//DECLARE THE LIST OF CONTROL TYPES FOR WHICH THE VIEW IS REFRESHED ON CHANGE
//self.refreshedControls = [ 'czr_cropped_image'];// [ 'czr_cropped_image', 'czr_multi_module', 'czr_module' ];
api.trigger( 'czr_skopeBase_initialized' );
}//initialize
});//$.extend()
})( wp.customize , jQuery, _);
@@ -0,0 +1,49 @@
//@global serverControlParams
var CZRSkopeBaseMths = CZRSkopeBaseMths || {};
( function ( api, $, _ ) {
$.extend( CZRSkopeBaseMths, {
//////////////////////////////////////////////////////////
/// <SKOPE HELPERSS>
// @return string
getSkopeProperty : function( what, skope_level ) {
what = what || 'skope_id';
skope_level = skope_level || 'local';
var _skope_data = _.findWhere( api.czr_currentSkopesCollection(), { skope : skope_level });
if ( _.isEmpty( _skope_data ) ){
// display an error message if local skope not found. Should always be defined.
if ( 'local' == skope_level ) {
api.errorLog( "getSkopeProperty => local skope missing, returning not_set" );
}
return "_skope_not_set_";//for example when trying to get a group skope_id in a context where there can't be a group skope like home or search.
} else if ( !_.has( _skope_data, what ) ) {
api.errorLog( "getSkopeProperty => " + what + " property does not exist" );
return "_skope_not_set_";
} else {
return _skope_data[ what ];
}
},
//@return string
firstToUpperCase : function( str ) {
return ! _.isString( str ) ? '' : str.substr(0, 1).toUpperCase() + str.substr(1);
}
// //@return string
// buildSkopeLink : function( skope_id ) {
// if ( ! api.czr_skope.has( skope_id ) ) {
// api.errorLog( 'buildSkopeLink : the requested skope id is not registered : ' + skope_id );
// return '';
// }
// var _link_title = [ serverControlParams.i18n.skope['Switch to scope'], api.czr_skope( skope_id )().title ].join(' : ');
// return [
// '<span class="czr-skope-switch" title=" ' + _link_title + '" data-skope-id="' + skope_id + '">',
// api.czr_skope( skope_id )().title,
// '</span>'
// ].join( '' );
// },
});//$.extend
})( wp.customize , jQuery, _ );
@@ -0,0 +1,132 @@
//@global serverControlParams
var CZRSkopeBaseMths = CZRSkopeBaseMths || {};
(function ( api, $, _ ) {
$.extend( CZRSkopeBaseMths, {
//Fired on 'czr-new-skopes-synced' triggered by the preview, each time the preview is refreshed.
//On a Save Action, api.czr_savedDirties has been populated =>
// 1) check if the server sends the same saved values
// 2) update the skope db properties with the latests saved ones
//
//A skope candidate is structured this way :
//{
// id:""
// long_title:"Site wide options"
// obj_id:""
// skope:"global"
// title:"Site wide options"
//}
//@see api_overrides
updateSkopeCollection : function( sent_collection ) {
var self = this,
_api_ready_collection = [];
//normalize each sent skopes
_.each( sent_collection, function( _skope ) {
var skope_candidate = $.extend( true, {}, _skope );//deep clone to avoid any shared references
_api_ready_collection.push( self.prepareSkopeForAPI( skope_candidate ) );
});
//set the new collection of current skopes
//=> this will instantiate the not instantiated skopes
api.czr_currentSkopesCollection( _api_ready_collection );
// set the group skope id
//console.log( "SKOPE COLLECTION UPDATED", api.czr_currentSkopesCollection() );
},
//@param skope_candidate
////A skope candidate is structured this way :
//{
// id:""
// long_title:"Site wide options"
// obj_id:""
// skope:"global"
// title:"Site wide options"
//}
prepareSkopeForAPI : function( skope_candidate ) {
if ( ! _.isObject( skope_candidate ) ) {
throw new Error('prepareSkopeForAPI : a skope must be an object to be API ready');
}
var api_ready_skope = skope_candidate;
_.each( FlatSkopeLocalizedData.defaultSkopeModel , function( _value, _key ) {
var _candidate_val = skope_candidate[_key];
switch( _key ) {
case 'title' :
if ( ! _.isString( _candidate_val ) ) {
throw new Error('prepareSkopeForAPI : a skope title property must a string');
}
api_ready_skope[_key] = _candidate_val;
break;
case 'long_title' :
if ( ! _.isString( _candidate_val ) ) {
throw new Error('prepareSkopeForAPI : a skope title property must a string');
}
api_ready_skope[_key] = _candidate_val;
break;
case 'ctx_title' :
if ( ! _.isString( _candidate_val ) ) {
throw new Error('prepareSkopeForAPI : a skope context title property must a string');
}
api_ready_skope[_key] = _candidate_val;
break;
case 'skope' :
if ( ! _.isString( _candidate_val ) || _.isEmpty( _candidate_val ) ) {
throw new Error('prepareSkopeForAPI : a skope "skope" property must a string not empty');
}
api_ready_skope[_key] = _candidate_val;
break;
case 'obj_id' :
if ( ! _.isString( _candidate_val ) ) {
throw new Error('prepareSkopeForAPI : invalid "obj_id" for skope ' + _candidate_val.skope );
}
api_ready_skope[_key] = _candidate_val;
break;
case 'skope_id' :
if ( ! _.isString( _candidate_val ) ) {
throw new Error('prepareSkopeForAPI : invalid "skope_key" for skope ' + _candidate_val.skope );
}
api_ready_skope[_key] = _candidate_val;
break;
case 'values' :
// if ( ! _.isString( _candidate_val ) ) {
// throw new Error('prepareSkopeForAPI : invalid "values" for skope ' + _candidate_val.skope );
// }
api_ready_skope[_key] = _candidate_val;
break;
default :
api_ready_skope[_key] = _candidate_val;
break;
}//switch
});
//Finally, generate the id and the title
api_ready_skope.id = api_ready_skope.skope + '_' + api_ready_skope.skope_id;
if ( ! _.isString( api_ready_skope.id ) || _.isEmpty( api_ready_skope.id ) ) {
throw new Error('prepareSkopeForAPI : a skope id must a string not empty');
}
if ( ! _.isString( api_ready_skope.title ) || _.isEmpty( api_ready_skope.title ) ) {
api_ready_skope.title = api_ready_skope.id;
api_ready_skope.long_title = api_ready_skope.id;
}
return api_ready_skope;
},
//cb of api.czr_currentSkopesCollection.callbacks
//fired in initialize
currentSkopesCollectionReact : function( to, from ) {
var dfd = $.Deferred();
//ON INITIAL COLLECTION POPULATE, RESOLVE THE DEFERRED STATE
//=> this way we can defer earlier actions.
//For example when autofocus is requested, the section might be expanded before the initial skope collection is sent from the preview.
if ( _.isEmpty( from ) && ! _.isEmpty( to ) ) {
api.czr_initialSkopeCollectionPopulated.resolve();
}
return dfd.resolve( 'changed' ).promise();
}//listenToSkopeCollection()
});//$.extend()
})( wp.customize , jQuery, _);
@@ -0,0 +1,13 @@
//@global serverControlParams
var CZRSkopeBaseMths = CZRSkopeBaseMths || {};
(function ( api, $ ) {
// Skope
$.extend( CZRSkopeBaseMths, api.Events );
var CZR_SkopeBase = api.Class.extend( CZRSkopeBaseMths );
// Schedule skope instantiation on api ready
// api.bind( 'ready' , function() {
// api.czr_skopeBase = new api.CZR_SkopeBase();
// });
api.czr_skopeBase = new CZR_SkopeBase();
})( wp.customize, jQuery );
@@ -0,0 +1,323 @@
//@global serverControlParams
var CZRSkopeBaseMths = CZRSkopeBaseMths || {};
(function ( api, $, _ ) {
$.extend( CZRSkopeBaseMths, {
initialize: function() {
var self = this;
///////////////////// DEFINITIONS /////////////////////
//Store the state of the first skope collection state
api.czr_initialSkopeCollectionPopulated = $.Deferred();
//the czr_skopeCollection stores all skopes instantiated by the user
//this collection is not updated directly
//=> it's updated on skope() instance change
api.czr_skopeCollection = new api.Value([]);//all available skope, including the current skopes
//the current skopes collection get updated each time the 'czr-new-skopes-synced' event is triggered on the api by the preview
api.czr_currentSkopesCollection = new api.Value([]);
//the currently active skopes
api.czr_activeSkopes = new api.Value( { local : '', group : ''} );
///////////////////// SKOPE COLLECTIONS SYNCHRONISATION AND LISTENERS /////////////////////
//LISTEN TO SKOPE SYNC => UPDATE SKOPE COLLECTION ON START AND ON EACH REFRESH
//the sent data look like :
//{
// czr_new_skopes : _wpCustomizeSettings.czr_new_skopes || [],
// isChangesetDirty : boolean
// }
api.bind( 'ready' , function() {
api.previewer.bind( 'czr-new-skopes-synced', function( skope_server_data ) {
if ( serverControlParams.isDevMode ) {
api.infoLog( 'API SKOPE SYNCED', skope_server_data );
}
// set the currently active stylesheet
if ( ! _.has( skope_server_data, 'czr_stylesheet') ) {
api.errorLog( "On 'czr-new-skopes-synced' : missing stylesheet in the server data" );
return;
}
api.czr_skopeBase.stylesheet = api.czr_skopeBase.stylesheet || new api.Value( api.settings.theme.stylesheet );
api.czr_skopeBase.stylesheet( skope_server_data.czr_stylesheet );
//api.consoleLog('czr-skopes-ready DATA', skope_server_data );
var preview = this,
previousSkopeCollection = api.czr_currentSkopesCollection();
//initialize skopes with the server sent skope_server_data
//if skope has not been initialized yet and the server sent wrong skope_server_data, then reject the skope ready promise()
if ( ! _.has( skope_server_data, 'czr_new_skopes') ) {
api.errorLog( "On 'czr-new-skopes-synced' : missing skopes in the server data" );
return;
}
// If no "group" skope has been sent, check if we should have one
// array( 'home', 'search', '404', 'date' ) <= have no group
if ( _.isEmpty( _.findWhere( skope_server_data.czr_new_skopes, { skope : 'group' } ) ) ){
var _local_ = _.findWhere( skope_server_data.czr_new_skopes, { skope : 'local' } );
if ( ! _.isEmpty( _local_ ) && ! _.contains( FlatSkopeLocalizedData.noGroupSkopeList, _local_.level ) ) {
api.errorLog( 'No group level skope sent while there should be one' );
}
}
//1) Updated the collection with normalized skopes => prepareSkopeForAPI + api.czr_currentSkopesCollection( collection )
//2) When the api.czr_currentSkopesCollection() Value is set => instantiates the missing skope
//3) Set the skope layout view when the skope embedded promise is resolved
if ( serverControlParams.isDevMode ) {
api.czr_skopeBase.updateSkopeCollection( skope_server_data.czr_new_skopes , preview.channel() );
} else {
try {
api.czr_skopeBase.updateSkopeCollection( skope_server_data.czr_new_skopes , preview.channel() );
} catch ( er ) {
console.log('UPDATE SKOPE COLLECTION ERROR', er);
return;
}
}
//@return void()
// => refresh skope notice below the skope switcher title
// => refresh bottom skope infos in the preview
// var _refreshSkopeInfosNotices = function() {
// console.log('REFRESH SKOPE TITLE IF NEEDED ?');
// //WRITE THE CURRENT SKOPE TITLE
// //self._writeCurrentSkopeTitle();
// };
//Always wait for the initial collection to be populated
api.czr_initialSkopeCollectionPopulated.then( function() {
//console.log('INITIAL SKOPE COLLECTION POPULATED');
if ( ! _.has( skope_server_data, 'czr_new_skopes' ) || _.isEmpty( skope_server_data.czr_new_skopes ) ) {
api.errorLog( 'Missing skope data after refresh', skope_server_data );
}
// set the local and group skope id
api.czr_activeSkopes( {
'local' : self.getSkopeProperty( 'skope_id', 'local' ),
'group' : self.getSkopeProperty( 'skope_id', 'group' )
});
// if ( ! _.isEmpty( previousSkopeCollection ) ) { //Rewrite the title when the local skope has changed
// var _prevLoc = _.findWhere( previousSkopeCollection , { skope : 'local' } ).opt_name,
// _newLoc =_.findWhere( skope_server_data.czr_new_skopes, { skope : 'local' } ).opt_name;
// if ( _newLoc !== _prevLoc ) {
// //REFRESH SKOPE INFOS IN TITLE AND PREVIEW FRAME
// _refreshSkopeInfosNotices();
// }
// }
});
});//api.previewer.bind
});//api.bind( 'ready'
//CURRENT SKOPE COLLECTION LISTENER
//The skope collection is set on 'czr-new-skopes-synced' triggered by the preview
//setup the callbacks of the skope collection update
//on init and on preview change : the collection of skopes is populated with new skopes
//=> instanciate the relevant skope object + render them
api.czr_currentSkopesCollection.bind( function( to, from ) {
return self.currentSkopesCollectionReact( to, from );
}, { deferred : true });
///////////////////// VARIOUS /////////////////////
//DECLARE THE LIST OF CONTROL TYPES FOR WHICH THE VIEW IS REFRESHED ON CHANGE
//self.refreshedControls = [ 'czr_cropped_image'];// [ 'czr_cropped_image', 'czr_multi_module', 'czr_module' ];
api.trigger( 'czr_skopeBase_initialized' );
}//initialize
});//$.extend()
})( wp.customize , jQuery, _);//@global serverControlParams
var CZRSkopeBaseMths = CZRSkopeBaseMths || {};
( function ( api, $, _ ) {
$.extend( CZRSkopeBaseMths, {
//////////////////////////////////////////////////////////
/// <SKOPE HELPERSS>
// @return string
getSkopeProperty : function( what, skope_level ) {
what = what || 'skope_id';
skope_level = skope_level || 'local';
var _skope_data = _.findWhere( api.czr_currentSkopesCollection(), { skope : skope_level });
if ( _.isEmpty( _skope_data ) ){
// display an error message if local skope not found. Should always be defined.
if ( 'local' == skope_level ) {
api.errorLog( "getSkopeProperty => local skope missing, returning not_set" );
}
return "_skope_not_set_";//for example when trying to get a group skope_id in a context where there can't be a group skope like home or search.
} else if ( !_.has( _skope_data, what ) ) {
api.errorLog( "getSkopeProperty => " + what + " property does not exist" );
return "_skope_not_set_";
} else {
return _skope_data[ what ];
}
},
//@return string
firstToUpperCase : function( str ) {
return ! _.isString( str ) ? '' : str.substr(0, 1).toUpperCase() + str.substr(1);
}
// //@return string
// buildSkopeLink : function( skope_id ) {
// if ( ! api.czr_skope.has( skope_id ) ) {
// api.errorLog( 'buildSkopeLink : the requested skope id is not registered : ' + skope_id );
// return '';
// }
// var _link_title = [ serverControlParams.i18n.skope['Switch to scope'], api.czr_skope( skope_id )().title ].join(' : ');
// return [
// '<span class="czr-skope-switch" title=" ' + _link_title + '" data-skope-id="' + skope_id + '">',
// api.czr_skope( skope_id )().title,
// '</span>'
// ].join( '' );
// },
});//$.extend
})( wp.customize , jQuery, _ );//@global serverControlParams
var CZRSkopeBaseMths = CZRSkopeBaseMths || {};
(function ( api, $, _ ) {
$.extend( CZRSkopeBaseMths, {
//Fired on 'czr-new-skopes-synced' triggered by the preview, each time the preview is refreshed.
//On a Save Action, api.czr_savedDirties has been populated =>
// 1) check if the server sends the same saved values
// 2) update the skope db properties with the latests saved ones
//
//A skope candidate is structured this way :
//{
// id:""
// long_title:"Site wide options"
// obj_id:""
// skope:"global"
// title:"Site wide options"
//}
//@see api_overrides
updateSkopeCollection : function( sent_collection ) {
var self = this,
_api_ready_collection = [];
//normalize each sent skopes
_.each( sent_collection, function( _skope ) {
var skope_candidate = $.extend( true, {}, _skope );//deep clone to avoid any shared references
_api_ready_collection.push( self.prepareSkopeForAPI( skope_candidate ) );
});
//set the new collection of current skopes
//=> this will instantiate the not instantiated skopes
api.czr_currentSkopesCollection( _api_ready_collection );
// set the group skope id
//console.log( "SKOPE COLLECTION UPDATED", api.czr_currentSkopesCollection() );
},
//@param skope_candidate
////A skope candidate is structured this way :
//{
// id:""
// long_title:"Site wide options"
// obj_id:""
// skope:"global"
// title:"Site wide options"
//}
prepareSkopeForAPI : function( skope_candidate ) {
if ( ! _.isObject( skope_candidate ) ) {
throw new Error('prepareSkopeForAPI : a skope must be an object to be API ready');
}
var api_ready_skope = skope_candidate;
_.each( FlatSkopeLocalizedData.defaultSkopeModel , function( _value, _key ) {
var _candidate_val = skope_candidate[_key];
switch( _key ) {
case 'title' :
if ( ! _.isString( _candidate_val ) ) {
throw new Error('prepareSkopeForAPI : a skope title property must a string');
}
api_ready_skope[_key] = _candidate_val;
break;
case 'long_title' :
if ( ! _.isString( _candidate_val ) ) {
throw new Error('prepareSkopeForAPI : a skope title property must a string');
}
api_ready_skope[_key] = _candidate_val;
break;
case 'ctx_title' :
if ( ! _.isString( _candidate_val ) ) {
throw new Error('prepareSkopeForAPI : a skope context title property must a string');
}
api_ready_skope[_key] = _candidate_val;
break;
case 'skope' :
if ( ! _.isString( _candidate_val ) || _.isEmpty( _candidate_val ) ) {
throw new Error('prepareSkopeForAPI : a skope "skope" property must a string not empty');
}
api_ready_skope[_key] = _candidate_val;
break;
case 'obj_id' :
if ( ! _.isString( _candidate_val ) ) {
throw new Error('prepareSkopeForAPI : invalid "obj_id" for skope ' + _candidate_val.skope );
}
api_ready_skope[_key] = _candidate_val;
break;
case 'skope_id' :
if ( ! _.isString( _candidate_val ) ) {
throw new Error('prepareSkopeForAPI : invalid "skope_key" for skope ' + _candidate_val.skope );
}
api_ready_skope[_key] = _candidate_val;
break;
case 'values' :
// if ( ! _.isString( _candidate_val ) ) {
// throw new Error('prepareSkopeForAPI : invalid "values" for skope ' + _candidate_val.skope );
// }
api_ready_skope[_key] = _candidate_val;
break;
default :
api_ready_skope[_key] = _candidate_val;
break;
}//switch
});
//Finally, generate the id and the title
api_ready_skope.id = api_ready_skope.skope + '_' + api_ready_skope.skope_id;
if ( ! _.isString( api_ready_skope.id ) || _.isEmpty( api_ready_skope.id ) ) {
throw new Error('prepareSkopeForAPI : a skope id must a string not empty');
}
if ( ! _.isString( api_ready_skope.title ) || _.isEmpty( api_ready_skope.title ) ) {
api_ready_skope.title = api_ready_skope.id;
api_ready_skope.long_title = api_ready_skope.id;
}
return api_ready_skope;
},
//cb of api.czr_currentSkopesCollection.callbacks
//fired in initialize
currentSkopesCollectionReact : function( to, from ) {
var dfd = $.Deferred();
//ON INITIAL COLLECTION POPULATE, RESOLVE THE DEFERRED STATE
//=> this way we can defer earlier actions.
//For example when autofocus is requested, the section might be expanded before the initial skope collection is sent from the preview.
if ( _.isEmpty( from ) && ! _.isEmpty( to ) ) {
api.czr_initialSkopeCollectionPopulated.resolve();
}
return dfd.resolve( 'changed' ).promise();
}//listenToSkopeCollection()
});//$.extend()
})( wp.customize , jQuery, _);//@global serverControlParams
var CZRSkopeBaseMths = CZRSkopeBaseMths || {};
(function ( api, $ ) {
// Skope
$.extend( CZRSkopeBaseMths, api.Events );
var CZR_SkopeBase = api.Class.extend( CZRSkopeBaseMths );
// Schedule skope instantiation on api ready
// api.bind( 'ready' , function() {
// api.czr_skopeBase = new api.CZR_SkopeBase();
// });
api.czr_skopeBase = new CZR_SkopeBase();
})( wp.customize, jQuery );
@@ -0,0 +1 @@
var CZRSkopeBaseMths=CZRSkopeBaseMths||{};!function(t,e,s){e.extend(CZRSkopeBaseMths,{initialize:function(){var r=this;t.czr_initialSkopeCollectionPopulated=e.Deferred(),t.czr_skopeCollection=new t.Value([]),t.czr_currentSkopesCollection=new t.Value([]),t.czr_activeSkopes=new t.Value({local:"",group:""}),t.bind("ready",function(){t.previewer.bind("czr-new-skopes-synced",function(e){if(serverControlParams.isDevMode&&t.infoLog("API SKOPE SYNCED",e),s.has(e,"czr_stylesheet")){t.czr_skopeBase.stylesheet=t.czr_skopeBase.stylesheet||new t.Value(t.settings.theme.stylesheet),t.czr_skopeBase.stylesheet(e.czr_stylesheet);t.czr_currentSkopesCollection();if(s.has(e,"czr_new_skopes")){if(s.isEmpty(s.findWhere(e.czr_new_skopes,{skope:"group"}))){var o=s.findWhere(e.czr_new_skopes,{skope:"local"});s.isEmpty(o)||s.contains(FlatSkopeLocalizedData.noGroupSkopeList,o.level)||t.errorLog("No group level skope sent while there should be one")}if(serverControlParams.isDevMode)t.czr_skopeBase.updateSkopeCollection(e.czr_new_skopes,this.channel());else try{t.czr_skopeBase.updateSkopeCollection(e.czr_new_skopes,this.channel())}catch(e){return void console.log("UPDATE SKOPE COLLECTION ERROR",e)}t.czr_initialSkopeCollectionPopulated.then(function(){s.has(e,"czr_new_skopes")&&!s.isEmpty(e.czr_new_skopes)||t.errorLog("Missing skope data after refresh",e),t.czr_activeSkopes({local:r.getSkopeProperty("skope_id","local"),group:r.getSkopeProperty("skope_id","group")})})}else t.errorLog("On 'czr-new-skopes-synced' : missing skopes in the server data")}else t.errorLog("On 'czr-new-skopes-synced' : missing stylesheet in the server data")})}),t.czr_currentSkopesCollection.bind(function(e,o){return r.currentSkopesCollectionReact(e,o)},{deferred:!0}),t.trigger("czr_skopeBase_initialized")}})}(wp.customize,jQuery,_);CZRSkopeBaseMths=CZRSkopeBaseMths||{};!function(t,e,s){e.extend(CZRSkopeBaseMths,{getSkopeProperty:function(e,o){e=e||"skope_id",o=o||"local";var r=s.findWhere(t.czr_currentSkopesCollection(),{skope:o});return s.isEmpty(r)?("local"==o&&t.errorLog("getSkopeProperty => local skope missing, returning not_set"),"_skope_not_set_"):s.has(r,e)?r[e]:(t.errorLog("getSkopeProperty => "+e+" property does not exist"),"_skope_not_set_")},firstToUpperCase:function(e){return s.isString(e)?e.substr(0,1).toUpperCase()+e.substr(1):""}})}(wp.customize,jQuery,_);CZRSkopeBaseMths=CZRSkopeBaseMths||{};!function(s,i,p){i.extend(CZRSkopeBaseMths,{updateSkopeCollection:function(e){var r=this,t=[];p.each(e,function(e){var o=i.extend(!0,{},e);t.push(r.prepareSkopeForAPI(o))}),s.czr_currentSkopesCollection(t)},prepareSkopeForAPI:function(t){if(!p.isObject(t))throw new Error("prepareSkopeForAPI : a skope must be an object to be API ready");var s=t;if(p.each(FlatSkopeLocalizedData.defaultSkopeModel,function(e,o){var r=t[o];switch(o){case"title":case"long_title":if(!p.isString(r))throw new Error("prepareSkopeForAPI : a skope title property must a string");s[o]=r;break;case"ctx_title":if(!p.isString(r))throw new Error("prepareSkopeForAPI : a skope context title property must a string");s[o]=r;break;case"skope":if(!p.isString(r)||p.isEmpty(r))throw new Error('prepareSkopeForAPI : a skope "skope" property must a string not empty');s[o]=r;break;case"obj_id":if(!p.isString(r))throw new Error('prepareSkopeForAPI : invalid "obj_id" for skope '+r.skope);s[o]=r;break;case"skope_id":if(!p.isString(r))throw new Error('prepareSkopeForAPI : invalid "skope_key" for skope '+r.skope);s[o]=r;break;case"values":default:s[o]=r}}),s.id=s.skope+"_"+s.skope_id,!p.isString(s.id)||p.isEmpty(s.id))throw new Error("prepareSkopeForAPI : a skope id must a string not empty");return p.isString(s.title)&&!p.isEmpty(s.title)||(s.title=s.id,s.long_title=s.id),s},currentSkopesCollectionReact:function(e,o){var r=i.Deferred();return p.isEmpty(o)&&!p.isEmpty(e)&&s.czr_initialSkopeCollectionPopulated.resolve(),r.resolve("changed").promise()}})}(wp.customize,jQuery,_);CZRSkopeBaseMths=CZRSkopeBaseMths||{};!function(e,o){jQuery.extend(CZRSkopeBaseMths,e.Events);var r=e.Class.extend(CZRSkopeBaseMths);e.czr_skopeBase=new r}(wp.customize);
@@ -0,0 +1,924 @@
<?php
namespace Nimble;
if ( did_action('nimble_skope_loaded') ) {
if ( ( defined( 'CZR_DEV' ) && CZR_DEV ) || ( defined( 'NIMBLE_DEV' ) && NIMBLE_DEV ) ) {
error_log( __FILE__ . ' => The skope has already been loaded' );
}
return;
}
// Set the namsepace as a global so we can use it when fired from another theme/plugin using the fmk
global $czr_skope_namespace;
$czr_skope_namespace = __NAMESPACE__ . '\\';
do_action( 'nimble_skope_loaded' );
//Creates a new instance
function Flat_Skop_Base( $params = array() ) {
return Flat_Skop_Base::skp_get_instance( $params );
}
/////////////////////////////////////////////////////////////////
// <DEFINITIONS>
// THE SKOPE MODEL
function skp_get_default_skope_model() {
return array(
'title' => '',
'long_title' => '',
'ctx_title' => '',
'id' => '',
'skope' => '',
//'level' => '',
'obj_id' => '',
'skope_id' => '',
'values' => ''
);
}
// those contexts have no group
function skp_get_no_group_skope_list() {
return array( 'home', 'search', '404', 'date' );
}
/////////////////////////////////////////////////////////////////
// </DEFINITIONS>
/////////////////////////////////////////////////////////////////
// HELPERS
function skp_trim_text( $text, $text_length, $more ) {
if ( !$text )
return '';
$text = trim( strip_tags( $text ) );
if ( !$text_length )
return $text;
$end_substr = $_text_length = strlen( $text );
if ( $_text_length > $text_length ){
$end_substr = strpos( $text, ' ' , $text_length);
$end_substr = ( $end_substr !== FALSE ) ? $end_substr : $text_length;
$text = substr( $text , 0 , $end_substr );
}
return ( ( $end_substr < $text_length ) && $more ) ? $text : $text . ' ' .$more ;
}
/////////////////////////////////////////////////////////////////
// SKOPE HELPERS
/**
* Return the current skope
* Front / Back agnostic.
* @param $_requesting_wot is a string with the following possible values : 'meta_type' (like post) , 'type' (like page), 'id' (like page id)
* @param $_return_string string param stating if the return value should be a string or an array
* @param $requested_parts is an array of parts looking like
* Array
* (
* [meta_type] => post
* [type] => page
* [obj_id] => 9
* )
* USE CASE when $requested_parts is passed : when a post gets deleted, we need to clean any skope posts associated. That's when we invoke skp_get_skope( null, true, $requested_parts )
* @return a string of all concatenated ctx parts (default) 0R an array of the ctx parts
*/
function skp_get_skope( $_requesting_wot = null, $_return_string = true, $requested_parts = array() ) {
//skope builder from the wp $query
//=> returns :
// the meta_type : post, tax, user
// the type : post_type, taxonomy name, author
// the id : post id, term id, user id
// if $parts are provided, use them.
// Note that the value of skp_get_query_skope() is cached when get the first time for better performance
$parts = ( is_array( $requested_parts ) && !empty( $requested_parts ) ) ? $requested_parts : skp_get_query_skope();
// error_log( '<SKOPE PARTS>' );
// error_log( print_r( $parts, true ) );
// error_log( '</SKOPE PARTS>' );
$_return = array();
$meta_type = $type = $obj_id = false;
if ( is_array( $parts ) && !empty( $parts ) ) {
$meta_type = isset( $parts['meta_type'] ) ? $parts['meta_type'] : false;
$type = isset( $parts['type'] ) ? $parts['type'] : false;
$obj_id = isset( $parts['obj_id'] ) ? $parts['obj_id'] : false;
}
switch ( $_requesting_wot ) {
case 'meta_type':
if ( false !== $meta_type ) {
$_return = array( "meta_type" => "{$meta_type}" );
}
break;
case 'type':
if ( false !== $type ) {
$_return = array( "type" => "{$type}" );
}
break;
case 'id':
if ( false !== $obj_id ) {
$_return = array( "id" => "{$obj_id}" );
}
break;
default:
//LOCAL
//here we don't check if there's a type this is the case where there must be one when a meta type (post, tax, user) is defined.
//typically the skope will look like post_page_25
if ( false !== $meta_type && false !== $obj_id ) {
$_return = array( "meta_type" => "{$meta_type}" , "type" => "{$type}", "id" => "{$obj_id}" );
}
//GROUP
else if ( false !== $meta_type && !$obj_id ) {
$_return = array( "meta_type" => "{$meta_type}", "type" => "{$type}" );
}
//LOCAL WITH NO GROUP : home ( when home displays "Your latests posts" ) , 404, search, date, post type archive
else if ( false !== $obj_id ) {
$_return = array( "id" => "{$obj_id}" );
}
else {
// don't print the skope error log if not in dev mode
// fixes : https://github.com/presscustomizr/czr-skope/issues/1
if ( defined( 'NIMBLE_DEV' ) && NIMBLE_DEV ) {
// the favicon request break skope building, so skip this case
// see https://github.com/presscustomizr/nimble-builder/issues/658
if ( '/favicon.ico' !== $_SERVER['REQUEST_URI'] ) {
error_log( __FUNCTION__ . ' error when building the local skope, no object_id provided.');
error_log( print_r( $parts, true) );
}
}
}
break;
}
//return the parts array if not a string requested
if ( !$_return_string ) {
return $_return;
}
//don't go further if not an array or empty
if ( !is_array( $_return ) || ( is_array( $_return ) && empty( $_return ) ) ) {
return '';
}
//if a specific part of the ctx is requested, don't concatenate
//return the part if exists
if ( !is_null( $_requesting_wot ) ) {
return isset( $_return[ $_requesting_wot ] ) ? $_return[ $_requesting_wot ] : '';
}
//generate the ctx string from the array of ctx_parts
$_concat = "";
foreach ( $_return as $_key => $_part ) {
if ( empty( $_concat) ) {
$_concat .= $_part;
} else {
$_concat .= '_'. $_part;
}
}
return $_concat;
}
/**
* skope builder from the wp $query
* !!has to be fired after 'template_redirect'
* Used on front ( not customizing preview ? => @todo make sure of this )
* @return array of ctx parts
*/
function skp_get_query_skope() {
//don't call get_queried_object if the $query is not defined yet
global $wp_the_query;
if ( !isset( $wp_the_query ) || empty( $wp_the_query ) ) {
return array();
}
// is it cached already ?
if ( !empty( Flat_Skop_Base()->query_skope ) ) {
return Flat_Skop_Base()->query_skope;
}
$queried_object = get_queried_object();
// error_log( '<GET QUERIED OBJECT>' . gettype( $queried_object ) );
// error_log( print_r( $wp_the_query , true ) );
// error_log( '</GET QUERIED OBJECT>' );
$meta_type = $type = $obj_id = false;
// The queried object is NULL on
// - home when displaying the latest posts
// - date archives
// - 404 page
// - search page
if ( !is_null( $queried_object ) && is_object( $queried_object ) ) {
//post, custom post types, page
if ( isset($queried_object->post_type) ) {
$meta_type = 'post';
$type = $queried_object->post_type;
$obj_id = $queried_object->ID;
}
//taxinomies : tags, categories, custom tax type
if ( isset($queried_object->taxonomy) && isset($queried_object->term_id) ) {
$meta_type = 'tax';
$type = $queried_object->taxonomy;
$obj_id = $queried_object->term_id;
}
}
//author archive page
if ( is_author() ) {
$meta_type = 'user';
$type = 'author';
$obj_id = $wp_the_query->get( 'author' );
}
//SKOPES WITH NO GROUPS
//post type archive object
if ( is_post_type_archive() ) {
$obj_id = 'post_type_archive' . '_'. $wp_the_query->get( 'post_type' );
}
if ( is_404() ) {
$obj_id = '404';
}
if ( is_search() ) {
$obj_id = 'search';
}
if ( is_date() ) {
$obj_id = 'date';
}
if ( skp_is_real_home() ) {
$obj_id = 'home';
// December 2018
// when the home page is a page, the skope now includes the page id, instead of being generic as it was since then : skp__post_page_home
// This has been introduced to facilitate the compatibility of Nimble Builder with multilanguage plugins like polylang
// => Allows user to create a different home page for each languages
//
// To summarize,
// Before dec 2018 :
// - home page is blog page => skope_id = skp___home
// - home page is page => skope_id = skp__post_page_home
//
// After Dec 2018
// - hope page is blog page => skope_id is unchanged = skp__home
// - home page is a page => skope_id is changed to = skp__post_page_{$static_home_page_id}
//
// This means that if Nimble sections, or any other contextualizations had been made on home when 'page' === get_option( 'show_on_front' ),
// for which the corresponding skope_id was skp__post_page_home,
// those settings have to be copied in the skp__post_page_{$static_home_page_id} skope settings
// If we are on the real home page, but displaying a static page then set the static page id as obj_id
if ( !is_home() && 'page' === get_option( 'show_on_front' ) ) {
$home_page_id = get_option( 'page_on_front' );
if ( 0 < $home_page_id ) {
$obj_id = $home_page_id;
}
}
}
// cache now
if ( did_action( 'wp' ) ) {
Flat_Skop_Base()->query_skope = apply_filters( 'skp_get_query_skope' , array( 'meta_type' => $meta_type , 'type' => $type , 'obj_id' => $obj_id ), $queried_object );
}
return Flat_Skop_Base()->query_skope;
}
//@return the skope prefix used both when customizing and on front
function skp_get_skope_id( $level = 'local' ) {
// CACHE THE SKOPE WHEN 'wp' DONE
// the skope id is used when filtering the options, called hundreds of times.
// We get higher performances with a cached value instead of using the skp_get_skope_id() function on each call.
$new_skope_ids = array( 'local' => '_skope_not_set_', 'group' => '_skope_not_set_' );
if ( did_action( 'wp' ) ) {
if ( empty( Flat_Skop_Base()->current_skope_ids ) ) {
$new_skope_ids['local'] = skp_build_skope_id( array( 'skope_string' => skp_get_skope(), 'skope_level' => 'local' ) );
$new_skope_ids['group'] = skp_build_skope_id( array( 'skope_level' => 'group' ) );
Flat_Skop_Base()->current_skope_ids = $new_skope_ids;
$skope_id_to_return = $new_skope_ids[ $level ];
// error_log('<SKOPE ID cached in skp_get_skope_id>');
// error_log( print_r( $new_skope_ids, true ) );
// error_log('</SKOPE ID cached in skp_get_skope_id>');
} else {
$new_skope_ids = Flat_Skop_Base()->current_skope_ids;
$skope_id_to_return = $new_skope_ids[ $level ];
}
} else {
$skope_id_to_return = array_key_exists( $level, $new_skope_ids ) ? $new_skope_ids[ $level ] : '_skope_not_set_';
}
// if ( !(bool)did_action( 'wp' ) ) {
// sek_error_log('ACTION WP NOT FIRED', did_action('wp'));
// }
// Jan 2021, while working on https://github.com/presscustomizr/nimble-builder-pro/issues/81
// when customizing and firing this function during ajax calls, the check for did_action('wp') will return 0.
// => which will lead to skope_id set to '_skope_not_set_'
// in order to prevent this, let's get the skope_id value from the customizer posted value when available.
if ( skp_is_customizing() && '_skope_not_set_' === $skope_id_to_return && 'local' === $level && !empty($_POST['local_skope_id']) ) {
$skope_id_to_return = sanitize_text_field($_POST['local_skope_id']);
}
// Feb 2021 => added for https://github.com/presscustomizr/nimble-builder/issues/478
if ( skp_is_customizing() && '_skope_not_set_' === $skope_id_to_return && 'group' === $level && !empty($_POST['group_skope_id']) ) {
$skope_id_to_return = sanitize_text_field($_POST['group_skope_id']);
}
$skope_id_to_return = apply_filters( 'skp_get_skope_id', $skope_id_to_return, $level );
// At this point, the skope_id should be set
if ( '_skope_not_set_' === $skope_id_to_return ) {
//error_log( __FUNCTION__ . ' error => skope_id not set for level ' . $level );
}
// error_log('$skope_id_to_return => ' . $level . ' ' . $skope_id_to_return );
// error_log( print_r( Flat_Skop_Base()->current_skope_ids , true ) );
return $skope_id_to_return;
}
//@param args = array(
// 'skope_string' => skp_get_skope(),
// 'skope_type' => $skp_type,
// 'skope_level' => 'local'
//)
//@return string
function skp_build_skope_id( $args = array() ) {
$skope_id = '_skope_not_set_';
// normalizes
$args = is_array( $args ) ? $args : array();
$args = wp_parse_args(
$args,
array( 'skope_string' => '', 'skope_type' => '', 'skope_level' => '' )
);
// set params if not provided
$args['skope_level'] = empty( $args['skope_level'] ) ? 'local' : $args['skope_level'];
$args['skope_string'] = ( 'local' == $args['skope_level'] && empty( $args['skope_string'] ) ) ? skp_get_skope() : $args['skope_string'];
$args['skope_type'] = ( 'group' == $args['skope_level'] && empty( $args['skope_type'] ) ) ? skp_get_skope( 'type' ) : $args['skope_type'];
// generate skope_id for two cases : local or group
switch( $args[ 'skope_level'] ) {
case 'local' :
$skope_id = strtolower( NIMBLE_SKOPE_ID_PREFIX . $args[ 'skope_string' ] );
break;
case 'group' :
if ( !empty( $args[ 'skope_type' ] ) ) {
$skope_id = strtolower( NIMBLE_SKOPE_ID_PREFIX . 'all_' . $args[ 'skope_type' ] );
}
break;
}
return $skope_id;
}
/**
* Used when localizing the customizer js params
* Can be a post ( post, pages, CPT) , tax(tag, cats, custom taxs), author, date, search page, 404.
* @param $args : array(
* 'level' => string,
* 'meta_type' => string
* 'long' => bool
* 'is_prefixed' => bool //<= indicated if we should add the "Options for" prefix
* )
* @return string title of the current ctx if exists. If not => false.
*/
function skp_get_skope_title( $args = array() ) {
$defaults = array(
'level' => '',
'meta_type' => null,
'long' => false,
'is_prefixed' => true
);
$args = wp_parse_args( $args, $defaults );
$level = $args['level'];
$meta_type = $args['meta_type'];
$long = $args['long'];
$is_prefixed = $args['is_prefixed'];
$_dyn_type = ( skp_is_customize_preview_frame() && isset( $_POST['dyn_type']) ) ? sanitize_text_field($_POST['dyn_type']) : '';
$type = skp_get_skope('type');
$skope = skp_get_skope();
$title = '';
if( 'local' == $level ) {
$type = skp_get_skope( 'type' );
$title = $is_prefixed ? __( 'Options for', 'text_doma') . ' ' : $title;
if ( skp_skope_has_a_group( $meta_type ) ) {
$_id = skp_get_skope('id');
switch ($meta_type) {
case 'post':
$type_obj = get_post_type_object( $type );
$title .= sprintf( '%1$s "%3$s" (id : %2$s)', strtolower( $type_obj->labels->singular_name ), $_id, get_the_title( $_id ) );
break;
case 'tax':
$type_obj = get_taxonomy( $type );
$term = get_term( $_id, $type );
$title .= sprintf( '%1$s "%3$s" (id : %2$s)', strtolower( $type_obj->labels->singular_name ), $_id, $term->name );
break;
case 'user':
$author = get_userdata( $_id );
$title .= sprintf( '%1$s "%3$s" (id : %2$s)', __('user', 'text_doma'), $_id, $author->user_login );
break;
}
} else if ( ( 'trans' == $_dyn_type || skp_skope_has_no_group( $skope ) ) ) {
if ( is_post_type_archive() ) {
global $wp_the_query;
$title .= sprintf( __( '%1$s archive page', 'text_doma'), $wp_the_query->get( 'post_type' ) );
} else {
$title .= strtolower( $skope );
}
} else {
$title .= __( 'Undefined', 'text_doma');
}
}
if ( 'group' == $level || 'special_group' == $level ) {
$title = $is_prefixed ? __( 'Options for all', 'text_doma') . ' ' : __( 'All' , 'text_doma' ) . ' ';
switch( $meta_type ) {
case 'post' :
$type_obj = get_post_type_object( $type );
$title .= strtolower( $type_obj->labels->name );
break;
case 'tax' :
$type_obj = get_taxonomy( $type );
$title .= strtolower( $type_obj->labels->name );
break;
case 'user' :
$title .= __('users', 'text_doma');
break;
}
}
if ( 'global' == $level ) {
$title = __( 'Sitewide options', 'text_doma');
}
$title = ucfirst( $title );
return skp_trim_text( $title, $long ? 45 : 28, '...');
}
//@return bool
//=> tells if the current skope is part of the ones without group
function skp_skope_has_no_group( $meta_type ) {
return in_array(
$meta_type,
skp_get_no_group_skope_list()
) || is_post_type_archive();
}
//@return bool
//Tells if the current skope has a group level
function skp_skope_has_a_group( $meta_type ) {
return in_array(
$meta_type,
array('post', 'tax', 'user')
);
}
//@return bool
function skp_is_real_home() {
// Warning : when show_on_front is a page, but no page_on_front has been picked yet, is_home() is true
// beware of https://github.com/presscustomizr/nimble-builder/issues/349
return ( is_home() && ( 'posts' == get_option( 'show_on_front' ) || '__nothing__' == get_option( 'show_on_front' ) ) )
|| ( is_home() && 0 == get_option( 'page_on_front' ) && 'page' == get_option( 'show_on_front' ) )//<= this is the case when the user want to display a page on home but did not pick a page yet
|| is_front_page();
}
/**
* Returns a boolean
*/
function skp_is_customizing() {
//checks if is customizing : two contexts, admin and front (preview frame)
global $pagenow;
$_is_ajaxing_from_customizer = isset( $_POST['customized'] ) || isset( $_POST['wp_customize'] );
$is_customizing = false;
// the check on $pagenow does NOT work on multisite install @see https://github.com/presscustomizr/nimble-builder/issues/240
// That's why we also check with other global vars
// @see wp-includes/theme.php, _wp_customize_include()
$is_customize_php_page = ( is_admin() && 'customize.php' == basename( $_SERVER['PHP_SELF'] ) );
$is_customize_admin_page_one = (
$is_customize_php_page
||
( isset( $_REQUEST['wp_customize'] ) && 'on' == sanitize_text_field($_REQUEST['wp_customize']) )
||
( !empty( $_GET['customize_changeset_uuid'] ) || !empty( $_POST['customize_changeset_uuid'] ) )
);
$is_customize_admin_page_two = is_admin() && isset( $pagenow ) && 'customize.php' == $pagenow;
if ( $is_customize_admin_page_one || $is_customize_admin_page_two ) {
$is_customizing = true;
//hu_is_customize_preview_frame() ?
// Note : is_customize_preview() is not able to differentiate when previewing in the customizer and when previewing a changeset draft.
// @todo => change this
} else if ( is_customize_preview() || ( !is_admin() && isset($_REQUEST['customize_messenger_channel']) ) ) {
$is_customizing = true;
// hu_doing_customizer_ajax()
} else if ( $_is_ajaxing_from_customizer && ( defined( 'DOING_AJAX' ) && DOING_AJAX ) ) {
$is_customizing = true;
}
return $is_customizing;
}
/**
* Is the customizer preview panel being displayed ?
* @return boolean
*/
function skp_is_customize_preview_frame() {
return is_customize_preview() || ( !is_admin() && isset($_REQUEST['customize_messenger_channel']) );
}
/**
* @return boolean
*/
function skp_is_previewing_live_changeset() {
return !isset( $_POST['customize_messenger_channel']) && is_customize_preview();
}
?><?php
////////////////////////////////////////////////////////////////
// FLAT SKOPE BASE
if ( !class_exists( 'Flat_Skop_Base' ) ) :
class Flat_Skop_Base {
static $instance;
public $query_skope = array();//<= will cache the query skope ( otherwise called multiple times ) on the first invokation of skp_get_query_skope() IF 'wp' done
public $current_skope_ids = array();// will cache the skope ids on the first invokation of skp_get_skope_id, if 'wp' done
public static function skp_get_instance( $params ) {
if ( !isset( self::$instance ) && !( self::$instance instanceof Flat_Skop_Base ) )
self::$instance = new Flat_Skope_Clean_Final( $params );
return self::$instance;
}
function __construct( $params = array() ) {
$defaults = array(
'base_url_path' => ''//NIMBLE_BASE_URL . '/inc/czr-skope/'
);
$params = wp_parse_args( $params, $defaults );
if ( !defined( 'NIMBLE_SKOPE_BASE_URL' ) ) { define( 'NIMBLE_SKOPE_BASE_URL' , $params['base_url_path'] ); }
if ( !defined( 'NIMBLE_SKOPE_ID_PREFIX' ) ) { define( 'NIMBLE_SKOPE_ID_PREFIX' , "skp__" ); }
$this->skp_register_and_load_control_assets();
$this->skp_export_skope_data_and_schedule_sending_to_panel();
$this->skp_schedule_cleaning_on_object_delete();
}//__construct
}
endif;
?><?php
/////////////////////////////////////////////////////////////////
// PRINT CUSTOMIZER JAVASCRIPT + LOCALIZED DATA
if ( !class_exists( 'Flat_Skop_Register_And_Load_Control_Assets' ) ) :
class Flat_Skop_Register_And_Load_Control_Assets extends Flat_Skop_Base {
// Fired in Flat_Skop_Base::__construct()
public function skp_register_and_load_control_assets() {
add_action( 'customize_controls_enqueue_scripts', array( $this, 'skp_enqueue_controls_js_css' ), 20 );
}
public function skp_enqueue_controls_js_css() {
$_use_unminified = defined('CZR_DEV')
&& true === CZR_DEV
// && false === strpos( dirname( dirname( dirname (__FILE__) ) ) , 'inc/wfc' )
&& file_exists( sprintf( '%s/assets/czr/js/czr-skope-base.js' , dirname( __FILE__ ) ) );
$_prod_script_path = sprintf(
'%1$s/assets/czr/js/%2$s' ,
NIMBLE_SKOPE_BASE_URL,
$_use_unminified ? 'czr-skope-base.js' : 'czr-skope-base.min.js'
);
wp_enqueue_script(
'czr-skope-base',
//dev / debug mode mode?
$_prod_script_path,
array('customize-controls' , 'jquery', 'underscore'),
( defined('WP_DEBUG') && true === WP_DEBUG ) ? time() : wp_get_theme()->version,
$in_footer = true
);
wp_localize_script(
'czr-skope-base',
'FlatSkopeLocalizedData',
array(
'noGroupSkopeList' => skp_get_no_group_skope_list(),
'defaultSkopeModel' => skp_get_default_skope_model(),
'i18n' => array()
)
);
}
}//class
endif;
?><?php
/* ------------------------------------------------------------------------- *
* CUSTOMIZE PREVIEW : export skope data and send skope to the panel
/* ------------------------------------------------------------------------- */
if ( !class_exists( 'Flat_Export_Skope_Data_And_Send_To_Panel' ) ) :
class Flat_Export_Skope_Data_And_Send_To_Panel extends Flat_Skop_Register_And_Load_Control_Assets {
// Fired in Flat_Skop_Base::__construct()
public function skp_export_skope_data_and_schedule_sending_to_panel() {
add_action( 'wp_head', array( $this, 'skp_print_server_skope_data') , 30 );
}
//hook : 'wp_footer'
public function skp_print_server_skope_data() {
if ( !skp_is_customize_preview_frame() )
return;
global $wp_query, $wp_customize;
$_meta_type = skp_get_skope( 'meta_type', true );
// $_czr_scopes = array( );
$_czr_skopes = $this->_skp_get_json_export_ready_skopes();
$_czr_query_data = $this->_skp_get_json_export_ready_query_data();
ob_start();
?>
var _doSend = function() {
// December 2020 : it may happen that the 'sync' event was already sent and that we missed it
// Typically when the site is slow.
// So we need to check if the "sync" event has fired already ( see customize-base.js, ::bind method )
// For more security, let's introduce a marker and attempt to re-sent after a moment if needed
window.czr_skopes_sent = false;
var _send = function() {
wp.customize.preview.send( 'czr-new-skopes-synced', {
czr_new_skopes : _wpCustomizeSettings.czr_new_skopes || [],
czr_stylesheet : _wpCustomizeSettings.czr_stylesheet || '',
isChangesetDirty : _wpCustomizeSettings.isChangesetDirty || false,
skopeGlobalDBOpt : _wpCustomizeSettings.skopeGlobalDBOpt || [],
} );
window.czr_skopes_sent = true;
};
jQuery( function() {
if ( wp.customize.preview.topics && wp.customize.preview.topics.sync && wp.customize.preview.topics.sync.fired() ) {
_send();
} else {
wp.customize.preview.bind( 'sync', function( events ) {
_send();
});
}
setTimeout( function() {
if ( !window.czr_skopes_sent ) {
_send();
}
}, 2500 );
});
};
// recursively try to load jquery every 200ms during 6s ( max 30 times )
var _doWhenCustomizeSettingsReady = function( attempts ) {
attempts = attempts || 0;
if ( typeof undefined !== typeof window._wpCustomizeSettings ) {
_wpCustomizeSettings.czr_new_skopes = <?php echo wp_json_encode( $_czr_skopes ); ?>;
_wpCustomizeSettings.czr_stylesheet = '<?php echo get_stylesheet(); ?>';
_wpCustomizeSettings.czr_query_params = <?php echo wp_json_encode($_czr_query_data); ?>;
_doSend();
} else if ( attempts < 30 ) {
setTimeout( function() {
attempts++;
_doWhenCustomizeSettingsReady( attempts );
}, 20 );
} else {
if ( window.console && window.console.log ) {
console.log('Nimble Builder problem : _wpCustomizeSettings is not defined');
}
}
};
_doWhenCustomizeSettingsReady();
<?php
$script = ob_get_clean();
wp_register_script( 'nb_print_skope_data_js', '');
wp_enqueue_script( 'nb_print_skope_data_js' );
wp_add_inline_script( 'nb_print_skope_data_js', $script );
}
// introduced in october 2019 for https://github.com/presscustomizr/nimble-builder/issues/401
private function _skp_get_json_export_ready_query_data() {
global $wp_query;
global $authordata;
add_filter('get_the_archive_title_prefix', '__return_false');
$archive_title = get_the_archive_title();
remove_filter('get_the_archive_title_prefix', '__return_false');
return [
'is_singular' => $wp_query->is_singular,
'is_archive' => $wp_query->is_archive,
'is_search' => $wp_query->is_search,
'is_attachment' => $wp_query->is_attachment,
'is_front_page' => is_front_page(),
'the_archive_title' => $archive_title,
'the_archive_description' => get_the_archive_description(),
'the_previous_post_link' => is_singular() ? get_previous_post_link( $format = '%link' ) : '',
'the_next_post_link' => is_singular() ? get_next_post_link( $format = '%link' ) : '',
'the_search_query' => get_search_query(),
'the_search_results_nb' => (int) $wp_query->found_posts,
'the_author_id' => isset( $authordata->ID ) ? $authordata->ID : 0,
'post_id' => get_the_ID(),
'query_vars' => $wp_query->query_vars
];
}
/* ------------------------------------------------------------------------- *
* CUSTOMIZE PREVIEW : BUILD SKOPES JSON
/* ------------------------------------------------------------------------- */
//generates the array of available scopes for a given context
//ex for a single post tagged #tag1 and #tag2 and categroized #cat1 :
//global
//all posts
//local
//posts tagged #tag1
//posts tagged #tag2
//posts categorized #cat1
//@return array()
//
//skp_get_skope_title() takes the following default args
//array(
// 'level' => '',
// 'meta_type' => null,
// 'long' => false,
// 'is_prefixed' => true
//)
private function _skp_get_json_export_ready_skopes() {
$skopes = array();
$_meta_type = skp_get_skope( 'meta_type', true );
//default properties of the scope object
$defaults = skp_get_default_skope_model();
//global and local and always sent
$skopes[] = wp_parse_args(
array(
'title' => skp_get_skope_title( array( 'level' => 'global' ) ),
'long_title' => skp_get_skope_title( array( 'level' => 'global', 'meta_type' => null, 'long' => true ) ),
'ctx_title' => skp_get_skope_title( array( 'level' => 'global', 'meta_type' => null, 'long' => true, 'is_prefixed' => false ) ),
'skope' => 'global',
'level' => '_all_'
),
$defaults
);
//SPECIAL GROUPS
//@todo
//GROUP
//Do we have a group ? => if yes, then there must be a meta type
if ( skp_get_skope('meta_type') ) {
$skopes[] = wp_parse_args(
array(
'title' => skp_get_skope_title( array( 'level' => 'group', 'meta_type' => $_meta_type ) ),
'long_title' => skp_get_skope_title( array( 'level' => 'group', 'meta_type' => $_meta_type, 'long' => true ) ),
'ctx_title' => skp_get_skope_title( array( 'level' => 'group', 'meta_type' => $_meta_type, 'long' => true, 'is_prefixed' => false ) ),
'skope' => 'group',
'level' => 'all_' . skp_get_skope('type'),
'skope_id' => skp_get_skope_id( 'group' )
),
$defaults
);
}
//LOCAL
$skopes[] = wp_parse_args(
array(
'title' => skp_get_skope_title( array( 'level' => 'local', 'meta_type' => $_meta_type ) ),
'long_title' => skp_get_skope_title( array( 'level' => 'local', 'meta_type' => $_meta_type, 'long' => true ) ),
'ctx_title' => skp_get_skope_title( array( 'level' => 'local', 'meta_type' => $_meta_type, 'long' => true, 'is_prefixed' => false ) ),
'skope' => 'local',
'level' => skp_get_skope(),
'obj_id' => skp_get_skope('id'),
'skope_id' => skp_get_skope_id( 'local' )
),
$defaults
);
return apply_filters( 'skp_json_export_ready_skopes', $skopes );
}
}//class
endif;
?><?php
if ( !class_exists( 'Flat_Skope_Clean_Final' ) ) :
final class Flat_Skope_Clean_Final extends Flat_Export_Skope_Data_And_Send_To_Panel {
// Fired in Flat_Skop_Base::__construct()
public function skp_schedule_cleaning_on_object_delete() {
add_action( 'delete_post', array( $this, 'skp_clean_skopified_posts' ) );
add_action( 'delete_term_taxonomy', array( $this, 'skp_clean_skopified_taxonomies' ) );
add_action( 'delete_user', array( $this, 'skp_clean_skopified_users' ) );
}
// Clean any associated skope post for all public post types : post, page, public cpt
// 'delete_post' Fires immediately before a post is deleted from the database.
// @see wp-includes/post.php
// don't have to return anything
public function skp_clean_skopified_posts( $postid ) {
$deletion_candidate = get_post( $postid );
if ( !$deletion_candidate || !is_object( $deletion_candidate ) )
return;
// Stop here if the post type is not considered "viewable".
// For built-in post types such as posts and pages, the 'public' value will be evaluated.
// For all others, the 'publicly_queryable' value will be used.
// For example, the 'revision' post type, which is purely internal and not skopable, won't pass this test.
if ( !is_post_type_viewable( $deletion_candidate->post_type ) )
return;
// Force the skope parts normally retrieved with skp_get_query_skope()
$skope_string = skp_get_skope( null, true, array(
'meta_type' => 'post',
'type' => $deletion_candidate->post_type,
'obj_id' => $postid
) );
// build a skope_id with the normalized function
$skope_id = skp_build_skope_id( array( 'skope_string' => $skope_string, 'skope_level' => 'local' ) );
// fetch the skope post id which, if exists, is set as a theme mod
$skope_post_id_candidate = get_theme_mod( $skope_id );
if ( $skope_post_id_candidate > 0 && get_post( $skope_post_id_candidate ) ) {
// permanently delete the skope post from db
wp_delete_post( $skope_post_id_candidate );
// remove the theme_mod
remove_theme_mod( $skope_id );
}
}
// 'delete_term_taxonomy' Fires immediately before a term taxonomy ID is deleted.
public function skp_clean_skopified_taxonomies( $term_id ) {
$deletion_candidate = get_term( $term_id );
if ( !$deletion_candidate || !is_object( $deletion_candidate ) )
return;
//error_log( print_r( $deletion_candidate, true ) );
// Force the skope parts normally retrieved with skp_get_query_skope()
$skope_string = skp_get_skope( null, true, array(
'meta_type' => 'tax',
'type' => $deletion_candidate->taxonomy,
'obj_id' => $term_id
) );
// build a skope_id with the normalized function
$skope_id = skp_build_skope_id( array( 'skope_string' => $skope_string, 'skope_level' => 'local' ) );
// fetch the skope post id which, if exists, is set as a theme mod
$skope_post_id_candidate = get_theme_mod( $skope_id );
if ( $skope_post_id_candidate > 0 && get_post( $skope_post_id_candidate ) ) {
// permanently delete the skope post from db
wp_delete_post( $skope_post_id_candidate );
// remove the theme_mod
remove_theme_mod( $skope_id );
//error_log( 'SUCCESSFULLY REMOVED SKOPE POST ID ' . $skope_post_id_candidate . ' AND THEME MOD ' . $skope_id );
}
}
// 'delete_user' Fires immediately before a user is deleted from the database.
public function skp_clean_skopified_users( $user_id ) {
// Force the skope parts normally retrieved with skp_get_query_skope()
$skope_string = skp_get_skope( null, true, array(
'meta_type' => 'user',
'type' => 'author',
'obj_id' => $user_id
) );
// build a skope_id with the normalized function
$skope_id = skp_build_skope_id( array( 'skope_string' => $skope_string, 'skope_level' => 'local' ) );
// fetch the skope post id which, if exists, is set as a theme mod
$skope_post_id_candidate = get_theme_mod( $skope_id );
if ( $skope_post_id_candidate > 0 && get_post( $skope_post_id_candidate ) ) {
// permanently delete the skope post from db
wp_delete_post( $skope_post_id_candidate );
// remove the theme_mod
remove_theme_mod( $skope_id );
//error_log( 'SUCCESSFULLY REMOVED SKOPE POST ID ' . $skope_post_id_candidate . ' AND THEME MOD ' . $skope_id );
}
}
}//class
endif;
?>