PluginProbe ʕ •ᴥ•ʔ
Custom Sidebars – Dynamic Sidebar Classic Widget Area Manager / 3.38
Custom Sidebars – Dynamic Sidebar Classic Widget Area Manager v3.38
trunk 2.1.2.0 3.0.0.0 3.0.0.1 3.0.1 3.0.2 3.0.3 3.0.4 3.0.5 3.0.6 3.0.7 3.0.7.1 3.0.8 3.0.8.1 3.0.9 3.1.0 3.1.1 3.1.2 3.1.3 3.1.4 3.1.5 3.1.6 3.2.0 3.2.1 3.2.2 3.2.3 3.2.4 3.3 3.31 3.32 3.35 3.36 3.37 3.38
custom-sidebars / inc / class-custom-sidebars-editor.php
custom-sidebars / inc Last commit date
external 1 year ago integrations 7 years ago class-custom-sidebars-checkup-notification.php 1 year ago class-custom-sidebars-cloning.php 1 year ago class-custom-sidebars-editor.php 1 year ago class-custom-sidebars-explain.php 1 year ago class-custom-sidebars-export.php 1 year ago class-custom-sidebars-replacer.php 3 years ago class-custom-sidebars-visibility.php 1 year ago class-custom-sidebars-widgets.php 9 years ago class-custom-sidebars.php 1 year ago
class-custom-sidebars-editor.php
1538 lines
1 <?php
2
3 add_action( 'cs_init', array( 'CustomSidebarsEditor', 'instance' ) );
4
5 /**
6 * Provides all the functionality for editing sidebars on the widgets page.
7 */
8 class CustomSidebarsEditor extends CustomSidebars {
9
10 private $modifiable = null;
11
12 /**
13 * Capability required to use *any* of the plugin features. If user does not
14 * have this capability then he will not see any change on admin dashboard.
15 * @var string
16 */
17 static protected $cap_required = 'edit_theme_options';
18
19 /**
20 * Metabox roles name
21 *
22 * @since 3.0.9
23 */
24 private $metabox_roles_name = 'custom_sidebars_metabox_roles';
25
26 /**
27 * Custom taxoniomies name
28 *
29 * @since 3.0.9
30 */
31 private $custom_taxonomies_name = 'custom_sidebars_custom_taxonomies';
32
33 /**
34 * Allow author to change sidebars
35 *
36 * @since 3.1.5
37 */
38 private $allow_author_name = 'custom_sidebars_allow_author';
39
40 /**
41 * Returns the singleton object.
42 *
43 * @since 2.0
44 */
45 public static function instance() {
46 static $Inst = null;
47 if ( null === $Inst ) {
48 $Inst = new CustomSidebarsEditor();
49 }
50 return $Inst;
51 }
52
53 /**
54 * Constructor is private -> singleton.
55 *
56 * @since 2.0
57 */
58 private function __construct() {
59 if ( ! is_admin() ) {
60 return;
61 }
62 // Add the sidebar metabox to posts.
63 add_action( 'add_meta_boxes', array( $this, 'add_meta_box' ) );
64 // Save the options from the sidebars-metabox.
65 add_action( 'save_post', array( $this, 'store_replacements' ) );
66 // Handle ajax requests.
67 add_action( 'cs_ajax_request', array( $this, 'handle_ajax' ) );
68 add_action( 'admin_init', array( $this, 'settings' ) );
69 }
70
71 /**
72 * Settings function
73 *
74 * @since 3.1.0
75 */
76 public function settings() {
77 /**
78 * metabox role
79 */
80 add_filter( 'screen_settings', array( $this, 'add_capabilities_select_box' ), 10, 2 );
81 add_action( 'wp_ajax_custom_sidebars_metabox_roles', array( $this, 'update_custom_sidebars_metabox_roles' ) );
82 add_action( 'wp_ajax_custom_sidebars_metabox_custom_taxonomies', array( $this, 'update_custom_sidebars_metabox_custom_taxonomies' ) );
83 add_action( 'wp_ajax_custom_sidebars_allow_author', array( $this, 'update_custom_sidebars_allow_author' ) );
84 /**
85 * Check user privileges
86 */
87 $user_can_save = $this->current_user_can_update_custom_sidebars();
88 if ( ! $user_can_save ) {
89 return;
90 }
91 // Add a custom column to post list.
92 $posttypes = self::get_post_types( 'objects' );
93 foreach ( $posttypes as $pt ) {
94 add_filter( 'manage_' . $pt->name . '_posts_columns', array( $this, 'post_columns' ) );
95 add_action( 'manage_' . $pt->name . '_posts_custom_column', array( $this, 'post_column_content' ), 10, 2
96 );
97 }
98 /** This action is documented in wp-admin/includes/screen.php */
99 add_filter( 'default_hidden_columns', array( $this, 'default_hidden_columns' ), 10, 2 );
100 add_action( 'quick_edit_custom_box', array( $this, 'post_quick_edit' ), 10, 2 );
101 add_action( 'bulk_edit_custom_box', array( $this, 'post_bulk_edit' ), 10, 2 );
102 add_action( 'admin_footer', array( $this, 'post_quick_edit_js' ) );
103 /**
104 * Bulk Edit save
105 *
106 * @since 3.0.8
107 */
108 add_action( 'save_post', array( $this, 'bulk_edit_save' ) );
109 }
110
111 /**
112 * Handles the ajax requests.
113 */
114 public function handle_ajax( $action ) {
115 $req = (object) array(
116 'status' => 'ERR',
117 );
118 $is_json = true;
119 $handle_it = false;
120 $view_file = '';
121 $sb_id = '';
122 if ( isset( $_POST['sb'] ) ) {
123 $sb_id = sanitize_key($_POST['sb']);
124 }
125 switch ( $action ) {
126 case 'get':
127 case 'save':
128 case 'delete':
129 case 'get-location':
130 case 'set-location':
131 case 'replaceable':
132 $handle_it = true;
133 $req->status = 'OK';
134 $req->action = $action;
135 $req->id = $sb_id;
136 break;
137 }
138 // The ajax request was not meant for us...
139 if ( ! $handle_it ) {
140 return false;
141 }
142 $sb_data = self::get_sidebar( $sb_id );
143 if ( ! current_user_can( self::$cap_required ) ) {
144 $req = self::req_err(
145 $req,
146 __( 'You do not have permission for this', 'custom-sidebars' )
147 );
148 } else {
149 $sidebar_data = map_deep( $_POST, 'sanitize_text_field' );
150 switch ( $action ) {
151 // Return details for the specified sidebar.
152 case 'get':
153 /**
154 * check nonce
155 */
156 if (
157 ! isset( $sidebar_data['_wpnonce'] )
158 || ! wp_verify_nonce( $sidebar_data['_wpnonce'], 'custom-sidebars-get' )
159 ) {
160 $req = self::req_err(
161 $req,
162 __( 'You do not have permission for this', 'custom-sidebars' )
163 );
164 } else {
165 $sb_data['advance'] = false;
166 $user_id = get_current_user_id();
167 if ( $user_id ) {
168 $advance = get_user_option( 'custom-sidebars-editor-advance', $user_id );
169 if ( is_array( $advance ) && isset( $advance[ $sb_data['id'] ] ) ) {
170 $sb_data['advance'] = $advance[ $sb_data['id'] ];
171 }
172 }
173 $req->sidebar = $sb_data;
174 }
175 break;
176 // Save or insert the specified sidebar.
177 case 'save':
178 $req = $this->save_item( $req, $sidebar_data );
179 break;
180 // Delete the specified sidebar.
181 case 'delete':
182 $req->sidebar = $sb_data;
183 $req = $this->delete_item( $req, $sidebar_data );
184 break;
185 // Get the location data.
186 case 'get-location':
187 $req->sidebar = $sb_data;
188 $req = $this->get_location_data( $req );
189 break;
190 // Update the location data.
191 case 'set-location':
192 $req->sidebar = $sb_data;
193 $req = $this->set_location_data( $req );
194 break;
195 // Toggle theme sidebar replaceable-flag.
196 case 'replaceable':
197 $req = $this->set_replaceable( $req );
198 break;
199 }
200 }
201 // Make the ajax response either as JSON or plain text.
202 if ( $is_json ) {
203 self::json_response( $req );
204 } else {
205 ob_start();
206 include CSB_VIEWS_DIR . $view_file;
207 $resp = ob_get_clean();
208 self::plain_response( $resp );
209 }
210 }
211
212 /**
213 * Saves the item specified by $data array and populates the response
214 * object. When $req->id is empty a new sidebar will be created. Otherwise
215 * the existing sidebar is updated.
216 *
217 * @since 2.0
218 * @param object $req Initial response object.
219 * @param array $data Sidebar data to save (typically this is $_POST).
220 * @return object Updated response object.
221 */
222 private function save_item( $req, $data ) {
223 /**
224 * check nonce
225 */
226 if (
227 ! isset( $data['_wpnonce'] )
228 || ! wp_verify_nonce( $data['_wpnonce'], 'custom-sidebars-edit-sidebar' )
229 ) {
230 return self::req_err(
231 $req,
232 __( 'You have no permission to do this operation.', 'custom-sidebars' )
233 );
234 }
235 $sidebars = self::get_custom_sidebars();
236 $sb_id = $req->id;
237 $sb_desc = '';
238 if ( isset( $data['description'] ) ) {
239 $sb_desc = stripslashes( trim( $data['description'] ) );
240 }
241 $sb_name = isset( $data['name'] )? $data['name']:'';
242 if ( function_exists( 'mb_substr' ) ) {
243 $sb_name = mb_substr( stripslashes( trim( $sb_name ) ), 0, 40 );
244 } else {
245 $sb_name = substr( stripslashes( trim( $sb_name ) ), 0, 40 );
246 }
247 if ( empty( $sb_name ) ) {
248 return self::req_err(
249 $req,
250 __( 'Sidebar-name cannot be empty', 'custom-sidebars' )
251 );
252 }
253 if ( empty( $sb_id ) ) {
254 // Create a new sidebar.
255 $action = 'insert';
256 $num = count( $sidebars );
257 do {
258 $num += 1;
259 $sb_id = self::$sidebar_prefix . $num;
260 } while ( self::get_sidebar( $sb_id, 'cust' ) );
261 $sidebar = array(
262 'id' => $sb_id,
263 );
264 } else {
265 // Update existing sidebar
266 $action = 'update';
267 $sidebar = self::get_sidebar( $sb_id, 'cust' );
268 if ( ! $sidebar ) {
269 return self::req_err(
270 $req,
271 __( 'The sidebar does not exist', 'custom-sidebars' )
272 );
273 }
274 }
275 if ( function_exists( 'mb_strlen' ) ) {
276 if ( mb_strlen( $sb_desc ) > 200 ) {
277 $sb_desc = mb_substr( $sb_desc, 0, 200 );
278 }
279 } else {
280 if ( strlen( $sb_desc ) > 200 ) {
281 $sb_desc = substr( $sb_desc, 0, 200 );
282 }
283 }
284 // Populate the sidebar object.
285 if ( 'insert' == $action || self::wpml_is_default_lang() ) {
286 $sidebar['name'] = $sb_name;
287 $sidebar['description'] = $sb_desc;
288 } else {
289 $sidebar['name_lang'] = $sb_name;
290 $sidebar['description_lang'] = $sb_desc;
291 }
292 foreach ( array( 'before', 'after' ) as $prefix ) {
293 foreach ( array( 'widget', 'title' ) as $sufix ) {
294 $name = sprintf( '%s_%s', $prefix, $sufix );
295 $sidebar[ $name ] = '';
296 if ( isset( $_POST[ $name ] ) ) {
297 $sidebar[ $name ] = stripslashes( trim( sanitize_text_field($_POST[ $name ]) ) );
298 }
299 }
300 }
301 if ( 'insert' == $action ) {
302 $sidebars[] = $sidebar;
303 /* translators: %1$s is replaced with the sidebar name */
304 $req->message = sprintf(__( 'Created new sidebar <strong>%1$s</strong>', 'custom-sidebars' ),esc_html( $sidebar['name'] ));
305 } else {
306 $found = false;
307 foreach ( $sidebars as $ind => $item ) {
308 if ( $item['id'] == $sb_id ) {
309 /* translators: %1$s is replaced with the sidebar name */
310 $req->message = sprintf(__( 'Updated sidebar <strong>%1$s</strong>', 'custom-sidebars' ),esc_html( $sidebar['name'] ));
311 $sidebars[ $ind ] = $sidebar;
312 $found = true;
313 break;
314 }
315 }
316 if ( ! $found ) {
317 return self::req_err(
318 $req,
319 __( 'The sidebar was not found', 'custom-sidebars' )
320 );
321 }
322 }
323 // Save the changes.
324 self::set_custom_sidebars( $sidebars );
325 self::refresh_sidebar_widgets();
326 $req->data = $sidebar;
327 $req->action = $action;
328 // Allow user to translate sidebar name/description via WPML.
329 self::wpml_update( $sidebars );
330 $req->data = self::wpml_translate( $sidebar );
331 /**
332 * save user preferences (advance).
333 *
334 * @since 3.1.3
335 */
336 $user_id = get_current_user_id();
337 if ( $user_id ) {
338 $advance = get_user_option( 'custom-sidebars-editor-advance', $user_id );
339 if ( ! is_array( $advance ) ) {
340 $advance = array();
341 }
342 $advance[ $req->data['id'] ] = isset( $_POST['advance'] ) && 'show' === $_POST['advance'];
343 update_user_option( $user_id, 'custom-sidebars-editor-advance', $advance );
344 }
345 return $req;
346 }
347
348 /**
349 * Delete the specified sidebar and update the response object.
350 *
351 * @since 2.0
352 * @since 3.0.8.1 Added the $data param.
353 *
354 * @param object $req Initial response object.
355 * @param array $data Sidebar data to save (typically this is $_POST).
356 * @return object Updated response object.
357 */
358 private function delete_item( $req, $data ) {
359 /**
360 * check nonce
361 */
362 if (
363 ! isset( $data['_wpnonce'] )
364 || ! wp_verify_nonce( $data['_wpnonce'], 'custom-sidebars-delete-sidebar' )
365 ) {
366 return self::req_err(
367 $req,
368 __( 'You have no permission to do this operation.', 'custom-sidebars' )
369 );
370 }
371 $sidebars = self::get_custom_sidebars();
372 $sidebar = self::get_sidebar( $req->id, 'cust' );
373 if ( ! $sidebar ) {
374 return self::req_err(
375 $req,
376 __( 'The sidebar does not exist', 'custom-sidebars' )
377 );
378 }
379 $found = false;
380 foreach ( $sidebars as $ind => $item ) {
381 if ( $item['id'] == $req->id ) {
382 $found = true;
383 /* translators: %1$s is replaced with the sidebar name */
384 $req->message = sprintf(__( 'Deleted sidebar <strong>%1$s</strong>', 'custom-sidebars' ),esc_html( $req->sidebar['name'] ));
385 unset( $sidebars[ $ind ] );
386 break;
387 }
388 }
389 if ( ! $found ) {
390 return self::req_err(
391 $req,
392 __( 'The sidebar was not found', 'custom-sidebars' )
393 );
394 }
395 // Save the changes.
396 self::set_custom_sidebars( $sidebars );
397 self::refresh_sidebar_widgets();
398 return $req;
399 }
400
401 /**
402 * Save the repaceable flag of a theme sidebar.
403 *
404 * @since 2.0
405 * @param object $req Initial response object.
406 * @return object Updated response object.
407 */
408 private function set_replaceable( $req ) {
409 $state = @sanitize_text_field($_POST['state']);
410 $options = self::get_options();
411 if ( 'true' === $state ) {
412 $req->status = true;
413 if ( ! in_array( $req->id, $options['modifiable'] ) ) {
414 $options['modifiable'][] = $req->id;
415 }
416 } else {
417 $req->status = false;
418 foreach ( $options['modifiable'] as $i => $sb_id ) {
419 if ( $sb_id == $req->id ) {
420 unset( $options['modifiable'][ $i ] );
421 break;
422 }
423 }
424 }
425 $options['modifiable'] = array_values( $options['modifiable'] );
426 self::set_options( $options );
427 $req->replaceable = (object) $options['modifiable'];
428 return $req;
429 }
430
431 /**
432 * Populates the response object for the "get-location" ajax call.
433 * Location data defines where a custom sidebar is displayed, i.e. on which
434 * pages it is used and which theme-sidebars are replaced.
435 *
436 * @since 2.0
437 * @param object $req Initial response object.
438 * @return object Updated response object.
439 */
440 private function get_location_data( $req ) {
441 $defaults = self::get_options();
442 $raw_posttype = self::get_post_types( 'objects' );
443 $raw_cat = self::get_all_categories();
444 $raw_taxonomies = array(
445 '_builtin' => self::get_taxonomies( 'objects', true ),
446 'custom' => self::get_taxonomies( 'objects', false ),
447 );
448 $archive_type = array(
449 '_blog' => __( 'Front Page', 'custom-sidebars' ),
450 '_search' => __( 'Search Results', 'custom-sidebars' ),
451 '_404' => __( 'Not Found (404)', 'custom-sidebars' ),
452 '_authors' => __( 'Any Author Archive', 'custom-sidebars' ),
453 '_date' => __( 'Date Archives', 'custom-sidebars' ),
454 );
455 /**
456 * taxonomies
457 *
458 * @since 3.0.7
459 */
460 $default_taxonomies = array();
461 foreach ( $raw_taxonomies['_builtin'] as $taxonomy ) {
462 $default_taxonomies[] = $taxonomy->labels->singular_name;
463 switch ( $taxonomy->name ) {
464 case 'post_format':
465 break;
466 case 'post_tag':
467 /**
468 * this a legacy and backward compatibility
469 */
470 /* translators: %1$s is replaced with the taxonomy name */
471 $archive_type['_tags'] = sprintf( __( '%s Archives', 'custom-sidebars' ), $taxonomy->labels->singular_name );
472 break;
473 case 'category':
474 /* translators: %1$s is replaced with the taxonomy name */
475 $archive_type[ '_'.$taxonomy->name ] = sprintf( __( '%s Archives', 'custom-sidebars' ), $taxonomy->labels->singular_name );
476 break;
477 }
478 }
479 foreach ( $raw_taxonomies['custom'] as $taxonomy ) {
480 if ( in_array( $taxonomy->labels->singular_name, $default_taxonomies ) ) {
481 /* translators: %1$s is replaced with the taxonomy name */
482 $archive_type[ '_taxonomy_'.$taxonomy->name ] = sprintf( __( '%s Archives', 'custom-sidebars' ), ucfirst( $taxonomy->name ) );
483 } else {
484 /* translators: %1$s is replaced with the taxonomy name */
485 $archive_type[ '_taxonomy_'.$taxonomy->name ] = sprintf( __( '%s Archives', 'custom-sidebars' ), $taxonomy->labels->singular_name );
486 }
487 }
488 /**
489 * sort array by values
490 */
491 asort( $archive_type );
492 $raw_authors = array();
493 $raw_authors = get_users(
494 array(
495 'order_by' => 'display_name',
496 'fields' => array( 'ID', 'display_name' ),
497 'role' => 'author',
498 )
499 );
500 // Collect required data for all posttypes.
501 $posttypes = array();
502 foreach ( $raw_posttype as $item ) {
503 $sel_single = @$defaults['post_type_single'][ $item->name ];
504 $posttypes[ $item->name ] = array(
505 'name' => $item->labels->name,
506 'single' => self::get_array( $sel_single ),
507 );
508 }
509 // Extract the data from categories list that we need.
510 $categories = array();
511 foreach ( $raw_cat as $item ) {
512 $sel_single = @$defaults['category_single'][ $item->term_id ];
513 $sel_archive = @$defaults['category_archive'][ $item->term_id ];
514 $categories[ $item->term_id ] = array(
515 'name' => $item->name,
516 'count' => $item->count,
517 'single' => self::get_array( $sel_single ),
518 'archive' => self::get_array( $sel_archive ),
519 );
520 }
521 // Build a list of archive types.
522 $archives = array(); // Start with a copy of the posttype list.
523 foreach ( $raw_posttype as $item ) {
524 if ( $item->name == 'post' ) {
525 $label = __( 'Post Index', 'custom-sidebars' );
526 } else {
527 if ( ! $item->has_archive ) { continue; }
528 /* translators: %1$s is replaced with the post type name */
529 $label = sprintf(__( '%1$s Archives', 'custom-sidebars' ),$item->labels->singular_name);
530 }
531 $sel_archive = @$defaults['post_type_archive'][ $item->name ];
532 $archives[ $item->name ] = array(
533 'name' => $label,
534 'archive' => self::get_array( $sel_archive ),
535 );
536 }
537 foreach ( $archive_type as $key => $name ) {
538 $sel_archive = @$defaults[ substr( $key, 1 ) ];
539 $archives[ $key ] = array(
540 'name' => $name,
541 'archive' => self::get_array( $sel_archive ),
542 );
543 }
544 /**
545 * Custom taxonomies archive
546 *
547 * @since 3.0.7
548 */
549 foreach ( $raw_taxonomies['custom'] as $t ) {
550 $taxonomy = $t->name;
551 if (
552 isset( $defaults['taxonomies_archive'] )
553 && isset( $defaults['taxonomies_archive'][ $taxonomy ] )
554 ) {
555 /* translators: %1$s is replaced with the taxonomy name */
556 $name = sprintf( __( '%s Archives', 'custom-sidebars' ), $t->labels->singular_name );
557 if ( in_array( $t->labels->singular_name, $default_taxonomies ) ) {
558 /* translators: %1$s is replaced with the taxonomy name */
559 $name = sprintf( __( '%s Archives', 'custom-sidebars' ), ucfirst( $taxonomy ) );
560 }
561 $sel_archive = $defaults['taxonomies_archive'][ $taxonomy ];
562 $key = '_taxonomy_'.$taxonomy;
563 $archives[ $key ] = array(
564 'name' => $name,
565 'archive' => self::get_array( $sel_archive ),
566 );
567 }
568 }
569 /**
570 * Custom taxonomies taxes
571 *
572 * @since 3.1.4
573 */
574 $allowed = get_option( $this->custom_taxonomies_name, array() );
575
576 foreach ( $allowed as $key ) {
577 $t = get_terms( $key );
578 $terms = array();
579 foreach ( $t as $item ) {
580 $sel_single = $sel_archive = array();
581 if (
582 isset( $defaults['taxonomies_single'] )
583 && isset( $defaults['taxonomies_single'][ $key ] )
584 && isset( $defaults['taxonomies_single'][ $key ][ $item->term_id ] )
585 ) {
586 $sel_single = $defaults['taxonomies_single'][ $key ][ $item->term_id ];
587 }
588 if (
589 isset( $defaults[ $key.'_archive' ] )
590 && isset( $defaults[ $key.'_archive' ][ $item->term_id ] )
591 ) {
592 $sel_archive = $defaults[ $key.'_archive' ][ $item->term_id ];
593 }
594 $terms[ $item->term_id ] = array(
595 'name' => $item->name,
596 'count' => $item->count,
597 'single' => self::get_array( $sel_single ),
598 'archive' => self::get_array( $sel_archive ),
599 );
600 }
601 $req->$key = $terms;
602 }
603 /**
604 * Category archive.
605 */
606 foreach ( $raw_taxonomies['_builtin'] as $t ) {
607 if ( 'category' == $t->name ) {
608 if ( isset( $defaults['category_archive'] ) ) {
609 $sel_archive = $defaults['category_archive'];
610 $archives['_category'] = array(
611 /* translators: %1$s is replaced with the category name */
612 'name' => sprintf( __( '%s Archives', 'custom-sidebars' ), $t->labels->singular_name ),
613 'archive' => self::get_array( $sel_archive ),
614 );
615 }
616 }
617 }
618 // Build a list of authors.
619 $authors = array();
620 foreach ( $raw_authors as $user ) {
621 $sel_archive = @$defaults['author_archive'][ @$user->ID ];
622 $authors[ @$user->ID ] = array(
623 'name' => @$user->display_name,
624 'archive' => self::get_array( $sel_archive ),
625 );
626 }
627 $req->authors = $authors;
628 $req->replaceable = $defaults['modifiable'];
629 $req->posttypes = $posttypes;
630 $req->categories = $categories;
631 $req->archives = $archives;
632 /**
633 * screen
634 */
635 $screen = array();
636 if (
637 isset( $defaults['screen'] )
638 && isset( $defaults['screen'][ $req->id ] )
639 ) {
640 $screen = $defaults['screen'][ $req->id ];
641 }
642 $req->screen = $screen;
643 /**
644 * Allow to change data of locations.
645 *
646 * @since 3.1.2
647 *
648 * @param object $req Object of avaialble data.
649 * @pages $defaults Data from db.
650 */
651 return apply_filters( 'custom_sidebars_get_location', $req, $defaults );
652 }
653
654 /**
655 * Save location data for a single sidebar and populate the response object.
656 * Location data defines where a custom sidebar is displayed, i.e. on which
657 * pages it is used and which theme-sidebars are replaced.
658 *
659 * @since 2.0
660 * @param object $req Initial response object.
661 * @return object Updated response object.
662 */
663 private function set_location_data( $req ) {
664 /**
665 * check nonce
666 */
667 $sidebar_data = map_deep( $_POST, 'sanitize_text_field' );
668
669 if (
670 ! isset( $sidebar_data['_wpnonce'] )
671 || ! wp_verify_nonce( $sidebar_data['_wpnonce'], 'custom-sidebars-set-location' )
672 ) {
673 return self::req_err(
674 $req,
675 __( 'You have no permission to do this operation.', 'custom-sidebars' )
676 );
677 }
678 $options = self::get_options();
679 $sidebars = $options['modifiable'];
680 $raw_posttype = self::get_post_types( 'objects' );
681 $raw_cat = self::get_all_categories();
682 $data = array();
683 $raw_taxonomies = array(
684 'custom' => self::get_taxonomies( 'names', false ),
685 );
686 foreach ( $sidebar_data as $key => $value ) {
687 if ( strlen( $key ) > 8 && '___cs___' == substr( $key, 0, 8 ) ) {
688 list( $prefix, $id ) = explode( '___', substr( $key, 8 ) );
689 if ( ! isset( $data[ $prefix ] ) ) {
690 $data[ $prefix ] = array();
691 }
692 $data[ $prefix ][ $id ] = $value;
693 }
694 }
695 $special_arc = array(
696 'blog',
697 '404',
698 'tags',
699 'authors',
700 'search',
701 'date',
702 );
703 $raw_authors = array();
704 $raw_authors = get_users(
705 array(
706 'order_by' => 'display_name',
707 'fields' => array( 'ID', 'display_name' ),
708 'role' => 'author',
709 )
710 );
711 // == Update the options
712 foreach ( $sidebars as $sb_id ) {
713 // Post-type settings.
714 foreach ( $raw_posttype as $item ) {
715 $pt = $item->name;
716 if (
717 is_array( @$data['pt'][ $sb_id ] ) &&
718 in_array( $pt, $data['pt'][ $sb_id ] )
719 ) {
720 $options['post_type_single'][ $pt ][ $sb_id ] = $req->id;
721 } elseif (
722 isset( $options['post_type_single'][ $pt ][ $sb_id ] ) &&
723 $options['post_type_single'][ $pt ][ $sb_id ] == $req->id
724 ) {
725 unset( $options['post_type_single'][ $pt ][ $sb_id ] );
726 }
727 if (
728 is_array( @$data['arc'][ $sb_id ] ) &&
729 in_array( $pt, $data['arc'][ $sb_id ] )
730 ) {
731 $options['post_type_archive'][ $pt ][ $sb_id ] = $req->id;
732 } elseif (
733 isset( $options['post_type_archive'][ $pt ][ $sb_id ] ) &&
734 $options['post_type_archive'][ $pt ][ $sb_id ] == $req->id
735 ) {
736 unset( $options['post_type_archive'][ $pt ][ $sb_id ] );
737 }
738 }
739 // Category settings.
740 foreach ( $raw_cat as $item ) {
741 $cat = $item->term_id;
742 if (
743 is_array( @$data['cat'][ $sb_id ] ) &&
744 in_array( $cat, $data['cat'][ $sb_id ] )
745 ) {
746 $options['category_single'][ $cat ][ $sb_id ] = $req->id;
747 } elseif (
748 isset( $options['category_single'][ $cat ][ $sb_id ] ) &&
749 $options['category_single'][ $cat ][ $sb_id ] == $req->id
750 ) {
751 unset( $options['category_single'][ $cat ][ $sb_id ] );
752 }
753 if (
754 is_array( @$data['arc-cat'][ $sb_id ] ) &&
755 in_array( $cat, $data['arc-cat'][ $sb_id ] )
756 ) {
757 $options['category_archive'][ $cat ][ $sb_id ] = $req->id;
758 } elseif (
759 isset( $options['category_archive'][ $cat ][ $sb_id ] ) &&
760 $options['category_archive'][ $cat ][ $sb_id ] == $req->id
761 ) {
762 unset( $options['category_archive'][ $cat ][ $sb_id ] );
763 }
764 }
765 foreach ( $special_arc as $key ) {
766 if (
767 is_array( @$data['arc'][ $sb_id ] ) &&
768 in_array( '_' . $key, $data['arc'][ $sb_id ] )
769 ) {
770 $options[ $key ][ $sb_id ] = $req->id;
771 } elseif (
772 isset( $options[ $key ][ $sb_id ] ) &&
773 $options[ $key ][ $sb_id ] == $req->id
774 ) {
775 unset( $options[ $key ][ $sb_id ] );
776 }
777 }
778 // Author settings.
779 foreach ( $raw_authors as $user ) {
780 $key = $user->ID;
781 if (
782 is_array( @$data['arc-aut'][ $sb_id ] ) &&
783 in_array( $key, $data['arc-aut'][ $sb_id ] )
784 ) {
785 $options['author_archive'][ $key ][ $sb_id ] = $req->id;
786 } elseif (
787 isset( $options['author_archive'][ $key ][ $sb_id ] ) &&
788 $options['author_archive'][ $key ][ $sb_id ] == $req->id
789 ) {
790 unset( $options['author_archive'][ $key ][ $sb_id ] );
791 }
792 }
793 /**
794 * Custom taxonomies
795 *
796 * @since 3.0.7
797 */
798 foreach ( $raw_taxonomies['custom'] as $taxonomy ) {
799 $key = '_taxonomy_'.$taxonomy;
800 if (
801 isset( $data['arc'][ $sb_id ] )
802 && is_array( $data['arc'][ $sb_id ] )
803 && in_array( $key, $data['arc'][ $sb_id ] )
804 ) {
805 $options['taxonomies_archive'][ $taxonomy ][ $sb_id ] = $req->id;
806 } elseif (
807 isset( $options['taxonomies_archive'][ $taxonomy ][ $sb_id ] ) &&
808 $options['taxonomies_archive'][ $taxonomy ][ $sb_id ] == $req->id
809 ) {
810 unset( $options['taxonomies_archive'][ $taxonomy ][ $sb_id ] );
811 }
812 /**
813 * single custom taxonomy
814 *
815 * @since 3.1.4
816 */
817 foreach ( $raw_taxonomies['custom'] as $taxonomy ) {
818 $key = '_taxonomy_'.$taxonomy.'_single';
819 $terms = get_terms( $taxonomy );
820 foreach ( $terms as $term ) {
821 $term_id = $term->term_id;
822 if (
823 isset( $data[ $taxonomy ][ $sb_id ] )
824 && is_array( $data[ $taxonomy ][ $sb_id ] )
825 && in_array( $term_id, $data[ $taxonomy ][ $sb_id ] )
826 ) {
827 $options['taxonomies_single'][ $taxonomy ][ $term_id ][ $sb_id ] = $req->id;
828 } elseif (
829 isset( $options['taxonomies_single'][ $taxonomy ][ $term_id ][ $sb_id ] ) &&
830 $options['taxonomies_single'][ $taxonomy ][ $term_id ][ $sb_id ] == $req->id
831 ) {
832 unset( $options['taxonomies_single'][ $taxonomy ][ $term_id ][ $sb_id ] );
833 }
834 }
835 }
836 }
837 /**
838 * category Archive
839 *
840 * @since 3.0.7
841 */
842 if (
843 isset( $data['arc'][ $sb_id ] )
844 && is_array( $data['arc'][ $sb_id ] )
845 && in_array( '_category', $data['arc'][ $sb_id ] )
846 ) {
847 $options['category_archive'][ $sb_id ] = $req->id;
848 } elseif (
849 isset( $options['category_archive'][ $sb_id ] ) &&
850 $options['category_archive'][ $sb_id ] == $req->id
851 ) {
852 unset( $options['category_archive'][ $sb_id ] );
853 }
854 }
855
856 /**
857 * screen size
858 */
859 $size = array();
860 if (
861 isset( $_POST['cs-screen'] )
862 && isset( $_POST['cs-screen']['mode'] )
863 && isset( $_POST['cs-screen']['minmax'] )
864 && isset( $_POST['cs-screen']['size'] )
865 && is_array( $_POST['cs-screen']['mode'] )
866 && is_array( $_POST['cs-screen']['minmax'] )
867 && is_array( $_POST['cs-screen']['size'] )
868 ) {
869 $screen_size = map_deep( $_POST['cs-screen'], 'sanitize_text_field' );
870 for ( $i = 0; $i < count( $screen_size['size'] ); $i++ ) {
871 if ( ! empty( $screen_size['size'][ $i ] ) ) {
872 $size[ $screen_size['size'][ $i ] ][ $screen_size['minmax'][ $i ] ] = $screen_size['mode'][ $i ];
873 }
874 }
875 krsort( $size );
876 }
877 $options['screen'][ $req->id ] = $size;
878 /* translators: %1$s is replaced with the sidebar name */
879 $req->message = sprintf(__( 'Updated sidebar <strong>%1$s</strong> settings.', 'custom-sidebars' ), esc_html( $req->sidebar['name'] ));
880 /**
881 * Allow to change data of locations before save.
882 *
883 * @since 3.1.2
884 *
885 * @param array $options Current options to save.
886 * @param string $req->id Sidebar
887 * @param array $sidebars Allowed sidebars.
888 * @oaram array $data Data send by request.
889 */
890 $options = apply_filters( 'custom_sidebars_set_location', $options, $req->id, $sidebars, $data );
891 self::set_options( $options );
892 return $req;
893 }
894
895 /**
896 * Registers the "Sidebars" meta box in the post-editor.
897 */
898 public function add_meta_box() {
899 global $post;
900 /**
901 * check capabilities
902 */
903 $user_can_change_sidebars = $this->check_author_ability_to_replace();
904 if ( ! $user_can_change_sidebars ) {
905 return;
906 }
907 $post_type = get_post_type( $post );
908 if ( ! $post_type ) {
909 return false;
910 }
911 if ( ! self::supported_post_type( $post_type ) ) {
912 return false;
913 }
914 /**
915 * Option that can be set in wp-config.php to remove the custom sidebar
916 * meta box for certain post types.
917 *
918 * @since 2.0
919 *
920 * @option bool TRUE will hide all meta boxes.
921 */
922 if (
923 defined( 'CUSTOM_SIDEBAR_DISABLE_METABOXES' ) &&
924 CUSTOM_SIDEBAR_DISABLE_METABOXES == true
925 ) {
926 return false;
927 }
928 $pt_obj = get_post_type_object( $post_type );
929 if ( $pt_obj->publicly_queryable || $pt_obj->public ) {
930 add_meta_box(
931 'customsidebars-mb',
932 __( 'Sidebars', 'custom-sidebars' ),
933 array( $this, 'print_metabox_editor' ),
934 $post_type,
935 'side'
936 );
937 }
938 }
939
940 /**
941 * Renders the Custom Sidebars meta box in the post-editor.
942 */
943 public function print_metabox_editor() {
944 global $post;
945 $this->print_sidebars_form( $post->ID, 'metabox' );
946 }
947
948 /**
949 * Renders the sidebar-fields inside the quick-edit form.
950 */
951 public function print_metabox_quick() {
952 $this->print_sidebars_form( 0, 'quick-edit' );
953 }
954
955 /**
956 * Renders the Custom Sidebars form.
957 *
958 * @param int $post_id The post-ID to display
959 * @param string $type Which form to display. 'metabox/quick-edit/col-sidebars'.
960 */
961 protected function print_sidebars_form( $post_id, $type = 'metabox' ) {
962 /**
963 * check capabilities
964 */
965 $user_can_change_sidebars = $this->check_author_ability_to_replace();
966 if ( ! $user_can_change_sidebars ) {
967 return;
968 }
969 global $wp_registered_sidebars;
970 $available = CustomSidebars::sort_sidebars_by_name( $wp_registered_sidebars );
971 $replacements = self::get_replacements( $post_id );
972 $sidebars = self::get_options( 'modifiable' );
973 $selected = array();
974 if ( ! empty( $sidebars ) ) {
975 foreach ( $sidebars as $s ) {
976 if ( isset( $replacements[ $s ] ) ) {
977 $selected[ $s ] = $replacements[ $s ];
978 } else {
979 $selected[ $s ] = '';
980 }
981 }
982 }
983 switch ( $type ) {
984 case 'col-sidebars':
985 include CSB_VIEWS_DIR . 'col-sidebars.php';
986 break;
987 case 'quick-edit':
988 include CSB_VIEWS_DIR . 'quick-edit.php';
989 break;
990 case 'bulk-edit':
991 /**
992 * @since 3.0.8
993 */
994 include CSB_VIEWS_DIR . 'bulk-edit.php';
995 break;
996 default:
997 include CSB_VIEWS_DIR . 'metabox.php';
998 break;
999 }
1000 }
1001
1002 public function store_replacements( $post_id ) {
1003 global $action;
1004 /**
1005 * check capabilities
1006 */
1007 $user_can_change_sidebars = $this->check_author_ability_to_replace();
1008 if ( ! $user_can_change_sidebars ) {
1009 return;
1010 }
1011 /*
1012 * Verify if this is an auto save routine. If it is our form has not
1013 * been submitted, so we dont want to do anything
1014 * (Copied and pasted from wordpress add_metabox_tutorial)
1015 */
1016 if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
1017 return $post_id;
1018 }
1019 /*
1020 * 'editpost' .. Saved from full Post-Editor screen.
1021 * 'inline-save' .. Saved via the quick-edit form.
1022 */
1023 if ( ( isset( $_REQUEST['action'] ) && 'inline-save' != $_REQUEST['action'] ) && 'editpost' != $action ) {
1024 return $post_id;
1025 }
1026 // Make sure meta is added to the post, not a revision.
1027 if ( $the_post = wp_is_post_revision( $post_id ) ) {
1028 $post_id = $the_post;
1029 }
1030 $sidebars = self::get_options( 'modifiable' );
1031 $data = array();
1032 if ( ! empty( $sidebars ) ) {
1033 foreach ( $sidebars as $sb_id ) {
1034 if ( isset( $_POST[ 'cs_replacement_' . $sb_id ] ) ) {
1035 $replacement = map_deep( $_POST[ 'cs_replacement_' . $sb_id], 'sanitize_text_field' );
1036 if ( ! empty( $replacement ) ) {
1037 $data[ $sb_id ] = $replacement;
1038 }
1039 }
1040 }
1041 }
1042 self::set_post_meta( $post_id, $data );
1043 }
1044
1045 // ========== WPML support.
1046 /**
1047 * Updates the WPML string register with the current sidebar string so the
1048 * user can translate the sidebar details using the WPML string translation.
1049 *
1050 * @since 2.0.9.7
1051 * @param array $custom_sidebars List of the custom sidebars.
1052 */
1053 static protected function wpml_update( $custom_sidebars ) {
1054 if ( ! function_exists( 'icl_register_string' ) ) { return false; }
1055 $theme_sidebars = self::get_sidebars();
1056 // This is used to identify the sidebar-translations by WPML.
1057 $context = 'Sidebar';
1058 // First do the theme sidebars, so they will be displayed in the
1059 // *bottom* of the translations list.
1060 foreach ( $theme_sidebars as $fields ) {
1061 self::wpml_update_field( $context, $fields['id'] . '-name', @$fields['name'], false );
1062 self::wpml_update_field( $context, $fields['id'] . '-description', @$fields['description'], false );
1063 }
1064 foreach ( $custom_sidebars as $fields ) {
1065 $name = isset( $fields['name_lang'] ) ? $fields['name_lang'] : $fields['name'];
1066 $description = isset( $fields['description_lang'] ) ? $fields['description_lang'] : $fields['description'];
1067 self::wpml_update_field( $context, $fields['id'] . '-name', $name, true );
1068 self::wpml_update_field( $context, $fields['id'] . '-description', $description, true );
1069 }
1070 }
1071
1072 /**
1073 * Updates the WPML string register for a single field.
1074 *
1075 * @since 2.0.9.7
1076 * @param string $context
1077 * @param string $field
1078 * @param string $value
1079 * @param bool $update_string If false then the translation will only be
1080 * registered but not updated.
1081 */
1082 static protected function wpml_update_field( $context, $field, $value, $update_string = true ) {
1083 global $sitepress, $sitepress_settings;
1084 if ( empty( $sitepress ) || empty( $sitepress_settings ) ) { return false; }
1085 if ( ! function_exists( 'icl_t' ) ) { return false; }
1086 if ( ! icl_st_is_registered_string( $context, $field ) ) {
1087 // Register the field if it does not exist.
1088 icl_register_string( $context, $field, $value, false );
1089 $active_languages = $sitepress->get_active_languages();
1090 foreach ( $active_languages as $lang => $data ) {
1091 icl_update_string_translation( $field, $lang, $value, ICL_STRING_TRANSLATION_COMPLETE );
1092 }
1093 $default_language = ! empty( $sitepress_settings['st']['strings_language'] )
1094 ? $sitepress_settings['st']['strings_language']
1095 : $sitepress->get_default_language();
1096 icl_update_string_translation( $field, $default_language, $value, ICL_STRING_TRANSLATION_COMPLETE );
1097 } else if ( $update_string ) {
1098 // Add translation.
1099 if ( defined( 'DOING_AJAX' ) ) {
1100 $current_language = $sitepress->get_language_cookie();
1101 } else {
1102 $current_language = $sitepress->get_current_language();
1103 }
1104 icl_update_string_translation( $field, $current_language, $value, ICL_STRING_TRANSLATION_COMPLETE );
1105 }
1106 }
1107
1108 /**
1109 * Returns boolean true, when site is currently using the default language.
1110 *
1111 * @since 2.0.9.7
1112 * @return bool
1113 */
1114 static protected function wpml_is_default_lang() {
1115 global $sitepress, $sitepress_settings;
1116 if ( empty( $sitepress ) || empty( $sitepress_settings ) ) { return true; }
1117 if ( ! function_exists( 'icl_t' ) ) { return true; }
1118 if ( defined( 'DOING_AJAX' ) ) {
1119 $current_language = $sitepress->get_language_cookie();
1120 } else {
1121 $current_language = $sitepress->get_current_language();
1122 }
1123 $default_language = ! empty( $sitepress_settings['st']['strings_language'] )
1124 ? $sitepress_settings['st']['strings_language']
1125 : $sitepress->get_default_language();
1126 return $default_language == $current_language;
1127 }
1128
1129 /**
1130 * Translates the text inside the specified sidebar object.
1131 *
1132 * @since 2.0.9.7
1133 * @param array $sidebar Sidebar object.
1134 * @return array Translated sidebar object.
1135 */
1136 static protected function wpml_translate( $sidebar ) {
1137 if ( ! function_exists( 'icl_t' ) ) { return $sidebar; }
1138 $context = 'Sidebar';
1139 // Translate the name and description.
1140 // Note: When changing a translation the icl_t() function will not
1141 // return the updated value due to caching.
1142 if ( isset( $sidebar['name_lang'] ) ) {
1143 $sidebar['name'] = $sidebar['name_lang'];
1144 } else {
1145 $sidebar['name'] = icl_t( $context, $sidebar['id'] . '-name', $sidebar['name'] );
1146 }
1147 if ( isset( $sidebar['description_lang'] ) ) {
1148 $sidebar['description'] = $sidebar['description_lang'];
1149 } else {
1150 $sidebar['description'] = icl_t( $context, $sidebar['id'] . '-description', $sidebar['description'] );
1151 }
1152 return $sidebar;
1153 }
1154
1155 //
1156 // ========== Custom column an Quick-Edit fields for post list.
1157 // http://shibashake.com/wordpress-theme/expand-the-wordpress-quick-edit-menu
1158 //
1159 /**
1160 * Adds a custom column to post-types that support custom sidebars.
1161 *
1162 * @since 2.0.9.7
1163 * @param array $columns Column list.
1164 * @return array Modified column list.
1165 */
1166 public function post_columns( $columns ) {
1167 // This column is added.
1168 $insert = array(
1169 'cs_replacement' => _x( 'Custom Sidebars', 'Column name on entries list.', 'custom-sidebars' ),
1170 );
1171 // Column is added after column 'title'.
1172 $insert_after = 'title';
1173 $pos = array_search( $insert_after, array_keys( $columns ) ) + 1;
1174 $columns = array_merge(
1175 array_slice( $columns, 0, $pos ),
1176 $insert,
1177 array_slice( $columns, $pos )
1178 );
1179 return $columns;
1180 }
1181
1182 /**
1183 * Display values in the custom column.
1184 *
1185 * @since 2.0.9.7
1186 * @param string $column_name Column-Key defined in post_columns above.
1187 * @param int $post_id Post-ID
1188 */
1189 public function post_column_content( $column_name, $post_id ) {
1190 switch ( $column_name ) {
1191 case 'cs_replacement':
1192 $this->print_sidebars_form( $post_id, 'col-sidebars' );
1193 break;
1194 }
1195 }
1196
1197 /**
1198 * Adds a custom field to the quick-edit box to select custom columns.
1199 *
1200 * @since 2.0.9.7
1201 * @param string $column_name Column-Key defined in post_columns above.
1202 * @param string $post_type Post-type that is currently edited.
1203 */
1204 public function post_quick_edit( $column_name, $post_type ) {
1205 if ( ! self::supported_post_type( $post_type ) ) { return false; }
1206 switch ( $column_name ) {
1207 case 'cs_replacement':
1208 $this->print_metabox_quick();
1209 break;
1210 }
1211 }
1212
1213 /**
1214 * Javascript to set the values of the quick-edit form.
1215 *
1216 * Note: There is only 1 quick-edit form on the page. The form is displayed
1217 * when the user clicks the quick edit action; all fields are then populated
1218 * with values of the corresponding post.
1219 *
1220 * @since 2.0.9.7
1221 */
1222 public function post_quick_edit_js() {
1223 global $current_screen;
1224 if ( ( $current_screen->base != 'edit' ) ) { return false; }
1225 if ( ! self::supported_post_type( $current_screen->post_type ) ) { return false; }
1226 ?>
1227 <script type="text/javascript">
1228 <!--
1229 jQuery(function() {
1230 // we create a copy of the WP inline edit post function
1231 var wp_inline_edit = inlineEditPost.edit;
1232 // and then we overwrite the function with our own code
1233 inlineEditPost.edit = function( id ) {
1234 // "call" the original WP edit function
1235 // we don't want to leave WordPress hanging
1236 wp_inline_edit.apply( this, arguments );
1237 // now we take care of our business.
1238 // get the post ID
1239 var post_id = 0;
1240 if ( typeof( id ) == 'object' ) {
1241 post_id = parseInt( this.getId( id ) );
1242 }
1243 if ( post_id > 0 ) {
1244 // define the edit row
1245 var edit_row = jQuery( '#edit-' + post_id );
1246 var post_row = jQuery( '#post-' + post_id );
1247 // Our custom column
1248 var sidebar_col = post_row.find( '.cs_replacement' );
1249 sidebar_col.find( '[data-sidebar]' ).each(function() {
1250 var key = jQuery( this ).attr( 'data-sidebar' ),
1251 val = jQuery( this ).attr( 'data-replaced' ),
1252 hide = 'yes' === jQuery( this ).attr( 'data-cshide' );
1253 if ( hide ) {
1254 edit_row.find( '.cs-replacement-field.' + key ).val( val ).parent().hide();
1255 } else {
1256 edit_row.find( '.cs-replacement-field.' + key ).val( val ).parent().show();
1257 }
1258 });
1259 }
1260 };
1261 });
1262 //-->
1263 </script>
1264 <?php
1265 }
1266
1267 /**
1268 * Hide column "Custom Sidebars" by default.
1269 *
1270 * @since 3.0.5
1271 *
1272 * @param array $hidden Array of hidden columns.
1273 * @param WP_Screen $screen Current WP screen.
1274 * @return array $hidden
1275 */
1276 public function default_hidden_columns( $hidden, $screen ) {
1277 if ( is_object( $screen ) && isset( $screen->post_type ) && 'post' == $screen->post_type ) {
1278 $hidden[] = 'cs_replacement';
1279 }
1280 return $hidden;
1281 }
1282
1283 /**
1284 * Adds a custom field to the bulk-edit box to select custom columns.
1285 *
1286 * @since 3.0.8
1287 * @param string $column_name Column-Key defined in post_columns above.
1288 * @param string $post_type Post-type that is currently edited.
1289 */
1290 public function post_bulk_edit( $column_name, $post_type ) {
1291 if ( ! self::supported_post_type( $post_type ) ) { return false; }
1292 switch ( $column_name ) {
1293 case 'cs_replacement':
1294 $this->print_metabox_bulk();
1295 break;
1296 }
1297 }
1298
1299 /**
1300 * Renders the sidebar-fields inside the bulk-edit form.
1301 *
1302 * @since 3.0.8
1303 */
1304 public function print_metabox_bulk() {
1305 $this->print_sidebars_form( 0, 'bulk-edit' );
1306 }
1307
1308 /**
1309 * Bulk Edit save
1310 *
1311 * @since 3.0.8
1312 */
1313 public function bulk_edit_save( $post_id ) {
1314 if ( ! isset( $_REQUEST['custom-sidebars-editor-bulk-edit'] ) ) {
1315 return;
1316 }
1317 if ( ! wp_verify_nonce( $_REQUEST['custom-sidebars-editor-bulk-edit'], 'bulk-edit-cs' ) ) {
1318 return;
1319 }
1320 if ( null == $this->modifiable ) {
1321 $this->modifiable = CustomSidebars::get_options( 'modifiable' );
1322 }
1323 if ( empty( $this->modifiable ) ) {
1324 return;
1325 }
1326 $update = false;
1327 $data = CustomSidebars::get_post_meta( $post_id );
1328 foreach ( $this->modifiable as $key ) {
1329 $k = sprintf( 'cs_replacement_%s', $key );
1330 $value = isset( $_REQUEST[ $k ] )? map_deep($_REQUEST[ $k ],'sanitize_text_field'):'-';
1331 if ( '-' != $value ) {
1332 $update = true;
1333 $data[ $key ] = $value;
1334 }
1335 }
1336 if ( ! $update ) {
1337 return;
1338 }
1339 self::set_post_meta( $post_id, $data );
1340 }
1341
1342 /**
1343 * Add capabilities for options on widgets.php
1344 *
1345 * @param string $screen_settings Screen settings.
1346 * @param WP_Screen $screen WP_Screen object.
1347 */
1348 public function add_capabilities_select_box( $screen_settings, $screen ) {
1349 if ( 'widgets' == $screen->base && current_user_can( 'manage_options' ) ) {
1350 $allowed = get_option( $this->metabox_roles_name, 'any' );
1351 $roles = get_editable_roles();
1352 $screen_settings .= '<fieldset class="metabox-prefs cs-roles">';
1353 $screen_settings .= wp_nonce_field( $this->metabox_roles_name, $this->metabox_roles_name, false, false );
1354 $screen_settings .= sprintf( '<legend>%s</legend>', __( 'Custom sidebars configuration is allowed for:', 'custom-sidebars' ) );
1355 foreach ( $roles as $role => $data ) {
1356 if ( isset( $data['capabilities'][ self::$cap_required ] ) && $data['capabilities'][ self::$cap_required ] ) {
1357 $checked = false;
1358 if ( is_string( $allowed ) && 'any' == $allowed ) {
1359 $checked = true;
1360 } else if ( is_array( $allowed ) && in_array( $role, $allowed ) ) {
1361 $checked = true;
1362 }
1363 $screen_settings .= sprintf(
1364 '<label><input type="checkbox" name="cs-roles[]" value="%s" %s /> %s</label>',
1365 esc_attr( $role ),
1366 checked( $checked, true, false ),
1367 esc_html( $data['name'] )
1368 );
1369 }
1370 }
1371 $screen_settings .= '</fieldset>';
1372 /**
1373 * allow author to edit custom sidebars
1374 */
1375 $screen_settings .= '<fieldset class="metabox-prefs cs-allow-author">';
1376 $screen_settings .= wp_nonce_field( $this->allow_author_name, $this->allow_author_name, false, false );
1377 $screen_settings .= sprintf( '<legend>%s</legend>', __( 'Allowed to replace sidebars:', 'custom-sidebars' ) );
1378 $checked = get_option( $this->allow_author_name, false );
1379 $screen_settings .= sprintf(
1380 '<label><input type="checkbox" name="cs-allow-author" value="%s" %s /> %s</label>',
1381 esc_attr( $role ),
1382 checked( $checked, true, false ),
1383 esc_html__( 'Allow entry author to change sidebars', 'custom-sidebars' )
1384 );
1385 $screen_settings .= '</fieldset>';
1386 /**
1387 * Custom taxonomies
1388 */
1389 $taxonomies = CustomSidebars::get_custom_taxonomies();
1390 if ( ! empty( $taxonomies ) ) {
1391 $allowed = get_option( $this->custom_taxonomies_name, array() );
1392 $screen_settings .= '<fieldset class="metabox-prefs cs-custom-taxonomies">';
1393 $screen_settings .= wp_nonce_field( $this->custom_taxonomies_name, $this->custom_taxonomies_name, false, false );
1394 $screen_settings .= sprintf( '<legend>%s</legend>', __( 'Allow Custom Taxonomies in Sidebar Location:', 'custom-sidebars' ) );
1395 foreach ( $taxonomies as $taxonomy_slug => $taxonomy ) {
1396 $checked = in_array( $taxonomy_slug, $allowed );
1397 $screen_settings .= sprintf(
1398 '<label><input type="checkbox" name="cs-custom-taxonomy[]" value="%s" %s /> %s</label>',
1399 esc_attr( $taxonomy_slug ),
1400 checked( $checked, true, false ),
1401 esc_html( $taxonomy->label )
1402 );
1403 }
1404 $screen_settings .= '</fieldset>';
1405 $screen_settings .= sprintf( '<p class="description">%s</p>', __( 'After turn on any Custom Taxonomy you need to reload this screen to be able choose it in Sidebar Location.', 'custom-sidebars' ) );
1406 }
1407 }
1408 return $screen_settings;
1409 }
1410
1411 /**
1412 * Update capabilities select box
1413 *
1414 * @since 3.0.9
1415 */
1416 public function update_custom_sidebars_metabox_roles() {
1417 $this->update_option_field( $this->metabox_roles_name );
1418 }
1419
1420 /**
1421 * Update custom taxoniomies select box
1422 *
1423 * @since 3.1.4
1424 */
1425 public function update_custom_sidebars_metabox_custom_taxonomies() {
1426 $this->update_option_field( $this->custom_taxonomies_name );
1427 }
1428
1429 /**
1430 * Helper for update metabox functions.
1431 *
1432 * @since 3.1.4
1433 */
1434 private function update_option_field( $name ) {
1435 /**
1436 * check required data
1437 */
1438 if ( ! isset( $_REQUEST['_wpnonce'] ) || ! isset( $_REQUEST['fields'] ) ) {
1439 wp_send_json_error();
1440 }
1441 /**
1442 * check nonce value
1443 */
1444 if ( ! wp_verify_nonce( $_REQUEST['_wpnonce'], $name ) ) {
1445 wp_send_json_error();
1446 }
1447 $value = array();
1448 foreach ( $_REQUEST['fields'] as $role => $status ) {
1449 if ( 'true' == $status ) {
1450 $value[] = $role;
1451 }
1452 }
1453 $status = add_option( $name, $value, '', 'no' );
1454 if ( ! $status ) {
1455 update_option( $name, $value );
1456 }
1457 wp_send_json_success();
1458 }
1459
1460 /**
1461 * Update entry author is allowed to change custom sidebars.
1462 *
1463 * @since 3.1.5
1464 */
1465 public function update_custom_sidebars_allow_author() {
1466 /**
1467 * check required data
1468 */
1469 if ( ! isset( $_REQUEST['_wpnonce'] ) ) {
1470 wp_send_json_error();
1471 }
1472 /**
1473 * check nonce value
1474 */
1475 if ( ! wp_verify_nonce( $_REQUEST['_wpnonce'], $this->allow_author_name ) ) {
1476 wp_send_json_error();
1477 }
1478 $value = isset( $_REQUEST['value'] )? 'true' === $_REQUEST['value'] : false;
1479 $status = add_option( $this->allow_author_name, $value, '', 'no' );
1480 if ( ! $status ) {
1481 update_option( $this->allow_author_name, $value );
1482 }
1483 wp_send_json_success();
1484 }
1485 /**
1486 * Check ability to save sidebars
1487 *
1488 * @since 3.0.9
1489 */
1490 public function current_user_can_update_custom_sidebars() {
1491 $allowed = get_option( $this->metabox_roles_name, 'any' );
1492 if ( is_string( $allowed ) && 'any' == $allowed ) {
1493 return true;
1494 } else {
1495 $current_user = wp_get_current_user();
1496 $current_user_roles = (array) $current_user->roles;
1497 foreach ( $allowed as $role ) {
1498 if ( in_array( $role, $current_user_roles ) ) {
1499 return true;
1500 }
1501 }
1502 }
1503 return false;
1504 }
1505
1506 /**
1507 * Get allowed taxoniomies.
1508 *
1509 * @since 3.1.4
1510 */
1511 public function get_allowed_custom_taxonmies() {
1512 $value = get_option( $this->custom_taxonomies_name );
1513 if ( empty( $value ) || ! is_array( $value ) ) {
1514 return array();
1515 }
1516 return $value;
1517 }
1518
1519 /**
1520 * Check author ability to change sidebars during entry edit
1521 *
1522 * @since 3.1.5
1523 */
1524 private function check_author_ability_to_replace() {
1525 global $post;
1526 if ( current_user_can( self::$cap_required ) ) {
1527 return true;
1528 }
1529 $checked = get_option( $this->allow_author_name, false );
1530 if ( $checked ) {
1531 if ( current_user_can( 'edit_posts', $post->ID ) ) {
1532 return true;
1533 }
1534 }
1535 return false;
1536 }
1537 };
1538