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-export.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-export.php
906 lines
1 <?php
2
3
4 add_action( 'cs_init', array( 'CustomSidebarsExport', 'instance' ) );
5
6 /**
7 * Provides functionality to export and import sidebar settings.
8 *
9 * @since 2.0
10 */
11 class CustomSidebarsExport extends CustomSidebars {
12
13 // Holds the contents of the import-file during preview/import.
14 static private $import_data = null;
15
16 // Used after preview. This holds only the items that were selected for import.
17 private $selected_data = null;
18
19 /**
20 * CSB version
21 */
22 private $version = '';
23
24 /**
25 * Returns the singleton object.
26 *
27 * @since 2.0
28 */
29 public static function instance() {
30 static $Inst = null;
31
32 if ( null === $Inst ) {
33 $Inst = new CustomSidebarsExport();
34 }
35
36 return $Inst;
37 }
38
39 /**
40 * Constructor is private -> singleton.
41 *
42 * @since 2.0
43 */
44 private function __construct() {
45 add_action( 'admin_init', array( $this, 'admin_init' ) );
46 }
47
48 /**
49 * Admin Init
50 *
51 * @since 3.1.6
52 */
53 public function admin_init() {
54 add_action( 'cs_widget_header', array( $this, 'widget_header' ) );
55 add_action( 'cs_ajax_request', array( $this, 'handle_ajax' ) );
56 }
57
58 /**
59 * Called by action 'cs_widget_header'. Output the export/import button in
60 * the widget header.
61 *
62 * @since 2.0
63 */
64 public function widget_header() {
65 ?>
66 <a href="#" class="cs-action btn-export"><?php esc_html_e( 'Import / Export Sidebars', 'custom-sidebars' ); ?></a>
67 <?php
68 }
69
70 /**
71 * When the custom sidebars section is visible we see if export-action
72 * needs to be processed.
73 *
74 * @since 2.0
75 */
76 public function handle_ajax( $ajax_action ) {
77 $req = (object) array(
78 'status' => 'ERR',
79 );
80 $is_json = true;
81 $handle_it = false;
82 $view_file = '';
83
84 switch ( $ajax_action ) {
85 case 'export':
86 case 'import':
87 case 'preview-import':
88 $handle_it = true;
89 $req->status = 'OK';
90 $req->action = $ajax_action;
91 break;
92 }
93
94 // The ajax request was not meant for us...
95 if ( ! $handle_it ) {
96 return false;
97 }
98
99 if ( ! current_user_can( self::$cap_required ) ) {
100 $req = self::req_err(
101 $req,
102 __( 'You do not have permission for this', 'custom-sidebars' )
103 );
104 } else {
105 switch ( $ajax_action ) {
106 case 'export':
107 $this->download_export_file();
108 break;
109
110 case 'preview-import':
111 $req = $this->read_import_file( $req );
112 if ( 'OK' == $req->status ) {
113 ob_start();
114 include CSB_VIEWS_DIR . 'import.php';
115 $req->html = ob_get_clean();
116 }
117 break;
118
119 case 'import':
120 $req = $this->prepare_import_data( $req );
121 break;
122 }
123 }
124
125 // Make the ajax response either as JSON or plain text.
126 if ( $is_json ) {
127 self::json_response( $req );
128 } else {
129 ob_start();
130 include CSB_VIEWS_DIR . $view_file;
131 $resp = ob_get_clean();
132
133 self::plain_response( $resp );
134 }
135 }
136
137
138 /*============================*\
139 ================================
140 == ==
141 == EXPORT ==
142 == ==
143 ================================
144 \*============================*/
145
146
147 /**
148 * Collects the plugin details for export.
149 *
150 * @since 2.0
151 */
152 private function get_export_data() {
153 global $wp_registered_widgets, $wp_version;
154 $theme = wp_get_theme();
155 $csb_info = get_plugin_data( CSB_PLUGIN );
156 $this->version = $csb_info['Version'];
157 $data = array();
158 // Add some meta-details to the export file.
159 $data['meta'] = array(
160 'created' => time(),
161 'wp_version' => $wp_version,
162 'csb_version' => $csb_info['Version'],
163 'theme_name' => $theme->get( 'Name' ),
164 'theme_version' => $theme->get( 'Version' ),
165 'description' => sanitize_text_field( @$_POST['export-description'] ),
166 );
167
168 // Export the custom sidebars.
169 $data['sidebars'] = self::get_custom_sidebars();
170
171 // Export the sidebar options (e.g. default replacement).
172 $data['options'] = self::get_options();
173
174 // Export category-information.
175 $data['categories'] = get_categories( array( 'hide_empty' => 0 ) );
176
177 /*
178 * Export all widget options.
179 *
180 * $wp_registered_widgets contains all widget-instances that were placed
181 * inside a sidebar. So we loop this array and fetch each widgets
182 * options individually:
183 *
184 * Widget options are saved inside options table with option_name
185 * "widget_<widget-slug>"; the options can be an array, e.g.
186 * "widget_search" contains options for all widget instances in any
187 * sidebar. When we place 2 search widgets in different sidebars there
188 * will be a list with two option-arrays.
189 */
190 $data['widgets'] = array();
191 foreach ( self::get_sidebar_widgets() as $sidebar => $widgets ) {
192 if ( 'wp_inactive_widgets' === $sidebar ) {
193 continue;
194 }
195 if ( is_array( $widgets ) ) {
196 $data['widgets'][ $sidebar ] = array();
197 foreach ( $widgets as $widget_id ) {
198 if ( isset( $wp_registered_widgets[ $widget_id ] ) ) {
199 $item = $wp_registered_widgets[ $widget_id ];
200 $cb = $item['callback'];
201 $widget = is_array( $cb ) ? reset( $cb ) : false;
202 $id = $widget_id;
203 if ( ! isset( $data['widgets'][ $sidebar ][ $id ] ) ) {
204 if ( preg_match( '/(\d+)$/', $widget_id, $matches ) ) {
205 $id = $matches[1];
206 }
207 }
208 if ( isset( $data['widgets'][ $sidebar ][ $id ] ) ) {
209 continue;
210 }
211 if ( is_object( $widget ) && method_exists( $widget, 'get_settings' ) ) {
212 /**
213 * set correct widget data
214 */
215 $widget->id = $widget_id;
216 $widget->number = $id;
217 /**
218 * get settings
219 */
220 $settings = $widget->get_settings();
221 $data['widgets'][ $sidebar ][ $id ] = array(
222 'name' => @$widget->name,
223 'classname' => get_class( $widget ),
224 'id_base' => @$widget->id_base,
225 'description' => @$widget->description,
226 'settings' => $settings[ @$widget->number ],
227 'version' => 3,
228 );
229 } else {
230 /**
231 * Widgets that are registered with the old widget API
232 * have a different structure:
233 *
234 * - Not an object but a callback function.
235 * - No standard options-form.
236 * -> No widget settings to export.
237 * -> No clone/visibility options to export.
238 * - Only one instance
239 * -> "id_base" is same as $widget_id
240 */
241 $data['widgets'][ $sidebar ][ $widget_id ] = array(
242 'name' => @$item['name'],
243 'classname' => @$item['classname'],
244 'id_base' => @$item['id'],
245 'description' => @$item['description'],
246 'settings' => @$item['params'],
247 'version' => 2,
248 );
249 }
250 /**
251 * remove empty settings
252 */
253 if ( isset( $data['widgets'][ $sidebar ][ $id ]['settings']['csb_visibility']['conditions'] ) ) {
254 foreach ( $data['widgets'][ $sidebar ][ $id ]['settings']['csb_visibility']['conditions'] as $condition_id => $condition_value ) {
255 if ( empty( $condition_value ) ) {
256
257 unset( $data['widgets'][ $sidebar ][ $id ]['settings']['csb_visibility']['conditions'][ $condition_id ] );
258
259 }
260 }
261 }
262 }
263 }
264 } else {
265 $data['widgets'][ $sidebar ] = $widgets;
266 }
267 }
268 return $data;
269 }
270
271 /**
272 * Generates the export file and sends it as a download to the browser.
273 *
274 * @since 2.0
275 */
276 private function download_export_file() {
277 /**
278 * check nonce
279 */
280 if (
281 ! isset( $_POST['_wpnonce'] )
282 || ! wp_verify_nonce( $_POST['_wpnonce'], 'custom-sidebars-export' )
283 ) {
284 $req = (object) array(
285 'status' => 'ERR',
286 );
287 $req = self::req_err(
288 $req,
289 __( 'You do not have permission for export sidebars.', 'custom-sidebars' )
290 );
291 self::json_response( $req );
292 }
293 /**
294 * build filename
295 */
296 $filename = $this->get_file_name();
297 $data = $this->get_export_data();
298 $content = '';
299 /**
300 * Check PHP version, for PHP < 5.3 do not add options
301 *
302 * @since 3.1.6
303 */
304 $version = phpversion();
305 $compare = version_compare( $version, '5.3', '<' );
306
307 // Send the download headers.
308 header( 'Pragma: public' );
309 header( 'Expires: 0' );
310 header( 'Cache-Control: must-revalidate, post-check=0, pre-check=0' );
311 header( 'Cache-Control: private', false ); // required for certain browsers
312 header( 'Content-type: application/json' );
313 header( 'Content-Disposition: attachment; filename="' . $filename . '"' );
314 header( 'Content-Transfer-Encoding: binary' );
315 header( 'Content-Length: ' . strlen( wp_json_encode($data) ) );
316 /**
317 * Finally send the export-file content.
318 */
319 echo wp_json_encode($data);
320 exit;
321 }
322
323 /**
324 * Generate export file name dynamically.
325 *
326 * Generate a unique file name to export in json.
327 *
328 * @since 3.1.6
329 *
330 * @return string File name.
331 */
332 private function get_file_name() {
333 /**
334 * get version if it is needded
335 */
336 if ( empty( $this->version ) ) {
337 $csb_info = get_plugin_data( CSB_PLUGIN );
338 $this->version = $csb_info['Version'];
339 }
340 // Get site name.
341 $site_name = sanitize_key( get_bloginfo( 'name' ) );
342 $site_name = empty( $site_name ) ? '' : $site_name . '.';
343 // Create export file name.
344 $filename = sprintf(
345 '%s.sidebars.%s.%s.json',
346 $site_name,
347 $this->version,
348 gmdate( 'Y-m-d.H-i-s' )
349 );
350 return $filename;
351 }
352
353 /*=============================*\
354 =================================
355 == ==
356 == PREVIEW ==
357 == ==
358 =================================
359 \*=============================*/
360
361
362 /**
363 * Checks if a valid export-file was uploaded and stores the file contents
364 * inside self::$import_data. The data is de-serialized.
365 * In error case the response object will be set to error status.
366 *
367 * @since 2.0
368 * @param object $req Initial response object for JSON response.
369 * @return object Updated response object.
370 */
371 private function read_import_file( $req ) {
372 /**
373 * check nonce
374 */
375 if (
376 ! isset( $_POST['_wpnonce'] )
377 || ! wp_verify_nonce( $_POST['_wpnonce'], 'custom-sidebars-import' )
378 ) {
379 $req = (object) array(
380 'status' => 'ERR',
381 );
382 $req = self::req_err(
383 $req,
384 __( 'You do not have permission for export sidebars.', 'custom-sidebars' )
385 );
386 self::json_response( $req );
387 }
388
389 if ( is_array( $_FILES['data'] ) ) {
390 switch ( $_FILES['data']['error'] ) {
391 case UPLOAD_ERR_OK:
392 // This is the expeted status!
393 break;
394
395 case UPLOAD_ERR_NO_FILE:
396 return self::req_err(
397 $req,
398 __( 'No file was uploaded', 'custom-sidebars' )
399 );
400
401 case UPLOAD_ERR_INI_SIZE:
402 case UPLOAD_ERR_FORM_SIZE:
403 return self::req_err(
404 $req,
405 __( 'Import file is too big', 'custom-sidebars' )
406 );
407
408 default:
409 return self::req_err(
410 $req,
411 __( 'Something went wrong', 'custom-sidebars' )
412 );
413 }
414
415 $content = file_get_contents( $_FILES['data']['tmp_name'] );
416 $data = json_decode( $content, true );
417
418 if (
419 is_array( $data['meta'] ) &&
420 is_array( $data['sidebars'] ) &&
421 is_array( $data['options'] ) &&
422 is_array( $data['widgets'] ) &&
423 is_array( $data['categories'] )
424 ) {
425 $data['meta']['filename'] = $_FILES['data']['name'];
426 $data['ignore'] = array();
427 self::$import_data = $data;
428
429 // Remove details that does not exist on current blog.
430 $this->prepare_data();
431 } else {
432 return self::req_err(
433 $req,
434 __( 'Unexpected import format', 'custom-sidebars' )
435 );
436 }
437 } else {
438 return self::req_err(
439 $req,
440 __( 'No file was uploaded', 'custom-sidebars' )
441 );
442 }
443
444 return $req;
445 }
446
447 /**
448 * Loads the import-data into the self::$import_data property.
449 * The data was prepared by the import-preview screen.
450 * Populates the response object.
451 *
452 * @since 2.0
453 * @param object $req Initial response object for JSON response.
454 * @return object Updated response object.
455 */
456 private function prepare_import_data( $req ) {
457 /**
458 * check nonce
459 */
460 if (
461 ! isset( $_POST['_wpnonce'] )
462 || ! wp_verify_nonce( $_POST['_wpnonce'], 'custom-sidebars-import' )
463 ) {
464 $req = (object) array(
465 'status' => 'ERR',
466 );
467 $req = self::req_err(
468 $req,
469 __( 'You do not have permission for import sidebars.', 'custom-sidebars' )
470 );
471 self::json_response( $req );
472 }
473
474 $data = json_decode( base64_decode( @sanitize_textarea_field($_POST['import_data']) ), true );
475
476 if (
477 is_array( $data['meta'] ) &&
478 is_array( $data['sidebars'] ) &&
479 is_array( $data['options'] ) &&
480 is_array( $data['widgets'] ) &&
481 is_array( $data['categories'] )
482 ) {
483 $data['ignore'] = array();
484 self::$import_data = $data;
485
486 // Remove details that does not exist on current blog.
487 $this->prepare_data();
488
489 // "selected_data" only contains the items that were selected for import.
490 $this->selected_data = self::$import_data;
491 unset( $this->selected_data['meta'] );
492 unset( $this->selected_data['categories'] );
493 unset( $this->selected_data['ignore'] );
494
495 if ( ! isset( $_POST['import_plugin_config'] ) ) {
496 unset( $this->selected_data['options'] );
497 }
498 if ( ! isset( $_POST['import_widgets'] ) ) {
499 unset( $this->selected_data['widgets'] );
500 } else {
501 foreach ( $this->selected_data['widgets'] as $id => $widgets ) {
502 $key = 'import_sb_' . $id;
503 if ( ! isset( $_POST[ $key ] ) ) {
504 unset( $this->selected_data['widgets'][ $id ] );
505 }
506 }
507 }
508 foreach ( $this->selected_data['sidebars'] as $id => $sidebar ) {
509 $key = 'import_sb_' . $sidebar['id'];
510 if ( ! isset( $_POST[ $key ] ) ) {
511 unset( $this->selected_data['sidebars'][ $id ] );
512 }
513 }
514
515 // Finally: Import the config!
516 $req = $this->do_import( $req );
517 } else {
518 return self::req_err(
519 $req,
520 __('Something unexpected happened and we could not finish the import. Please try again.', 'custom-sidebars')
521 );
522 }
523
524 return $req;
525 }
526
527 /**
528 * Loops through the import data array and removes configuration which is
529 * not relevant for the current blog. I.e. posttypes that are not registered
530 * or categories that do not match the current blog.
531 *
532 * @since 2.0
533 */
534 private function prepare_data() {
535 global $wp_registered_widgets;
536 $theme_sidebars = self::get_sidebars();
537 $valid_categories = array();
538 $valid_sidebars = array();
539 $valid_widgets = array();
540
541 // =====
542 // Normalize the sidebar list (change numeric index to sidebar-id).
543 $sidebars_remapped = array();
544 foreach ( self::$import_data['sidebars'] as $sidebar ) {
545 $sidebars_remapped[ $sidebar['id'] ] = $sidebar;
546 }
547 self::$import_data['sidebars'] = $sidebars_remapped;
548
549 // =====
550 // Get a list of existing/valid sidebar-IDs.
551 $valid_sidebars = array_merge(
552 array_keys( $theme_sidebars ),
553 array_keys( self::$import_data['sidebars'] )
554 );
555
556 // =====
557 // Check for theme-sidebars that do not exist.
558 foreach ( self::$import_data['options']['modifiable'] as $id => $sb_id ) {
559 if ( ! isset( $theme_sidebars[ $sb_id ] ) ) {
560 if ( ! isset( self::$import_data['ignore']['sidebars'] ) ) {
561 self::$import_data['ignore']['sidebars'] = array();
562 }
563 self::$import_data['ignore']['sidebars'][] = $sb_id;
564 unset( self::$import_data['options']['modifiable'][ $id ] );
565 }
566 }
567
568 // =====
569 // Remove invalid sidebars from the default replacement options.
570 foreach ( array( 'post_type_single', 'post_type_archive', 'category_single', 'category_archive' ) as $key ) {
571 foreach ( self::$import_data['options'][ $key ] as $id => $list ) {
572 $list = $this->_remove_sidebar_from_list( $list, $valid_sidebars );
573 self::$import_data['options'][ $key ][ $id ] = $list;
574 }
575 }
576 foreach ( array( 'blog', 'tags', 'authors', 'search', 'date' ) as $key ) {
577 $list = self::$import_data['options'][ $key ];
578 $list = $this->_remove_sidebar_from_list( $list, $valid_sidebars );
579 self::$import_data['options'][ $key ] = $list;
580 }
581
582 // =====
583 // Check for missing/different categories.
584 foreach ( get_categories( array( 'hide_empty' => 0 ) ) as $cat ) {
585 $valid_categories[ $cat->term_id ] = $cat;
586 }
587 foreach ( self::$import_data['categories'] as $infos ) {
588 $id = $infos['term_id'];
589 if (
590 empty( $valid_categories[ $id ] ) ||
591 $valid_categories[ $id ]->slug != $infos['slug']
592 ) {
593 if ( ! isset( self::$import_data['ignore']['categories'] ) ) {
594 self::$import_data['ignore']['categories'] = array();
595 }
596 self::$import_data['ignore']['categories'][] = $infos['name'];
597 unset( self::$import_data['categories'][ $id ] );
598
599 // Remove the categories from the config array.
600 unset( self::$import_data['options']['category_posts'][ $id ] );
601 unset( self::$import_data['options']['category_pages'][ $id ] );
602 }
603 }
604
605 // =====
606 // Remove missing widgets from import data.
607 foreach ( $wp_registered_widgets as $widget ) {
608 if ( is_array( $widget['callback'] ) ) {
609 $classname = get_class( $widget['callback'][0] );
610 } else {
611 $classname = $widget['classname'];
612 }
613 $valid_widgets[ $classname ] = true;
614 }
615 foreach ( self::$import_data['widgets'] as $sb_id => $sidebar ) {
616 if ( ! is_array( $sidebar ) ) { continue; }
617 foreach ( $sidebar as $id => $widget_instance ) {
618 $version = $widget_instance['version'];
619 $instance_class = $widget_instance['classname'];
620 $exists = (true === @$valid_widgets[ $instance_class ]);
621 if ( ! $exists ) {
622 if ( ! isset( self::$import_data['ignore']['widgets'] ) ) {
623 self::$import_data['ignore']['widgets'] = array();
624 }
625 self::$import_data['ignore']['widgets'][] = $widget_instance['name'];
626 unset( $sidebar[ $id ] );
627 }
628 }
629 self::$import_data['widgets'][ $sb_id ] = $sidebar;
630 }
631 }
632
633 /**
634 * Helper function that is used by prepare_data.
635 *
636 * @since 2.0
637 */
638 private function _remove_sidebar_from_list( $list, $valid_list ) {
639 /**
640 * do not process if $list is not an array or is an empty array
641 */
642 if ( ! is_array( $list ) || empty( $list ) ) {
643 return $list;
644 }
645 foreach ( $list as $id => $value ) {
646 if ( ! in_array( $value, $valid_list ) ) {
647 unset( $list[ $id ] );
648 } else if ( ! in_array( $id, $valid_list ) ) {
649 unset( $list[ $id ] );
650 }
651 }
652 return $list;
653 }
654
655 /**
656 * Returns the contents of the uploaded import file for preview or import.
657 *
658 * @since 2.0
659 */
660 static public function get_import_data() {
661 return self::$import_data;
662 }
663
664
665 /*============================*\
666 ================================
667 == ==
668 == IMPORT ==
669 == ==
670 ================================
671 \*============================*/
672
673 /**
674 * Process the import data provided in self::$import_data.
675 * Save the configuration to database.
676 * Populates the response object.
677 *
678 * @since 2.0
679 * @param object $req Initial response object for JSON response.
680 * @return object Updated response object.
681 */
682 private function do_import( $req ) {
683 $data = $this->selected_data;
684 $msg = array();
685
686 // =====================================================================
687 // Import custom sidebars
688
689 $sidebars = self::get_custom_sidebars();
690 $sidebar_count = 0;
691 // First replace existing sidebars.
692 foreach ( $sidebars as $idx => $sidebar ) {
693 $sb_id = $sidebar['id'];
694 if ( isset( $data['sidebars'][ $sb_id ] ) ) {
695 $new_sidebar = $data['sidebars'][ $sb_id ];
696 $sidebars[ $idx ] = array(
697 'name' => @$new_sidebar['name'],
698 'id' => $sb_id,
699 'description' => @$new_sidebar['description'],
700 'before_widget' => @$new_sidebar['before_widget'],
701 'after_widget' => @$new_sidebar['after_widget'],
702 'before_title' => @$new_sidebar['before_title'],
703 'after_title' => @$new_sidebar['after_title'],
704 );
705 $sidebar_count += 1;
706 unset( $data['sidebars'][ $sb_id ] );
707 }
708 }
709 // Second add new sidebars.
710 foreach ( $data['sidebars'] as $sb_id => $new_sidebar ) {
711 $sidebars[] = array(
712 'name' => @$new_sidebar['name'],
713 'id' => $sb_id,
714 'description' => @$new_sidebar['description'],
715 'before_widget' => @$new_sidebar['before_widget'],
716 'after_widget' => @$new_sidebar['after_widget'],
717 'before_title' => @$new_sidebar['before_title'],
718 'after_title' => @$new_sidebar['after_title'],
719 );
720 $sidebar_count += 1;
721 }
722 if ( $sidebar_count > 0 ) {
723 self::set_custom_sidebars( $sidebars );
724 $msg[] = sprintf(
725 /* translators: %d is replaced with the number of custom sidebars imported */
726 _n('Imported %d custom sidebar!', 'Imported %d custom sidebars!', $sidebar_count, 'custom-sidebars'),
727 $sidebar_count
728 );
729 }
730
731 // =====================================================================
732 // Import plugin settings
733 if ( ! empty( $data['options'] ) ) {
734 self::set_options( $data['options'] );
735 $msg[] = __( 'Plugin options were imported!', 'custom-sidebars' );
736 }
737
738 // =====================================================================
739 // Import widgets
740 $widget_count = 0;
741 $def_sidebars = get_option( 'sidebars_widgets', array() );
742
743
744 $widget_list = array();
745 $orig_POST = $_POST;
746 /**
747 * First replace existing sidebars.
748 */
749 if ( isset( $data['widgets'] ) && is_array( $data['widgets'] ) ) {
750 foreach ( $data['widgets'] as $sb_id => $sidebar ) {
751 // --- 1. Remove all widgets from the sidebar
752 // @see wp-admin/includes/ajax-actions.php : function wp_ajax_save_widget()
753 // Empty the sidebar, in case it contains widgets.
754 $old_widgets = @$def_sidebars[ $sb_id ];
755 $def_sidebars[ $sb_id ] = array();
756 wp_set_sidebars_widgets( $def_sidebars );
757 // Also remove the widget-instances from wp-option table.
758 if ( ! is_array( $old_widgets ) ) {
759 $old_widgets = array();
760 }
761 foreach ( $old_widgets as $widget_id ) {
762 $id_base = preg_replace( '/-[0-9]+$/', '', $widget_id );
763 $_POST = array(
764 'sidebar' => $sb_id,
765 'widget-' . $id_base => array(),
766 'the-widget-id' => $widget_id,
767 'delete_widget' => '1',
768 );
769 $this->_refresh_widget_settings( $id_base );
770 }
771 // --- 2. Import the new widgets to the sidebar
772 foreach ( $sidebar as $class => $widget ) {
773 $widget_base = $widget['id_base'];
774 $widget_name = $this->_add_new_widget( $widget_base, $widget['settings'] );
775 if ( ! empty( $widget_name ) ) {
776 $def_sidebars[ $sb_id ][] = $widget_name;
777 $widget_count += 1;
778 }
779 }
780 }
781 }
782 $_POST = $orig_POST;
783 if ( $widget_count > 0 ) {
784 wp_set_sidebars_widgets( $def_sidebars );
785 $msg[] = sprintf(
786 /* translators: %d is replaced with the number of imported widgets */
787 _n('Imported %d widget!', 'Imported %d widgets!', $widget_count, 'custom-sidebars'),
788 $widget_count
789 );
790 }
791
792 $req->message = base64_encode( implode( '<br />', $msg ) );
793
794 // We return a HTTP header to refresh the widgets page.
795 header( 'HTTP/1.1 302 Found' );
796 header( 'Location: ' . admin_url( 'widgets.php?cs-msg=' . $req->message ) );
797 die();
798 }
799
800 /**
801 * Helper function used by the "do_import()" handler.
802 * Updates the widget-data in DB.
803 *
804 * @since 2.0
805 */
806 private function _refresh_widget_settings( $id_base ) {
807 global $wp_registered_widget_updates;
808
809 foreach ( (array) $wp_registered_widget_updates as $name => $control ) {
810
811 if ( $name == $id_base ) {
812 if ( ! is_callable( $control['callback'] ) ) {
813 continue;
814 }
815
816 ob_start();
817 if ( is_object( $control['callback'] ) ) {
818 $control['callback']->updated = false;
819 }
820 call_user_func_array( $control['callback'], $control['params'] );
821 ob_end_clean();
822
823 break;
824 }
825 }
826 }
827
828 /**
829 * Helper function used by the "do_import()" handler.
830 * Updates the widget-data in DB.
831 *
832 * @since 2.0
833 */
834 private function _add_new_widget( $id_base, $instance ) {
835 global $wp_registered_widget_updates;
836 $widget_name = false;
837
838 foreach ( (array) $wp_registered_widget_updates as $name => $control ) {
839
840 if ( $name == $id_base ) {
841 if ( ! is_callable( $control['callback'] ) ) {
842 continue;
843 }
844
845 if ( is_array( $control['callback'] ) ) {
846 $obj = $control['callback'][0];
847 } else {
848 // We cannot import data from old widgets API.
849 break;
850 }
851 $obj->updated = false;
852
853 $all_instances = $obj->get_settings();
854
855 // Find out what the next free number is.
856 $new_number = 0;
857 foreach ( $all_instances as $number => $data ) {
858 $new_number = $number > $new_number ? $number : $new_number;
859 }
860 $new_number += 1;
861 $widget_name = $id_base . '-' . $new_number;
862 /**
863 * reset previous data
864 */
865 $keys = array( 'title', 'text', 'filter', 'csb_visibility', 'csb_clone' );
866 foreach ( $keys as $key ) {
867 if ( isset( $_POST[ $key ] ) ) {
868 unset( $_POST[ $key ] );
869 }
870 }
871 /**
872 * set current values
873 */
874 foreach ( $instance as $key => $value ) {
875 $_POST[ $key ] = $value;
876 }
877
878 /**
879 * Filter a widget's settings before saving.
880 *
881 * Returning false will effectively short-circuit the widget's ability
882 * to update settings.
883 *
884 * @see wp-includes/widgets.php : function "update_callback()"
885 * @since WordPress 2.8.0
886 *
887 * @param array $instance The current widget instance's settings.
888 * @param array $new_instance Array of new widget settings.
889 * @param array $old_instance Array of old widget settings.
890 * @param WP_Widget $this The current widget instance.
891 */
892 $instance = apply_filters( 'widget_update_callback', $instance, $instance, array(), $obj );
893 if ( false !== $instance ) {
894 $all_instances[ $new_number ] = $instance;
895 }
896
897 $obj->save_settings( $all_instances );
898
899 break;
900 }
901 }
902
903 return $widget_name;
904 }
905 };
906