first commit
This commit is contained in:
+556
@@ -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;
|
||||
?>
|
||||
+45
@@ -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;
|
||||
|
||||
?>
|
||||
+192
@@ -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;
|
||||
|
||||
?>
|
||||
+105
@@ -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
|
||||
}
|
||||
};
|
||||
+136
@@ -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, _ );
|
||||
+132
@@ -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, _);
|
||||
+49
@@ -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, _ );
|
||||
+132
@@ -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, _);
|
||||
+13
@@ -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 );
|
||||
+1
@@ -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;
|
||||
|
||||
?>
|
||||
Reference in New Issue
Block a user