Hueman Addons - Version 1.0.9

Version Description

: December 6th, 2016 = * updated : customizer compatibility with Hueman version 3.2.11

Download this release

Release Info

Developer nikeo
Plugin Icon 128x128 Hueman Addons
Version 1.0.9
Comparing to
See all releases

Code changes from version 1.0.8 to 1.0.9

assets/czr/css/czr-control-footer.css ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Rate link */
2
+ #customize-footer-actions .collapse-sidebar-label {
3
+ display: none;
4
+ }
5
+ .czr-rate-link {
6
+ position: absolute;
7
+ bottom: 0;
8
+ left: 40px;
9
+ right: 0;
10
+ padding: 4px 12px 4px 0;
11
+ font-size: 10px;
12
+ line-height: 14px;
13
+ text-align: right;
14
+ }
15
+ .rtl .tc-rate-link {
16
+ text-align: left;
17
+ left: auto;
18
+ right: 40px;
19
+ padding: 4px 0 4px 12px;
20
+ }
21
+ .wp-full-overlay.collapsed .czr-rate-link {
22
+ display: none;
23
+ }
24
+ .czr-rate-link .czr-stars {
25
+ color: #E6B800;
26
+ text-shadow: 0px 1px 0px rgba(0, 0, 0, 0.6);
27
+ }
28
+
29
+
30
+ @media screen and (min-width: 1025px) {
31
+ .wp-customizer .expanded #customize-footer-actions {
32
+ height: 85px;
33
+ background: inherit;
34
+ }
35
+ }
ha-fire.php ADDED
@@ -0,0 +1,205 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Plugin Name: Hueman Addons
4
+ * Plugin URI: http://presscustomizr.com
5
+ * Description: Hueman Theme Addons
6
+ * Version: 1.0.9
7
+ * Text Domain: hueman-addons
8
+ * Author: Press Customizr
9
+ * Author URI: http://presscustomizr.com
10
+ * License: GPLv2 or later
11
+ */
12
+
13
+
14
+ /**
15
+ * Fires the plugin
16
+ * @author Nicolas GUILLAUME
17
+ * @since 1.0
18
+ */
19
+ if ( ! class_exists( 'HU_AD' ) ) :
20
+ class HU_AD {
21
+ //Access any method or var of the class with classname::$instance -> var or method():
22
+ static $instance;
23
+
24
+ public static $theme;
25
+ public static $theme_name;
26
+ public $is_customizing;
27
+
28
+ public static function ha_get_instance() {
29
+ if ( ! isset( self::$instance ) && ! ( self::$instance instanceof HU_AD ) )
30
+ self::$instance = new HU_AD();
31
+ return self::$instance;
32
+ }
33
+
34
+
35
+ function __construct() {
36
+ self::$instance =& $this;
37
+
38
+ //checks if is customizing : two context, admin and front (preview frame)
39
+ $this -> is_customizing = $this -> ha_is_customizing();
40
+
41
+ self::$theme = $this -> ha_get_theme();
42
+ self::$theme_name = $this -> ha_get_theme_name();
43
+
44
+ if( ! defined( 'HA_BASE_PATH' ) ) define( 'HA_BASE_PATH' , plugin_dir_path( __FILE__ ) );
45
+ if( ! defined( 'HA_BASE_URL' ) ) define( 'HA_BASE_URL' , trailingslashit( plugins_url( basename( __DIR__ ) ) ) );
46
+
47
+ if( ! defined( 'HA_SKOP_ON' ) ) define( 'HA_SKOP_ON' , false );
48
+ if( ! defined( 'HA_SEK_ON' ) ) define( 'HA_SEK_ON' , false );
49
+
50
+ //stop execution if not Hueman
51
+ if ( false === strpos( self::$theme_name, 'hueman' ) ) {
52
+ add_action( 'admin_notices', array( $this , 'ha_admin_notice' ) );
53
+ return;
54
+ }
55
+ //TEXT DOMAIN
56
+ //adds plugin text domain
57
+ add_action( 'plugins_loaded', array( $this , 'ha_plugin_lang' ) );
58
+
59
+ //fire
60
+ $this -> ha_load();
61
+ }//construct
62
+
63
+
64
+
65
+
66
+ function ha_load() {
67
+ /* ------------------------------------------------------------------------- *
68
+ * Loads Features
69
+ /* ------------------------------------------------------------------------- */
70
+ require_once( HA_BASE_PATH . 'inc/sharrre/ha-sharrre.php' );
71
+ new HA_Sharrre();
72
+ require_once( HA_BASE_PATH . 'inc/shortcodes/ha-shortcodes.php' );
73
+ new HA_Shortcodes();
74
+
75
+ /* ------------------------------------------------------------------------- *
76
+ * Loads Customizer
77
+ /* ------------------------------------------------------------------------- */
78
+ require_once( HA_BASE_PATH . 'inc/czr/ha-czr.php' );
79
+ new HA_Czr();
80
+
81
+ /* ------------------------------------------------------------------------- *
82
+ * Loads BETAS
83
+ /* ------------------------------------------------------------------------- */
84
+ if ( HA_SKOP_ON ) {
85
+ require_once( HA_BASE_PATH . 'inc/skop/init-skop.php' );
86
+ }
87
+ if ( HA_SEK_ON ) {
88
+ require_once( HA_BASE_PATH . 'inc/sek/init-sektions.php' );
89
+ }
90
+ }
91
+
92
+
93
+ function ha_plugin_lang() {
94
+ load_plugin_textdomain( 'hueman-addons' , false, basename( dirname( __FILE__ ) ) . '/lang' );
95
+ }
96
+
97
+ /**
98
+ * @uses wp_get_theme() the optional stylesheet parameter value takes into account the possible preview of a theme different than the one activated
99
+ *
100
+ * @return the (parent) theme object
101
+ */
102
+ function ha_get_theme(){
103
+ // Return the already set theme
104
+ if ( self::$theme )
105
+ return self::$theme;
106
+ // $_REQUEST['theme'] is set both in live preview and when we're customizing a non active theme
107
+ $stylesheet = $this -> is_customizing && isset($_REQUEST['theme']) ? $_REQUEST['theme'] : '';
108
+
109
+ //gets the theme (or parent if child)
110
+ $ha_theme = wp_get_theme($stylesheet);
111
+
112
+ return $ha_theme -> parent() ? $ha_theme -> parent() : $ha_theme;
113
+
114
+ }
115
+
116
+ /**
117
+ *
118
+ * @return the theme name
119
+ *
120
+ */
121
+ function ha_get_theme_name(){
122
+ $ha_theme = $this -> ha_get_theme();
123
+
124
+ return sanitize_file_name( strtolower( $ha_theme -> Name ) );
125
+ }
126
+
127
+
128
+
129
+ function ha_admin_notice() {
130
+ $what = __( 'works only with the Hueman theme', 'hueman-addons' );
131
+
132
+ ?>
133
+ <div class="error">
134
+ <p>
135
+ <?php
136
+ printf( __( 'The <strong>%1$s</strong> plugin %2$s.' ,'hueman-addons' ),
137
+ 'Hueman Addons',
138
+ $what
139
+ );
140
+ ?>
141
+ </p>
142
+ </div>
143
+ <?php
144
+ }
145
+
146
+
147
+ /**
148
+ * Is the customizer left panel being displayed ?
149
+ * @return boolean
150
+ * @since 3.3+
151
+ */
152
+ function ha_is_customize_left_panel() {
153
+ global $pagenow;
154
+ return is_admin() && isset( $pagenow ) && 'customize.php' == $pagenow;
155
+ }
156
+
157
+
158
+ /**
159
+ * Is the customizer preview panel being displayed ?
160
+ * @return boolean
161
+ * @since 3.3+
162
+ */
163
+ function ha_is_customize_preview_frame() {
164
+ return ! is_admin() && isset($_REQUEST['wp_customize']);
165
+ }
166
+
167
+
168
+ /**
169
+ * Always include wp_customize or customized in the custom ajax action triggered from the customizer
170
+ * => it will be detected here on server side
171
+ * typical example : the donate button
172
+ *
173
+ * @return boolean
174
+ * @since 3.3+
175
+ */
176
+ function ha_doing_customizer_ajax() {
177
+ $_is_ajaxing_from_customizer = isset( $_POST['customized'] ) || isset( $_POST['wp_customize'] );
178
+ return $_is_ajaxing_from_customizer && ( defined( 'DOING_AJAX' ) && DOING_AJAX );
179
+ }
180
+
181
+ /**
182
+ * Are we in a customization context ? => ||
183
+ * 1) Left panel ?
184
+ * 2) Preview panel ?
185
+ * 3) Ajax action from customizer ?
186
+ * @return bool
187
+ * @since 3.3+
188
+ */
189
+ function ha_is_customizing() {
190
+ //checks if is customizing : two contexts, admin and front (preview frame)
191
+ return in_array( 1, array(
192
+ $this -> ha_is_customize_left_panel(),
193
+ $this -> ha_is_customize_preview_frame(),
194
+ $this -> ha_doing_customizer_ajax()
195
+ ) );
196
+ }
197
+
198
+ } //end of class
199
+ endif;
200
+
201
+ //Creates a new instance
202
+ function HU_AD() {
203
+ return HU_AD::ha_get_instance();
204
+ }
205
+ HU_AD();
hueman-addons.php DELETED
@@ -1,334 +0,0 @@
1
- <?php
2
- /**
3
- * Plugin Name: Hueman Addons
4
- * Plugin URI: http://presscustomizr.com
5
- * Description: Hueman Theme Addons
6
- * Version: 1.0.8
7
- * Text Domain: hueman-addons
8
- * Author: Press Customizr
9
- * Author URI: http://presscustomizr.com
10
- * License: GPLv2 or later
11
- */
12
-
13
-
14
- /**
15
- * Fires the plugin
16
- * @author Nicolas GUILLAUME
17
- * @since 1.0
18
- */
19
- if ( ! class_exists( 'HU_addons_plugin' ) ) :
20
- class HU_addons_plugin {
21
- //Access any method or var of the class with classname::$instance -> var or method():
22
- static $instance;
23
-
24
- public static $theme;
25
- public static $theme_name;
26
- public $is_customizing;
27
-
28
-
29
- function __construct() {
30
- self::$instance =& $this;
31
-
32
- //checks if is customizing : two context, admin and front (preview frame)
33
- $this -> is_customizing = $this -> tc_is_customizing();
34
-
35
- self::$theme = $this -> tc_get_theme();
36
- self::$theme_name = $this -> tc_get_theme_name();
37
-
38
- //stop execution if not Hueman
39
- if ( false === strpos( self::$theme_name, 'hueman' ) ) {
40
- add_action( 'admin_notices', array( $this , 'hu_admin_notice' ) );
41
- return;
42
- }
43
-
44
- //TEXT DOMAIN
45
- //adds plugin text domain
46
- add_action( 'plugins_loaded', array( $this , 'hu_plugin_lang' ) );
47
-
48
- //SHORTCODES
49
- // Load custom shortcodes
50
- // @fromfull => should me moved in a plugin
51
- add_action( 'wp', array($this, 'hu_shortcodes_actions') );
52
-
53
-
54
-
55
- //SHARRRE
56
- add_action( 'wp_enqueue_scripts', array( $this, 'hu_addons_scripts' ) );
57
- add_filter( 'hu_social_links_sec', array( $this, 'hu_register_sharrre_settings'));
58
- add_action( 'wp', array($this, 'hu_sharrre_front_actions') );
59
-
60
- //CUSTOMIZER PANEL JS
61
- add_action( 'customize_controls_print_footer_scripts', array( $this, 'hu_extend_visibilities' ), 100 );
62
- }//end of construct
63
-
64
-
65
-
66
-
67
- //hook : hu_social_links_sec
68
- function hu_register_sharrre_settings( $settings ) {
69
- $sharrre_settings = array(
70
- 'sharrre' => array(
71
- 'default' => 1,
72
- 'control' => 'HU_controls',
73
- 'label' => __('Display social sharing buttons in your single posts', 'hueman-addons'),
74
- 'title' => __('Social Sharring Bar Settings', 'hueman-addons'),
75
- 'notice' => __('Display social sharing buttons in each single articles.', 'hueman-addons'),
76
- 'section' => 'social_links_sec',
77
- 'type' => 'checkbox',
78
- 'priority' => 40
79
- ),
80
- 'sharrre-scrollable' => array(
81
- 'default' => 1,
82
- 'control' => 'HU_controls',
83
- 'label' => __('Make the Share Bar "sticky"', 'hueman-addons'),
84
- 'notice' => __('Make the social share bar stick to the browser window when scrolling down a post.', 'hueman-addons'),
85
- 'section' => 'social_links_sec',
86
- 'type' => 'checkbox',
87
- 'priority' => 50
88
- ),
89
- 'sharrre-twitter-on' => array(
90
- 'default' => 1,
91
- 'control' => 'HU_controls',
92
- 'label' => __('Enable Twitter Button', 'hueman-addons'),
93
- 'section' => 'social_links_sec',
94
- 'type' => 'checkbox',
95
- 'notice' => __('Since Nov. 2015, Twitter disabled the share counts from its API. If you want to get the display count anyway, you can create an account for free (as of Feb. 2016) on [https://opensharecount.com/]. The Hueman Addons plugin is configured to use opensharecount.', 'hueman-addons'),
96
- 'priority' => 60
97
- ),
98
- 'twitter-username' => array(
99
- 'default' => '',
100
- 'control' => 'HU_controls',
101
- 'label' => __('Twitter Username (without "@")', 'hueman-addons'),
102
- 'notice' => __('Simply enter your username without the "@" prefix. Your username will be added to share-tweets of your posts (optional).', 'hueman-addons'),
103
- 'section' => 'social_links_sec',
104
- 'type' => 'text',
105
- 'transport' => 'postMessage',
106
- 'priority' => 70
107
- ),
108
- 'sharrre-facebook-on' => array(
109
- 'default' => 1,
110
- 'control' => 'HU_controls',
111
- 'label' => __('Enable Facebook Button', 'hueman-addons'),
112
- 'section' => 'social_links_sec',
113
- 'type' => 'checkbox',
114
- 'priority' => 80
115
- ),
116
- 'sharrre-google-on' => array(
117
- 'default' => 1,
118
- 'control' => 'HU_controls',
119
- 'label' => __('Enable Google Plus Button', 'hueman-addons'),
120
- 'section' => 'social_links_sec',
121
- 'type' => 'checkbox',
122
- 'priority' => 90
123
- ),
124
- 'sharrre-pinterest-on' => array(
125
- 'default' => 0,
126
- 'control' => 'HU_controls',
127
- 'label' => __('Enable Pinterest Button', 'hueman-addons'),
128
- 'section' => 'social_links_sec',
129
- 'type' => 'checkbox',
130
- 'priority' => 100
131
- ),
132
- 'sharrre-linkedin-on' => array(
133
- 'default' => 0,
134
- 'control' => 'HU_controls',
135
- 'label' => __('Enable LinkedIn Button', 'hueman-addons'),
136
- 'section' => 'social_links_sec',
137
- 'type' => 'checkbox',
138
- 'priority' => 100
139
- )
140
- );
141
-
142
- return array_merge( $sharrre_settings, $settings );
143
- }
144
-
145
- function hu_plugin_lang() {
146
- load_plugin_textdomain( 'hueman-addons' , false, basename( dirname( __FILE__ ) ) . '/lang' );
147
- }
148
-
149
- /**************************************************************
150
- ** SHORTCODES
151
- **************************************************************/
152
- function hu_shortcodes_actions() {
153
- load_template( dirname( __FILE__ ) . '/inc/shortcodes.php' );
154
- }
155
-
156
-
157
-
158
- /**************************************************************
159
- ** SHARRRE
160
- **************************************************************/
161
- function hu_sharrre_front_actions() {
162
- if ( ! is_single() )
163
- return;
164
- //alter the single entry wrapper class
165
- add_filter( 'hu_single_entry_class', array($this, 'hu_maybe_add_sharrre_class'));
166
-
167
- //hook the sharrre content to the single post template
168
- add_action( 'hu_after_single_entry_inner', array($this, 'hu_maybe_print_sharrre_template') );
169
- }
170
-
171
-
172
- //@param $classes = array of classes
173
- //hook : hu_single_entry_class
174
- function hu_maybe_add_sharrre_class( $classes ) {
175
- if ( ! hu_are_share_buttons_enabled() )
176
- return $classes;
177
- $classes[] = 'share';
178
- return $classes;
179
- }
180
-
181
- //hook : hu_after_single_entry_inner
182
- function hu_maybe_print_sharrre_template() {
183
- if ( ! hu_are_share_buttons_enabled() )
184
- return;
185
-
186
- load_template( dirname( __FILE__ ) . '/inc/sharrre-template.php' );
187
- }
188
-
189
-
190
-
191
-
192
-
193
-
194
- //hook : wp_enqueue_scripts
195
- function hu_addons_scripts() {
196
- if ( is_singular() ) {
197
- wp_enqueue_script(
198
- 'sharrre',
199
- sprintf( '%1$s/assets/front/js/jQuerySharrre%2$s', plugins_url( basename( __DIR__ ) ), (defined('TC_DEV') && true === TC_DEV) ? '.js' : '.min.js' ),
200
- array( 'jquery' ),
201
- '',
202
- true
203
- );
204
- }
205
- }
206
-
207
-
208
- //hook : 'customize_controls_enqueue_scripts'
209
- function hu_extend_visibilities() {
210
- ?>
211
- <script type="text/javascript">
212
- (function (api, $, _) {
213
- var _oldDeps = api.CZR_visibilities.prototype.controlDeps;
214
- api.CZR_visibilities.prototype.controlDeps = _.extend( _oldDeps, {
215
- 'sharrre' : {
216
- controls: [
217
- 'sharrre-scrollable',
218
- 'sharrre-twitter-on',
219
- 'twitter-username',
220
- 'sharrre-facebook-on',
221
- 'sharrre-google-on',
222
- 'sharrre-pinterest-on',
223
- 'sharrre-linkedin-on'
224
- ],
225
- callback : function (to) {
226
- return '0' !== to && false !== to && 'off' !== to;
227
- }
228
- },
229
- 'sharrre-twitter-on' : {
230
- controls: [
231
- 'twitter-username'
232
- ],
233
- callback : function (to) {
234
- return '0' !== to && false !== to && 'off' !== to;
235
- }
236
- }
237
- });
238
- }) ( wp.customize, jQuery, _);
239
- </script>
240
- <?php
241
- }
242
-
243
-
244
-
245
- /**
246
- * @uses wp_get_theme() the optional stylesheet parameter value takes into account the possible preview of a theme different than the one activated
247
- *
248
- * @return the (parent) theme object
249
- */
250
- function tc_get_theme(){
251
- // Return the already set theme
252
- if ( self::$theme )
253
- return self::$theme;
254
- // $_REQUEST['theme'] is set both in live preview and when we're customizing a non active theme
255
- $stylesheet = $this -> is_customizing && isset($_REQUEST['theme']) ? $_REQUEST['theme'] : '';
256
-
257
- //gets the theme (or parent if child)
258
- $tc_theme = wp_get_theme($stylesheet);
259
-
260
- return $tc_theme -> parent() ? $tc_theme -> parent() : $tc_theme;
261
-
262
- }
263
-
264
- /**
265
- *
266
- * @return the theme name
267
- *
268
- */
269
- function tc_get_theme_name(){
270
- $tc_theme = $this -> tc_get_theme();
271
-
272
- return sanitize_file_name( strtolower( $tc_theme -> Name ) );
273
- }
274
-
275
-
276
-
277
- function hu_admin_notice() {
278
- $what = __( 'works only with the Hueman theme', 'hueman-addons' );
279
-
280
- ?>
281
- <div class="error">
282
- <p>
283
- <?php
284
- printf( __( 'The <strong>%1$s</strong> plugin %2$s.' ,'hueman-addons' ),
285
- 'Hueman Addons',
286
- $what
287
- );
288
- ?>
289
- </p>
290
- </div>
291
- <?php
292
- }
293
-
294
-
295
- /**
296
- * Returns a boolean on the customizer's state
297
- * @since 3.2.9
298
- */
299
- function tc_is_customizing() {
300
- //checks if is customizing : two contexts, admin and front (preview frame)
301
- global $pagenow;
302
- $bool = false;
303
- if ( is_admin() && isset( $pagenow ) && 'customize.php' == $pagenow )
304
- $bool = true;
305
- if ( ! is_admin() && isset($_REQUEST['wp_customize']) )
306
- $bool = true;
307
- if ( $this -> tc_doing_customizer_ajax() )
308
- $bool = true;
309
- return $bool;
310
- }
311
-
312
- /**
313
- * Returns a boolean
314
- * @since 3.3.2
315
- */
316
- function tc_doing_customizer_ajax() {
317
- return isset( $_POST['customized'] ) && ( defined( 'DOING_AJAX' ) && DOING_AJAX );
318
- }
319
-
320
- } //end of class
321
-
322
- //Creates a new instance of front and admin
323
- new HU_addons_plugin;
324
-
325
- endif;
326
-
327
- //@return bool
328
- function hu_are_share_buttons_enabled() {
329
- if ( ! hu_is_checked('sharrre') )
330
- return;
331
- if ( ! hu_is_checked('sharrre-twitter-on') && ! hu_is_checked('sharrre-facebook-on') && ! hu_is_checked('sharrre-google-on') && ! hu_is_checked('sharrre-pinterest-on') && ! hu_is_checked('sharrre-linkedin-on') )
332
- return;
333
- return true;
334
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
inc/czr/ha-czr.php ADDED
@@ -0,0 +1,124 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class HA_Czr {
3
+ static $instance;
4
+ function __construct() {
5
+ self::$instance =& $this;
6
+
7
+ //CUSTOMIZER PANEL JS
8
+ add_action( 'customize_controls_print_footer_scripts', array( $this, 'hu_extend_visibilities' ), 100 );
9
+ //Various DOM ready actions + print rate link + template
10
+ add_action( 'customize_controls_print_footer_scripts' , array( $this, 'hu_various_dom_ready' ) );
11
+ //control style
12
+ add_action( 'customize_controls_enqueue_scripts' , array( $this, 'hu_customize_controls_js_css' ) );
13
+ }
14
+
15
+ /**************************************************************
16
+ ** CUSTOMIZER
17
+ **************************************************************/
18
+ /**
19
+ * Add script to controls
20
+ * Dependency : customize-controls located in wp-includes/script-loader.php
21
+ * Hooked on customize_controls_enqueue_scripts located in wp-admin/customize.php
22
+ * @package Hueman
23
+ * @since Hueman 3.3.0
24
+ */
25
+ function hu_customize_controls_js_css() {
26
+
27
+ wp_enqueue_style(
28
+ 'hu-czr-addons-controls-style',
29
+ sprintf( '%1$sassets/czr/css/czr-control-footer.css', HA_BASE_URL ),
30
+ array( 'customize-controls' ),
31
+ time(),
32
+ $media = 'all'
33
+ );
34
+
35
+ }
36
+
37
+
38
+
39
+
40
+ //hook : customize_controls_print_footer_scripts
41
+ function hu_various_dom_ready() {
42
+ ?>
43
+ <script id="rate-tpl" type="text/template" >
44
+ <?php
45
+ printf( '<span class="czr-rate-link">%1$s %2$s, <br/>%3$s <a href="%4$s" title="%5$s" class="czr-stars" target="_blank">%6$s</a> %7$s</span>',
46
+ __( 'If you like' , 'hueman' ),
47
+ __( 'the Hueman theme' , 'hueman'),
48
+ __( 'we would love to receive a' , 'hueman' ),
49
+ 'https://' . 'wordpress.org/support/view/theme-reviews/hueman?filter=5',
50
+ __( 'Review the Hueman theme' , 'hueman' ),
51
+ '&#9733;&#9733;&#9733;&#9733;&#9733;',
52
+ __( 'rating. Thanks :) !' , 'hueman')
53
+ );
54
+ ?>
55
+ </script>
56
+ <script id="rate-theme" type="text/javascript">
57
+ (function ($) {
58
+ $( function($) {
59
+ //Render the rate link
60
+ _render_rate_czr();
61
+ function _render_rate_czr() {
62
+ var _cta = _.template(
63
+ $( "script#rate-tpl" ).html()
64
+ );
65
+ $('#customize-footer-actions').append( _cta() );
66
+ }
67
+
68
+ /* Append text to the content panel title */
69
+ if ( $('#accordion-panel-hu-content-panel').find('.accordion-section-title').first().length ) {
70
+ $('#accordion-panel-hu-content-panel').find('.accordion-section-title').first().append(
71
+ $('<span/>', { html : ' ( Home, Blog, Layout, Sidebars, Slideshows, ... )' } ).css('font-style', 'italic').css('font-size', '14px')
72
+ );
73
+ }
74
+ });
75
+ })(jQuery)
76
+ </script>
77
+ <?php
78
+ }
79
+
80
+
81
+ //hook : 'customize_controls_enqueue_scripts'
82
+ function hu_extend_visibilities() {
83
+ ?>
84
+ <script type="text/javascript">
85
+ (function (api, $, _) {
86
+ if ( ! _.has( api, 'CZR_ctrlDependencies') )
87
+ return;
88
+ //@return boolean
89
+ var _is_checked = function( to ) {
90
+ return 0 !== to && '0' !== to && false !== to && 'off' !== to;
91
+ };
92
+ api.CZR_ctrlDependencies.prototype.dominiDeps = _.extend(
93
+ api.CZR_ctrlDependencies.prototype.dominiDeps,
94
+ [
95
+ {
96
+ dominus : 'sharrre',
97
+ servi : [
98
+ 'sharrre-scrollable',
99
+ 'sharrre-twitter-on',
100
+ 'twitter-username',
101
+ 'sharrre-facebook-on',
102
+ 'sharrre-google-on',
103
+ 'sharrre-pinterest-on',
104
+ 'sharrre-linkedin-on'
105
+ ],
106
+ visibility : function (to) {
107
+ return _is_checked(to);
108
+ }
109
+ },
110
+ {
111
+ dominus : 'sharrre-twitter-on',
112
+ servi : ['twitter-username'],
113
+ visibility : function (to) {
114
+ return _is_checked(to);
115
+ }
116
+ },
117
+ ]
118
+ );
119
+ }) ( wp.customize, jQuery, _);
120
+ </script>
121
+ <?php
122
+ }
123
+
124
+ }//end of class
inc/sek/assets/js/dom-autoscroller.js ADDED
@@ -0,0 +1,287 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.autoScroller = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
2
+ var createPointCB = require('create-point-cb');
3
+
4
+ /*
5
+ git remote add origin https://github.com/hollowdoor/dom_autoscroller.git
6
+ git push -u origin master
7
+ */
8
+
9
+
10
+
11
+ function AutoScroller(elements, options){
12
+ var self = this, pixels = 2;
13
+ options = options || {};
14
+
15
+ this.margin = options.margin || -1;
16
+ this.scrolling = false;
17
+ this.scrollWhenOutside = options.scrollWhenOutside || false;
18
+
19
+ var point = {}, pointCB = createPointCB(point), down = false;
20
+
21
+ window.addEventListener('mousemove', pointCB, false);
22
+ window.addEventListener('touchmove', pointCB, false);
23
+
24
+ if(!isNaN(options.pixels)){
25
+ pixels = options.pixels;
26
+ }
27
+
28
+ if(typeof options.autoScroll === 'boolean'){
29
+ this.autoScroll = options.autoScroll ? function(){return true;} : function(){return false;};
30
+ }else if(typeof options.autoScroll === 'undefined'){
31
+ this.autoScroll = function(){return false;};
32
+ }else if(typeof options.autoScroll === 'function'){
33
+ this.autoScroll = options.autoScroll;
34
+ }
35
+
36
+ this.destroy = function() {
37
+ window.removeEventListener('mousemove', pointCB, false);
38
+ window.removeEventListener('touchmove', pointCB, false);
39
+ window.removeEventListener('mousedown', onDown, false);
40
+ window.removeEventListener('touchstart', onDown, false);
41
+ window.removeEventListener('mouseup', onUp, false);
42
+ window.removeEventListener('touchend', onUp, false);
43
+ };
44
+
45
+ var hasWindow = null, temp = [];
46
+ for(var i=0; i<elements.length; i++){
47
+ if(elements[i] === window){
48
+ hasWindow = window;
49
+ break;
50
+ }else{
51
+ temp.push(elements[i])
52
+ }
53
+ }
54
+
55
+ elements = temp;
56
+ temp = null;
57
+
58
+ Object.defineProperties(this, {
59
+ down: {
60
+ get: function(){ return down; }
61
+ },
62
+ interval: {
63
+ get: function(){ return 1/pixels * 1000; }
64
+ },
65
+ pixels: {
66
+ set: function(i){ pixels = i; },
67
+ get: function(){ return pixels; }
68
+ }
69
+ });
70
+
71
+ window.addEventListener('mousedown', onDown, false);
72
+ window.addEventListener('touchstart', onDown, false);
73
+ window.addEventListener('mouseup', onUp, false);
74
+ window.addEventListener('touchend', onUp, false);
75
+
76
+ function onDown(){
77
+ down = true;
78
+ }
79
+
80
+ function onUp(){
81
+ down = false;
82
+ }
83
+
84
+ var n = 0, current;
85
+
86
+ window.addEventListener('mousemove', onMove, false);
87
+ window.addEventListener('touchmove', onMove, false);
88
+
89
+ function onMove(event){
90
+
91
+ if(!self.autoScroll()) return;
92
+ if(!event.target) return;
93
+ var target = event.target, last;
94
+
95
+ if(!current || !inside(point, current)){
96
+ if(!current && target){
97
+ current = null;
98
+ while(target = target.parentNode){
99
+ for(var i=0; i<elements.length; i++){
100
+ if(elements[i] === target && inside(point, elements[i])){
101
+ current = elements[i];
102
+ break;
103
+ }
104
+ }
105
+ }
106
+ }else{
107
+ last = current;
108
+ current = null;
109
+ for(var i=0; i<elements.length; i++){
110
+ if(elements[i] !== last && inside(point, elements[i])){
111
+ current = elements[i];
112
+ }
113
+ }
114
+ }
115
+ }
116
+
117
+ if(hasWindow){
118
+ autoScroll(hasWindow);
119
+ }
120
+ if(!current) return;
121
+
122
+ autoScroll(current);
123
+ }
124
+
125
+ function autoScroll(el){
126
+ var rect = getRect(el);
127
+
128
+ if(point.y < rect.top + self.margin){
129
+ autoScrollV(el, -1, rect);
130
+ }else if(point.y > rect.bottom - self.margin){
131
+ autoScrollV(el, 1, rect);
132
+ }
133
+
134
+ if(point.x < rect.left + self.margin){
135
+ autoScrollH(el, -1, rect);
136
+ }else if(point.x > rect.right - self.margin){
137
+ autoScrollH(el, 1, rect);
138
+ }
139
+ }
140
+
141
+
142
+
143
+ function autoScrollV(el, amount, rect){
144
+ if(!self.autoScroll()) return;
145
+ if(!self.scrollWhenOutside && !inside(point, el, rect)) return;
146
+
147
+ if(el === window){
148
+ window.scrollTo(el.pageXOffset, el.pageYOffset + amount);
149
+ }else{
150
+
151
+ el.scrollTop = el.scrollTop + amount;
152
+ }
153
+
154
+ setTimeout(function(){
155
+ if(point.y < rect.top + self.margin){
156
+ autoScrollV(el, amount, rect);
157
+ }else if(point.y > rect.bottom - self.margin){
158
+ autoScrollV(el, amount, rect);
159
+ }
160
+ }, self.interval);
161
+ }
162
+
163
+ function autoScrollH(el, amount, rect){
164
+
165
+ if(!self.autoScroll()) return;
166
+ if(!self.scrollWhenOutside && !inside(point, el, rect)) return;
167
+
168
+ if(el === window){
169
+ window.scrollTo(el.pageXOffset + amount, el.pageYOffset);
170
+ }else{
171
+ el.scrollLeft = el.scrollLeft + amount;
172
+ }
173
+
174
+ setTimeout(function(){
175
+ if(point.x < rect.left + self.margin){
176
+ autoScrollH(el, amount, rect);
177
+ }else if(point.x > rect.right - self.margin){
178
+ autoScrollH(el, amount, rect);
179
+ }
180
+ }, self.interval);
181
+ }
182
+
183
+ }
184
+
185
+ module.exports = function AutoScrollerFactory(element, options){
186
+ return new AutoScroller(element, options);
187
+ };
188
+
189
+ function getRect(el){
190
+ if(el === window){
191
+ return {
192
+ top: 0,
193
+ left: 0,
194
+ right: window.innerWidth,
195
+ bottom: window.innerHeight,
196
+ width: window.innerWidth,
197
+ height: window.innerHeight
198
+ };
199
+
200
+ }else{
201
+ try{
202
+ return el.getBoundingClientRect();
203
+ }catch(e){
204
+ throw new TypeError("Can't call getBoundingClientRect on "+el);
205
+ }
206
+
207
+ }
208
+ }
209
+
210
+ function inside(point, el, rect){
211
+ rect = rect || getRect(el);
212
+ return (point.y > rect.top && point.y < rect.bottom &&
213
+ point.x > rect.left && point.x < rect.right);
214
+ }
215
+
216
+ },{"create-point-cb":2}],2:[function(require,module,exports){
217
+ module.exports = function createPointCB(object){
218
+
219
+ // A persistent object (as opposed to returned object) is used to save memory
220
+ // This is good to prevent layout thrashing, or for games, and such
221
+
222
+ // NOTE
223
+ // This uses IE fixes which should be OK to remove some day. :)
224
+ // Some speed will be gained by removal of these.
225
+
226
+ // pointCB should be saved in a variable on return
227
+ // This allows the usage of element.removeEventListener
228
+
229
+ return function pointCB(event){
230
+
231
+ event = event || window.event; // IE-ism
232
+ object.target = event.target || event.srcElement || event.originalTarget;
233
+ object.element = this;
234
+ object.type = event.type;
235
+
236
+ // Support touch
237
+ // http://www.creativebloq.com/javascript/make-your-site-work-touch-devices-51411644
238
+
239
+ if(event.targetTouches){
240
+ object.x = event.targetTouches[0].clientX;
241
+ object.y = event.targetTouches[0].clientY;
242
+ object.pageX = event.pageX;
243
+ object.pageY = event.pageY;
244
+ }else{
245
+
246
+ // If pageX/Y aren't available and clientX/Y are,
247
+ // calculate pageX/Y - logic taken from jQuery.
248
+ // (This is to support old IE)
249
+ // NOTE Hopefully this can be removed soon.
250
+
251
+ if (event.pageX === null && event.clientX !== null) {
252
+ var eventDoc = (event.target && event.target.ownerDocument) || document;
253
+ var doc = eventDoc.documentElement;
254
+ var body = eventDoc.body;
255
+
256
+ object.pageX = event.clientX +
257
+ (doc && doc.scrollLeft || body && body.scrollLeft || 0) -
258
+ (doc && doc.clientLeft || body && body.clientLeft || 0);
259
+ object.pageY = event.clientY +
260
+ (doc && doc.scrollTop || body && body.scrollTop || 0) -
261
+ (doc && doc.clientTop || body && body.clientTop || 0 );
262
+ }else{
263
+ object.pageX = event.pageX;
264
+ object.pageY = event.pageY;
265
+ }
266
+
267
+ // pageX, and pageY change with page scroll
268
+ // so we're not going to use those for x, and y.
269
+ // NOTE Most browsers also alias clientX/Y with x/y
270
+ // so that's something to consider down the road.
271
+
272
+ object.x = event.clientX;
273
+ object.y = event.clientY;
274
+ }
275
+
276
+ };
277
+
278
+ //NOTE Remember accessibility, Aria roles, and labels.
279
+ };
280
+
281
+ /*
282
+ git remote add origin https://github.com/hollowdoor/create_point_cb.git
283
+ git push -u origin master
284
+ */
285
+
286
+ },{}]},{},[1])(1)
287
+ });
inc/sek/assets/js/dom-autoscroller.min.js ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
1
+ (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.autoScroller = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
2
+ function AutoScroller(e,t){function n(){w=!0}function o(){w=!1}function i(t){if(s.autoScroll()&&t.target){var n,o=t.target;if(!h||!inside(c,h))if(!h&&o){for(h=null;o=o.parentNode;)for(var i=0;i<e.length;i++)if(e[i]===o&&inside(c,e[i])){h=e[i];break}}else{n=h,h=null;for(var i=0;i<e.length;i++)e[i]!==n&&inside(c,e[i])&&(h=e[i])}f&&r(f),h&&r(h)}}function r(e){var t=getRect(e);c.y<t.top+s.margin?l(e,-1,t):c.y>t.bottom-s.margin&&l(e,1,t),c.x<t.left+s.margin?u(e,-1,t):c.x>t.right-s.margin&&u(e,1,t)}function l(e,t,n){s.autoScroll()&&(s.scrollWhenOutside||inside(c,e,n))&&(e===window?window.scrollTo(e.pageXOffset,e.pageYOffset+t):e.scrollTop=e.scrollTop+t,setTimeout(function(){c.y<n.top+s.margin?l(e,t,n):c.y>n.bottom-s.margin&&l(e,t,n)},s.interval))}function u(e,t,n){s.autoScroll()&&(s.scrollWhenOutside||inside(c,e,n))&&(e===window?window.scrollTo(e.pageXOffset+t,e.pageYOffset):e.scrollLeft=e.scrollLeft+t,setTimeout(function(){c.x<n.left+s.margin?u(e,t,n):c.x>n.right-s.margin&&u(e,t,n)},s.interval))}var s=this,d=2;t=t||{},this.margin=t.margin||-1,this.scrolling=!1,this.scrollWhenOutside=t.scrollWhenOutside||!1;var c={},a=createPointCB(c),w=!1;window.addEventListener("mousemove",a,!1),window.addEventListener("touchmove",a,!1),isNaN(t.pixels)||(d=t.pixels),"boolean"==typeof t.autoScroll?this.autoScroll=t.autoScroll?function(){return!0}:function(){return!1}:"undefined"==typeof t.autoScroll?this.autoScroll=function(){return!1}:"function"==typeof t.autoScroll&&(this.autoScroll=t.autoScroll),this.destroy=function(){window.removeEventListener("mousemove",a,!1),window.removeEventListener("touchmove",a,!1),window.removeEventListener("mousedown",n,!1),window.removeEventListener("touchstart",n,!1),window.removeEventListener("mouseup",o,!1),window.removeEventListener("touchend",o,!1)};for(var f=null,v=[],g=0;g<e.length;g++){if(e[g]===window){f=window;break}v.push(e[g])}e=v,v=null,Object.defineProperties(this,{down:{get:function(){return w}},interval:{get:function(){return 1/d*1e3}},pixels:{set:function(e){d=e},get:function(){return d}}}),window.addEventListener("mousedown",n,!1),window.addEventListener("touchstart",n,!1),window.addEventListener("mouseup",o,!1),window.addEventListener("touchend",o,!1);var h;window.addEventListener("mousemove",i,!1),window.addEventListener("touchmove",i,!1)}function getRect(e){if(e===window)return{top:0,left:0,right:window.innerWidth,bottom:window.innerHeight,width:window.innerWidth,height:window.innerHeight};try{return e.getBoundingClientRect()}catch(t){throw new TypeError("Can't call getBoundingClientRect on "+e)}}function inside(e,t,n){return n=n||getRect(t),e.y>n.top&&e.y<n.bottom&&e.x>n.left&&e.x<n.right}var createPointCB=require("create-point-cb");module.exports=function(e,t){return new AutoScroller(e,t)};
3
+ },{"create-point-cb":2}],2:[function(require,module,exports){
4
+ module.exports=function(e){return function(t){if(t=t||window.event,e.target=t.target||t.srcElement||t.originalTarget,e.element=this,e.type=t.type,t.targetTouches)e.x=t.targetTouches[0].clientX,e.y=t.targetTouches[0].clientY,e.pageX=t.pageX,e.pageY=t.pageY;else{if(null===t.pageX&&null!==t.clientX){var l=t.target&&t.target.ownerDocument||document,n=l.documentElement,c=l.body;e.pageX=t.clientX+(n&&n.scrollLeft||c&&c.scrollLeft||0)-(n&&n.clientLeft||c&&c.clientLeft||0),e.pageY=t.clientY+(n&&n.scrollTop||c&&c.scrollTop||0)-(n&&n.clientTop||c&&c.clientTop||0)}else e.pageX=t.pageX,e.pageY=t.pageY;e.x=t.clientX,e.y=t.clientY}}};
5
+ },{}]},{},[1])(1)
6
+ });
inc/sek/assets/js/dragula.min.js ADDED
@@ -0,0 +1,905 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.dragula = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
2
+ 'use strict';
3
+
4
+ var cache = {};
5
+ var start = '(?:^|\\s)';
6
+ var end = '(?:\\s|$)';
7
+
8
+ function lookupClass (className) {
9
+ var cached = cache[className];
10
+ if (cached) {
11
+ cached.lastIndex = 0;
12
+ } else {
13
+ cache[className] = cached = new RegExp(start + className + end, 'g');
14
+ }
15
+ return cached;
16
+ }
17
+
18
+ function addClass (el, className) {
19
+ var current = el.className;
20
+ if (!current.length) {
21
+ el.className = className;
22
+ } else if (!lookupClass(className).test(current)) {
23
+ el.className += ' ' + className;
24
+ }
25
+ }
26
+
27
+ function rmClass (el, className) {
28
+ el.className = el.className.replace(lookupClass(className), ' ').trim();
29
+ }
30
+
31
+ module.exports = {
32
+ add: addClass,
33
+ rm: rmClass
34
+ };
35
+
36
+ },{}],2:[function(require,module,exports){
37
+ (function (global){
38
+ 'use strict';
39
+
40
+ var emitter = require('contra/emitter');
41
+ var crossvent = require('crossvent');
42
+ var classes = require('./classes');
43
+ var doc = document;
44
+ var documentElement = doc.documentElement;
45
+
46
+ function dragula (initialContainers, options) {
47
+ var len = arguments.length;
48
+ if (len === 1 && Array.isArray(initialContainers) === false) {
49
+ options = initialContainers;
50
+ initialContainers = [];
51
+ }
52
+ var _mirror; // mirror image
53
+ var _source; // source container
54
+ var _item; // item being dragged
55
+ var _offsetX; // reference x
56
+ var _offsetY; // reference y
57
+ var _moveX; // reference move x
58
+ var _moveY; // reference move y
59
+ var _initialSibling; // reference sibling when grabbed
60
+ var _currentSibling; // reference sibling now
61
+ var _copy; // item used for copying
62
+ var _renderTimer; // timer for setTimeout renderMirrorImage
63
+ var _lastDropTarget = null; // last container item was over
64
+ var _grabbed; // holds mousedown context until first mousemove
65
+
66
+ var o = options || {};
67
+ if (o.moves === void 0) { o.moves = always; }
68
+ if (o.accepts === void 0) { o.accepts = always; }
69
+ if (o.invalid === void 0) { o.invalid = invalidTarget; }
70
+ if (o.containers === void 0) { o.containers = initialContainers || []; }
71
+ if (o.isContainer === void 0) { o.isContainer = never; }
72
+ if (o.copy === void 0) { o.copy = false; }
73
+ if (o.copySortSource === void 0) { o.copySortSource = false; }
74
+ if (o.revertOnSpill === void 0) { o.revertOnSpill = false; }
75
+ if (o.removeOnSpill === void 0) { o.removeOnSpill = false; }
76
+ if (o.direction === void 0) { o.direction = 'vertical'; }
77
+ if (o.ignoreInputTextSelection === void 0) { o.ignoreInputTextSelection = true; }
78
+ if (o.mirrorContainer === void 0) { o.mirrorContainer = doc.body; }
79
+
80
+ var drake = emitter({
81
+ containers: o.containers,
82
+ start: manualStart,
83
+ end: end,
84
+ cancel: cancel,
85
+ remove: remove,
86
+ destroy: destroy,
87
+ canMove: canMove,
88
+ dragging: false
89
+ });
90
+
91
+ if (o.removeOnSpill === true) {
92
+ drake.on('over', spillOver).on('out', spillOut);
93
+ }
94
+
95
+ events();
96
+
97
+ return drake;
98
+
99
+ function isContainer (el) {
100
+ return drake.containers.indexOf(el) !== -1 || o.isContainer(el);
101
+ }
102
+
103
+ function events (remove) {
104
+ var op = remove ? 'remove' : 'add';
105
+ touchy(documentElement, op, 'mousedown', grab);
106
+ touchy(documentElement, op, 'mouseup', release);
107
+ }
108
+
109
+ function eventualMovements (remove) {
110
+ var op = remove ? 'remove' : 'add';
111
+ touchy(documentElement, op, 'mousemove', startBecauseMouseMoved);
112
+ }
113
+
114
+ function movements (remove) {
115
+ var op = remove ? 'remove' : 'add';
116
+ crossvent[op](documentElement, 'selectstart', preventGrabbed); // IE8
117
+ crossvent[op](documentElement, 'click', preventGrabbed);
118
+ }
119
+
120
+ function destroy () {
121
+ events(true);
122
+ release({});
123
+ }
124
+
125
+ function preventGrabbed (e) {
126
+ if (_grabbed) {
127
+ e.preventDefault();
128
+ }
129
+ }
130
+
131
+ function grab (e) {
132
+ _moveX = e.clientX;
133
+ _moveY = e.clientY;
134
+
135
+ var ignore = whichMouseButton(e) !== 1 || e.metaKey || e.ctrlKey;
136
+ if (ignore) {
137
+ return; // we only care about honest-to-god left clicks and touch events
138
+ }
139
+ var item = e.target;
140
+ var context = canStart(item);
141
+ if (!context) {
142
+ return;
143
+ }
144
+ _grabbed = context;
145
+ eventualMovements();
146
+ if (e.type === 'mousedown') {
147
+ if (isInput(item)) { // see also: https://github.com/bevacqua/dragula/issues/208
148
+ item.focus(); // fixes https://github.com/bevacqua/dragula/issues/176
149
+ } else {
150
+ e.preventDefault(); // fixes https://github.com/bevacqua/dragula/issues/155
151
+ }
152
+ }
153
+ }
154
+
155
+ function startBecauseMouseMoved (e) {
156
+ if (!_grabbed) {
157
+ return;
158
+ }
159
+ if (whichMouseButton(e) === 0) {
160
+ release({});
161
+ return; // when text is selected on an input and then dragged, mouseup doesn't fire. this is our only hope
162
+ }
163
+ // truthy check fixes #239, equality fixes #207
164
+ if (e.clientX !== void 0 && e.clientX === _moveX && e.clientY !== void 0 && e.clientY === _moveY) {
165
+ return;
166
+ }
167
+ if (o.ignoreInputTextSelection) {
168
+ var clientX = getCoord('clientX', e);
169
+ var clientY = getCoord('clientY', e);
170
+ var elementBehindCursor = doc.elementFromPoint(clientX, clientY);
171
+ if (isInput(elementBehindCursor)) {
172
+ return;
173
+ }
174
+ }
175
+
176
+ var grabbed = _grabbed; // call to end() unsets _grabbed
177
+ eventualMovements(true);
178
+ movements();
179
+ end();
180
+ start(grabbed);
181
+
182
+ var offset = getOffset(_item);
183
+ _offsetX = getCoord('pageX', e) - offset.left;
184
+ _offsetY = getCoord('pageY', e) - offset.top;
185
+
186
+ classes.add(_copy || _item, 'gu-transit');
187
+ renderMirrorImage();
188
+ drag(e);
189
+ }
190
+
191
+ function canStart (item) {
192
+ if (drake.dragging && _mirror) {
193
+ return;
194
+ }
195
+ if (isContainer(item)) {
196
+ return; // don't drag container itself
197
+ }
198
+ var handle = item;
199
+ while (getParent(item) && isContainer(getParent(item)) === false) {
200
+ if (o.invalid(item, handle)) {
201
+ return;
202
+ }
203
+ item = getParent(item); // drag target should be a top element
204
+ if (!item) {
205
+ return;
206
+ }
207
+ }
208
+ var source = getParent(item);
209
+ if (!source) {
210
+ return;
211
+ }
212
+ if (o.invalid(item, handle)) {
213
+ return;
214
+ }
215
+
216
+ var movable = o.moves(item, source, handle, nextEl(item));
217
+ if (!movable) {
218
+ return;
219
+ }
220
+
221
+ return {
222
+ item: item,
223
+ source: source
224
+ };
225
+ }
226
+
227
+ function canMove (item) {
228
+ return !!canStart(item);
229
+ }
230
+
231
+ function manualStart (item) {
232
+ var context = canStart(item);
233
+ if (context) {
234
+ start(context);
235
+ }
236
+ }
237
+
238
+ function start (context) {
239
+ if (isCopy(context.item, context.source)) {
240
+ _copy = context.item.cloneNode(true);
241
+ drake.emit('cloned', _copy, context.item, 'copy');
242
+ }
243
+
244
+ _source = context.source;
245
+ _item = context.item;
246
+ _initialSibling = _currentSibling = nextEl(context.item);
247
+
248
+ drake.dragging = true;
249
+ drake.emit('drag', _item, _source);
250
+ }
251
+
252
+ function invalidTarget () {
253
+ return false;
254
+ }
255
+
256
+ function end () {
257
+ if (!drake.dragging) {
258
+ return;
259
+ }
260
+ var item = _copy || _item;
261
+ drop(item, getParent(item));
262
+ }
263
+
264
+ function ungrab () {
265
+ _grabbed = false;
266
+ eventualMovements(true);
267
+ movements(true);
268
+ }
269
+
270
+ function release (e) {
271
+ ungrab();
272
+
273
+ if (!drake.dragging) {
274
+ return;
275
+ }
276
+ var item = _copy || _item;
277
+ var clientX = getCoord('clientX', e);
278
+ var clientY = getCoord('clientY', e);
279
+ var elementBehindCursor = getElementBehindPoint(_mirror, clientX, clientY);
280
+ var dropTarget = findDropTarget(elementBehindCursor, clientX, clientY);
281
+ if (dropTarget && ((_copy && o.copySortSource) || (!_copy || dropTarget !== _source))) {
282
+ drop(item, dropTarget);
283
+ } else if (o.removeOnSpill) {
284
+ remove();
285
+ } else {
286
+ cancel();
287
+ }
288
+ }
289
+
290
+ function drop (item, target) {
291
+ var parent = getParent(item);
292
+ if (_copy && o.copySortSource && target === _source) {
293
+ parent.removeChild(_item);
294
+ }
295
+ if (isInitialPlacement(target)) {
296
+ drake.emit('cancel', item, _source, _source);
297
+ } else {
298
+ drake.emit('drop', item, target, _source, _currentSibling);
299
+ }
300
+ cleanup();
301
+ }
302
+
303
+ function remove () {
304
+ if (!drake.dragging) {
305
+ return;
306
+ }
307
+ var item = _copy || _item;
308
+ var parent = getParent(item);
309
+ if (parent) {
310
+ parent.removeChild(item);
311
+ }
312
+ drake.emit(_copy ? 'cancel' : 'remove', item, parent, _source);
313
+ cleanup();
314
+ }
315
+
316
+ function cancel (revert) {
317
+ if (!drake.dragging) {
318
+ return;
319
+ }
320
+ var reverts = arguments.length > 0 ? revert : o.revertOnSpill;
321
+ var item = _copy || _item;
322
+ var parent = getParent(item);
323
+ var initial = isInitialPlacement(parent);
324
+ if (initial === false && reverts) {
325
+ if (_copy) {
326
+ parent.removeChild(_copy);
327
+ } else {
328
+ _source.insertBefore(item, _initialSibling);
329
+ }
330
+ }
331
+ if (initial || reverts) {
332
+ drake.emit('cancel', item, _source, _source);
333
+ } else {
334
+ drake.emit('drop', item, parent, _source, _currentSibling);
335
+ }
336
+ cleanup();
337
+ }
338
+
339
+ function cleanup () {
340
+ var item = _copy || _item;
341
+ ungrab();
342
+ removeMirrorImage();
343
+ if (item) {
344
+ classes.rm(item, 'gu-transit');
345
+ }
346
+ if (_renderTimer) {
347
+ clearTimeout(_renderTimer);
348
+ }
349
+ drake.dragging = false;
350
+ if (_lastDropTarget) {
351
+ drake.emit('out', item, _lastDropTarget, _source);
352
+ }
353
+ drake.emit('dragend', item);
354
+ _source = _item = _copy = _initialSibling = _currentSibling = _renderTimer = _lastDropTarget = null;
355
+ }
356
+
357
+ function isInitialPlacement (target, s) {
358
+ var sibling;
359
+ if (s !== void 0) {
360
+ sibling = s;
361
+ } else if (_mirror) {
362
+ sibling = _currentSibling;
363
+ } else {
364
+ sibling = nextEl(_copy || _item);
365
+ }
366
+ return target === _source && sibling === _initialSibling;
367
+ }
368
+
369
+ function findDropTarget (elementBehindCursor, clientX, clientY) {
370
+ var target = elementBehindCursor;
371
+ while (target && !accepted()) {
372
+ target = getParent(target);
373
+ }
374
+ return target;
375
+
376
+ function accepted () {
377
+ var droppable = isContainer(target);
378
+ if (droppable === false) {
379
+ return false;
380
+ }
381
+
382
+ var immediate = getImmediateChild(target, elementBehindCursor);
383
+ var reference = getReference(target, immediate, clientX, clientY);
384
+ var initial = isInitialPlacement(target, reference);
385
+ if (initial) {
386
+ return true; // should always be able to drop it right back where it was
387
+ }
388
+ return o.accepts(_item, target, _source, reference);
389
+ }
390
+ }
391
+
392
+ function drag (e) {
393
+ if (!_mirror) {
394
+ return;
395
+ }
396
+ e.preventDefault();
397
+
398
+ var clientX = getCoord('clientX', e);
399
+ var clientY = getCoord('clientY', e);
400
+ var x = clientX - _offsetX;
401
+ var y = clientY - _offsetY;
402
+
403
+ _mirror.style.left = x + 'px';
404
+ _mirror.style.top = y + 'px';
405
+
406
+ var item = _copy || _item;
407
+ var elementBehindCursor = getElementBehindPoint(_mirror, clientX, clientY);
408
+ var dropTarget = findDropTarget(elementBehindCursor, clientX, clientY);
409
+ var changed = dropTarget !== null && dropTarget !== _lastDropTarget;
410
+ if (changed || dropTarget === null) {
411
+ out();
412
+ _lastDropTarget = dropTarget;
413
+ over();
414
+ }
415
+ var parent = getParent(item);
416
+ if (dropTarget === _source && _copy && !o.copySortSource) {
417
+ if (parent) {
418
+ parent.removeChild(item);
419
+ }
420
+ return;
421
+ }
422
+ var reference;
423
+ var immediate = getImmediateChild(dropTarget, elementBehindCursor);
424
+ if (immediate !== null) {
425
+ reference = getReference(dropTarget, immediate, clientX, clientY);
426
+ } else if (o.revertOnSpill === true && !_copy) {
427
+ reference = _initialSibling;
428
+ dropTarget = _source;
429
+ } else {
430
+ if (_copy && parent) {
431
+ parent.removeChild(item);
432
+ }
433
+ return;
434
+ }
435
+ if (
436
+ (reference === null && changed) ||
437
+ reference !== item &&
438
+ reference !== nextEl(item)
439
+ ) {
440
+ _currentSibling = reference;
441
+ dropTarget.insertBefore(item, reference);
442
+ drake.emit('shadow', item, dropTarget, _source);
443
+ }
444
+ function moved (type) { drake.emit(type, item, _lastDropTarget, _source); }
445
+ function over () { if (changed) { moved('over'); } }
446
+ function out () { if (_lastDropTarget) { moved('out'); } }
447
+ }
448
+
449
+ function spillOver (el) {
450
+ classes.rm(el, 'gu-hide');
451
+ }
452
+
453
+ function spillOut (el) {
454
+ if (drake.dragging) { classes.add(el, 'gu-hide'); }
455
+ }
456
+
457
+ function renderMirrorImage () {
458
+ if (_mirror) {
459
+ return;
460
+ }
461
+ var rect = _item.getBoundingClientRect();
462
+ _mirror = _item.cloneNode(true);
463
+ _mirror.style.width = getRectWidth(rect) + 'px';
464
+ _mirror.style.height = getRectHeight(rect) + 'px';
465
+ classes.rm(_mirror, 'gu-transit');
466
+ classes.add(_mirror, 'gu-mirror');
467
+ o.mirrorContainer.appendChild(_mirror);
468
+ touchy(documentElement, 'add', 'mousemove', drag);
469
+ classes.add(o.mirrorContainer, 'gu-unselectable');
470
+ drake.emit('cloned', _mirror, _item, 'mirror');
471
+ }
472
+
473
+ function removeMirrorImage () {
474
+ if (_mirror) {
475
+ classes.rm(o.mirrorContainer, 'gu-unselectable');
476
+ touchy(documentElement, 'remove', 'mousemove', drag);
477
+ getParent(_mirror).removeChild(_mirror);
478
+ _mirror = null;
479
+ }
480
+ }
481
+
482
+ function getImmediateChild (dropTarget, target) {
483
+ var immediate = target;
484
+ while (immediate !== dropTarget && getParent(immediate) !== dropTarget) {
485
+ immediate = getParent(immediate);
486
+ }
487
+ if (immediate === documentElement) {
488
+ return null;
489
+ }
490
+ return immediate;
491
+ }
492
+
493
+ function getReference (dropTarget, target, x, y) {
494
+ var horizontal = o.direction === 'horizontal';
495
+ var reference = target !== dropTarget ? inside() : outside();
496
+ return reference;
497
+
498
+ function outside () { // slower, but able to figure out any position
499
+ var len = dropTarget.children.length;
500
+ var i;
501
+ var el;
502
+ var rect;
503
+ for (i = 0; i < len; i++) {
504
+ el = dropTarget.children[i];
505
+ rect = el.getBoundingClientRect();
506
+ if (horizontal && (rect.left + rect.width / 2) > x) { return el; }
507
+ if (!horizontal && (rect.top + rect.height / 2) > y) { return el; }
508
+ }
509
+ return null;
510
+ }
511
+
512
+ function inside () { // faster, but only available if dropped inside a child element
513
+ var rect = target.getBoundingClientRect();
514
+ if (horizontal) {
515
+ return resolve(x > rect.left + getRectWidth(rect) / 2);
516
+ }
517
+ return resolve(y > rect.top + getRectHeight(rect) / 2);
518
+ }
519
+
520
+ function resolve (after) {
521
+ return after ? nextEl(target) : target;
522
+ }
523
+ }
524
+
525
+ function isCopy (item, container) {
526
+ return typeof o.copy === 'boolean' ? o.copy : o.copy(item, container);
527
+ }
528
+ }
529
+
530
+ function touchy (el, op, type, fn) {
531
+ var touch = {
532
+ mouseup: 'touchend',
533
+ mousedown: 'touchstart',
534
+ mousemove: 'touchmove'
535
+ };
536
+ var pointers = {
537
+ mouseup: 'pointerup',
538
+ mousedown: 'pointerdown',
539
+ mousemove: 'pointermove'
540
+ };
541
+ var microsoft = {
542
+ mouseup: 'MSPointerUp',
543
+ mousedown: 'MSPointerDown',
544
+ mousemove: 'MSPointerMove'
545
+ };
546
+ if (global.navigator.pointerEnabled) {
547
+ crossvent[op](el, pointers[type], fn);
548
+ } else if (global.navigator.msPointerEnabled) {
549
+ crossvent[op](el, microsoft[type], fn);
550
+ } else {
551
+ crossvent[op](el, touch[type], fn);
552
+ crossvent[op](el, type, fn);
553
+ }
554
+ }
555
+
556
+ function whichMouseButton (e) {
557
+ if (e.touches !== void 0) { return e.touches.length; }
558
+ if (e.which !== void 0 && e.which !== 0) { return e.which; } // see https://github.com/bevacqua/dragula/issues/261
559
+ if (e.buttons !== void 0) { return e.buttons; }
560
+ var button = e.button;
561
+ if (button !== void 0) { // see https://github.com/jquery/jquery/blob/99e8ff1baa7ae341e94bb89c3e84570c7c3ad9ea/src/event.js#L573-L575
562
+ return button & 1 ? 1 : button & 2 ? 3 : (button & 4 ? 2 : 0);
563
+ }
564
+ }
565
+
566
+ function getOffset (el) {
567
+ var rect = el.getBoundingClientRect();
568
+ return {
569
+ left: rect.left + getScroll('scrollLeft', 'pageXOffset'),
570
+ top: rect.top + getScroll('scrollTop', 'pageYOffset')
571
+ };
572
+ }
573
+
574
+ function getScroll (scrollProp, offsetProp) {
575
+ if (typeof global[offsetProp] !== 'undefined') {
576
+ return global[offsetProp];
577
+ }
578
+ if (documentElement.clientHeight) {
579
+ return documentElement[scrollProp];
580
+ }
581
+ return doc.body[scrollProp];
582
+ }
583
+
584
+ function getElementBehindPoint (point, x, y) {
585
+ var p = point || {};
586
+ var state = p.className;
587
+ var el;
588
+ p.className += ' gu-hide';
589
+ el = doc.elementFromPoint(x, y);
590
+ p.className = state;
591
+ return el;
592
+ }
593
+
594
+ function never () { return false; }
595
+ function always () { return true; }
596
+ function getRectWidth (rect) { return rect.width || (rect.right - rect.left); }
597
+ function getRectHeight (rect) { return rect.height || (rect.bottom - rect.top); }
598
+ function getParent (el) { return el.parentNode === doc ? null : el.parentNode; }
599
+ function isInput (el) { return el.tagName === 'INPUT' || el.tagName === 'TEXTAREA' || el.tagName === 'SELECT' || isEditable(el); }
600
+ function isEditable (el) {
601
+ if (!el) { return false; } // no parents were editable
602
+ if (el.contentEditable === 'false') { return false; } // stop the lookup
603
+ if (el.contentEditable === 'true') { return true; } // found a contentEditable element in the chain
604
+ return isEditable(getParent(el)); // contentEditable is set to 'inherit'
605
+ }
606
+
607
+ function nextEl (el) {
608
+ return el.nextElementSibling || manually();
609
+ function manually () {
610
+ var sibling = el;
611
+ do {
612
+ sibling = sibling.nextSibling;
613
+ } while (sibling && sibling.nodeType !== 1);
614
+ return sibling;
615
+ }
616
+ }
617
+
618
+ function getEventHost (e) {
619
+ // on touchend event, we have to use `e.changedTouches`
620
+ // see http://stackoverflow.com/questions/7192563/touchend-event-properties
621
+ // see https://github.com/bevacqua/dragula/issues/34
622
+ if (e.targetTouches && e.targetTouches.length) {
623
+ return e.targetTouches[0];
624
+ }
625
+ if (e.changedTouches && e.changedTouches.length) {
626
+ return e.changedTouches[0];
627
+ }
628
+ return e;
629
+ }
630
+
631
+ function getCoord (coord, e) {
632
+ var host = getEventHost(e);
633
+ var missMap = {
634
+ pageX: 'clientX', // IE8
635
+ pageY: 'clientY' // IE8
636
+ };
637
+ if (coord in missMap && !(coord in host) && missMap[coord] in host) {
638
+ coord = missMap[coord];
639
+ }
640
+ return host[coord];
641
+ }
642
+
643
+ module.exports = dragula;
644
+
645
+ }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
646
+
647
+ },{"./classes":1,"contra/emitter":4,"crossvent":8}],3:[function(require,module,exports){
648
+ 'use strict';
649
+
650
+ var ticky = require('ticky');
651
+
652
+ module.exports = function debounce (fn, args, ctx) {
653
+ if (!fn) { return; }
654
+ ticky(function run () {
655
+ fn.apply(ctx || null, args || []);
656
+ });
657
+ };
658
+
659
+ },{"ticky":6}],4:[function(require,module,exports){
660
+ 'use strict';
661
+
662
+ var atoa = require('atoa');
663
+ var debounce = require('./debounce');
664
+
665
+ module.exports = function emitter (thing, options) {
666
+ var opts = options || {};
667
+ var evt = {};
668
+ if (thing === undefined) { thing = {}; }
669
+ thing.on = function (type, fn) {
670
+ if (!evt[type]) {
671
+ evt[type] = [fn];
672
+ } else {
673
+ evt[type].push(fn);
674
+ }
675
+ return thing;
676
+ };
677
+ thing.once = function (type, fn) {
678
+ fn._once = true; // thing.off(fn) still works!
679
+ thing.on(type, fn);
680
+ return thing;
681
+ };
682
+ thing.off = function (type, fn) {
683
+ var c = arguments.length;
684
+ if (c === 1) {
685
+ delete evt[type];
686
+ } else if (c === 0) {
687
+ evt = {};
688
+ } else {
689
+ var et = evt[type];
690
+ if (!et) { return thing; }
691
+ et.splice(et.indexOf(fn), 1);
692
+ }
693
+ return thing;
694
+ };
695
+ thing.emit = function () {
696
+ var args = atoa(arguments);
697
+ return thing.emitterSnapshot(args.shift()).apply(this, args);
698
+ };
699
+ thing.emitterSnapshot = function (type) {
700
+ var et = (evt[type] || []).slice(0);
701
+ return function () {
702
+ var args = atoa(arguments);
703
+ var ctx = this || thing;
704
+ if (type === 'error' && opts.throws !== false && !et.length) { throw args.length === 1 ? args[0] : args; }
705
+ et.forEach(function emitter (listen) {
706
+ if (opts.async) { debounce(listen, args, ctx); } else { listen.apply(ctx, args); }
707
+ if (listen._once) { thing.off(type, listen); }
708
+ });
709
+ return thing;
710
+ };
711
+ };
712
+ return thing;
713
+ };
714
+
715
+ },{"./debounce":3,"atoa":5}],5:[function(require,module,exports){
716
+ module.exports = function atoa (a, n) { return Array.prototype.slice.call(a, n); }
717
+
718
+ },{}],6:[function(require,module,exports){
719
+ var si = typeof setImmediate === 'function', tick;
720
+ if (si) {
721
+ tick = function (fn) { setImmediate(fn); };
722
+ } else {
723
+ tick = function (fn) { setTimeout(fn, 0); };
724
+ }
725
+
726
+ module.exports = tick;
727
+ },{}],7:[function(require,module,exports){
728
+ (function (global){
729
+
730
+ var NativeCustomEvent = global.CustomEvent;
731
+
732
+ function useNative () {
733
+ try {
734
+ var p = new NativeCustomEvent('cat', { detail: { foo: 'bar' } });
735
+ return 'cat' === p.type && 'bar' === p.detail.foo;
736
+ } catch (e) {
737
+ }
738
+ return false;
739
+ }
740
+
741
+ /**
742
+ * Cross-browser `CustomEvent` constructor.
743
+ *
744
+ * https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent.CustomEvent
745
+ *
746
+ * @public
747
+ */
748
+
749
+ module.exports = useNative() ? NativeCustomEvent :
750
+
751
+ // IE >= 9
752
+ 'function' === typeof document.createEvent ? function CustomEvent (type, params) {
753
+ var e = document.createEvent('CustomEvent');
754
+ if (params) {
755
+ e.initCustomEvent(type, params.bubbles, params.cancelable, params.detail);
756
+ } else {
757
+ e.initCustomEvent(type, false, false, void 0);
758
+ }
759
+ return e;
760
+ } :
761
+
762
+ // IE <= 8
763
+ function CustomEvent (type, params) {
764
+ var e = document.createEventObject();
765
+ e.type = type;
766
+ if (params) {
767
+ e.bubbles = Boolean(params.bubbles);
768
+ e.cancelable = Boolean(params.cancelable);
769
+ e.detail = params.detail;
770
+ } else {
771
+ e.bubbles = false;
772
+ e.cancelable = false;
773
+ e.detail = void 0;
774
+ }
775
+ return e;
776
+ }
777
+
778
+ }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
779
+
780
+ },{}],8:[function(require,module,exports){
781
+ (function (global){
782
+ 'use strict';
783
+
784
+ var customEvent = require('custom-event');
785
+ var eventmap = require('./eventmap');
786
+ var doc = global.document;
787
+ var addEvent = addEventEasy;
788
+ var removeEvent = removeEventEasy;
789
+ var hardCache = [];
790
+
791
+ if (!global.addEventListener) {
792
+ addEvent = addEventHard;
793
+ removeEvent = removeEventHard;
794
+ }
795
+
796
+ module.exports = {
797
+ add: addEvent,
798
+ remove: removeEvent,
799
+ fabricate: fabricateEvent
800
+ };
801
+
802
+ function addEventEasy (el, type, fn, capturing) {
803
+ return el.addEventListener(type, fn, capturing);
804
+ }
805
+
806
+ function addEventHard (el, type, fn) {
807
+ return el.attachEvent('on' + type, wrap(el, type, fn));
808
+ }
809
+
810
+ function removeEventEasy (el, type, fn, capturing) {
811
+ return el.removeEventListener(type, fn, capturing);
812
+ }
813
+
814
+ function removeEventHard (el, type, fn) {
815
+ var listener = unwrap(el, type, fn);
816
+ if (listener) {
817
+ return el.detachEvent('on' + type, listener);
818
+ }
819
+ }
820
+
821
+ function fabricateEvent (el, type, model) {
822
+ var e = eventmap.indexOf(type) === -1 ? makeCustomEvent() : makeClassicEvent();
823
+ if (el.dispatchEvent) {
824
+ el.dispatchEvent(e);
825
+ } else {
826
+ el.fireEvent('on' + type, e);
827
+ }
828
+ function makeClassicEvent () {
829
+ var e;
830
+ if (doc.createEvent) {
831
+ e = doc.createEvent('Event');
832
+ e.initEvent(type, true, true);
833
+ } else if (doc.createEventObject) {
834
+ e = doc.createEventObject();
835
+ }
836
+ return e;
837
+ }
838
+ function makeCustomEvent () {
839
+ return new customEvent(type, { detail: model });
840
+ }
841
+ }
842
+
843
+ function wrapperFactory (el, type, fn) {
844
+ return function wrapper (originalEvent) {
845
+ var e = originalEvent || global.event;
846
+ e.target = e.target || e.srcElement;
847
+ e.preventDefault = e.preventDefault || function preventDefault () { e.returnValue = false; };
848
+ e.stopPropagation = e.stopPropagation || function stopPropagation () { e.cancelBubble = true; };
849
+ e.which = e.which || e.keyCode;
850
+ fn.call(el, e);
851
+ };
852
+ }
853
+
854
+ function wrap (el, type, fn) {
855
+ var wrapper = unwrap(el, type, fn) || wrapperFactory(el, type, fn);
856
+ hardCache.push({
857
+ wrapper: wrapper,
858
+ element: el,
859
+ type: type,
860
+ fn: fn
861
+ });
862
+ return wrapper;
863
+ }
864
+
865
+ function unwrap (el, type, fn) {
866
+ var i = find(el, type, fn);
867
+ if (i) {
868
+ var wrapper = hardCache[i].wrapper;
869
+ hardCache.splice(i, 1); // free up a tad of memory
870
+ return wrapper;
871
+ }
872
+ }
873
+
874
+ function find (el, type, fn) {
875
+ var i, item;
876
+ for (i = 0; i < hardCache.length; i++) {
877
+ item = hardCache[i];
878
+ if (item.element === el && item.type === type && item.fn === fn) {
879
+ return i;
880
+ }
881
+ }
882
+ }
883
+
884
+ }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
885
+
886
+ },{"./eventmap":9,"custom-event":7}],9:[function(require,module,exports){
887
+ (function (global){
888
+ 'use strict';
889
+
890
+ var eventmap = [];
891
+ var eventname = '';
892
+ var ron = /^on/;
893
+
894
+ for (eventname in global) {
895
+ if (ron.test(eventname)) {
896
+ eventmap.push(eventname.slice(2));
897
+ }
898
+ }
899
+
900
+ module.exports = eventmap;
901
+
902
+ }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
903
+
904
+ },{}]},{},[2])(2)
905
+ });
inc/sek/assets/js/fittext.js ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*global jQuery */
2
+ /*!
3
+ * FitText.js 1.2
4
+ *
5
+ * Copyright 2011, Dave Rupert http://daverupert.com
6
+ * Released under the WTFPL license
7
+ * http://sam.zoy.org/wtfpl/
8
+ *
9
+ * Date: Thu May 05 14:23:00 2011 -0600
10
+ */
11
+
12
+ (function( $ ){
13
+
14
+ $.fn.fitText = function( kompressor, options ) {
15
+
16
+ // Setup options
17
+ var compressor = kompressor || 1,
18
+ settings = $.extend({
19
+ 'minFontSize' : Number.NEGATIVE_INFINITY,
20
+ 'maxFontSize' : Number.POSITIVE_INFINITY
21
+ }, options);
22
+
23
+ return this.each(function(){
24
+
25
+ // Store the object
26
+ var $this = $(this);
27
+
28
+ // Resizer() resizes items based on the object width divided by the compressor * 10
29
+ var resizer = function () {
30
+ $this.css('font-size', Math.max(Math.min($this.width() / (compressor*10), parseFloat(settings.maxFontSize)), parseFloat(settings.minFontSize)));
31
+ };
32
+
33
+ // Call once to set.
34
+ resizer();
35
+
36
+ // Call on resize. Opera debounces their resize by default.
37
+ $(window).on('resize.fittext orientationchange.fittext', resizer);
38
+
39
+ });
40
+
41
+ };
42
+
43
+ })( jQuery );
inc/sek/fp-prototype/czr-content_picker-ajax_actions.php ADDED
@@ -0,0 +1,256 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Customizer ajax content picker actions
4
+ *
5
+ *
6
+ * @package Hueman
7
+ * @since 3.0+
8
+ * @author Nicolas GUILLAUME <nicolas@presscustomizr.com>,. Rocco ALIBERTI <rocco@presscustomizr.com>
9
+ * @copyright Copyright (c) 2016, Nicolas GUILLAUME, Rocco ALIBERTI
10
+ * @link http://presscustomizr.com/hueman
11
+ * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
12
+ */
13
+ if ( ! class_exists( 'HA_customize_ajax_content_picker_actions' ) ) :
14
+ class HA_customize_ajax_content_picker_actions {
15
+ static $instance;
16
+ /**
17
+ * Constructor.
18
+ *
19
+ * @access public
20
+ *
21
+ */
22
+ public function __construct( ) {
23
+ if ( ! current_user_can( 'edit_theme_options' ) ) {
24
+ return;
25
+ }
26
+
27
+ self::$instance =& $this;
28
+
29
+ add_action( 'wp_ajax_load-available-content-items-customizer', array( $this, 'ajax_load_available_items' ) );
30
+ add_action( 'wp_ajax_search-available-content-items-customizer', array( $this, 'ajax_search_available_items' ) );
31
+ }
32
+
33
+
34
+ /**
35
+ * Ajax handler for loading available content items.
36
+ */
37
+ public function ajax_load_available_items() {
38
+ check_ajax_referer( 'czr-content-picker-nonce', 'CZRCpNonce' );
39
+
40
+ if ( ! current_user_can( 'edit_theme_options' ) ) {
41
+ wp_die( -1 );
42
+ }
43
+ if ( empty( $_POST['type'] ) || empty( $_POST['object'] ) ) {
44
+ wp_send_json_error( 'czr_contents_missing_type_or_object_parameter' );
45
+ }
46
+ $type = sanitize_key( $_POST['type'] );
47
+ $object = /*sanitize_key(*/ $_POST['object'] /*)*/;
48
+ $page = empty( $_POST['page'] ) ? 0 : absint( $_POST['page'] );
49
+ $items = $this->load_available_items_query( $type, $object, $page );
50
+ if ( is_wp_error( $items ) ) {
51
+ wp_send_json_error( $items->get_error_code() );
52
+ } else {
53
+ wp_send_json_success( array( 'items' => $items ) );
54
+ }
55
+ }
56
+
57
+ /**
58
+ * Performs the post_type and taxonomy queries for loading available items.
59
+ *
60
+ * @since
61
+ * @access public
62
+ *
63
+ * @param string $type Optional. Accepts any custom object type and has built-in support for
64
+ * 'post_type' and 'taxonomy'. Default is 'post_type'.
65
+ * @param string $object Optional. Accepts any registered taxonomy or post type name. Default is 'page'.
66
+ * @param int $page Optional. The page number used to generate the query offset. Default is '0'.
67
+ * @return WP_Error|array Returns either a WP_Error object or an array of menu items.
68
+ */
69
+ public function load_available_items_query( $type = 'post_type', $object = 'page', $page = 0 ) {
70
+ $items = array();
71
+ if ( 'post_type' === $type ) {
72
+ $post_type = get_post_types( array( 'public' => true ) );
73
+ if ( ! $post_type ) {
74
+ return new WP_Error( 'czr_contents_invalid_post_type' );
75
+ }
76
+ $posts = get_posts( array(
77
+ 'numberposts' => 10,
78
+ 'offset' => 10 * $page,
79
+ 'orderby' => 'date',
80
+ 'order' => 'DESC',
81
+ 'post_type' => $post_type,
82
+ ) );
83
+ foreach ( $posts as $post ) {
84
+ $post_title = $post->post_title;
85
+ if ( '' === $post_title ) {
86
+ /* translators: %d: ID of a post */
87
+ $post_title = sprintf( __( '#%d (no title)', 'hueman' ), $post->ID );
88
+ }
89
+ $items[] = array(
90
+ 'title' => html_entity_decode( $post_title, ENT_QUOTES, get_bloginfo( 'charset' ) ),
91
+ 'type' => 'post_type',
92
+ 'type_label' => get_post_type_object( $post->post_type )->labels->singular_name,
93
+ 'object' => $post->post_type,
94
+ 'id' => intval( $post->ID ),
95
+ 'url' => get_permalink( intval( $post->ID ) ),
96
+ );
97
+ }
98
+ } elseif ( 'taxonomy' === $type ) {
99
+ $taxonomies = get_taxonomies( array( 'show_in_nav_menus' => true ), 'names' );
100
+ $terms = get_terms( $taxonomies, array(
101
+ 'child_of' => 0,
102
+ 'exclude' => '',
103
+ 'hide_empty' => false,
104
+ 'hierarchical' => 1,
105
+ 'include' => '',
106
+ 'number' => 10,
107
+ 'offset' => 10 * $page,
108
+ 'order' => 'DESC',
109
+ 'orderby' => 'count',
110
+ 'pad_counts' => false,
111
+ ) );
112
+ if ( is_wp_error( $terms ) ) {
113
+ return $terms;
114
+ }
115
+ foreach ( $terms as $term ) {
116
+ $items[] = array(
117
+ 'title' => html_entity_decode( $term->name, ENT_QUOTES, get_bloginfo( 'charset' ) ),
118
+ 'type' => 'taxonomy',
119
+ 'type_label' => get_taxonomy( $term->taxonomy )->labels->singular_name,
120
+ 'object' => $term->taxonomy,
121
+ 'id' => intval( $term->term_id ),
122
+ 'url' => get_term_link( intval( $term->term_id ), $term->taxonomy ),
123
+ );
124
+ }
125
+ }
126
+
127
+ /**
128
+ * Filters the available items.
129
+ *
130
+ * @since
131
+ *
132
+ * @param array $items The array of menu items.
133
+ * @param string $type The object type.
134
+ * @param string $object The object name.
135
+ * @param int $page The current page number.
136
+ */
137
+ $items = apply_filters( 'czr_customize_content_picker_available_items', $items, $type, $object, $page );
138
+ return $items;
139
+ }
140
+
141
+
142
+ /**
143
+ * Ajax handler for searching available menu items.
144
+ *
145
+ * @since 4.3.0
146
+ * @access public
147
+ */
148
+ public function ajax_search_available_items() {
149
+ check_ajax_referer( 'czr-content-picker-nonce', 'CZRCpNonce' );
150
+ if ( ! current_user_can( 'edit_theme_options' ) ) {
151
+ wp_die( -1 );
152
+ }
153
+ if ( empty( $_POST['search'] ) ) {
154
+ wp_send_json_error( 'czr_contents_missing_search_parameter' );
155
+ }
156
+ $p = isset( $_POST['page'] ) ? absint( $_POST['page'] ) : 0;
157
+ if ( $p < 1 ) {
158
+ $p = 1;
159
+ }
160
+ $s = sanitize_text_field( wp_unslash( $_POST['search'] ) );
161
+ $type = sanitize_key( $_POST['type'] );
162
+ $object = /*sanitize_key(*/ $_POST['object'] /*)*/;
163
+ $items = $this->search_available_items_query( array( 'pagenum' => $p, 's' => $s, 'object' => $object, 'type' => $type ) );
164
+ if ( empty( $items ) ) {
165
+ wp_send_json_error( array( 'message' => __( 'No results found.', 'hueman') ) );
166
+ } else {
167
+ wp_send_json_success( array( 'items' => $items ) );
168
+ }
169
+ }
170
+
171
+
172
+ /**
173
+ * Performs post queries for available-item searching.
174
+ *
175
+ * Based on WP_Editor::wp_link_query().
176
+ *
177
+ * @since 4.3.0
178
+ * @access public
179
+ *
180
+ * @param array $args Optional. Accepts 'pagenum' and 's' (search) arguments.
181
+ * @return array Menu items.
182
+ */
183
+ public function search_available_items_query( $args = array() ) {
184
+ //TODO: need a search only on the allowed types
185
+ $items = array();
186
+ if ( 'post_type' === $args['type'] ) {
187
+ $query = array(
188
+ 'suppress_filters' => true,
189
+ 'update_post_term_cache' => false,
190
+ 'update_post_meta_cache' => false,
191
+ 'post_status' => 'publish',
192
+ 'posts_per_page' => 10,
193
+ );
194
+ $args['pagenum'] = isset( $args['pagenum'] ) ? absint( $args['pagenum'] ) : 1;
195
+ $query['offset'] = $args['pagenum'] > 1 ? $query['posts_per_page'] * ( $args['pagenum'] - 1 ) : 0;
196
+ $query['post_type'] = get_post_types( array( 'public' => true ) );
197
+ if ( isset( $args['s'] ) ) {
198
+ $query['s'] = $args['s'];
199
+ }
200
+
201
+ // Query posts.
202
+ $get_posts = new WP_Query( $query );
203
+ // Check if any posts were found.
204
+ if ( $get_posts->post_count ) {
205
+ foreach ( $get_posts->posts as $post ) {
206
+ $post_title = $post->post_title;
207
+ if ( '' === $post_title ) {
208
+ /* translators: %d: ID of a post */
209
+ $post_title = sprintf( __( '#%d (no title)', 'hueman' ), $post->ID );
210
+ }
211
+ $items[] = array(
212
+ 'title' => html_entity_decode( $post_title, ENT_QUOTES, get_bloginfo( 'charset' ) ),
213
+ 'type' => 'post_type',
214
+ 'type_label' => get_post_type_object( $post->post_type )->labels->singular_name,
215
+ 'object' => $post->post_type,
216
+ 'id' => intval( $post->ID ),
217
+ 'url' => get_permalink( intval( $post->ID ) ),
218
+ );
219
+ }
220
+ }
221
+ } elseif ( 'taxonomy' === $args['type'] ) {
222
+ // Query taxonomy terms.
223
+ $taxonomies = get_taxonomies( array( 'show_in_nav_menus' => true ), 'names' );
224
+ $terms = get_terms( $taxonomies, array(
225
+ 'name__like' => $args['s'],
226
+ 'number' => 10,
227
+ 'offset' => 10 * ($args['pagenum'] - 1),
228
+ ) );
229
+
230
+ // Check if any taxonomies were found.
231
+ if ( ! empty( $terms ) ) {
232
+ foreach ( $terms as $term ) {
233
+ $items[] = array(
234
+ 'title' => html_entity_decode( $term->name, ENT_QUOTES, get_bloginfo( 'charset' ) ),
235
+ 'type' => 'taxonomy',
236
+ 'type_label' => get_taxonomy( $term->taxonomy )->labels->singular_name,
237
+ 'object' => $term->taxonomy,
238
+ 'id' => intval( $term->term_id ),
239
+ 'url' => get_term_link( intval( $term->term_id ), $term->taxonomy ),
240
+ );
241
+ }
242
+ }
243
+ /**
244
+ * Filters the available menu items during a search request.
245
+ *
246
+ * @since 4.5.0
247
+ *
248
+ * @param array $items The array of menu items.
249
+ * @param array $args Includes 'pagenum' and 's' (search) arguments.
250
+ */
251
+ $items = apply_filters( 'czr_customize_content_picker_searched_items', $items, $args );
252
+ }
253
+ return $items;
254
+ }
255
+ }
256
+ endif;
inc/sek/fp-prototype/czr-fp-ajax_actions.php ADDED
@@ -0,0 +1,101 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ *
4
+ *
5
+ * @package Hueman
6
+ * @since 3.0+
7
+ * @author Nicolas GUILLAUME <nicolas@presscustomizr.com>,. Rocco ALIBERTI <rocco@presscustomizr.com>
8
+ * @copyright Copyright (c) 2016, Nicolas GUILLAUME, Rocco ALIBERTI
9
+ * @link http://presscustomizr.com/hueman
10
+ * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
11
+ */
12
+ if ( ! class_exists( 'HA_customize_ajax_fp_actions' ) ) :
13
+ class HA_customize_ajax_fp_actions {
14
+ static $instance;
15
+ /**
16
+ * Constructor.
17
+ *
18
+ * @access public
19
+ *
20
+ */
21
+ public function __construct( ) {
22
+ if ( ! current_user_can( 'edit_theme_options' ) ) {
23
+ return;
24
+ }
25
+
26
+ self::$instance =& $this;
27
+
28
+ add_action( 'wp_ajax_get-fp-post' , array( $this, 'ajax_get_fp_post' ) );
29
+ add_action( 'wp_ajax_get-fp-post-tb' , array( $this, 'ajax_get_fp_post_tb' ) );
30
+
31
+ }
32
+
33
+
34
+ /**
35
+ * Ajax handler for loading available content items.
36
+ */
37
+ public function ajax_get_fp_post() {
38
+ check_ajax_referer( 'czr-featured-pages-nonce', 'CZRFPNonce' );
39
+
40
+ if ( ! current_user_can( 'edit_theme_options' ) ) {
41
+ wp_die( -1 );
42
+ }
43
+ if ( empty( $_POST['id'] ) ) {
44
+ wp_send_json_error( 'czr_fp_missing_id_parameter' );
45
+ }
46
+ $id = sanitize_key( $_POST['id'] );
47
+
48
+
49
+ $_post_info = $this-> get_fp_post( $id );
50
+
51
+ if ( is_wp_error( $_post_info ) ) {
52
+ wp_send_json_error( $_post_info ->get_error_code() );
53
+ } else {
54
+ wp_send_json_success( array( 'post_info' => $_post_info ) );
55
+ }
56
+ }
57
+
58
+ /**
59
+ * Ajax handler for loading available content items.
60
+ */
61
+ public function ajax_get_fp_post_tb() {
62
+ check_ajax_referer( 'czr-featured-pages-nonce', 'CZRFPNonce' );
63
+
64
+ if ( ! current_user_can( 'edit_theme_options' ) ) {
65
+ wp_die( -1 );
66
+ }
67
+ if ( empty( $_POST['id'] ) ) {
68
+ wp_send_json_error( 'czr_fp_missing_id_parameter' );
69
+ }
70
+ $id = sanitize_key( $_POST['id'] );
71
+
72
+ $_post_tb = $this-> get_fp_post_tb( $id );
73
+
74
+ if ( is_wp_error( $_post_tb ) ) {
75
+ wp_send_json_error( $_post_tb ->get_error_code() );
76
+ } else {
77
+ wp_send_json_success( $_post_tb );
78
+ }
79
+ }
80
+
81
+ public function get_fp_post( $id ) {
82
+ $_post = get_post( $id );
83
+
84
+ if ( empty( $_post ) )
85
+ return array();
86
+
87
+ //parse post
88
+ //we need 1) thumbnail_id 2) excerpt
89
+ //1) thumbnail_id
90
+ $_post_info['thumbnail'] = get_post_thumbnail_id( $id );
91
+
92
+ //2) excerpt
93
+ $_post_info['excerpt'] = wp_trim_words( apply_filters('the_excerpt', $_post -> post_content ) );;
94
+ return $_post_info;
95
+ }
96
+
97
+ public function get_fp_post_tb( $id ) {
98
+ return get_post_thumbnail_id( $id );
99
+ }
100
+ }
101
+ endif;
inc/sek/fp-prototype/functions.php ADDED
@@ -0,0 +1,138 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /* Featured Pages prototype testing functions */
3
+
4
+ /* Customizer panel/sections/settings */
5
+ add_filter( 'hu_add_panel_map' , 'ha_fp_popul_panels_map', 20 );
6
+ function ha_fp_popul_panels_map( $panels_map ) {
7
+ return array_merge( $panels_map, array(
8
+ 'hu-fp-panel' => array(
9
+ 'priority' => 40,
10
+ 'capability' => 'edit_theme_options',
11
+ 'title' => __( 'Featured Pages' , 'hueman' ),
12
+ 'description' => __( 'Featured Pages Prototype for the Hueman theme.' , 'hueman' )
13
+ )
14
+ ));
15
+ }
16
+
17
+ add_filter( 'hu_add_section_map' , 'ha_fp_prototype_popul_section_map' );
18
+ function ha_fp_prototype_popul_section_map( $_sections ) {
19
+
20
+ return array_merge( $_sections, array(
21
+ 'fp_prototype_sec' => array(
22
+ 'title' => __( 'Featured Pages Prototype', 'hueman' ),
23
+ 'priority' => 30,
24
+ 'panel' => 'hu-fp-panel'
25
+ )
26
+ ));
27
+ }
28
+
29
+ add_filter( 'hu_add_setting_control_map', 'ha_popul_setting_control_fp_map', 20, 2);
30
+ function ha_popul_setting_control_fp_map( $_map, $get_default = null ) {
31
+ $_section_map = call_user_func_array('ha_fp_prototype_sec', array($get_default) );
32
+ return array_merge( $_map, $_section_map );
33
+ }
34
+
35
+ function ha_fp_prototype_sec( $get_default = null ){
36
+ return array(
37
+ 'fp-prototype' => array(
38
+ 'default' => array(),//empty array by default
39
+ 'control' => 'HU_Customize_Modules',
40
+ 'label' => __('Create and organize your Featured Pages', 'hueman'),
41
+ 'section' => 'fp_prototype_sec',
42
+ 'type' => 'czr_module',
43
+ 'module_type' => 'czr_fp_module',
44
+ 'priority' => 10
45
+ )
46
+ );
47
+ }
48
+ /* end Customizer panel/section/settings */
49
+
50
+
51
+ //Allow fp option as array
52
+ // add_filter( 'hu_get_skope_excluded_options', 'ha_exclude_fp_option' );
53
+ // function ha_exclude_fp_option( $_excluded ) {
54
+ // return array_merge( $_excluded, array('fp-prototype') );
55
+ // }
56
+
57
+ //Add czr templates
58
+ if ( hu_is_customize_left_panel() ) {
59
+ //Print modules and inputs templates
60
+ ha_load_fp_tmpl();
61
+ }
62
+
63
+ function ha_load_fp_tmpl() {
64
+ $_tmpl = array(
65
+ 'tmpl/modules/fp-module-tmpl.php',
66
+ );
67
+ foreach ($_tmpl as $_path) {
68
+ require_once( get_template_directory() . '/functions/czr/fp-prototype/' . $_path );
69
+ }
70
+ }
71
+
72
+
73
+ if ( is_admin() ) {
74
+ //load ajax content picker
75
+ require_once( get_template_directory() . '/functions/czr/fp-prototype/czr-content_picker-ajax_actions.php');
76
+ new HU_customize_ajax_content_picker_actions();
77
+
78
+ //load ajax fp
79
+ require_once( get_template_directory() . '/functions/czr/fp-prototype/czr-fp-ajax_actions.php');
80
+ new HU_customize_ajax_fp_actions();
81
+ }
82
+
83
+ //Add content picker nonce to the server control params
84
+ add_filter( 'hu_js_customizer_control_params', 'ha_add_cp_nonce');
85
+ function ha_add_cp_nonce( $params ) {
86
+ return array_merge( $params, array(
87
+ 'CZRCpNonce' => wp_create_nonce( 'czr-content-picker-nonce' ),
88
+ 'CZRFPNonce' => wp_create_nonce( 'czr-featured-pages-nonce' )
89
+ ));
90
+ }
91
+
92
+
93
+ //Add image uploader button_labels and other useful translated strings
94
+ add_filter( 'controls_translated_strings', 'ha_add_translated_strings');
95
+ function ha_add_translated_strings( $strings) {
96
+ return array_merge( $strings, array(
97
+ 'featuredPageAdded' => __('New Featured Page created ! Scroll down to edit it.', 'hueman'),
98
+ 'featuredPageTitle' => __( 'Featured Page', 'hueman'),
99
+ 'featuredPageImgReset' => __( 'Set to the post featured image', 'hueman'),
100
+ 'featuredPageResetErr' => __( 'Sorry this post has no featured image', 'hueman' ),
101
+ 'featuredPageResetSucc'=> __( 'Featured image found, updating ..', 'hueman' )
102
+ ));
103
+ }
104
+
105
+
106
+ //DUMMY FEATURED PAGES RENDERING
107
+ add_action( '__after_header', 'dummy_featured_pages' );
108
+ function dummy_featured_pages() {
109
+ $fps = hu_get_option('fp-prototype');
110
+ if ( empty($fps) ) return;
111
+ $fp_n = count($fps);
112
+ ?>
113
+ <div class="fps group" style="margin-bottom:100px;clear:both;">
114
+ <div class="fps-inner">
115
+ <?php
116
+ foreach( $fps as $fp_i => $fp ) {
117
+ if ( ! is_array( $fp['fp-post'] ) )
118
+ continue;
119
+ if ( empty( $fp['fp-text'] ) ) {
120
+ $_post = get_post($fp['fp-post'][0]['id']);
121
+ $_excerpt = wp_trim_words( apply_filters('the_excerpt', $_post -> post_content ) );
122
+ }else
123
+ $_excerpt = $fp['fp-text'];
124
+
125
+ printf( '<div class="fp" style="width:%1$s%%;box-sizing:border-box;padding:10px;float:left">%5$s
126
+ <h1>%2$s</h1><p>%3$s</p><a href="%4$s">%2$s</a></div>',
127
+ 100/$fp_n,
128
+ $fp['fp-title'],
129
+ $_excerpt,
130
+ get_permalink( $fp['fp-post'][0]['id'] ),
131
+ ! empty ($fp['fp-image']) ? wp_get_attachment_image( $fp['fp-image'] ) : get_the_post_thumbnail($fp['fp-post'][0]['id'])
132
+ );
133
+ }
134
+ ?>
135
+ </div>
136
+ </div>
137
+ <?php
138
+ }
inc/sek/fp-prototype/tmpl/modules/fp-module-tmpl.php ADDED
@@ -0,0 +1,61 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ add_action( 'customize_controls_print_footer_scripts', 'ha_print_fp_pre_add_view_template' , 1 );
3
+ add_action( 'customize_controls_print_footer_scripts', 'ha_print_fp_item_content_template' , 1 );
4
+
5
+ function ha_print_fp_pre_add_view_template() {
6
+ $css_attr = HU_customize::$instance -> css_attr;
7
+ ?>
8
+
9
+ <script type="text/html" id="tmpl-czr-module-fp-pre-add-view-content">
10
+ <div class="<?php echo $css_attr['sub_set_wrapper']; ?>" data-input-type="content_picker">
11
+ <div class="customize-control-title"><?php _e('Select a content to feature', 'hueman'); ?></div>
12
+ <div class="czr-input">
13
+ <span data-type="fp-post"></span>
14
+ </div>
15
+ </div>
16
+ </script>
17
+ <?php
18
+ }
19
+
20
+
21
+
22
+
23
+
24
+ function ha_print_fp_item_content_template() {
25
+ $css_attr = HU_customize::$instance -> css_attr;
26
+ //the following template is a "sub view"
27
+ //it's rendered :
28
+ //1) on customizer start, depending on what is fetched from the db
29
+ //2) dynamically when designing from the customizer
30
+ //data looks like : { id : 'sidebar-one', title : 'A Title One' }
31
+ ?>
32
+
33
+ <script type="text/html" id="tmpl-czr-module-fp-view-content">
34
+ <div class="<?php echo $css_attr['sub_set_wrapper']; ?>" data-input-type="content_picker">
35
+ <div class="customize-control-title"><?php _e('Select a content to feature', 'hueman'); ?></div>
36
+ <div class="czr-input">
37
+ <span data-type="fp-post"></span>
38
+ </div>
39
+ </div>
40
+ <div class="<?php echo $css_attr['sub_set_wrapper']; ?>" data-input-type="text">
41
+ <div class="customize-control-title"><?php _e('Featured Page Title', 'hueman'); ?></div>
42
+ <div class="czr-input">
43
+ <input data-type="fp-title" type="text" value="{{ data['fp-title'] }}" placeholder="<?php _e('Enter a title', 'hueman'); ?>"/>
44
+ </div>
45
+ </div>
46
+ <div class="<?php echo $css_attr['sub_set_wrapper']; ?>" data-input-type="textarea">
47
+ <div class="customize-control-title"><?php _e('Featured Page Text', 'hueman'); ?></div>
48
+ <div class="czr-input">
49
+ <input data-type="fp-text" type="textarea" value="{{ data['fp-text'] }}" placeholder="<?php _e('Enter a text', 'hueman'); ?>"/>
50
+ </div>
51
+ </div>
52
+ <div class="<?php echo $css_attr['sub_set_wrapper']; ?>" data-input-type="upload">
53
+ <div class="customize-control-title"><?php _e('Fetured Page Image', 'hueman'); ?></div>
54
+ <div class="<?php echo $css_attr['sub_set_input']; ?>">
55
+ <input data-type="fp-image" type="hidden" value="{{ data['fp-image'] }}"/>
56
+ <div class="<?php echo $css_attr['img_upload_container']; ?>"></div>
57
+ </div>
58
+ </div>
59
+ </script>
60
+ <?php
61
+ }
inc/sek/init-sektions.php ADDED
@@ -0,0 +1,393 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ //require_once( HA_BASE_PATH . 'inc/skop/skop-options.php' );
3
+ if ( hu_is_customizing() ) {
4
+ require_once( HA_BASE_PATH . 'inc/sek/sektions-customizer.php' );
5
+ require_once( HA_BASE_PATH . 'inc/sek/tmpl/multi-module-tmpl.php');
6
+ require_once( HA_BASE_PATH . 'inc/sek/tmpl/sektion-module-tmpl.php' );
7
+ require_once( HA_BASE_PATH . 'inc/sek/tmpl/text-module-tmpl.php' );
8
+
9
+ //module list
10
+ require_once( HA_BASE_PATH . 'inc/sek/tmpl/available-modules-list-tmpl.php' );
11
+
12
+ //sektion settings
13
+ require_once( HA_BASE_PATH . 'inc/sek/tmpl/sektion-settings-tmpl.php' );
14
+ }
15
+
16
+ //add this option in the list of possible array options
17
+ // add_filter('ha_get_skope_excluded_options', 'ha_allow_sektion_array_option');
18
+ // function ha_allow_sektion_array_option( $excluded ) {
19
+ // return array_merge( $excluded, array('sektions', 'module-collection'));
20
+ // }
21
+
22
+ add_filter( 'hu_add_section_map', 'ha_add_sek_section' );
23
+ function ha_add_sek_section( $_current_sections ) {
24
+ $_new_sections = array(
25
+ 'content_sektions_sec' => array(
26
+ 'title' => __( 'Dynamic Sections', 'hueman' ),
27
+ 'priority' => 100,
28
+ 'panel' => 'hu-content-panel'
29
+ )
30
+ );
31
+ return array_merge( $_current_sections, $_new_sections );
32
+ }
33
+
34
+ add_filter( 'hu_add_setting_control_map' , 'ha_add_sek_settings' );
35
+ function ha_add_sek_settings($_map) {
36
+ $_sek_set = array(
37
+ 'sektions' => array(
38
+ 'default' => array(),//empty array by default
39
+ 'control' => 'HU_Customize_Modules',
40
+ 'label' => __('Build your page live', 'hueman'),
41
+ 'section' => 'content_sektions_sec',
42
+ 'type' => 'czr_module',
43
+ 'module_type' => 'czr_sektion_module',
44
+ 'transport' => 'postMessage',
45
+ 'priority' => 10,
46
+ 'syncCollection' => 'module-collection'
47
+ ),
48
+ 'module-collection' => array(
49
+ 'default' => array(),//empty array by default
50
+ 'control' => 'HU_Customize_Modules',
51
+ //'label' => __('Build your page live', 'hueman'),
52
+ 'section' => 'content_sektions_sec',
53
+ 'type' => 'czr_multi_module',
54
+ //'module_type' => 'czr_module_list',
55
+ 'transport' => 'postMessage',
56
+ 'priority' => 10
57
+ )
58
+ );
59
+
60
+ return array_merge( $_map, $_sek_set );
61
+ }
62
+
63
+
64
+
65
+
66
+
67
+
68
+
69
+
70
+
71
+
72
+
73
+
74
+
75
+
76
+ add_action( '__before_main', function() {
77
+ ?>
78
+ <div id="sektions-before-content">
79
+ <?php do_action('__print_sektions_before_content'); ?>
80
+ </div>
81
+ <?php
82
+ });
83
+
84
+
85
+
86
+ function ha_print_modified_sektions() {
87
+ ha_print_sektions();
88
+ }
89
+ function ha_print_modified_modules() {
90
+ ha_print_sektions();
91
+ }
92
+
93
+
94
+
95
+ add_action('__print_sektions_before_content', 'ha_print_sektions');
96
+ function ha_print_sektions() {
97
+ //get current customizer ajax request data
98
+ /* if ( is_array($_POST) )
99
+ array_walk_recursive($_POST, function(&$v) { $v = htmlspecialchars($v); }); */
100
+ /*?>
101
+ <pre>
102
+ <?php print_r(ha_get_czr_post_values()); ?>
103
+ </pre>
104
+ <?php*/
105
+ $sektions = hu_get_option('sektions');
106
+ if ( ! $sektions || empty($sektions) || ! is_array($sektions) )
107
+ return;
108
+
109
+ $_layouts = array(
110
+ 1 => 'one-full',
111
+ 2 => 'one-half',
112
+ 3 => 'one-third',
113
+ 4 => 'one-fourth'
114
+ );
115
+ foreach ( $sektions as $_k => $_sek ) {
116
+ $_col_nb = count($_sek['columns']);
117
+ $_layout_class = array_key_exists( $_col_nb, $_layouts) ? $_layouts[$_col_nb] : 'one-full';
118
+ $i = 1;
119
+ ?>
120
+ <section class="content czr-sektion" id="sek-<?php echo $_sek['id'] ?>" data-sek-id="<?php echo $_sek['id'] ?>">
121
+
122
+ <h2>Section : <?php echo $_sek['id']; ?></h2>
123
+
124
+ <?php foreach ( $_sek['columns'] as $key => $_col ) : ?>
125
+ <?php $_last = ( $i == $_col_nb ) ? 'last' : ''; ?>
126
+
127
+ <div class="grid <?php echo $_layout_class ?> <?php echo $_last ?>">
128
+ <?php if ( empty($_col['modules']) ) : ?>
129
+ <div class="hu-placeholder-widget">
130
+ <h3>Add a module to column :<br><span class="zone-name"><?php echo $_col['id']; ?></span></h3>
131
+ </div>
132
+ <?php else : ?>
133
+ <?php ha_print_modules( $_col['modules'] ); ?>
134
+ <?php endif; ?>
135
+ </div>
136
+
137
+ <?php $i++; ?>
138
+ <?php endforeach; ?>
139
+ </section>
140
+ <?php
141
+ }//foreach
142
+ }
143
+
144
+
145
+ function ha_print_modules( $modules = array() ) {
146
+ foreach ( $modules as $key => $mod ) {
147
+ $mod = ha_get_module_from_collection( $mod['id'] );
148
+ if ( ! function_exists( $mod['module_type'] . '_render' ) )
149
+ continue;
150
+ ?>
151
+ <div class="hu-module-wrapper" data-module-id="<?php echo $mod['id']; ?>">
152
+ <?php if ( ! $mod['dirty'] ) : ?>
153
+ <?php ha_print_mod_placeholder( $mod['module_type'] ); ?>
154
+ <?php else : ?>
155
+ <?php call_user_func_array( $mod['module_type'] . '_render', array( $mod )); ?>
156
+ <?php endif; ?>
157
+ </div>
158
+ <?php
159
+
160
+ }
161
+ }
162
+
163
+
164
+ function ha_get_module_from_collection( $mod_id ) {
165
+ $module_collection = hu_get_option('module-collection');
166
+ foreach ($module_collection as $key => $mod) {
167
+ if ( $mod['id'] != $mod_id )
168
+ continue;
169
+ return $mod;
170
+ }
171
+ }
172
+
173
+
174
+
175
+ function ha_print_mod_placeholder( $module_type ) {
176
+ $_icon_map = array(
177
+ 'czr_text_module' => 'short_text',
178
+ 'czr_text_editor_module' => 'subject',
179
+ 'czr_slide_module' => 'slideshow'
180
+ );
181
+ $_icon = ! isset( $_icon_map[$module_type] ) ? 'not_interested' : $_icon_map[$module_type];
182
+ ?>
183
+ <div class="czr-module-placeholder">
184
+ <i class="material-icons"><?php echo $_icon; ?></i>
185
+ </div>
186
+ <?php
187
+ }
188
+
189
+
190
+
191
+
192
+
193
+
194
+
195
+
196
+
197
+
198
+ function czr_text_module_render( $mod ) {
199
+ //this is a single item static module.
200
+ //=> the module attributes are stored in the first items
201
+ $default_text = 'No text set. Add text in this module.';
202
+ $att = isset( $mod['items'][0] ) ? $mod['items'][0] : array();
203
+ $att = wp_parse_args(
204
+ $att,
205
+ array('text' => '<span style="color:orange">' . $default_text . '</span>')
206
+ );
207
+
208
+ ?>
209
+ <p><?php echo empty( $att['text'] ) ? $default_text : $att['text'] ?></p>
210
+ <?php
211
+ }
212
+
213
+ function czr_text_editor_module_render( $mod ) {
214
+ //this is a single item static module.
215
+ //=> the module attributes are stored in the first items
216
+ $att = isset( $mod['items'][0] ) ? $mod['items'][0] : array();
217
+ $att = wp_parse_args(
218
+ $att,
219
+ array('text' => '<span style="color:orange">No text set. Add text in this module.</span>')
220
+ );
221
+
222
+ echo apply_filters('the_content', $att['text'] );
223
+ }
224
+
225
+
226
+ function czr_slide_module_render( $mod ) {
227
+ //this is a multi item crud module.
228
+ $slider_items = $mod['items'];
229
+ $slider_id = $mod['id'];
230
+ ?>
231
+ <script type="text/javascript">
232
+ // Check if first slider image is loaded, and load flexslider on document ready
233
+ jQuery(function($){
234
+ var $_slider_wrapper = $('#<?php echo $slider_id ?>'),
235
+ $_firstImage = $_slider_wrapper.find('img').filter(':first');
236
+
237
+ if ( ! $_firstImage.length ) return;
238
+
239
+ var checkforloaded = setInterval(function() {
240
+ var image = $_firstImage.get(0);
241
+
242
+ if (image && image.complete || image.readyState == 'complete' || image.readyState == 4) {
243
+ clearInterval(checkforloaded);
244
+
245
+ $_slider_wrapper.flexslider({
246
+ animation: "slide",
247
+ useCSS: false, // Fix iPad flickering issue
248
+ directionNav: true,
249
+ controlNav: true,
250
+ pauseOnHover: true,
251
+ animationSpeed: 400,
252
+ smoothHeight: true,
253
+ touch: <?php echo apply_filters('hu_flexslider_touch_support' , true); ?>,
254
+ slideshow: 'true',
255
+ slideshowSpeed: 5000
256
+ });
257
+ }
258
+ }, 20);
259
+ });
260
+ </script>
261
+ <div class="container" style="margin-bottom:100px;clear:both;">
262
+ <div class="container-inner">
263
+ <div class="slider-prototype flexslider " id="<?php echo $slider_id ?>" >
264
+ <ul class="slides">
265
+ <?php foreach ( $slider_items as $slide_att ): ?>
266
+ <?php
267
+ $slide_att = wp_parse_args(
268
+ $slide_att,
269
+ array(
270
+ 'title' => '',
271
+ 'slide-background' => '',
272
+ 'slide-title' => '',
273
+ 'slide-subtitle' => ''
274
+ )
275
+ );
276
+ ?>
277
+ <li>
278
+ <?php echo isset( $slide_att['slide-background'] ) ? wp_get_attachment_image( $slide_att['slide-background'], 'full') : '<img/>' ?>
279
+ <p class="flex-caption">
280
+ <?php echo isset( $slide_att['slide-title'] ) ? '<h2 class="title">'. $slide_att['slide-title'] .'</h2>' : ''; ?>
281
+ <?php echo isset( $slide_att['slide-subtitle'] ) ? '<span class="subt-title" style="clear:both">'. $slide_att['slide-subtitle'] .'</span>' : ''; ?>
282
+ </p>
283
+ </li>
284
+ <?php endforeach; ?>
285
+ </ul>
286
+ </div>
287
+ </div>
288
+ </div>
289
+ <?php
290
+ }
291
+
292
+
293
+
294
+
295
+
296
+
297
+
298
+
299
+
300
+
301
+
302
+
303
+
304
+
305
+
306
+ //ADD SOME BASIC STYLING + SCRIPTS
307
+ add_action('wp_head', function() {
308
+ ?>
309
+ <style type="text/css" id="czr-sektions-style">
310
+ .main { clear : both; }
311
+ #sektions-before-content {
312
+ background: #fff;
313
+ clear: both;
314
+ width: 100%;
315
+ float: left;
316
+ position: relative;
317
+ }
318
+ .czr-sektion {
319
+ float:left;
320
+ z-index: 10;
321
+ margin: 0 0 3%;
322
+ padding: 1% 0;
323
+ border: 2px solid #eee;
324
+ }
325
+ .hu-module-wrapper {
326
+ padding: 1% 0;
327
+ text-align: center;
328
+ border: 2px dotted #aaa;
329
+ overflow: hidden;
330
+ position:relative
331
+ }
332
+ .czr-module-placeholder .material-icons {
333
+ font-size: inherit;
334
+ color: #aaa;
335
+ }
336
+ .czr-hover-placeholder .material-icons {
337
+ font-size: inherit;
338
+ color: rgba(255, 255, 255, 0.55);
339
+ }
340
+ /* USED WHEN CUSTOMIZING */
341
+ .czr-hover-placeholder {
342
+ opacity: 0;
343
+ -webkit-transition: opacity .18s;
344
+ transition: opacity .18s;
345
+ position:absolute;
346
+ top:0;
347
+ left:0;
348
+ background:rgba(0, 0, 0, 0.5);
349
+ text-align: center;
350
+ }
351
+ </style>
352
+ <script type="text/javascript" id="czr-placeholder-fittext">
353
+ jQuery( function($){
354
+ var doFitText = function() {
355
+ $(".czr-module-placeholder").each( function() {
356
+ $(this).fitText( 0.3, { minFontSize: '50px', maxFontSize: '300px' } );
357
+ });
358
+ };
359
+ doFitText();
360
+ if ( 'function' == typeof(_) && ! _.isUndefined( wp.customize ) ) {
361
+ wp.customize.selectiveRefresh.bind('partial-content-rendered' , function() {
362
+ doFitText();
363
+ });
364
+ }
365
+ });
366
+ </script>
367
+ <?php
368
+ });
369
+ add_action('wp_enqueue_scripts', function() {
370
+ wp_enqueue_style( 'google-material-icons', '//fonts.googleapis.com/icon?family=Material+Icons', array(), null, 'all' );
371
+ wp_enqueue_script(
372
+ 'czr-fittext',
373
+ get_template_directory_uri() .'/functions/skop-sek/sektions/assets/js/fittext.js',
374
+ array(),
375
+ HUEMAN_VER,
376
+ true
377
+ );
378
+ });
379
+
380
+
381
+
382
+
383
+
384
+
385
+ /* HELPERS */
386
+ if ( ! function_exists( 'ha_get_czr_post_values' ) ) {
387
+ function ha_get_czr_post_values() {
388
+ if ( ! isset( $_POST['customized'] ) )
389
+ return array();
390
+
391
+ return json_decode( wp_unslash( $_POST['customized'] ), true );
392
+ }
393
+ }
inc/sek/sektions-customizer.php ADDED
@@ -0,0 +1,72 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ //add control class
4
+ add_action ( 'customize_register' , 'ha_load_sektions_control', 20, 1 );
5
+ function ha_load_sektions_control($manager) {
6
+ $manager -> register_control_type( 'HU_Customize_Modules' );
7
+ }
8
+
9
+ add_action ( 'customize_register' , 'ha_register_sektions_partials' );
10
+ //hook : customize_register
11
+ function ha_register_sektions_partials( WP_Customize_Manager $wp_customize ) {
12
+
13
+ // Abort if selective refresh is not available.
14
+ if ( ! isset( $wp_customize->selective_refresh ) ) {
15
+ return;
16
+ }
17
+
18
+ $wp_customize->selective_refresh->add_partial( 'sektions', array(
19
+ 'selector' => '#sektions-before-content',
20
+ 'settings' => array( 'hu_theme_options[sektions]' ),
21
+ 'render_callback' => 'ha_print_modified_sektions',
22
+ //'type' => 'my_partial'
23
+ ) );
24
+
25
+ $wp_customize->selective_refresh->add_partial( 'module-collection', array(
26
+ 'selector' => '#sektions-before-content',
27
+ 'settings' => array( 'hu_theme_options[module-collection]' ),
28
+ 'render_callback' => 'ha_print_modified_modules',
29
+ //'type' => 'my_partial'
30
+ ) );
31
+ }
32
+
33
+
34
+ add_action( 'customize_controls_enqueue_scripts' , 'ha_enqueue_sektion_scripts' );
35
+ function ha_enqueue_sektion_scripts() {
36
+ wp_enqueue_script(
37
+ 'czr-dragula',
38
+ get_template_directory_uri() .'/functions/skop-sek/sektions/assets/js/dragula.min.js',//'https://cdnjs.cloudflare.com/ajax/libs/dragula/3.7.1/dragula.min.js',
39
+ array(),
40
+ HUEMAN_VER,
41
+ true
42
+ );
43
+ wp_enqueue_script(
44
+ 'czr-dragula-autoscroller-patch',
45
+ get_template_directory_uri() .'/functions/skop-sek/sektions/assets/js/dom-autoscroller.min.js',
46
+ array(),
47
+ HUEMAN_VER,
48
+ true
49
+ );
50
+
51
+
52
+ // wp_enqueue_style( 'test-jquery-ui-style', '//code.jquery.com/ui/1.11.4/themes/smoothness/jquery-ui.css', array(), null, 'all' );
53
+ // wp_enqueue_script( 'jquery-ui-core' );
54
+ // wp_enqueue_script('jquery-ui-widget' );
55
+ // wp_enqueue_script('jquery-ui-mouse');
56
+ // wp_enqueue_script(
57
+ // 'jquery-ui-resizable',
58
+ // null,
59
+ // array( 'jquery', 'jquery-ui-core', 'jquery-ui-widget', 'jquery-ui-mouse')
60
+ // // HUEMAN_VER,
61
+ // // $media = 'all'
62
+ // );
63
+ // wp_enqueue_script(
64
+ // 'jquery-ui-droppable',
65
+ // null,
66
+ // array( 'jquery', 'jquery-ui-core', 'jquery-ui-widget' )
67
+ // // HUEMAN_VER,
68
+ // // $media = 'all'
69
+ // );
70
+ }
71
+
72
+ //add_action('customize_preview_init' , 'ha_print_dragula_css');
inc/sek/tmpl/available-modules-list-tmpl.php ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /////////////////////////////////////////////////////
3
+ /// ALL MODULES TMPL //////////////////////
4
+ /////////////////////////////////////////////////////
5
+ add_action( 'customize_controls_print_footer_scripts', 'ha_print_available_module_list_tmpl' , 1 );
6
+ function ha_print_available_module_list_tmpl() {
7
+ $css_attr = HU_customize::$instance -> css_attr;
8
+ ?>
9
+
10
+ <script type="text/html" id="tmpl-czr-available-modules">
11
+ <div id="czr-module-list-panel">
12
+ <div id="czr-available-modules-filter">
13
+ <label class="screen-reader-text" for="czr-modules-search"><?php _e( 'Search Modules' ); ?></label>
14
+ <input type="search" id="modules-search" placeholder="<?php esc_attr_e( 'Search modules&hellip;' ) ?>" />
15
+ </div>
16
+ <ul id="czr-available-modules-list"></ul>
17
+ </div>
18
+ </script>
19
+
20
+ <?php
21
+ }
22
+ ?>
23
+
24
+
25
+
inc/sek/tmpl/multi-module-tmpl.php ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ //add specific js templates for this control
3
+ //this is usually called in the manager for "registered" controls that need to be rendered with js
4
+ //for this control, we'll do it another way because we need several js templates
5
+ //=> that's why this control has not been "registered" and js templates are printed with the following action
6
+ add_action( 'customize_controls_print_footer_scripts', 'ha_print_multi_modules_control_templates' , 1 );
7
+ function ha_print_multi_modules_control_templates() {
8
+ $css_attr = HU_customize::$instance -> css_attr;
9
+ //Render the control wrapper
10
+ ?>
11
+ <script type="text/html" id="tmpl-customize-control-czr_multi_module-content"></script>
12
+ <?php
13
+ }
inc/sek/tmpl/sektion-module-tmpl.php ADDED
@@ -0,0 +1,83 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ add_action( 'customize_controls_print_footer_scripts', 'ha_print_sektion_pre_add_view_template' , 1 );
3
+ function ha_print_sektion_pre_add_view_template() {
4
+ $css_attr = HU_customize::$instance -> css_attr;
5
+ ?>
6
+
7
+ <script type="text/html" id="tmpl-czr-module-sektion-pre-add-view-content">
8
+ <div class="czr-sub-set">
9
+ <div class="customize-control-title"><?php _e('Select a layout', 'hueman'); ?></div>
10
+ <div class="czr-input">
11
+ <select data-type="sektion-layout">
12
+ <option value="1"><?php _e('1 column', 'hueman'); ?></option>
13
+ <option value="2"><?php _e('2 columns', 'hueman'); ?></option>
14
+ <option value="3"><?php _e('3 columns', 'hueman'); ?></option>
15
+ <option value="4"><?php _e('4 columns', 'hueman'); ?></option>
16
+ </select>
17
+ </div>
18
+ </div>
19
+ </script>
20
+ <?php
21
+ }
22
+
23
+
24
+
25
+ add_action( 'customize_controls_print_footer_scripts', 'ha_print_sek_item_view_template' , 1 );
26
+ function ha_print_sek_item_view_template() {
27
+ $css_attr = HU_customize::$instance -> css_attr;
28
+ ?>
29
+
30
+ <script type="text/html" id="tmpl-czr-module-sektion-rud-item-part">
31
+ <div class="<?php echo $css_attr['item_header']; ?> czr-custom-model">
32
+ <div class="<?php echo $css_attr['item_title']; ?> <?php echo $css_attr['item_sort_handle']; ?>"><h4>{{ data.title }}</h4></div>
33
+ <div class="<?php echo $css_attr['item_btns']; ?>"><a title="<?php _e('Edit', 'hueman'); ?>" href="javascript:void(0);" class="fa fa-pencil <?php echo $css_attr['edit_view_btn']; ?>"></a>&nbsp;<a title="<?php _e('Remove', 'hueman'); ?>" href="javascript:void(0);" class="fa fa-trash <?php echo $css_attr['display_alert_btn']; ?>"></a></div>
34
+ <div class="<?php echo $css_attr['remove_alert_wrapper']; ?>"></div>
35
+ </div>
36
+ <!-- <div class="czr-dragula-fake-container"> - Move the module here - </div> -->
37
+ </script>
38
+ <?php
39
+ }
40
+
41
+
42
+
43
+ add_action( 'customize_controls_print_footer_scripts', 'ha_print_sektion_item_content_template' , 1 );
44
+ function ha_print_sektion_item_content_template() {
45
+ $css_attr = HU_customize::$instance -> css_attr;
46
+ ?>
47
+
48
+ <script type="text/html" id="tmpl-czr-module-sektion-view-content">
49
+ <div class="<?php echo $css_attr['sub_set_wrapper']; ?>" data-input-type="text">
50
+ <div class="customize-control-title"><?php _e('Section Block', 'hueman'); ?></div>
51
+ <div class="czr-sektion-buttons">
52
+ <a title="<?php _e('Edit Settings', 'hueman'); ?>" href="javascript:void(0);" class="fa fa-cog czr-edit-sek-settings"></a>
53
+ </div>
54
+ <!-- <div class="czr-input">
55
+ <input data-type="sektion-block" type="text" value="{{ data['sektion-block'] }}"></input>
56
+ </div> -->
57
+ </div>
58
+ <div class="czr-column-wrapper"></div>
59
+ </script>
60
+ <?php
61
+ }
62
+
63
+
64
+ //Renders a basic column html structure
65
+ //=> modules will be appended in the ul tag
66
+ add_action( 'customize_controls_print_footer_scripts', 'ha_print_sektion_column_template' , 1 );
67
+ function ha_print_sektion_column_template() {
68
+ $css_attr = HU_customize::$instance -> css_attr;
69
+ ?>
70
+
71
+ <script type="text/html" id="tmpl-czr-sektion-column">
72
+ <div class="czr-column" data-id="{{ data.id }}">
73
+ <div class="czr-column-header">
74
+ <span class="czr-col-drag-handler fa fa-arrows-alt"></span>
75
+ <h4>Column : {{ data.id }}</h4>
76
+ </div>
77
+
78
+ <ul class="czr-module-collection-wrapper <# if ( data.module_type ) {#> {{ data.module_type }} <# } #>"></ul>
79
+ <button type="button" class="button-secondary add-new-module" aria-expanded="true" aria-controls="czr-available-modules-list">Add Content Module</button>
80
+ </div>
81
+ </script>
82
+ <?php
83
+ }
inc/sek/tmpl/sektion-settings-tmpl.php ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /////////////////////////////////////////////////////
3
+ /// ALL MODULES TMPL //////////////////////
4
+ /////////////////////////////////////////////////////
5
+ add_action( 'customize_controls_print_footer_scripts', 'ha_print_sektion_settings_tmpl' , 1 );
6
+ function ha_print_sektion_settings_tmpl() {
7
+ $css_attr = HU_customize::$instance -> css_attr;
8
+ ?>
9
+
10
+ <script type="text/html" id="tmpl-czr-sektion-settings-panel">
11
+ <div id="czr-sektion-settings-panel">
12
+ <h3>Sektion Settings Panel</h3>
13
+ <div class="czr-sek-set-panel-header">
14
+ <ul class="czr-sek-set-panel-tabs">
15
+ <li class="czr-sek-set-tab czr-tab-active" data-tab-index="1">
16
+ <span class="czr-sek-tab-link">Tab 1</span>
17
+ </li>
18
+ <li class="czr-sek-set-tab" data-tab-index="2">
19
+ <span class="czr-sek-tab-link">Tab 2</span>
20
+ </li>
21
+ <li class="czr-sek-set-tab" data-tab-index="3">
22
+ <span class="czr-sek-tab-link">Tab 3</span>
23
+ </li>
24
+ </ul>
25
+ </div>
26
+ <div class="czr-sek-set-panel-content">
27
+ <div class="czr-tab-1 czr-tab-active">
28
+ <p>Content of Tab 1</p>
29
+ </div>
30
+ <div class="czr-tab-2">
31
+ <p>Content of Tab 2</p>
32
+ </div>
33
+ <div class="czr-tab-3">
34
+ <p>Content of Tab 3</p>
35
+ </div>
36
+ </div>
37
+ </div>
38
+ </script>
39
+
40
+ <?php
41
+ }
42
+ ?>
43
+
44
+
inc/sek/tmpl/text-module-tmpl.php ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ add_action( 'customize_controls_print_footer_scripts', 'ha_print_text_item_content_template' , 1 );
3
+ function ha_print_text_item_content_template() {
4
+ $css_attr = HU_customize::$instance -> css_attr;
5
+ ?>
6
+
7
+ <script type="text/html" id="tmpl-czr-module-text-view-content">
8
+ <div class="<?php echo $css_attr['sub_set_wrapper']; ?> width-100" data-input-type="textarea">
9
+ <div class="customize-control-title"><h4><?php _e('Text Module', 'hueman'); ?> {{{ data.id }}}</h4></div>
10
+ <div class="czr-input">
11
+ <textarea data-type="text" name="textarea" rows="10" cols="50">{{{ data.text }}}</textarea>
12
+ </div>
13
+ </div>
14
+ </script>
15
+ <?php
16
+ }
inc/sharrre/ha-sharrre.php ADDED
@@ -0,0 +1,166 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /* ------------------------------------------------------------------------- *
3
+ * Public Functions
4
+ /* ------------------------------------------------------------------------- */
5
+ //@return bool
6
+ function ha_are_share_buttons_enabled() {
7
+ if ( ! hu_is_checked('sharrre') )
8
+ return;
9
+ if ( ! hu_is_checked('sharrre-twitter-on') && ! hu_is_checked('sharrre-facebook-on') && ! hu_is_checked('sharrre-google-on') && ! hu_is_checked('sharrre-pinterest-on') && ! hu_is_checked('sharrre-linkedin-on') )
10
+ return;
11
+ return true;
12
+ }
13
+
14
+
15
+
16
+ /* ------------------------------------------------------------------------- *
17
+ * Class
18
+ /* ------------------------------------------------------------------------- */
19
+ class HA_Sharrre {
20
+ static $instance;
21
+ function __construct() {
22
+ self::$instance =& $this;
23
+ //front
24
+ add_action( 'wp' , array($this, 'ha_sharrre_front_actions') );
25
+
26
+ //scripts
27
+ add_action( 'wp_enqueue_scripts' , array( $this, 'ha_addons_scripts' ) );
28
+
29
+ //customizer
30
+ add_filter( 'hu_social_links_sec' , array( $this, 'ha_register_sharrre_settings'));
31
+ }
32
+
33
+
34
+ /* ------------------------------------------------------------------------- *
35
+ * Front End
36
+ /* ------------------------------------------------------------------------- */
37
+ //hook : 'wp'
38
+ function ha_sharrre_front_actions() {
39
+ if ( ! is_single() )
40
+ return;
41
+ //alter the single entry wrapper class
42
+ add_filter( 'hu_single_entry_class', array($this, 'ha_maybe_add_sharrre_class'));
43
+
44
+ //hook the sharrre content to the single post template
45
+ add_action( 'hu_after_single_entry_inner', array($this, 'ha_maybe_print_sharrre_template') );
46
+ }
47
+
48
+
49
+ //@param $classes = array of classes
50
+ //hook : hu_single_entry_class
51
+ function ha_maybe_add_sharrre_class( $classes ) {
52
+ if ( ! ha_are_share_buttons_enabled() )
53
+ return $classes;
54
+ $classes[] = 'share';
55
+ return $classes;
56
+ }
57
+
58
+ //hook : hu_after_single_entry_inner
59
+ function ha_maybe_print_sharrre_template() {
60
+ if ( ! ha_are_share_buttons_enabled() )
61
+ return;
62
+
63
+ require_once( HA_BASE_PATH . 'inc/sharrre/sharrre-template.php' );
64
+ }
65
+
66
+
67
+ /* ------------------------------------------------------------------------- *
68
+ * Scripts
69
+ /* ------------------------------------------------------------------------- */
70
+ //hook : wp_enqueue_scripts
71
+ function ha_addons_scripts() {
72
+ if ( is_singular() ) {
73
+ wp_enqueue_script(
74
+ 'sharrre',
75
+ sprintf( '%1$sassets/front/js/jQuerySharrre%2$s', HA_BASE_URL, (defined('TC_DEV') && true === TC_DEV) ? '.js' : '.min.js' ),
76
+ array( 'jquery' ),
77
+ '',
78
+ true
79
+ );
80
+ }
81
+ }
82
+
83
+
84
+
85
+ /* ------------------------------------------------------------------------- *
86
+ * Customizer
87
+ /* ------------------------------------------------------------------------- */
88
+ //add customizer settings
89
+ //hook : hu_social_links_sec
90
+ function ha_register_sharrre_settings( $settings ) {
91
+ $sharrre_settings = array(
92
+ 'sharrre' => array(
93
+ 'default' => 1,
94
+ 'control' => 'HU_controls',
95
+ 'label' => __('Display social sharing buttons in your single posts', 'hueman-addons'),
96
+ 'title' => __('Social Sharring Bar Settings', 'hueman-addons'),
97
+ 'notice' => __('Display social sharing buttons in each single articles.', 'hueman-addons'),
98
+ 'section' => 'social_links_sec',
99
+ 'type' => 'checkbox',
100
+ 'priority' => 40
101
+ ),
102
+ 'sharrre-scrollable' => array(
103
+ 'default' => 1,
104
+ 'control' => 'HU_controls',
105
+ 'label' => __('Make the Share Bar "sticky"', 'hueman-addons'),
106
+ 'notice' => __('Make the social share bar stick to the browser window when scrolling down a post.', 'hueman-addons'),
107
+ 'section' => 'social_links_sec',
108
+ 'type' => 'checkbox',
109
+ 'priority' => 50
110
+ ),
111
+ 'sharrre-twitter-on' => array(
112
+ 'default' => 1,
113
+ 'control' => 'HU_controls',
114
+ 'label' => __('Enable Twitter Button', 'hueman-addons'),
115
+ 'section' => 'social_links_sec',
116
+ 'type' => 'checkbox',
117
+ 'notice' => __('Since Nov. 2015, Twitter disabled the share counts from its API. If you want to get the display count anyway, you can create an account for free (as of Feb. 2016) on [https://opensharecount.com/]. The Hueman Addons plugin is configured to use opensharecount.', 'hueman-addons'),
118
+ 'priority' => 60
119
+ ),
120
+ 'twitter-username' => array(
121
+ 'default' => '',
122
+ 'control' => 'HU_controls',
123
+ 'label' => __('Twitter Username (without "@")', 'hueman-addons'),
124
+ 'notice' => __('Simply enter your username without the "@" prefix. Your username will be added to share-tweets of your posts (optional).', 'hueman-addons'),
125
+ 'section' => 'social_links_sec',
126
+ 'type' => 'text',
127
+ 'transport' => 'postMessage',
128
+ 'priority' => 70
129
+ ),
130
+ 'sharrre-facebook-on' => array(
131
+ 'default' => 1,
132
+ 'control' => 'HU_controls',
133
+ 'label' => __('Enable Facebook Button', 'hueman-addons'),
134
+ 'section' => 'social_links_sec',
135
+ 'type' => 'checkbox',
136
+ 'priority' => 80
137
+ ),
138
+ 'sharrre-google-on' => array(
139
+ 'default' => 1,
140
+ 'control' => 'HU_controls',
141
+ 'label' => __('Enable Google Plus Button', 'hueman-addons'),
142
+ 'section' => 'social_links_sec',
143
+ 'type' => 'checkbox',
144
+ 'priority' => 90
145
+ ),
146
+ 'sharrre-pinterest-on' => array(
147
+ 'default' => 0,
148
+ 'control' => 'HU_controls',
149
+ 'label' => __('Enable Pinterest Button', 'hueman-addons'),
150
+ 'section' => 'social_links_sec',
151
+ 'type' => 'checkbox',
152
+ 'priority' => 100
153
+ ),
154
+ 'sharrre-linkedin-on' => array(
155
+ 'default' => 0,
156
+ 'control' => 'HU_controls',
157
+ 'label' => __('Enable LinkedIn Button', 'hueman-addons'),
158
+ 'section' => 'social_links_sec',
159
+ 'type' => 'checkbox',
160
+ 'priority' => 100
161
+ )
162
+ );
163
+
164
+ return array_merge( $sharrre_settings, $settings );
165
+ }
166
+ }//end of class
inc/{sharrre-template.php → sharrre/sharrre-template.php} RENAMED
@@ -59,7 +59,7 @@
59
  enableHover: false,
60
  enableTracking: true,
61
  buttons:{size: 'tall'},
62
- urlCurl: '<?php echo plugins_url( basename( dirname( dirname( __FILE__ ) ) ) ) . "/assets/front/js/sharrre.php"; ?>',
63
  click: function(api, options){
64
  api.simulateClick();
65
  api.openPopup('googlePlus');
59
  enableHover: false,
60
  enableTracking: true,
61
  buttons:{size: 'tall'},
62
+ urlCurl: '<?php echo HA_BASE_URL . "assets/front/js/sharrre.php"; ?>',
63
  click: function(api, options){
64
  api.simulateClick();
65
  api.openPopup('googlePlus');
inc/shortcodes/ha-shortcodes.php ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class HA_Shortcodes {
3
+ static $instance;
4
+ function __construct() {
5
+ self::$instance =& $this;
6
+ add_action( 'wp', array($this, 'ha_shortcodes_actions') );
7
+ }
8
+
9
+ function ha_shortcodes_actions() {
10
+ require_once( HA_BASE_PATH . 'inc/shortcodes/shortcodes.php' );
11
+ }
12
+ }//end of class
inc/{shortcodes.php → shortcodes/shortcodes.php} RENAMED
@@ -1,12 +1,11 @@
1
  <?php
2
- //@fromfull => should be moved into a plugin
3
  /* ------------------------------------------------------------------------- *
4
  * Basic Shortcodes
5
  /* ------------------------------------------------------------------------- */
6
 
7
  /* Columns / Grid
8
  /* ------------------------------------ */
9
- function hu_column_shortcode($atts,$content=NULL) {
10
  extract( shortcode_atts( array(
11
  'size' => 'one-third',
12
  'last' => false
@@ -18,44 +17,44 @@
18
  $output.='<div class="clear"></div>';
19
  return $output;
20
  }
21
- add_shortcode('column','hu_column_shortcode');
22
 
23
  /* Hr
24
  /* ------------------------------------ */
25
- function hu_hr_shortcode($atts,$content=NULL) {
26
  $output = '<div class="hr"></div>';
27
  return $output;
28
  }
29
- add_shortcode('hr','hu_hr_shortcode');
30
 
31
  /* Highlight
32
  /* ------------------------------------ */
33
- function hu_highlight_shortcode($atts,$content=NULL) {
34
  $output = '<span class="highlight">'.strip_tags($content).'</span>';
35
  return $output;
36
  }
37
- add_shortcode('highlight','hu_highlight_shortcode');
38
 
39
  /* Dropcap
40
  /* ------------------------------------ */
41
- function hu_dropcap_shortcode($atts,$content=NULL) {
42
  $output = '<span class="dropcap">'.strip_tags($content).'</span>';
43
  return $output;
44
  }
45
- add_shortcode('dropcap','hu_dropcap_shortcode');
46
 
47
  /* Pullquote Left
48
  /* ------------------------------------ */
49
- function hu_pullquote_left_shortcode($atts,$content=NULL) {
50
  $output = '<span class="pullquote-left">'.strip_tags($content).'</span>';
51
  return $output;
52
  }
53
- add_shortcode('pullquote-left','hu_pullquote_left_shortcode');
54
 
55
  /* Pullquote Right
56
  /* ------------------------------------ */
57
- function hu_pullquote_right_shortcode($atts,$content=NULL) {
58
  $output = '<span class="pullquote-right">'.strip_tags($content).'</span>';
59
  return $output;
60
  }
61
- add_shortcode('pullquote-right','hu_pullquote_right_shortcode');
1
  <?php
 
2
  /* ------------------------------------------------------------------------- *
3
  * Basic Shortcodes
4
  /* ------------------------------------------------------------------------- */
5
 
6
  /* Columns / Grid
7
  /* ------------------------------------ */
8
+ function ha_column_shortcode($atts,$content=NULL) {
9
  extract( shortcode_atts( array(
10
  'size' => 'one-third',
11
  'last' => false
17
  $output.='<div class="clear"></div>';
18
  return $output;
19
  }
20
+ add_shortcode('column','ha_column_shortcode');
21
 
22
  /* Hr
23
  /* ------------------------------------ */
24
+ function ha_hr_shortcode($atts,$content=NULL) {
25
  $output = '<div class="hr"></div>';
26
  return $output;
27
  }
28
+ add_shortcode('hr','ha_hr_shortcode');
29
 
30
  /* Highlight
31
  /* ------------------------------------ */
32
+ function ha_highlight_shortcode($atts,$content=NULL) {
33
  $output = '<span class="highlight">'.strip_tags($content).'</span>';
34
  return $output;
35
  }
36
+ add_shortcode('highlight','ha_highlight_shortcode');
37
 
38
  /* Dropcap
39
  /* ------------------------------------ */
40
+ function ha_dropcap_shortcode($atts,$content=NULL) {
41
  $output = '<span class="dropcap">'.strip_tags($content).'</span>';
42
  return $output;
43
  }
44
+ add_shortcode('dropcap','ha_dropcap_shortcode');
45
 
46
  /* Pullquote Left
47
  /* ------------------------------------ */
48
+ function ha_pullquote_left_shortcode($atts,$content=NULL) {
49
  $output = '<span class="pullquote-left">'.strip_tags($content).'</span>';
50
  return $output;
51
  }
52
+ add_shortcode('pullquote-left','ha_pullquote_left_shortcode');
53
 
54
  /* Pullquote Right
55
  /* ------------------------------------ */
56
+ function ha_pullquote_right_shortcode($atts,$content=NULL) {
57
  $output = '<span class="pullquote-right">'.strip_tags($content).'</span>';
58
  return $output;
59
  }
60
+ add_shortcode('pullquote-right','ha_pullquote_right_shortcode');
inc/skop/init-skop.php ADDED
@@ -0,0 +1,312 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ add_action('hu_hueman_loaded', 'ha_load_skop_options');
3
+ function ha_load_skop_options() {
4
+ require_once( HA_BASE_PATH . 'inc/skop/skop-options.php' );
5
+
6
+ function HA_SKOP_OPT() {
7
+ return HA_Skop_Option::ha_skop_opt_instance();
8
+ }
9
+ HA_SKOP_OPT();
10
+ }
11
+
12
+ if ( HU_AD() -> ha_is_customizing() ) {
13
+ add_action('customize_register', 'ha_augment_customizer');//extend WP_Customize_Setting
14
+ require_once( HA_BASE_PATH . 'inc/skop/skop-customize-register.php' );
15
+ require_once( HA_BASE_PATH . 'inc/skop/tmpl/skope-tmpls.php' );
16
+
17
+ //Customizer Ajax : we must for Hueman to be loaded (some Hueman constants are used)
18
+ add_action('hu_hueman_loaded', 'ha_load_skop_ajax');
19
+ }
20
+
21
+ //hook : customize_register
22
+ function ha_augment_customizer() {
23
+ require_once( HA_BASE_PATH . 'inc/skop/skop-customizer-augment.php' );
24
+ }
25
+ //hook : 'hu_hueman_loaded'
26
+ function ha_load_skop_ajax() {
27
+ require_once( HA_BASE_PATH . 'inc/skop/skop-ajax.php' );
28
+ }
29
+
30
+
31
+ //DISABLE PARTIAL REFRESH FOR NOW
32
+ //filter declared in init-core
33
+ add_filter( 'hu_partial_refresh_on', '__return_false');
34
+
35
+ //map ctx and db opt type
36
+ //@return string
37
+ function ha_get_skope_dyn_type( $meta_type ) {
38
+ $_map = array(
39
+ 'post' => 'post_meta',
40
+ 'tax' => 'term_meta',
41
+ 'user' => 'user_meta',
42
+ );
43
+ return isset( $_map[$meta_type] ) ? $_map[$meta_type] : 'trans';
44
+ }
45
+
46
+
47
+ function ha_get_dyn_types() {
48
+ return apply_filters( 'ha_dyn_types',
49
+ array( 'option', 'post_meta', 'term_meta', 'user_meta', 'trans' )
50
+ );
51
+ }
52
+
53
+
54
+
55
+ /**
56
+ * Return the current ctx. Front / Back agnostic.
57
+ * @param $_requesting_wot is a string with the follwing possible values : 'meta_type' (like post) , 'type' (like page), 'id' (like page id)
58
+ * @param $_return_string string param stating if the return value should be a string or an array
59
+ * @return a string of all concatenated ctx parts (default) 0R an array of the ctx parts
60
+ */
61
+ function ha_get_skope( $_requesting_wot = null, $_return_string = true ) {
62
+ //Contx builder from the wp $query
63
+ //=> returns :
64
+ // the meta_type : post, tax, user
65
+ // the type : post_type, taxonomy name, author
66
+ // the id : post id, term id, user id
67
+ $parts = ha_get_query_skope();
68
+ $_return = array();
69
+ $meta_type = $type = $obj_id = '';
70
+
71
+ if ( is_array( $parts) && ! empty( $parts ) ) {
72
+ $meta_type = isset( $parts['meta_type'] ) ? $parts['meta_type'] : false;
73
+ $type = isset( $parts['type'] ) ? $parts['type'] : false;
74
+ $obj_id = isset( $parts['obj_id'] ) ? $parts['obj_id'] : false;
75
+ }
76
+
77
+ switch ( $_requesting_wot ) {
78
+ case 'meta_type':
79
+ if ( false != $meta_type )
80
+ $_return = array( "meta_type" => "{$meta_type}" );
81
+ break;
82
+
83
+ case 'type':
84
+ if ( false != $type )
85
+ $_return = array( "type" => "{$type}" );
86
+ break;
87
+
88
+ case 'id':
89
+ if ( false != $obj_id )
90
+ $_return = array( "id" => "{$obj_id}" );
91
+ break;
92
+
93
+ default:
94
+ if ( false != $meta_type && false != $obj_id && false != $obj_id )
95
+ $_return = array( "meta_type" => "{$meta_type}" , "type" => "{$type}", "id" => "{$obj_id}" );
96
+ else if ( false != $meta_type && ! $obj_id )
97
+ $_return = array( "meta_type" => "{$meta_type}", "type" => "{$type}" );
98
+ else if ( false != $obj_id )
99
+ $_return = array( "id" => "{$obj_id}" );
100
+ break;
101
+ }
102
+
103
+ //return the parts array if not a string requested
104
+ if ( ! $_return_string ) {
105
+ return $_return;
106
+ }
107
+
108
+ //don't go further if not an array or empty
109
+ if ( ! is_array( $_return ) || ( is_array( $_return ) && empty( $_return ) ) )
110
+ return '';
111
+
112
+ //if a specific part of the ctx is requested, don't concatenate
113
+ //return the part if exists
114
+ if ( ! is_null($_requesting_wot) )
115
+ return isset($_return[$_requesting_wot]) ? $_return[$_requesting_wot] : '';
116
+
117
+ //generate the ctx string from the array of ctx_parts
118
+ $_concat = "";
119
+ foreach ( $_return as $_key => $_part ) {
120
+ if ( empty( $_concat) )
121
+ $_concat .= $_part;
122
+ else
123
+ $_concat .= '_'. $_part;
124
+ }
125
+ return $_concat;
126
+ }
127
+
128
+
129
+
130
+
131
+ /**
132
+ * Contx builder from the wp $query
133
+ * !! has to be fired after 'template_redirect'
134
+ * Used on front ( not customizing preview ? => @todo make sure of this )
135
+ * @return array of ctx parts
136
+ */
137
+ function ha_get_query_skope() {
138
+ //don't call get_queried_object if the $query is not defined yet
139
+ global $wp_query;
140
+ if ( ! isset($wp_query) || empty($wp_query) )
141
+ return array();
142
+
143
+ $current_obj = get_queried_object();
144
+ $meta_type = false;
145
+ $type = false;
146
+ $obj_id = false;
147
+
148
+
149
+ if ( is_object($current_obj) ) {
150
+ //post, custom post types, page
151
+ if ( isset($current_obj -> post_type) ) {
152
+ $meta_type = 'post';
153
+ $type = $current_obj -> post_type;
154
+ $obj_id = $current_obj -> ID;
155
+ }
156
+
157
+ //taxinomies : tags, categories, custom tax type
158
+ if ( isset($current_obj -> taxonomy) && isset($current_obj -> term_id) ) {
159
+ $meta_type = 'tax';
160
+ $type = $current_obj -> taxonomy;
161
+ $obj_id = $current_obj -> term_id;
162
+ }
163
+ }
164
+
165
+ //author archive page
166
+ if ( is_author() ) {
167
+ $meta_type = 'user';
168
+ $type = 'author';
169
+ $obj_id = get_query_var('author');
170
+ }
171
+
172
+ if ( is_404() )
173
+ $obj_id = '404';
174
+ if ( is_search() )
175
+ $obj_id = 'search';
176
+ if ( is_date() )
177
+ $obj_id = 'date';
178
+ if ( hu_is_home() )
179
+ $obj_id = 'home';
180
+
181
+ return apply_filters( 'ha_get_query_skope' , array( 'meta_type' => $meta_type , 'type' => $type , 'obj_id' => $obj_id ) , $current_obj );
182
+ }
183
+
184
+
185
+
186
+
187
+ /**
188
+ * Used when localizing the customizer js params
189
+ * Can be a post ( post, pages, CPT) , tax(tag, cats, custom taxs), author, date, search page, 404.
190
+ * @return string title of the current ctx if exists. If not => false.
191
+ */
192
+ function ha_get_skope_title( $level, $meta_type = null, $long = false ) {
193
+ $_dyn_type = ( hu_is_customize_preview_frame() && isset($_POST['dyn_type']) ) ? $_POST['dyn_type'] : '';
194
+ $type = ha_get_skope('type');
195
+ $skope = ha_get_skope();
196
+ $title = '';
197
+
198
+ if( 'local' == $level ) {
199
+ $type = ha_get_skope('type');
200
+ if ( HA_SKOP_OPT() -> ha_can_have_meta_opt( $meta_type ) ) {
201
+ $_id = ha_get_skope('id');
202
+
203
+ switch ($meta_type) {
204
+ case 'post':
205
+ $type_obj = get_post_type_object( $type );
206
+ $title = sprintf( '%1$s (%2$s), "%3$s"', $type_obj -> labels -> singular_name, $_id, get_the_title( $_id ) );
207
+ break;
208
+
209
+ case 'tax':
210
+ $type_obj = get_taxonomy( $type );
211
+ $term = get_term( $_id, $type );
212
+ $title = sprintf( '%1$s (%2$s), "%3$s"', $type_obj -> labels -> singular_name, $_id, $term -> name );
213
+ break;
214
+
215
+ case 'user':
216
+ $author = get_userdata( $_id );
217
+ $title = sprintf( '%1$s (%2$s), "%3$s"', __('User', 'hueman'), $_id, $author -> user_login );
218
+ break;
219
+ }
220
+
221
+ } else if ( ( 'trans' == $_dyn_type || HA_SKOP_OPT() -> ha_can_have_trans_opt( $skope ) ) ) {
222
+ $title = ucfirst( ha_get_skope() );
223
+ }
224
+ }
225
+ if ( 'group' == $level || 'special_group' == $level ) {
226
+ $title = __('All', 'hueman');
227
+ switch( $meta_type ) {
228
+ case 'post' :
229
+ $type_obj = get_post_type_object( $type );
230
+ $title .= ' ' . $type_obj -> labels -> name;
231
+ break;
232
+
233
+ case 'tax' :
234
+ $type_obj = get_taxonomy( $type );
235
+ $title .= ' ' . $type_obj -> labels -> name;
236
+ break;
237
+
238
+ case 'user' :
239
+ $title .= ' ' . __('Users', 'hueman');
240
+ break;
241
+ }
242
+ }
243
+ if ( 'global' == $level ) {
244
+ $title = 'Global Options';
245
+ }
246
+ return ha_trim_text( $title, $long ? 45 : 25, '..."');
247
+ }
248
+
249
+
250
+
251
+
252
+
253
+ /*****************************************************
254
+ * ADMIN CONTEXT
255
+ *****************************************************/
256
+ //@todo author case not handled
257
+ function ha_get_admin_ctx() {
258
+ if ( ! is_admin() )
259
+ return array();
260
+
261
+ global $tag;
262
+ $current_screen = get_current_screen();
263
+ $post = get_post();
264
+ $meta_type = false;
265
+ $type = false;
266
+ $obj_id = false;
267
+
268
+ //post case : page, post CPT
269
+ if ( 'post' == $current_screen->base
270
+ && 'add' != $current_screen->action
271
+ && ( $post_type_object = get_post_type_object( $post->post_type ) )
272
+ && current_user_can( 'read_post', $post->ID )
273
+ && ( $post_type_object->public )
274
+ && ( $post_type_object->show_in_admin_bar )
275
+ && ( 'draft' != $post->post_status ) )
276
+ {
277
+ $meta_type = 'post';
278
+ $type = $post -> post_type;
279
+ $obj_id = $post -> ID;
280
+ }
281
+ //tax case : tags, cats, custom tax
282
+ elseif ( 'edit-tags' == $current_screen->base
283
+ && isset( $tag ) && is_object( $tag )
284
+ && ( $tax = get_taxonomy( $tag->taxonomy ) )
285
+ && $tax->public )
286
+ {
287
+ $meta_type = 'tax';
288
+ $type = $tag -> taxonomy ;
289
+ $obj_id = $tag -> term_id;
290
+ }
291
+ return apply_filters( 'ha_get_admin_ctx' , array( $meta_type , $type , $obj_id ) );
292
+ }
293
+
294
+
295
+ function ha_trim_text( $text, $text_length, $more ) {
296
+ if ( ! $text )
297
+ return '';
298
+
299
+ $text = trim( strip_tags( $text ) );
300
+
301
+ if ( ! $text_length )
302
+ return $text;
303
+
304
+ $end_substr = $_text_length = strlen( $text );
305
+
306
+ if ( $_text_length > $text_length ){
307
+ $end_substr = strpos( $text, ' ' , $text_length);
308
+ $end_substr = ( $end_substr !== FALSE ) ? $end_substr : $text_length;
309
+ $text = substr( $text , 0 , $end_substr );
310
+ }
311
+ return ( ( $end_substr < $text_length ) && $more ) ? $text : $text . ' ' .$more ;
312
+ }
inc/skop/skop-ajax.php ADDED
@@ -0,0 +1,193 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*****************************************************
3
+ * AJAX
4
+ *****************************************************/
5
+ add_action( 'wp_ajax_' . HU_OPT_AJAX_ACTION , 'ha_ajax_get_opt' );
6
+
7
+ add_action( 'wp_ajax_czr_skope_reset', 'ha_ajax_reset_skope' );
8
+ add_action( 'wp_ajax_czr_setting_reset', 'ha_ajax_reset_setting' );
9
+ /**
10
+ * Ajax handler for getting an attachment.
11
+ *
12
+ * @since 3.5.0
13
+ */
14
+ function ha_ajax_get_opt() {
15
+ if ( ! isset( $_REQUEST['opt_name'] ) || ! isset( $_REQUEST['dyn_type'] ) || ! isset( $_REQUEST['stylesheet'] ) )
16
+ wp_send_json_error();
17
+ if ( ! current_user_can( 'edit_theme_options' ) )
18
+ wp_send_json_error();
19
+
20
+ $_trans = get_transient( $_REQUEST['opt_name'] );
21
+ wp_send_json_success( $_trans );
22
+ }
23
+
24
+
25
+ function ha_ajax_reset_skope() {
26
+ global $wp_customize;
27
+ if ( ! $wp_customize->is_preview() ) {
28
+ wp_send_json_error( 'not_preview' );
29
+ } else if ( ! current_user_can( 'customize' ) ) {
30
+ status_header( 403 );
31
+ wp_send_json_error( 'customize_not_allowed' );
32
+ } else if ( ! isset( $_SERVER['REQUEST_METHOD'] ) || 'POST' !== $_SERVER['REQUEST_METHOD'] ) {
33
+ status_header( 405 );
34
+ wp_send_json_error( 'bad_method' );
35
+ }
36
+ $action = 'save-customize_' . $wp_customize->get_stylesheet();
37
+ if ( ! check_ajax_referer( $action, 'nonce', false ) ) {
38
+ wp_send_json_error( 'invalid_nonce' );
39
+ }
40
+ // Do we have to switch themes?
41
+ if ( ! $wp_customize->is_theme_active() ) {
42
+ // Temporarily stop previewing the theme to allow switch_themes()
43
+ // to operate properly.
44
+ $wp_customize->stop_previewing_theme();
45
+ switch_theme( $wp_customize->get_stylesheet() );
46
+ update_option( 'theme_switched_via_customizer', true );
47
+ $wp_customize->start_previewing_theme();
48
+ }
49
+
50
+ if ( ! isset( $_POST['opt_name'] ) || ! isset( $_POST['dyn_type'] ) )
51
+ return wp_send_json_error();
52
+
53
+ //$attempt will store the maybe wp error status
54
+ $attempt = '';
55
+ switch ( $_POST['dyn_type'] ) {
56
+ case 'trans':
57
+ $attempt = delete_transient( $_POST['opt_name'] );
58
+ break;
59
+ case 'post_meta':
60
+ if ( ! isset( $_POST['obj_id'] ) ) {
61
+ wp_send_json_error( 'Missing $_POST["obj_id"] when attempting to delete a post meta');
62
+ }
63
+ $attempt = delete_post_meta( $_POST['obj_id'] , $_POST['opt_name'] );
64
+ break;
65
+ case 'term_meta':
66
+ if ( ! isset( $_POST['obj_id'] ) ) {
67
+ wp_send_json_error( 'Missing $_POST["obj_id"] when attempting to delete a term meta');
68
+ }
69
+ $attempt = delete_term_meta( $_POST['obj_id'] , $_POST['opt_name'] );
70
+ break;
71
+ case 'user_meta':
72
+ if ( ! isset( $_POST['obj_id'] ) ) {
73
+ wp_send_json_error( 'Missing $_POST["obj_id"] when attempting to delete a user meta');
74
+ }
75
+ $attempt = delete_user_meta( $_POST['obj_id'] , $_POST['opt_name'] );
76
+ break;
77
+ case 'option' :
78
+ $options = get_option( $_POST['opt_name'] );
79
+ $_opts_to_keep = array();
80
+ foreach ( $options as $key => $value ) {
81
+ if ( HU_utils::$inst -> hu_is_option_protected( $key ) )
82
+ $_opts_to_keep[$key] = $value;
83
+ }
84
+ //wp_send_json_success( 'PROTECTED OPTIONS : ' . json_encode( HU_utils::$inst -> hu_get_protected_options() ) );
85
+ $attempt = update_option( $_POST['opt_name'], $_opts_to_keep );
86
+ break;
87
+ }
88
+ if ( is_wp_error( $attempt ) ) {
89
+ status_header( 500 );
90
+ wp_send_json_error( $attempt->get_error_message() );
91
+ }
92
+ wp_send_json_success( $_POST['opt_name'] . ' has been reset.');
93
+ }
94
+
95
+
96
+
97
+
98
+ function ha_ajax_reset_setting() {
99
+ global $wp_customize;
100
+ if ( ! $wp_customize->is_preview() ) {
101
+ wp_send_json_error( 'not_preview' );
102
+ } else if ( ! current_user_can( 'customize' ) ) {
103
+ status_header( 403 );
104
+ wp_send_json_error( 'customize_not_allowed' );
105
+ } else if ( ! isset( $_SERVER['REQUEST_METHOD'] ) || 'POST' !== $_SERVER['REQUEST_METHOD'] ) {
106
+ status_header( 405 );
107
+ wp_send_json_error( 'bad_method' );
108
+ }
109
+ $action = 'save-customize_' . $wp_customize->get_stylesheet();
110
+ if ( ! check_ajax_referer( $action, 'nonce', false ) ) {
111
+ wp_send_json_error( 'invalid_nonce' );
112
+ }
113
+ // Do we have to switch themes?
114
+ if ( ! $wp_customize->is_theme_active() ) {
115
+ // Temporarily stop previewing the theme to allow switch_themes()
116
+ // to operate properly.
117
+ $wp_customize->stop_previewing_theme();
118
+ switch_theme( $wp_customize->get_stylesheet() );
119
+ update_option( 'theme_switched_via_customizer', true );
120
+ $wp_customize->start_previewing_theme();
121
+ }
122
+
123
+ if ( ! isset( $_POST['opt_name'] ) || ! isset( $_POST['dyn_type'] ) || ! isset( $_POST['set_id'] ) )
124
+ return wp_send_json_error('Error when trying to reset an option, the ajax post request is missing a param.');
125
+
126
+ $new_values = array();
127
+ $short_opt_name = hu_extract_setting_name( $_POST['set_id'] );
128
+ //$attempt will store the maybe wp error status
129
+ $attempt = '';
130
+ switch ( $_POST['dyn_type'] ) {
131
+ case 'trans':
132
+ $current_values = get_transient( $_POST['opt_name'] );
133
+ foreach ( $current_values as $_id => $value) {
134
+ if ( $short_opt_name != $_id )
135
+ $new_values[$_id] = $value;
136
+ }
137
+ $attempt = set_transient( $_POST['opt_name'], $new_values, 60*24*365*100 );
138
+ break;
139
+
140
+ case 'post_meta':
141
+ if ( ! isset( $_POST['obj_id'] ) ) {
142
+ wp_send_json_error( 'Missing $_POST["obj_id"] when attempting to delete a post meta');
143
+ }
144
+ $current_values = get_post_meta( $_POST['obj_id'] , $_POST['opt_name'], true );
145
+ foreach ( $current_values as $_id => $value) {
146
+ if ( $short_opt_name != $_id )
147
+ $new_values[$_id] = $value;
148
+ }
149
+ $attempt = update_post_meta( $_POST['obj_id'] , $_POST['opt_name'], $new_values );
150
+ break;
151
+
152
+ case 'term_meta':
153
+ if ( ! isset( $_POST['obj_id'] ) ) {
154
+ wp_send_json_error( 'Missing $_POST["obj_id"] when attempting to delete a term meta');
155
+ }
156
+ $current_values = get_term_meta( $_POST['obj_id'] , $_POST['opt_name'], true );
157
+ foreach ( $current_values as $_id => $value) {
158
+ if ( $short_opt_name != $_id )
159
+ $new_values[$_id] = $value;
160
+ }
161
+ $attempt = update_term_meta( $_POST['obj_id'] , $_POST['opt_name'], $new_values );
162
+ break;
163
+
164
+ case 'user_meta':
165
+ if ( ! isset( $_POST['obj_id'] ) ) {
166
+ wp_send_json_error( 'Missing $_POST["obj_id"] when attempting to delete a user meta');
167
+ }
168
+ $current_values = get_user_meta( $_POST['obj_id'] , $_POST['opt_name'], true );
169
+ foreach ( $current_values as $_id => $value) {
170
+ if ( $short_opt_name != $_id )
171
+ $new_values[$_id] = $value;
172
+ }
173
+ $attempt = update_user_meta( $_POST['obj_id'] , $_POST['opt_name'], $new_values );
174
+ break;
175
+
176
+ case 'option' :
177
+ $current_values = hu_get_raw_option( null, HU_THEME_OPTIONS );
178
+ foreach ( $current_values as $_id => $value ) {
179
+ if ( HU_utils::$inst -> hu_is_option_protected( $_id ) )
180
+ $new_values[$_id] = $value;
181
+ else if ( $short_opt_name != $_id )
182
+ $new_values[$_id] = $value;
183
+ }
184
+ //wp_send_json_success( 'PROTECTED OPTIONS : ' . json_encode( HU_utils::$inst -> hu_get_protected_options() ) );
185
+ $attempt = update_option( $_POST['opt_name'], $new_values );
186
+ break;
187
+ }
188
+ if ( is_wp_error( $attempt ) ) {
189
+ status_header( 500 );
190
+ wp_send_json_error( $attempt->get_error_message() );
191
+ }
192
+ wp_send_json_success( '||| ' . $_POST['set_id'] . ' has been deleted from ' . $_POST['dyn_type'] . ' |||' );
193
+ }
inc/skop/skop-customize-register.php ADDED
@@ -0,0 +1,589 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*****************************************************
3
+ * CUSTOMIZER
4
+ *****************************************************/
5
+
6
+ //modify some WP built-in settings
7
+ //Assign an extended class to Header_Image Settings
8
+ add_action( 'customize_register' , 'ha_alter_wp_customizer_settings' , 100, 1 );
9
+ function ha_alter_wp_customizer_settings( $manager ) {
10
+ if ( is_object( $manager->get_setting( 'header_image_data' ) ) ) {
11
+ $manager -> remove_setting( 'header_image_data' );
12
+ $manager -> add_setting( new HA_Customize_Header_Image_Data_Setting( $manager, 'header_image_data', array(
13
+ 'theme_supports' => 'custom-header',
14
+ ) ) );
15
+ $manager -> remove_setting( 'header_image' );
16
+ $manager -> add_setting( new HA_Customize_Header_Image_Setting( $manager, 'header_image', array(
17
+ 'default' => get_theme_support( 'custom-header', 'default-image' ),
18
+ 'theme_supports' => 'custom-header',
19
+ ) ) );
20
+ }
21
+ }
22
+
23
+
24
+
25
+ add_action( 'customize_register' , 'ha_skopify_customizer_save');
26
+ function ha_skopify_customizer_save() {
27
+ //Which options are we targeting there?
28
+ // 1) the theme options
29
+ // 2) the WP built in options
30
+ $_options_to_skope = HU_customize::$instance -> hu_get_wp_builtin_settings();
31
+ $_options_to_skope[] = HU_THEME_OPTIONS;
32
+
33
+ if ( apply_filters( 'ha_skope_sidebars_widgets', false ) ) {
34
+ $_options_to_skope[] = 'sidebars_widgets';
35
+ $_options_to_skope = array_merge( $_options_to_skope, hu_get_registered_widgets_option_names() );
36
+ }
37
+
38
+ //loop on the targeted option to dynamically set the type on save
39
+ foreach ( $_options_to_skope as $_opt_name ) {
40
+ add_action( "customize_save_{$_opt_name}" , 'ha_set_setting_type' );
41
+ }
42
+
43
+ add_action( 'customize_update_trans' , 'ha_customizer_set_trans', 10, 2 );
44
+ add_action( 'customize_update_post_meta' , 'ha_customizer_set_post_meta', 10, 2 );
45
+ add_action( 'customize_update_term_meta' , 'ha_customizer_set_term_meta', 10, 2 );
46
+ add_action( 'customize_update_user_meta' , 'ha_customizer_set_user_meta', 10, 2 );
47
+
48
+ //EXPERIMENT
49
+ $theme_name = strtolower(THEMENAME);//is always the parent theme name
50
+ add_action( "customize_save_{$theme_name}_global_skope" , 'ha_set_setting_type' );
51
+ add_action( 'customize_update_global_option' , 'ha_customizer_set_global_option', 10, 2 );
52
+ }
53
+
54
+
55
+
56
+ //hook : customize_save_hu_theme_options
57
+ //at this point, the nonce has already been checked by the customizer manager
58
+ //if 'wp_default_type' is specified, then always falls back to wp type
59
+ //=> 'wp_default_type' is typically used when saving a skope excluded setting. It should not be parsed by this action because it option name based but this is a security.
60
+ function ha_set_setting_type( $setting ) {
61
+ $value = $setting->post_value();
62
+ if ( ! $setting->check_capabilities() || ! isset( $value ) )
63
+ return;
64
+ if ( 'theme_mod' != $setting -> type )
65
+ $setting -> type = ( ! isset($_POST['dyn_type']) || 'wp_default_type' == $_POST['dyn_type'] ) ? $setting -> type : $_POST['dyn_type'];
66
+ else if ( isset($_POST['skope']) && 'global' == $_POST['skope'] ) {
67
+ $setting -> type = 'theme_mod';
68
+ }
69
+ else {
70
+ $setting -> type = ( ! isset($_POST['dyn_type']) || 'wp_default_type' == $_POST['dyn_type'] ) ? $setting -> type : $_POST['dyn_type'];
71
+ }
72
+ }
73
+
74
+
75
+
76
+
77
+
78
+
79
+
80
+
81
+
82
+
83
+
84
+
85
+
86
+
87
+
88
+ /**
89
+ * Will attempt to replace a specific value in a multidimensional array.
90
+ *
91
+ * @since 3.4.0
92
+ *
93
+ * @param $root
94
+ * @param $keys
95
+ * @param mixed $value The value to update.
96
+ * @return mixed
97
+ */
98
+ function ha_multidimensional_replace( $root, $keys, $value ) {
99
+ if ( ! isset( $value ) )
100
+ return $root;
101
+ elseif ( empty( $keys ) ) // If there are no keys, we're replacing the root.
102
+ return $value;
103
+
104
+ $result = ha_multidimensional( $root, $keys, true );
105
+
106
+ if ( isset( $result ) )
107
+ $result['node'][ $result['key'] ] = $value;
108
+
109
+ return $root;
110
+ }
111
+
112
+
113
+ /**
114
+ * Multidimensional helper function.
115
+ *
116
+ * @since 3.4.0
117
+ *
118
+ * @param $root
119
+ * @param $keys
120
+ * @param bool $create Default is false.
121
+ * @return array|void Keys are 'root', 'node', and 'key'.
122
+ */
123
+ function ha_multidimensional( &$root, $keys, $create = false ) {
124
+ if ( $create && empty( $root ) )
125
+ $root = array();
126
+
127
+ if ( ! isset( $root ) || empty( $keys ) )
128
+ return;
129
+
130
+ $last = array_pop( $keys );
131
+ $node = &$root;
132
+
133
+ foreach ( $keys as $key ) {
134
+ if ( $create && ! isset( $node[ $key ] ) )
135
+ $node[ $key ] = array();
136
+
137
+ if ( ! is_array( $node ) || ! isset( $node[ $key ] ) )
138
+ return;
139
+
140
+ $node = &$node[ $key ];
141
+ }
142
+
143
+ if ( $create ) {
144
+ if ( ! is_array( $node ) ) {
145
+ // account for an array overriding a string or object value
146
+ $node = array();
147
+ }
148
+ if ( ! isset( $node[ $last ] ) ) {
149
+ $node[ $last ] = array();
150
+ }
151
+ }
152
+
153
+ if ( ! isset( $node[ $last ] ) )
154
+ return;
155
+
156
+ return array(
157
+ 'root' => &$root,
158
+ 'node' => &$node,
159
+ 'key' => $last,
160
+ );
161
+ }
162
+
163
+
164
+
165
+
166
+
167
+
168
+
169
+
170
+ //this utility is used to preprocess the value for any type : trans, meta
171
+ //@param value : array()
172
+ //@param $setting : setting instance
173
+ //@todo : improve performances by getting the aggregated multidimensional, just like WP does
174
+ //@return updated option associative array( opt_name1 => value 1, opt_name2 => value2, ... )
175
+ function ha_customizer_preprocess_save_value( $new_value, $setting, $current_value ) {
176
+ //assign a default val to the set_name var
177
+ $set_name = $setting -> id;
178
+ $id_data = $setting -> manager -> get_setting( $setting -> id ) -> id_data();
179
+ $is_multidimensional = ! empty( $id_data['keys'] );
180
+
181
+ if ( $is_multidimensional && ! ha_is_theme_multidimensional_setting( $setting -> id ) ) {
182
+ $id_base = $id_data['base'];
183
+ $set_name = $id_base;
184
+ $root = ( is_array($current_value) && isset($current_value[$set_name]) ) ? $current_value[$set_name] : array();
185
+ $root = ha_multidimensional_replace( $root, $id_data['keys'], $new_value );
186
+ $new_value = $root;
187
+ }
188
+
189
+ $new_value = apply_filters('ha_customizer_preprocess_save_value', $new_value, $current_value, $setting );
190
+
191
+ //hu_theme_options case
192
+ if ( ha_is_theme_multidimensional_setting( $setting -> id ) ) {
193
+ $set_name = ha_extract_setting_name( $setting -> id );
194
+ }
195
+
196
+ //bail if no set name set here
197
+ if ( ! isset($set_name ) )
198
+ return $current_value;
199
+
200
+ if ( ! $current_value || ! is_array($current_value) ) {
201
+ $to_return = array( $set_name => $new_value );
202
+ } else {
203
+ $to_return = $current_value;
204
+ $to_return[$set_name] = $new_value;
205
+ }
206
+ return $to_return;
207
+ }
208
+
209
+
210
+
211
+ //hook : customize_update_global_option
212
+ //at this point, the nonce has already been checked by the customizer manager
213
+ //This callback is fired in WP_Customize_Setting::update()
214
+ //@param $value has been sanitized in WP_Customize_Setting::save() at this point, by WP_Customize_Manager::post_value()
215
+ function ha_customizer_set_global_option( $value, $setting ) {
216
+ if ( ! $_POST['opt_name'] || $_POST['opt_name'] != HA_SKOP_OPT() -> global_skope_optname || ! $setting->check_capabilities() || ! isset( $value ) )
217
+ return;
218
+ $opt_val = hu_get_raw_option( HA_SKOP_OPT() -> global_skope_optname );
219
+ $new_value = ha_customizer_preprocess_save_value( $value, $setting, $opt_val );
220
+ update_option( $_POST['opt_name'], $new_value );
221
+ }
222
+
223
+
224
+ //hook : customize_update_trans
225
+ //at this point, the nonce has already been checked by the customizer manager
226
+ //This callback is fired in WP_Customize_Setting::update()
227
+ //@param $value has been sanitized in WP_Customize_Setting::save() at this point, by WP_Customize_Manager::post_value()
228
+ function ha_customizer_set_trans( $value, $setting ) {
229
+ if ( ! $_POST['opt_name'] || ! $setting->check_capabilities() || ! isset( $value ) )
230
+ return;
231
+ $trans_val = get_transient( $_POST['opt_name'] );
232
+ $new_value = ha_customizer_preprocess_save_value( $value, $setting, $trans_val );
233
+ set_transient( $_POST['opt_name'], $new_value, 60*24*365*100 );
234
+ }
235
+
236
+
237
+ //This callback is fired in WP_Customize_Setting::update()
238
+ //@param $value has been sanitized in WP_Customize_Setting::save() at this point, by WP_Customize_Manager::post_value()
239
+ function ha_customizer_set_post_meta($value, $setting) {
240
+ if ( ! $_POST['opt_name'] || ! $_POST['obj_id'] || ! $setting->check_capabilities() || ! isset( $value ) )
241
+ return;
242
+
243
+ $meta_val = get_post_meta( $_POST['obj_id'] , $_POST['opt_name'], true );
244
+ $new_value = ha_customizer_preprocess_save_value( $value, $setting, $meta_val );
245
+ update_post_meta( $_POST['obj_id'] , $_POST['opt_name'], $new_value );
246
+ }
247
+
248
+ //This callback is fired in WP_Customize_Setting::update()
249
+ //@param $value has been sanitized in WP_Customize_Setting::save() at this point, by WP_Customize_Manager::post_value()
250
+ function ha_customizer_set_term_meta($value, $setting) {
251
+ if ( ! $_POST['opt_name'] || ! $_POST['obj_id'] || ! $setting->check_capabilities() || ! isset( $value ) )
252
+ return;
253
+
254
+ $meta_val = get_term_meta( $_POST['obj_id'] , $_POST['opt_name'], true );
255
+ $new_value = ha_customizer_preprocess_save_value( $value, $setting, $meta_val );
256
+ update_term_meta( $_POST['obj_id'] , $_POST['opt_name'], $new_value );
257
+ }
258
+
259
+ //This callback is fired in WP_Customize_Setting::update()
260
+ //@param $value has been sanitized in WP_Customize_Setting::save() at this point, by WP_Customize_Manager::post_value()
261
+ function ha_customizer_set_user_meta($value, $setting) {
262
+ if ( ! $_POST['opt_name'] || ! $_POST['obj_id'] || ! $setting->check_capabilities() || ! isset( $value ) )
263
+ return;
264
+
265
+ $meta_val = get_user_meta( $_POST['obj_id'] , $_POST['opt_name'], true );
266
+ $new_value = ha_customizer_preprocess_save_value( $value, $setting, $meta_val );
267
+ update_user_meta( $_POST['obj_id'] , $_POST['opt_name'], $new_value );
268
+ }
269
+
270
+
271
+
272
+
273
+
274
+ //Extract the option name from the theme options array
275
+ function ha_extract_setting_name( $setting_id ) {
276
+ if ( false === strpos( $setting_id, HU_THEME_OPTIONS) )
277
+ return $setting_id;
278
+ return str_replace(array('[', ']', HU_THEME_OPTIONS ), '', $setting_id);
279
+ }
280
+
281
+
282
+
283
+ function ha_is_theme_multidimensional_setting( $setting_id ) {
284
+ return false !== strpos( $setting_id, HU_THEME_OPTIONS );
285
+ }
286
+
287
+
288
+
289
+
290
+
291
+
292
+
293
+
294
+
295
+
296
+
297
+
298
+
299
+
300
+ /*****************************************************
301
+ * CUSTOMIZE PANEL : ADD LOCALIZED PARAMS
302
+ *****************************************************/
303
+ //filter 'hu_js_customizer_control_params' is declared in functions/czr/czr-resources.php
304
+ add_filter( 'hu_js_customizer_control_params', function( $_params ) {
305
+ return array_merge(
306
+ $_params,
307
+ array(
308
+ 'isSkopOn' => defined( 'HA_SKOP_ON' ) ? HA_SKOP_ON : false,
309
+ 'defaultSkopeModel' => ha_get_default_scope_model(),
310
+ 'skopeDynTypes' => ha_get_dyn_types(),//the list of possible dyn types : array( 'post_meta', 'term_meta', 'user_meta', 'trans' )
311
+ 'defaultOptionsValues' => HU_utils::$inst -> hu_get_default_options(),
312
+ 'skopeExcludedSettings' => HU_utils::$inst -> hu_get_skope_excluded_options(),
313
+ 'globalSkopeOptName' => HA_SKOP_OPT() -> global_skope_optname,
314
+ 'isSidebarsWigetsAuthorized' => (bool)apply_filters( 'ha_skope_sidebars_widgets', false )
315
+ )
316
+ );
317
+ });
318
+
319
+
320
+
321
+
322
+
323
+
324
+
325
+
326
+
327
+
328
+
329
+
330
+
331
+
332
+ /*****************************************************
333
+ * PREVIEW FRAME : PROCESS SKOPE EXPORTS
334
+ *****************************************************/
335
+ //hook : customize_preview_init
336
+ add_action( 'wp_footer', 'ha_print_server_skope_data', 30 );
337
+ function ha_print_server_skope_data() {
338
+ if ( ! hu_is_customize_preview_frame() )
339
+ return;
340
+ global $wp_query, $wp_customize;
341
+ $_meta_type = ha_get_skope( 'meta_type', true );
342
+
343
+ // $_czr_scopes = array(
344
+ // 'local' => array(
345
+ // 'level' => ha_get_skope(),
346
+ // 'dyn_type' => ha_get_skope_dyn_type( $_meta_type ),
347
+ // 'opt_name' => HA_SKOP_OPT() -> ha_get_skope_opt_name(),
348
+ // 'is_default' => false,
349
+ // 'is_winner' => true
350
+ // ),
351
+ // 'global' => array(
352
+ // 'ctx' => '_all_',
353
+ // 'dyn_type' => 'option',
354
+ // 'opt_name' => HU_THEME_OPTIONS,
355
+ // 'is_default' => true,
356
+ // 'is_winner' => false
357
+ // )
358
+ // );
359
+ $_czr_skopes = ha_get_json_export_ready_skopes();
360
+ $_skope_global_db_opts = ha_get_saved_opt_names_for_skope( 'global', HU_THEME_OPTIONS );
361
+ ?>
362
+ <script type="text/javascript" id="czr-print-skop">
363
+ (function ( _export ){
364
+ _export.czr_skopes = <?php echo wp_json_encode( $_czr_skopes ); ?>;
365
+ //for the 'global' skope, we only send the option name instead of sending the heavy and performance expensive entire set of option
366
+ //@todo : do we still need to send this ?
367
+ _export.skopeGlobalDBOpt = <?php echo wp_json_encode( $_skope_global_db_opts ); ?>
368
+ })( _wpCustomizeSettings );
369
+ </script>
370
+ <?php
371
+ }
372
+
373
+
374
+
375
+ //@return the name of the currently saved option for a given skope
376
+ //only used for the 'global' skope for now
377
+ //@todo other skope cases
378
+ function ha_get_saved_opt_names_for_skope( $skope = null, $opt_name = null, $opt_group = null ) {
379
+ $skope = is_null( $skope ) ? 'global' : $skope;
380
+ $_opts = hu_get_raw_option( $opt_name, $opt_group );
381
+ $defaults = HU_utils::$inst -> hu_get_default_options();
382
+ $_saved_opts = array();
383
+ if ( ! is_array( $_opts ) )
384
+ return array();
385
+ foreach ( $_opts as $key => $value) {
386
+ if ( HU_utils::$inst -> hu_is_option_protected( $key ) )
387
+ continue;
388
+ if ( ! HU_utils::$inst -> hu_is_option_skoped($key) )
389
+ continue;
390
+ if ( ha_is_option_set_to_default( $key, $value, $defaults ) )
391
+ continue;
392
+ $_saved_opts[] = $key;
393
+ }
394
+ return $_saved_opts;
395
+ }
396
+
397
+
398
+
399
+ function ha_is_option_set_to_default( $opt_name, $value, $defaults ) {
400
+ if ( ! is_array( $defaults ) || ! array_key_exists($opt_name, $defaults) )
401
+ return;
402
+ //@todo : for value written as associative array, we might need a more advanced comparison tool using array_diff_assoc()
403
+ return $value == $defaults[$opt_name];
404
+ }
405
+
406
+
407
+
408
+ //generates the array of available scopes for a given context
409
+ //ex for a single post tagged #tag1 and #tag2 and categroized #cat1 :
410
+ //global
411
+ //all posts
412
+ //local
413
+ //posts tagged #tag1
414
+ //posts tagged #tag2
415
+ //posts categorized #cat1
416
+ //@return array()
417
+ function ha_get_json_export_ready_skopes() {
418
+ $skopes = array();
419
+ $_meta_type = ha_get_skope( 'meta_type', true );
420
+
421
+ //default properties of the scope object
422
+ $defaults = ha_get_default_scope_model();
423
+
424
+ //global and local and always sent
425
+ $skopes[] = wp_parse_args(
426
+ array(
427
+ 'title' => ha_get_skope_title( 'global' ),
428
+ 'long_title' => ha_get_skope_title( 'global', null, true ),
429
+ 'skope' => 'global',
430
+ 'level' => '_all_',
431
+ 'dyn_type' => 'option',
432
+ 'opt_name' => HU_THEME_OPTIONS,
433
+ 'is_default' => true,
434
+ 'is_winner' => false,
435
+ 'is_primary' => true,
436
+ 'has_db_val' => ! empty( ha_get_saved_opt_names_for_skope( 'global', HU_THEME_OPTIONS ) )
437
+ //for the 'global' skope, we only send the option name instead of sending the heavy and performance expensive entire set of option
438
+ //@see ha_print_server_skope_data
439
+ //'db' => hu_get_raw_option( null, HU_THEME_OPTIONS )
440
+ ),
441
+ $defaults
442
+ );
443
+
444
+
445
+ //SPECIAL GROUPS
446
+ //@todo
447
+
448
+
449
+ //GROUP
450
+ //Do we have a group ? => if yes, then there must be a meta type
451
+ if ( ha_get_skope('meta_type') ) {
452
+ $group_opt_name = HA_SKOP_OPT() -> ha_get_skope_opt_name( 'group' );
453
+ $skopes[] = wp_parse_args(
454
+ array(
455
+ 'title' => ha_get_skope_title( 'group', $_meta_type ),
456
+ 'long_title' => ha_get_skope_title( 'group', $_meta_type, true),
457
+ 'skope' => 'group',
458
+ 'level' => 'all_' . ha_get_skope('type'),
459
+ 'dyn_type' => 'trans',//a group is always saved as trans
460
+ 'opt_name' => $group_opt_name,
461
+ 'db' => ha_get_api_ready_skope_db_option( 'group', $_meta_type, $group_opt_name ),
462
+ 'has_db_val' => ! empty( HA_SKOP_OPT() -> ha_get_skope_opt( 'group', $_meta_type, $group_opt_name ) )
463
+ ),
464
+ $defaults
465
+ );
466
+ }
467
+
468
+
469
+ //LOCAL
470
+ $loc_opt_name = HA_SKOP_OPT() -> ha_get_skope_opt_name( 'local');
471
+ $skopes[] = wp_parse_args(
472
+ array(
473
+ 'title' => ha_get_skope_title( 'local', $_meta_type ),
474
+ 'long_title' => ha_get_skope_title( 'local', $_meta_type, true),
475
+ 'skope' => 'local',
476
+ 'level' => ha_get_skope(),
477
+ 'dyn_type' => ha_get_skope_dyn_type( $_meta_type ),
478
+ 'opt_name' => $loc_opt_name,
479
+ 'obj_id' => ha_get_skope('id'),
480
+ 'db' => ha_get_api_ready_skope_db_option( 'local', $_meta_type, $loc_opt_name ),
481
+ 'is_winner' => true,
482
+ 'has_db_val' => ! empty( HA_SKOP_OPT() -> ha_get_skope_opt( 'local', $_meta_type, $loc_opt_name ) )
483
+ ),
484
+ $defaults
485
+ );
486
+ return $skopes;
487
+ }
488
+
489
+
490
+
491
+
492
+ //normalizes the skope model server and clien side (json sent to customizer)
493
+ function ha_get_default_scope_model() {
494
+ return array(
495
+ 'title' => '',
496
+ 'long_title' => '',
497
+ 'id' => '',
498
+ 'skope' => '',
499
+ 'level' => '',
500
+ 'dyn_type' => '',
501
+ 'opt_name' => '',
502
+ 'obj_id' => '',
503
+ 'is_default' => false,
504
+ 'is_winner' => false,
505
+ 'is_forced' => false,//will this scope be visible on load ? is_primary true = yes
506
+ 'db' => array(),
507
+ 'has_db_val' => false
508
+ );
509
+ }
510
+
511
+
512
+
513
+ //the purpose of this function is to return the list of db saved skope values
514
+ //for multidimensional settings like sidebars_widgets* or widget_*, the setting name has to be preprocessed
515
+ //so that it looks like in the customizer api.
516
+ //Ex widget_archives = array( [3] => array( ... ) ) should become widget_archives[3] = array(...)
517
+ //
518
+ //The value
519
+ //
520
+ //@param level string. 'local' for ex.
521
+ //@param meta_type string. 'trans' for ex
522
+ //@param db_opt_name string. name of option in db
523
+ function ha_get_api_ready_skope_db_option( $level, $meta_type, $db_opt_name ) {
524
+ $skope_db_val = HA_SKOP_OPT() -> ha_get_skope_opt( $level, $meta_type, $db_opt_name );
525
+ $skope_db_val = ! is_array( $skope_db_val ) ? array() : $skope_db_val;
526
+ $ha_skop_opt_inst = HA_SKOP_OPT();
527
+ $theme_setting_list = $ha_skop_opt_inst::$_theme_setting_list;
528
+ $theme_option_group = HU_THEME_OPTIONS;
529
+ $api_ready_db_val = array();
530
+ global $wp_customize;
531
+
532
+ foreach ( $skope_db_val as $opt_name => $data ) {
533
+ //is multidimensional ?
534
+ //the theme settings are not.
535
+ //some built-in settings like blogdescription, custom_logo are not either
536
+ //for now only sidebars_widgets* and widget_*
537
+ if ( ! ha_is_wp_setting_multidimensional( $opt_name ) ) {
538
+ //handles wp built-in not dimensional settings
539
+ if ( is_object( $wp_customize -> get_setting( $opt_name ) ) )
540
+ $data = apply_filters( "customize_sanitize_js_{$opt_name}", $data, $wp_customize -> get_setting( $opt_name ) );
541
+
542
+ //handles theme settings
543
+ if ( in_array( $opt_name, $theme_setting_list ) ) {
544
+ $czr_opt_id = "{$theme_option_group}[{$opt_name}]";
545
+ if ( is_object( $wp_customize -> get_setting( $czr_opt_id ) ) ) {
546
+ $data = apply_filters( "customize_sanitize_js_{$czr_opt_id}", $data, $wp_customize -> get_setting( $czr_opt_id ) );
547
+ }
548
+ }
549
+
550
+ $api_ready_db_val[$opt_name] = $data;
551
+ }
552
+ else {
553
+ $to_merge = ha_build_multidimensional_db_option( $opt_name, $data );
554
+ //apply js sanitization function
555
+ //=> ex. For widgets : 'sanitize_widget_js_instance'
556
+ foreach( $to_merge as $set_id => $value ) {
557
+ //@see class-wp-customize-setting.php::js_value()
558
+ $to_merge[$set_id] = apply_filters( "customize_sanitize_js_{$set_id}", $value, $wp_customize -> get_setting( $set_id ) );
559
+ }
560
+ $api_ready_db_val = array_merge( $api_ready_db_val, $to_merge );
561
+ }
562
+ }
563
+ return $api_ready_db_val;
564
+ }
565
+
566
+
567
+
568
+ //@return bool
569
+ //check if multidimensional base on a list of wp multidimensionals
570
+ function ha_is_wp_setting_multidimensional( $base_name ) {
571
+ $wp_multidimensional_prefix = array( 'sidebars_widgets', 'widget_', 'nav_menu' );
572
+ $found_match = false;
573
+ foreach ( $wp_multidimensional_prefix as $_prefix ) {
574
+ if ( $_prefix != substr($base_name, 0, strlen($_prefix) ) )
575
+ continue;
576
+ $found_match = true;
577
+ }
578
+ return $found_match;
579
+ }
580
+
581
+
582
+ function ha_build_multidimensional_db_option( $opt_name, $data ) {
583
+ $api_ready = array();
584
+ foreach ( $data as $key => $value) {
585
+ $new_key = implode( array( $opt_name, '[', $key , ']') );
586
+ $api_ready[$new_key] = $value;
587
+ }
588
+ return $api_ready;
589
+ }
inc/skop/skop-customizer-augment.php ADDED
@@ -0,0 +1,157 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*****************************************************
3
+ * //hook : customize_register
4
+ *****************************************************/
5
+ /******************************************************
6
+ * HEADER IMAGE OVERRIDES FOR SKOPE
7
+ *******************************************************/
8
+ // Overrides the WP built-in header image class update method.
9
+ // => otherwise the skope can't be done because it's normally processed on save
10
+ // on WP_Customize_Setting::update in do_action( "customize_update_{$this->type}", $value, $this );
11
+ /**
12
+ * A setting that is used to filter a value, but will not save the results.
13
+ *
14
+ * Results should be properly handled using another setting or callback.
15
+ *
16
+ * @since 3.4.0
17
+ *
18
+ * @see WP_Customize_Setting
19
+ */
20
+ final class HA_Customize_Header_Image_Data_Setting extends WP_Customize_Setting {
21
+ public $id = 'header_image_data';
22
+
23
+ /**
24
+ * @since 3.4.0
25
+ *
26
+ * @global Custom_Image_Header $custom_image_header
27
+ *
28
+ * @param $value
29
+ */
30
+ public function update( $value ) {
31
+ global $custom_image_header;
32
+
33
+ // If the value doesn't exist (removed or random),
34
+ // use the header_image value.
35
+ if ( ! $value )
36
+ $value = $this->manager->get_setting('header_image')->post_value();
37
+
38
+ //when saving as trans, post_meta, term_meta, or user_meta
39
+ if ( 'theme_mod' != $this->type ) {
40
+ //get the wp like header_image_data
41
+ //Are we in a skope customization context ? If so the dyn type has already been set and overrides the type Setting property
42
+ if ( isset($_POST['dyn_type']) && $this->type == $_POST['dyn_type'] ) {
43
+ $value = $this -> ha_get_header_image_data( $value );
44
+ }
45
+
46
+ do_action( "customize_update_{$this->type}", $value, $this );
47
+ add_filter( "pre_set_theme_mod_{$this->id}", array( $this, 'filter_option'), 1000, 2 );
48
+ add_filter( "pre_set_theme_mod_header_image", array( $this, 'filter_option'), 1000, 2 );
49
+
50
+
51
+ } else {
52
+ if ( is_array( $value ) && isset( $value['choice'] ) )
53
+ $custom_image_header->set_header_image( $value['choice'] );
54
+ else
55
+ $custom_image_header->set_header_image( $value );
56
+ }
57
+ }
58
+
59
+
60
+ public function filter_option( $value, $old_value ) {
61
+ return $old_value;
62
+ }
63
+
64
+
65
+
66
+ //@param choice can be a string or an array
67
+ //@see : set_header_image() in wp-admin/custom-header.php
68
+ public function ha_get_header_image_data( $choice ) {
69
+ global $custom_image_header;
70
+ if ( is_array( $choice ) || is_object( $choice ) ) {
71
+ $choice = (array) $choice;
72
+ if ( ! isset( $choice['attachment_id'] ) || ! isset( $choice['url'] ) )
73
+ return;
74
+
75
+ $choice['url'] = esc_url_raw( $choice['url'] );
76
+
77
+ $header_image_data = (object) array(
78
+ 'attachment_id' => $choice['attachment_id'],
79
+ 'url' => $choice['url'],
80
+ 'thumbnail_url' => $choice['url'],
81
+ 'height' => $choice['height'],
82
+ 'width' => $choice['width'],
83
+ );
84
+
85
+ update_post_meta( $choice['attachment_id'], '_wp_attachment_is_custom_header', get_stylesheet() );
86
+
87
+ //synchronizes the header_image option value for this skope
88
+ if ( false != $_POST['opt_name'] ) {
89
+ $db_option_name = esc_attr( $_POST['opt_name'] );
90
+ $obj_id = ( isset( $_POST['obj_id'] ) && false != $_POST['obj_id'] ) ? esc_attr( $_POST['obj_id'] ) : null;
91
+ HA_SKOP_OPT() -> ha_set_skope_option_val( 'header_image', $choice['url'], $db_option_name, $this->type, $obj_id );
92
+ }
93
+ //set_theme_mod( 'header_image', $choice['url'] );
94
+ //set_theme_mod( 'header_image_data', $header_image_data );
95
+ return $header_image_data;
96
+ }
97
+
98
+ if ( in_array( $choice, array( 'remove-header', 'random-default-image', 'random-uploaded-image' ) ) ) {
99
+ if ( false != $_POST['opt_name'] ) {
100
+ $db_option_name = esc_attr( $_POST['opt_name'] );
101
+ $obj_id = ( isset( $_POST['obj_id'] ) && false != $_POST['obj_id'] ) ? esc_attr( $_POST['obj_id'] ) : null;
102
+ HA_SKOP_OPT() -> ha_set_skope_option_val( 'header_image', $choice, $db_option_name, $this->type, $obj_id );
103
+ }
104
+ //set_theme_mod( 'header_image', $choice );
105
+ //remove_theme_mod( 'header_image_data' );
106
+ return;
107
+ }
108
+
109
+ $uploaded = get_uploaded_header_images();
110
+ if ( $uploaded && isset( $uploaded[ $choice ] ) ) {
111
+ $header_image_data = $uploaded[ $choice ];
112
+
113
+ } else {
114
+ $custom_image_header->process_default_headers();
115
+ if ( isset( $custom_image_header->default_headers[ $choice ] ) )
116
+ $header_image_data = $custom_image_header->default_headers[ $choice ];
117
+ else
118
+ return;
119
+ }
120
+
121
+ //set_theme_mod( 'header_image', esc_url_raw( $header_image_data['url'] ) );
122
+ //set_theme_mod( 'header_image_data', $header_image_data );
123
+ return $header_image_data;
124
+ }
125
+ }//HA_Customize_Header_Image_Data_Setting
126
+
127
+
128
+
129
+
130
+ // Overrides the WP built-in header image class update method.
131
+ // => otherwise the skope can't be done because it's normally processed on save
132
+ // on WP_Customize_Setting::update in do_action( "customize_update_{$this->type}", $value, $this );
133
+ /**
134
+ * A setting that is used to filter a value, but will not save the results.
135
+ *
136
+ * Results should be properly handled using another setting or callback.
137
+ *
138
+ * @since 3.4.0
139
+ *
140
+ * @see WP_Customize_Setting
141
+ */
142
+ final class HA_Customize_Header_Image_Setting extends WP_Customize_Setting {
143
+ public $id = 'header_image';
144
+
145
+ /**
146
+ * @since 3.4.0
147
+ *
148
+ * @global Custom_Image_Header $custom_image_header
149
+ *
150
+ * @param $value
151
+ */
152
+ public function update( $value ) {
153
+
154
+ if ( 'theme_mod' != $this->type )
155
+ do_action( "customize_update_{$this->type}", $value, $this );
156
+ }
157
+ }
inc/skop/skop-options.php ADDED
@@ -0,0 +1,654 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ if ( ! class_exists( 'HA_Skop_Option' ) ) :
3
+ final class HA_Skop_Option {
4
+ public static $instance;
5
+
6
+ public static $_global_opt;
7
+ public static $_group_opt;
8
+ public static $_special_group_opt;
9
+ public static $_local_opt;
10
+ public static $_skope_excluded_settings;
11
+ public static $_theme_setting_list;
12
+ public $global_skope_optname;
13
+
14
+ public static function ha_skop_opt_instance() {
15
+ if ( ! isset( self::$instance ) && ! ( self::$instance instanceof HA_Skop_Option ) )
16
+ self::$instance = new HA_Skop_Option();
17
+ return self::$instance;
18
+ }
19
+
20
+ function __construct() {
21
+ // if ( hu_is_customize_preview_frame() ) {
22
+ // //refresh the theme options right after the _preview_filter when previewing
23
+ // add_action( 'customize_preview_init' , array( $this , 'ha_cache_options' ) );
24
+ // } else {
25
+ // add_action( 'wp' , array( $this, 'ha_cache_options' ) );
26
+ // }
27
+ add_action( 'wp' , array( $this, 'ha_cache_options' ), 99999 );
28
+
29
+
30
+ //SIDEBAR WIDGETS
31
+ add_filter('sidebars_widgets', array($this, 'ha_use_skope_widgets') );
32
+
33
+ //SIDEBAR ON PREVIEW : fix the problem of a customized val being an empty array of wp_inactive_widgets;
34
+ //This filter is ha_customize_val_before_multidimensional_filter_{$opt_name}
35
+ //add_filter('ha_customize_val_before_multidimensional_filter_sidebars_widgets', array($this, 'ha_set_customized_sidebars_val'), 10, 2 );
36
+
37
+
38
+ //CACHE SOME USEFUL LIST OF SETTINGS : THEME SETTINGS AND SKOPE EXCLUDED SETTINGS
39
+ $this -> ha_cache_skope_excluded_settings();
40
+ $this -> ha_cache_theme_setting_list();
41
+ // add_action( 'after_setup_theme', array( $this, 'ha_cache_skope_excluded_settings' ) );
42
+ // add_action( 'after_setup_theme', array( $this, 'ha_cache_theme_setting_list' ) );
43
+
44
+ //FILTER THE LIST OF SKOPE EXCLUDED SETTINGS
45
+ //=> merge the default ones with those defined in the setting map
46
+ add_filter( 'hu_get_skope_excluded_options', array( $this, 'ha_set_excluded_skope_settings') );
47
+
48
+ //SETUP FILTERS FOR WP OPTIONS AND THEME OPTIONS
49
+ add_action( 'wp', array( $this, 'ha_setup_skope_option_filters' ), 1000 );
50
+
51
+ //SET THE NAME OF THE GLOBAL SKOPE OPTION
52
+ //This option stores all global skope settings : theme and wp.
53
+ //It is updated each time the global skope get saved or reset in the customizer
54
+ //It is used to send the list of currently modified global settings in db
55
+ $theme_name = strtolower(THEMENAME);//is always the parent theme name
56
+ $this -> global_skope_optname = "{$theme_name}_global_skope";
57
+ }//construct
58
+
59
+
60
+ /*****************************************************
61
+ * SET AND GET CACHED OPTIONS
62
+ *****************************************************/
63
+ //the purpose of this function is to store the various skope options as properties
64
+ //instead of getting them each time
65
+ //fired on customize_preview_init if in preview frame
66
+ //fired by constructor otherwise
67
+ //@return void()
68
+ //HOOK : WP
69
+ function ha_cache_options() {
70
+ $meta_type = ha_get_skope( 'meta_type', true );
71
+ $_skope_list = array( 'global', 'group', 'special_group', 'local' );
72
+ foreach ($_skope_list as $_skp ) {
73
+ switch ( $_skp ) {
74
+ case 'global':
75
+ HA_Skop_Option::$_global_opt = false === get_option( HU_THEME_OPTIONS ) ? array() : (array)get_option( HU_THEME_OPTIONS );
76
+ break;
77
+ case 'group':
78
+ $db_opt_name = $this -> ha_get_skope_opt_name( 'group' );
79
+ HA_Skop_Option::$_group_opt = $this -> ha_get_skope_opt( 'group', $meta_type, $db_opt_name );
80
+ HA_Skop_Option::$_group_opt = ! HA_Skop_Option::$_group_opt ? array() : HA_Skop_Option::$_group_opt;
81
+ break;
82
+ case 'special_group':
83
+ $db_opt_name = $this -> ha_get_skope_opt_name( 'special_group' );
84
+ HA_Skop_Option::$_special_group_opt = $this -> ha_get_skope_opt( 'special_group', $meta_type, $db_opt_name );
85
+ HA_Skop_Option::$_special_group_opt = ! HA_Skop_Option::$_special_group_opt ? array() : HA_Skop_Option::$_special_group_opt;
86
+ break;
87
+ case 'local':
88
+ $db_opt_name = $this -> ha_get_skope_opt_name( 'local' );
89
+ HA_Skop_Option::$_local_opt = $this -> ha_get_skope_opt( 'local', $meta_type, $db_opt_name );
90
+ HA_Skop_Option::$_local_opt = ! HA_Skop_Option::$_local_opt ? array() : HA_Skop_Option::$_local_opt;
91
+ break;
92
+ }
93
+ }
94
+ }
95
+
96
+
97
+ //Get the skoped option from the db
98
+ //The option name is based on the current skope
99
+ //=> this can't be fired before 'wp'
100
+ //
101
+ //@param level : local, group, special_group
102
+ //@param type : post
103
+ function ha_get_skope_opt( $level, $meta_type, $db_opt_name ) {
104
+ $skope = ha_get_skope();
105
+ $_dyn_type = ( hu_is_customize_preview_frame() && isset($_POST['dyn_type']) ) ? $_POST['dyn_type'] : '';
106
+ $_opt = array();
107
+
108
+ if( 'local' == $level ) {
109
+ if ( $this -> ha_can_have_meta_opt( $meta_type ) ) {
110
+ $_id = ha_get_skope('id');
111
+ switch ($meta_type) {
112
+ case 'post':
113
+ $_opt = get_post_meta( $_id , $db_opt_name, true );
114
+ break;
115
+
116
+ case 'tax':
117
+ $_opt = get_term_meta( $_id , $db_opt_name, true );
118
+ break;
119
+
120
+ case 'user':
121
+ $_opt = get_user_meta( $_id , $db_opt_name, true );
122
+ break;
123
+ }
124
+ } else if ( ( 'trans' == $_dyn_type || $this -> ha_can_have_trans_opt( $skope ) ) && false !== get_transient( $db_opt_name ) ) {
125
+ $_opt = get_transient( $db_opt_name );
126
+ }
127
+ }
128
+ if ( 'group' == $level || 'special_group' == $level ) {
129
+ if ( false !== get_transient( $db_opt_name ) ) {
130
+ $_opt = get_transient( $db_opt_name );
131
+ }
132
+ }
133
+ return $_opt;
134
+ }
135
+
136
+
137
+
138
+ //@return the array of cached opt
139
+ function ha_get_cached_opt( $skope = null, $opt_name = null ) {
140
+ $skope = is_null( $skope ) ? 'local' : $skope;
141
+ $_opt_array = array();
142
+
143
+ switch ( $skope ) {
144
+ case 'global':
145
+ $_opt_array = HA_Skop_Option::$_global_opt;
146
+ break;
147
+ case 'group':
148
+ $_opt_array = HA_Skop_Option::$_group_opt;
149
+ break;
150
+ case 'special_group':
151
+ $_opt_array = HA_Skop_Option::$_special_group_opt;
152
+ break;
153
+ case 'local':
154
+ $_opt_array = HA_Skop_Option::$_local_opt;
155
+ break;
156
+ }
157
+ if ( is_null( $opt_name ) )
158
+ return $_opt_array;
159
+ else
160
+ return isset( $_opt_array[$opt_name] ) ? $_opt_array[$opt_name] : '_no_set_';
161
+ }
162
+
163
+
164
+
165
+
166
+ /*****************************************************
167
+ * CACHE THE LIST OF THEME SETTINGS ONLY
168
+ *****************************************************/
169
+ //hook : after_setup_theme
170
+ //Note : the 'sidebar-areas' setting is not listed in that list because registered specifically
171
+ function ha_cache_theme_setting_list() {
172
+ if ( is_array(self::$_theme_setting_list) && ! empty( self::$_theme_setting_list ) )
173
+ return;
174
+ $_settings_map = HU_utils_settings_map::$instance -> hu_get_customizer_map( null, 'add_setting_control' );
175
+ $_settings = array();
176
+ foreach ( $_settings_map as $_id => $data ) {
177
+ $_settings[] = $_id;
178
+ }
179
+ $default_options = HU_utils::$inst -> hu_get_default_options();
180
+ self::$_theme_setting_list = $_settings;
181
+ }
182
+
183
+
184
+
185
+
186
+
187
+
188
+ /*****************************************************
189
+ * CACHE AND SET SETTINGS EXCLUDED FROM SKOPE
190
+ *****************************************************/
191
+ //hook : after_setup_theme
192
+ function ha_cache_skope_excluded_settings() {
193
+ if ( is_array(self::$_skope_excluded_settings) && ! empty( self::$_skope_excluded_settings ) )
194
+ return;
195
+ $_settings_map = HU_utils_settings_map::$instance -> hu_get_customizer_map( null, 'add_setting_control' );
196
+ $_excluded = array();
197
+ foreach ( $_settings_map as $_id => $data ) {
198
+ if ( isset($data['skoped']) && false === $data['skoped'] )
199
+ $_excluded[] = $_id;
200
+ }
201
+ self::$_skope_excluded_settings = $_excluded;
202
+ }
203
+
204
+ //FILTER THE LIST OF SKOPE EXCLUDED SETTINGS
205
+ //=> merge the default ones with those defined in the setting map
206
+ //hook : hu_get_skope_excluded_options declared in HU_Utils::hu_get_skope_excluded_options
207
+ function ha_set_excluded_skope_settings( $_default_excluded ) {
208
+ return array_merge( $_default_excluded, self::$_skope_excluded_settings );
209
+ }
210
+
211
+
212
+
213
+
214
+
215
+
216
+
217
+ /*****************************************************
218
+ * SIDEBARS AND WIDGETS SPECIFICS
219
+ *****************************************************/
220
+ //hook filter: sidebar_widgets
221
+ function ha_use_skope_widgets( $original ) {
222
+ // if ( 0 == did_action('wp') )
223
+ // return $original;
224
+ if ( ! apply_filters( 'ha_skope_sidebars_widgets', false ) )
225
+ return $original;
226
+
227
+ $db_skope_widgets = get_option('sidebars_widgets');
228
+ $db_skope_widgets = is_array($db_skope_widgets) ? $db_skope_widgets : array();
229
+ $new_sidebar_widgets = $db_skope_widgets;
230
+ $defaut_hu_widget_ids = hu_get_widget_zone_ids();
231
+
232
+ foreach ( $original as $key => $value) {
233
+ if ( in_array( $key, $defaut_hu_widget_ids ) || ! is_array($value) )
234
+ continue;
235
+ //adds any additional entry that the original array contains and that is not a widget id
236
+ //=> ex : orphaned_widgets_1, array_version, ..., wp_inactive_widgets
237
+ $new_sidebar_widgets[$key] = (array)$value;
238
+ }
239
+ //then check if we have only array type values in the new sidebars_widgets
240
+ foreach ($new_sidebar_widgets as $k => $v) {
241
+ if ( ! is_array($v) )
242
+ unset($new_sidebar_widgets[$k]);
243
+ }
244
+
245
+ //then make sure that a widget can not be both active in a sidebar AND part of the wp_inactive_widgets list
246
+ if ( isset($new_sidebar_widgets['wp_inactive_widgets']) && is_array($new_sidebar_widgets['wp_inactive_widgets']) ) {
247
+ foreach ( $new_sidebar_widgets as $sidebar => $wdg_list ) {
248
+ //skip all entries that are not real sidebars
249
+ if ( 'wp_inactive_widgets' == $sidebar )
250
+ continue;
251
+ if ( 'array_version' == $sidebar )
252
+ continue;
253
+ if ( 'orphaned_' == substr($sidebar, 0, strlen('orphaned_') ) )
254
+ continue;
255
+
256
+ foreach ( $wdg_list as $wdg_id ) {
257
+ if ( false === array_search( $wdg_id, $new_sidebar_widgets['wp_inactive_widgets'] ) )
258
+ continue;
259
+ $key_to_remove = array_search( $wdg_id, $new_sidebar_widgets['wp_inactive_widgets'] );
260
+ unset( $new_sidebar_widgets['wp_inactive_widgets'][$key_to_remove] );
261
+ }//foreach
262
+ }//foreach
263
+ }//if
264
+ return $new_sidebar_widgets;
265
+ }
266
+
267
+
268
+ //hook : 'ha_customize_val_before_multidimensional_filter_sidebars_widgets'
269
+ //DEPRECATED
270
+ function ha_set_customized_sidebars_val( $customized_val, $opt_name ) {
271
+ if ( is_array($customized_val) && isset($customized_val['sidebars_widgets[wp_inactive_widgets']) && 1 == count($customized_val) )
272
+ return '_not_customized_';
273
+ return $customized_val;
274
+ }
275
+
276
+
277
+
278
+
279
+
280
+
281
+
282
+ /*****************************************************
283
+ * FILTER WP AND THEME OPTIONS
284
+ *****************************************************/
285
+ //hook : wp
286
+ function ha_setup_skope_option_filters() {
287
+ //FILTER THEME OPTIONS
288
+ add_filter( 'hu_opt', array( $this, 'ha_filter_hu_opt_for_skope' ), 10, 4 );
289
+
290
+ //FILTER WP OPTIONS
291
+ $theme = get_option( 'stylesheet' );
292
+ $wp_options = array(
293
+ 'blogname',
294
+ 'blogdescription',
295
+ "theme_mods_{$theme}"//header_image, custom_logo
296
+ );
297
+
298
+ if ( apply_filters( 'ha_skope_sidebars_widgets', false ) ) {
299
+ $wp_options[] = 'sidebars_widgets';
300
+ $wp_options = array_merge( $wp_options, hu_get_registered_widgets_option_names() );
301
+ }
302
+
303
+ foreach ( $wp_options as $wp_opt ) {
304
+ add_filter( "option_{$wp_opt}", array( $this, 'ha_filter_wp_builtin_options'), 2000, 2 );
305
+ }
306
+ }
307
+
308
+
309
+ ///////FILTER WP OPTIONS
310
+ //hook : option_{$wp_opt}
311
+ //Example of filtered option : sidebars_widgets
312
+ function ha_filter_wp_builtin_options( $value, $option_name = null ) {
313
+ if ( is_null( $option_name ) )
314
+ return $value;
315
+ $theme = get_option( 'stylesheet' );
316
+ if ( "theme_mods_{$theme}" == $option_name ) {
317
+ $skoped_theme_mods = array();
318
+ if ( is_array($value) ) {
319
+ foreach( $value as $_opt_name => $_val ) {
320
+ $skoped_theme_mods[$_opt_name] = $this -> ha_filter_hu_opt_for_skope( $_val, $_opt_name, null );
321
+ }
322
+ return $skoped_theme_mods;
323
+ }
324
+ } else {
325
+ return $this -> ha_filter_hu_opt_for_skope( $value, $option_name, null );//the option group is null
326
+ }
327
+ }
328
+
329
+
330
+
331
+ ///////FILTER THEME OPTIONS
332
+ //which option to get ?
333
+ //1) WHEN CUSTOMIZING
334
+ //- if dyn_type is 'option', then let wp do the job
335
+ //- if dyn_type is not option,
336
+ // A) the requested option name is currently being customized
337
+ // => if so, then get the customized value
338
+ // B) the requested option is not being customized, then get the saved db option using dyn_type and opt_name from $_POST
339
+ //
340
+ //2) WHEN NOT CUSTOMIZING
341
+ // A) the current context can have a meta option : posts (post, page, cpt), tax, authors
342
+ // => retrieve the meta and check if an entry exists for this option
343
+ // B) the current context can have specific global options like home, all_posts, all_pages, all_{custom_post_type}
344
+ // all_tag, all_cat, all_{custom_tax}, all_authors, 404, search, date
345
+ // => if so then check if the current option has an entry in this specific global and return it
346
+ // C) the current context has no specific global option, then fall back on the default value
347
+ //
348
+ //HOOK : hu_opt
349
+ function ha_filter_hu_opt_for_skope( $_opt_val , $opt_name , $opt_group = HU_THEME_OPTIONS , $_default_val = null ) {
350
+ //if the opt group not null, we are retrieving a theme option
351
+ $_new_val = $_opt_val;
352
+
353
+ //CUSTOMIZING
354
+ $_customized_val = $this -> ha_get_customized_value( $opt_name );
355
+ if ( hu_is_customize_preview_frame() && '_not_customized_' != $_customized_val ) {
356
+ return $_customized_val;
357
+ } else {
358
+ if ( hu_is_customize_preview_frame() ) {
359
+ $cust_skope = $this -> ha_get_current_customized_skope();
360
+ $_new_val = $this -> ha_get_preview_inherited_val( $opt_name, $_opt_val, $cust_skope );
361
+ } else {
362
+ $skop_opts = array(
363
+ 'local' => $this -> ha_get_cached_opt( 'local', $opt_name ),
364
+ 'group' => $this -> ha_get_cached_opt( 'group', $opt_name ),
365
+ 'special_group' => $this -> ha_get_cached_opt( 'special_group', $opt_name ),
366
+ 'global' => $_opt_val
367
+ );
368
+
369
+ //priority
370
+ //loop until a value is found
371
+ //skip the global skope
372
+ $_found_val = false;
373
+ foreach ( $skop_opts as $_key => $_value) {
374
+ if ( 'global' == $_key || $_found_val )
375
+ continue;
376
+ //cast to array. Ex : header_image_data might be saved as an object
377
+ $_value = is_object( $_value ) ? (array)$_value : $_value;
378
+
379
+ if ( is_array($_value) || '_no_set_' != (string)$_value ) {
380
+ $_new_val = $_value;
381
+ $_found_val = true;
382
+ }
383
+ }
384
+ }
385
+
386
+ }
387
+ //falls back to global
388
+ return $_new_val;
389
+ }
390
+
391
+
392
+
393
+
394
+
395
+
396
+
397
+
398
+ /*****************************************************
399
+ * GET VALUES WHEN PREVIEWING : APPLY INHERITANCE
400
+ *****************************************************/
401
+ //recursive method
402
+ //apply the skope inheritance to return the relevant value
403
+ private function ha_get_preview_inherited_val( $opt_name, $original_opt_val, $skope ) {
404
+ $skop_opt_val = $this -> ha_get_cached_opt( $skope, $opt_name );
405
+ //cast to array if the saved option is an object. For Ex : header_image_data can be an object
406
+ $skop_opt_val = 'object' == gettype( $skop_opt_val ) ? (array)$skop_opt_val : $skop_opt_val;
407
+ if ( is_array($skop_opt_val) || '_no_set_' != (string)$skop_opt_val )
408
+ return $skop_opt_val;
409
+
410
+ if ( 'global' == $skope )
411
+ return $original_opt_val;
412
+
413
+ $parent_skope = $this -> ha_get_parent_skope_name( $skope );
414
+ return $this -> ha_get_preview_inherited_val( $opt_name, $original_opt_val, $parent_skope );
415
+
416
+ }
417
+
418
+
419
+ private function ha_get_parent_skope_name( $skope, $_index = null ) {
420
+ $hierark = array( 'local', 'group', 'special_group', 'global' );
421
+ $parent_ind = -1;
422
+ //get the parent index
423
+ foreach( $hierark as $_key => $_skp ) {
424
+ if ( $skope == $_skp && -1 == $parent_ind )
425
+ $parent_ind = intval( $_key + 1 ) ;
426
+ continue;
427
+ }
428
+ return isset( $hierark[$parent_ind] ) ? $hierark[$parent_ind] : 'global';
429
+ }
430
+
431
+
432
+
433
+
434
+
435
+
436
+ /*****************************************************
437
+ * GET CUSTOMIZED VALUE
438
+ *****************************************************/
439
+ //@return bool
440
+ //check if a theme option or a wp option is dirty customized
441
+ //important the $opt_name param is always the short option name, for example
442
+ // hueman option ex : use-header-image => when customizing, this option will be hu_theme_options[use-header-image]
443
+ // wp option ex1 : blogdescription => unchanged name when customizing, because not multidimensional
444
+ // wp option ex2 : sidebars_widgets => is multidimensional and will be like sidebars_widgets[primary]
445
+ //
446
+ // Consequently :
447
+ // 1) we first check if each customized options contain a key == opt_name
448
+ // 2) then we check if each customized option is multidimensional and starts with the provided opt_name
449
+ function ha_get_customized_value( $opt_name ) {
450
+ //return '_not_customized_';
451
+ if ( ! hu_is_customize_preview_frame() )
452
+ return '_not_customized_';
453
+
454
+ $_customized_val = '_not_customized_';
455
+ global $wp_customize;
456
+
457
+ $post_values = $wp_customize->unsanitized_post_values();
458
+
459
+ //make sure post values is always an array
460
+ if ( false === $post_values || ! is_array($post_values) )
461
+ $post_values = array();
462
+
463
+ // if ( empty( $post_values ) )
464
+ // return '_not_customized_';
465
+
466
+ //let's set the setting_id to the opt_name by default
467
+ $setting_id = $opt_name;
468
+
469
+ //WP BUIT-IN SETTING NOT MULTIDIMENSIONAL CASE
470
+ if ( array_key_exists( $opt_name, $post_values ) && is_object( $wp_customize -> get_setting( $opt_name ) ) )
471
+ $_customized_val = $wp_customize -> post_value( $wp_customize -> get_setting( $opt_name ) );
472
+
473
+ //THEME SETTING CASE
474
+ //let's build the option name as it in the customizer
475
+ $_theme_option_prefix = strtolower(HU_THEME_OPTIONS);
476
+ $_theme_opt_name = "{$_theme_option_prefix}[{$opt_name}]";
477
+ if ( array_key_exists( $_theme_opt_name, $post_values ) && is_object( $wp_customize -> get_setting( $_theme_opt_name ) ) )
478
+ $_customized_val = $wp_customize -> post_value( $wp_customize -> get_setting( $_theme_opt_name ) );
479
+
480
+ //MULTIDIMENSIONAL CASE
481
+ //If we still have no match at this stage, $_customized_val == '_not_customized_'
482
+ //Loop all the registered settings
483
+ //then for each setting, check if it's multidimensional and get its id base
484
+ //then try to find a match in the unsanitized post values sent by $_POST request
485
+ $found_match = false;
486
+ if ( '_not_customized_' == $_customized_val ) {
487
+ foreach ( $wp_customize -> settings() as $_setting ) {
488
+ if ( $found_match )
489
+ continue;
490
+
491
+ $id_data = $_setting -> id_data();
492
+ $is_multidimensional = ! empty( $id_data['keys'] );
493
+ $setting_id = $_setting -> id;
494
+
495
+ //already covered before but let's do it again. To be removed.
496
+ if ( ! $is_multidimensional && $_setting -> id == $opt_name && array_key_exists( $_setting -> id, $post_values ) ) {
497
+ $_customized_val = $post_values[$_setting -> id];
498
+ $found_match = true;
499
+ }
500
+ else if ( $is_multidimensional && $opt_name == $id_data['base'] ) {
501
+ $f_match = false;
502
+ foreach ( $post_values as $_cust_opt_name => $val ) {
503
+ //try to find a prefix match option. For ex : sidebars_widgets
504
+ if ( $opt_name != substr($_cust_opt_name, 0, strlen( $opt_name ) ) || $f_match )
505
+ continue;
506
+ // $_customized_val = apply_filters( "ha_customize_val_before_multidimensional_filter_{$opt_name}", $_customized_val, $opt_name );
507
+ // if ( '_not_customized_' == $_customized_val )
508
+ // continue;
509
+ $_customized_val = $_setting -> _multidimensional_preview_filter( $val );
510
+ $f_match = true;
511
+ }
512
+ }
513
+ }//foreach
514
+ }//if
515
+
516
+ //apply WP default checks
517
+ // if ( '_not_customized_' == $_customized_val )
518
+ // return $_customized_val;
519
+ // $valid = $wp_customize ->get_setting( $setting_id ) -> validate( $_customized_val );
520
+ // if ( is_wp_error( $valid ) ) {
521
+ // wp_send_json_error( 'Invalid value for setting ' . $setting_id );
522
+ // return '_not_customized_';
523
+ // }
524
+ // $value = $wp_customize ->get_setting( $setting_id ) ->sanitize( $_customized_val );
525
+ // if ( is_null( $value ) || is_wp_error( $value ) ) {
526
+ // wp_send_json_error( 'null or not passed the sanitize tests setting ' . $setting_id );
527
+ // return '_not_customized_';
528
+ // }
529
+
530
+ //APPLY A SPECIAL TREATMENT
531
+ return apply_filters( "ha_get_customize_val_{$opt_name}", $_customized_val, $opt_name );
532
+ }
533
+
534
+
535
+
536
+
537
+
538
+
539
+
540
+
541
+
542
+
543
+
544
+
545
+
546
+
547
+ /******************************************************
548
+ * HELPERS
549
+ *******************************************************/
550
+ //@return the name of the option as a string for a given skope
551
+ function ha_get_skope_opt_name( $level = 'local', $special = '' ) {
552
+ $name = '';
553
+ switch ($level) {
554
+ case 'local':
555
+ $name = strtolower( THEMENAME . '_czr_' . ha_get_skope() );
556
+ break;
557
+ case 'group' :
558
+ if ( ! empty( ha_get_skope('type') ) )
559
+ $name = strtolower( THEMENAME . '_czr_all_' . ha_get_skope('type') );
560
+ break;
561
+ case 'special_group' :
562
+ $name = strtolower( THEMENAME . '_czr_all_' . ha_get_skope('type') . $special );
563
+ break;
564
+ case 'global':
565
+ $name = HU_THEME_OPTIONS;
566
+ break;
567
+ }
568
+ return $name;
569
+ }
570
+
571
+ //@return the current posted skope string
572
+ //falls back on 'global'
573
+ function ha_get_current_customized_skope() {
574
+ if ( '__no_posted__' == $this -> ha_get_sanitized_post_value( 'skope' ) )
575
+ return 'global';
576
+ return $this -> ha_get_sanitized_post_value( 'skope' );
577
+ }
578
+
579
+
580
+ //@return a sanitized esc_attr() value from the $_POST array
581
+ function ha_get_sanitized_post_value( $param ) {
582
+ return isset($_POST[$param]) ? esc_attr( $_POST[$param ] ) : '__no_posted__';
583
+ }
584
+
585
+
586
+ function ha_can_have_meta_opt( $meta_type ) {
587
+ return in_array(
588
+ $meta_type,
589
+ array('post', 'tax', 'user')
590
+ );
591
+ }
592
+
593
+
594
+ function ha_can_have_trans_opt( $meta_type ) {
595
+ return in_array(
596
+ $meta_type,
597
+ array('home', 'search', '404', 'date')
598
+ );
599
+ }
600
+
601
+
602
+ //Write the new skope option in db
603
+ //it can be a transient, post_meta, term_meta or user_meta
604
+ function ha_set_skope_option_val( $opt_name, $new_value, $db_option_name = null, $type = null, $obj_id = null ) {
605
+ if ( empty($opt_name) || is_null($db_option_name ) || is_null($type) )
606
+ return;
607
+
608
+ $current_val = false;
609
+ switch ($type) {
610
+ case 'trans':
611
+ $_val = get_transient( $opt_name );
612
+ $_val = $this -> ha_preprocess_skope_val( $new_value, $opt_name, $_val );
613
+ set_transient( $opt_name, $_val, 60*24*365*100 );
614
+ break;
615
+
616
+ case 'post_meta':
617
+ if ( is_null( $obj_id ) )
618
+ return;
619
+ $_val = get_post_meta( $obj_id , $db_option_name, true );
620
+ $_val = $this -> ha_preprocess_skope_val( $new_value, $opt_name, $_val );
621
+ update_post_meta( $obj_id , $db_option_name, $_val );
622
+ break;
623
+
624
+ case 'term_meta':
625
+ if ( is_null( $obj_id ) )
626
+ return;
627
+ $_val = get_term_meta( $obj_id , $db_option_name, true );
628
+ $_val = $this -> ha_preprocess_skope_val( $new_value, $opt_name, $_val );
629
+ update_term_meta( $obj_id , $db_option_name, $_val );
630
+ break;
631
+
632
+ case 'user_meta':
633
+ if ( is_null( $obj_id ) )
634
+ return;
635
+ $_val = get_user_meta( $obj_id , $db_option_name, true );
636
+ $_val = $this -> ha_preprocess_skope_val( $new_value, $opt_name, $_val );
637
+ update_user_meta( $obj_id , $db_option_name, $_val );
638
+ break;
639
+ }
640
+ }
641
+
642
+ //@return updated option associative array( opt_name1 => value 1, opt_name2 => value2, ... )
643
+ function ha_preprocess_skope_val( $new_value, $opt_name, $current_value ) {
644
+ if ( ! $current_value || ! is_array($current_value) ) {
645
+ $to_return = array( $opt_name => $new_value );
646
+ } else {
647
+ $to_return = $current_value;
648
+ $to_return[$opt_name] = $new_value;
649
+ }
650
+ return $to_return;
651
+ }
652
+
653
+ }//class
654
+ endif;
inc/skop/tmpl/skope-tmpls.php ADDED
@@ -0,0 +1,73 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ add_action( 'customize_controls_print_footer_scripts', 'ha_print_skope_templates' );
3
+ //data example :
4
+ // id:"global"
5
+ // ctx:"_all_"
6
+ // dyn_type:"option"
7
+ // el:"czr-scope-global"
8
+ // is_default:true
9
+ // is_winner:false
10
+ // opt_name:"hu_theme_options"
11
+ function ha_print_skope_templates() {
12
+ ?>
13
+
14
+ <?php /* SINGLE SKOPE TMPL */ ?>
15
+ <script type="text/html" id="tmpl-czr-skope">
16
+ <div class="{{data.el}} czr-scope" data-scope-id="{{data.id}}" data-dyn-type="{{data.dyn_type}}">
17
+ <div class="czr-scope-header">
18
+ <span class="czr-scope-reset fa fa-refresh czr-pull-left" title="Reset"></span>
19
+ <span class="czr-scope-switch fa fa-toggle-off czr-pull-right" title="Switch to / active ?"></span>
20
+ </div>
21
+ <div class="czr-scope-content"><h4>{{data.title}}</h4></div>
22
+ <div class="czr-scope-footer">
23
+ <span class="czr-scope-winner fa fa-check czr-pull-left info" title="Is applied on front end ?"></span>
24
+ <span class="czr-scope-force fa fa-exclamation-circle czr-pull-right" title="Force priority"></span>
25
+ </div>
26
+ </div>
27
+ </script>
28
+
29
+
30
+
31
+ <?php /* RESET SKOPE PANEL TMPL */ ?>
32
+ <script type="text/html" id="tmpl-czr-reset-skope">
33
+ <div id="czr-reset-skope-pane" data-scope-id="{{data.id}}">
34
+ <div class="czr-reset-content">
35
+ <div class="czr-reset-warning">
36
+ <h2>{{data.warning_message}}</h2>
37
+ <p>This is irreversible</p>
38
+ <span class="button czr-scope-do-reset">YES RESET NOW</span>&nbsp;
39
+ <span class="button czr-scope-reset-cancel">CANCEL</span>
40
+ </div>
41
+ <div class="czr-resetting">
42
+ <span class="czr-spinner"></span>
43
+ </div>
44
+ <div class="czr-reset-success">
45
+ <h2>{{data.success_message}}</h2>
46
+ </div>
47
+ <div class="czr-reset-fail">
48
+ <h2>There was a problem when trying to reset {{data.id}}.</h2>
49
+ </div>
50
+ </div>
51
+ </div>
52
+ </script>
53
+
54
+ <?php /* RESET CONTROL TMPL */ ?>
55
+ <script type="text/html" id="tmpl-czr-reset-control">
56
+ <div class="czr-remove-alert-wrapper czr-ctrl-reset-warning">
57
+ <p>{{data.warning_message}}</p>
58
+ <span class="czr-control-do-reset button">Yes</span> <span class="czr-cancel-button button">No</span>
59
+ <span class="czr-spinner"></span>
60
+ <div class="czr-reset-success">
61
+ <p>{{data.success_message}}</p>
62
+ </div>
63
+ <div class="czr-reset-fail">
64
+ <p>There was a problem when trying to reset.</p>
65
+ </div>
66
+ </div>
67
+ </script>
68
+ <?php
69
+ }
70
+
71
+
72
+
73
+
lang/en_US.po CHANGED
@@ -1,6 +1,6 @@
1
  msgid ""
2
  msgstr ""
3
- "Project-Id-Version: Hueman Addons v1.0.8\n"
4
  "POT-Creation-Date: 2016-05-05 14:53+0200\n"
5
  "PO-Revision-Date: 2016-05-05 14:53+0200\n"
6
  "Last-Translator: \n"
1
  msgid ""
2
  msgstr ""
3
+ "Project-Id-Version: Hueman Addons v1.0.9\n"
4
  "POT-Creation-Date: 2016-05-05 14:53+0200\n"
5
  "PO-Revision-Date: 2016-05-05 14:53+0200\n"
6
  "Last-Translator: \n"
readme.txt CHANGED
@@ -5,7 +5,7 @@ Plugin URI: https://wordpress.org/plugins/hueman-addons/
5
  Tags: hueman theme, hueman
6
  Requires at least: 3.4
7
  Tested up to: 4.7
8
- Stable tag: 1.0.8
9
  License: GPLv2 or later
10
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
11
 
@@ -37,6 +37,9 @@ The plugin has been designed specifically for the Hueman WordPress theme. Lightw
37
 
38
 
39
  == Changelog ==
 
 
 
40
  = 1.0.8 : September 15th, 2016 =
41
  * fixed typos
42
 
5
  Tags: hueman theme, hueman
6
  Requires at least: 3.4
7
  Tested up to: 4.7
8
+ Stable tag: 1.0.9
9
  License: GPLv2 or later
10
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
11
 
37
 
38
 
39
  == Changelog ==
40
+ = 1.0.9 : December 6th, 2016 =
41
+ * updated : customizer compatibility with Hueman version 3.2.11
42
+
43
  = 1.0.8 : September 15th, 2016 =
44
  * fixed typos
45