PluginProbe ʕ •ᴥ•ʔ
Custom Sidebars – Dynamic Sidebar Classic Widget Area Manager / 3.32
Custom Sidebars – Dynamic Sidebar Classic Widget Area Manager v3.32
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 7 years ago integrations 7 years ago class-custom-sidebars-checkup-notification.php 5 years ago class-custom-sidebars-cloning.php 9 years ago class-custom-sidebars-editor.php 7 years ago class-custom-sidebars-explain.php 7 years ago class-custom-sidebars-export.php 8 years ago class-custom-sidebars-replacer.php 7 years ago class-custom-sidebars-visibility.php 7 years ago class-custom-sidebars-widgets.php 9 years ago class-custom-sidebars.php 5 years ago
class-custom-sidebars-export.php
920 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 _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' => htmlspecialchars( @$_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 if ( $compare ) {
307 $content = json_encode( $data );
308 } else {
309 $option = defined( 'JSON_PRETTY_PRINT' )? JSON_PRETTY_PRINT : null;
310 $content = json_encode( $data, $option );
311 }
312 // Send the download headers.
313 header( 'Pragma: public' );
314 header( 'Expires: 0' );
315 header( 'Cache-Control: must-revalidate, post-check=0, pre-check=0' );
316 header( 'Cache-Control: private', false ); // required for certain browsers
317 header( 'Content-type: application/json' );
318 header( 'Content-Disposition: attachment; filename="' . $filename . '"' );
319 header( 'Content-Transfer-Encoding: binary' );
320 header( 'Content-Length: ' . strlen( $content ) );
321 /**
322 * Finally send the export-file content.
323 */
324 echo $content;
325 exit;
326 }
327
328 /**
329 * Generate export file name dynamically.
330 *
331 * Generate a unique file name to export in json.
332 *
333 * @since 3.1.6
334 *
335 * @return string File name.
336 */
337 private function get_file_name() {
338 /**
339 * get version if it is needded
340 */
341 if ( empty( $this->version ) ) {
342 $csb_info = get_plugin_data( CSB_PLUGIN );
343 $this->version = $csb_info['Version'];
344 }
345 // Get site name.
346 $site_name = sanitize_key( get_bloginfo( 'name' ) );
347 $site_name = empty( $site_name ) ? '' : $site_name . '.';
348 // Create export file name.
349 $filename = sprintf(
350 '%s.sidebars.%s.%s.json',
351 $site_name,
352 $this->version,
353 date( 'Y-m-d.H-i-s' )
354 );
355 return $filename;
356 }
357
358 /*=============================*\
359 =================================
360 == ==
361 == PREVIEW ==
362 == ==
363 =================================
364 \*=============================*/
365
366
367 /**
368 * Checks if a valid export-file was uploaded and stores the file contents
369 * inside self::$import_data. The data is de-serialized.
370 * In error case the response object will be set to error status.
371 *
372 * @since 2.0
373 * @param object $req Initial response object for JSON response.
374 * @return object Updated response object.
375 */
376 private function read_import_file( $req ) {
377 /**
378 * check nonce
379 */
380 if (
381 ! isset( $_POST['_wpnonce'] )
382 || ! wp_verify_nonce( $_POST['_wpnonce'], 'custom-sidebars-import' )
383 ) {
384 $req = (object) array(
385 'status' => 'ERR',
386 );
387 $req = self::req_err(
388 $req,
389 __( 'You do not have permission for export sidebars.', 'custom-sidebars' )
390 );
391 self::json_response( $req );
392 }
393
394 if ( is_array( $_FILES['data'] ) ) {
395 switch ( $_FILES['data']['error'] ) {
396 case UPLOAD_ERR_OK:
397 // This is the expeted status!
398 break;
399
400 case UPLOAD_ERR_NO_FILE:
401 return self::req_err(
402 $req,
403 __( 'No file was uploaded', 'custom-sidebars' )
404 );
405
406 case UPLOAD_ERR_INI_SIZE:
407 case UPLOAD_ERR_FORM_SIZE:
408 return self::req_err(
409 $req,
410 __( 'Import file is too big', 'custom-sidebars' )
411 );
412
413 default:
414 return self::req_err(
415 $req,
416 __( 'Something went wrong', 'custom-sidebars' )
417 );
418 }
419
420 $content = file_get_contents( $_FILES['data']['tmp_name'] );
421 $data = json_decode( $content, true );
422
423 if (
424 is_array( $data['meta'] ) &&
425 is_array( $data['sidebars'] ) &&
426 is_array( $data['options'] ) &&
427 is_array( $data['widgets'] ) &&
428 is_array( $data['categories'] )
429 ) {
430 $data['meta']['filename'] = $_FILES['data']['name'];
431 $data['ignore'] = array();
432 self::$import_data = $data;
433
434 // Remove details that does not exist on current blog.
435 $this->prepare_data();
436 } else {
437 return self::req_err(
438 $req,
439 __( 'Unexpected import format', 'custom-sidebars' )
440 );
441 }
442 } else {
443 return self::req_err(
444 $req,
445 __( 'No file was uploaded', 'custom-sidebars' )
446 );
447 }
448
449 return $req;
450 }
451
452 /**
453 * Loads the import-data into the self::$import_data property.
454 * The data was prepared by the import-preview screen.
455 * Populates the response object.
456 *
457 * @since 2.0
458 * @param object $req Initial response object for JSON response.
459 * @return object Updated response object.
460 */
461 private function prepare_import_data( $req ) {
462 /**
463 * check nonce
464 */
465 if (
466 ! isset( $_POST['_wpnonce'] )
467 || ! wp_verify_nonce( $_POST['_wpnonce'], 'custom-sidebars-import' )
468 ) {
469 $req = (object) array(
470 'status' => 'ERR',
471 );
472 $req = self::req_err(
473 $req,
474 __( 'You do not have permission for import sidebars.', 'custom-sidebars' )
475 );
476 self::json_response( $req );
477 }
478
479 $data = json_decode( base64_decode( @$_POST['import_data'] ), true );
480
481 if (
482 is_array( $data['meta'] ) &&
483 is_array( $data['sidebars'] ) &&
484 is_array( $data['options'] ) &&
485 is_array( $data['widgets'] ) &&
486 is_array( $data['categories'] )
487 ) {
488 $data['ignore'] = array();
489 self::$import_data = $data;
490
491 // Remove details that does not exist on current blog.
492 $this->prepare_data();
493
494 // "selected_data" only contains the items that were selected for import.
495 $this->selected_data = self::$import_data;
496 unset( $this->selected_data['meta'] );
497 unset( $this->selected_data['categories'] );
498 unset( $this->selected_data['ignore'] );
499
500 if ( ! isset( $_POST['import_plugin_config'] ) ) {
501 unset( $this->selected_data['options'] );
502 }
503 if ( ! isset( $_POST['import_widgets'] ) ) {
504 unset( $this->selected_data['widgets'] );
505 } else {
506 foreach ( $this->selected_data['widgets'] as $id => $widgets ) {
507 $key = 'import_sb_' . $id;
508 if ( ! isset( $_POST[ $key ] ) ) {
509 unset( $this->selected_data['widgets'][ $id ] );
510 }
511 }
512 }
513 foreach ( $this->selected_data['sidebars'] as $id => $sidebar ) {
514 $key = 'import_sb_' . $sidebar['id'];
515 if ( ! isset( $_POST[ $key ] ) ) {
516 unset( $this->selected_data['sidebars'][ $id ] );
517 }
518 }
519
520 // Finally: Import the config!
521 $req = $this->do_import( $req );
522 } else {
523 return self::req_err(
524 $req,
525 __(
526 'Something unexpected happened and we could not finish ' .
527 'the import. Please try again.', 'custom-sidebars'
528 )
529 );
530 }
531
532 return $req;
533 }
534
535 /**
536 * Loops through the import data array and removes configuration which is
537 * not relevant for the current blog. I.e. posttypes that are not registered
538 * or categories that do not match the current blog.
539 *
540 * @since 2.0
541 */
542 private function prepare_data() {
543 global $wp_registered_widgets;
544 $theme_sidebars = self::get_sidebars();
545 $valid_categories = array();
546 $valid_sidebars = array();
547 $valid_widgets = array();
548
549 // =====
550 // Normalize the sidebar list (change numeric index to sidebar-id).
551 $sidebars_remapped = array();
552 foreach ( self::$import_data['sidebars'] as $sidebar ) {
553 $sidebars_remapped[ $sidebar['id'] ] = $sidebar;
554 }
555 self::$import_data['sidebars'] = $sidebars_remapped;
556
557 // =====
558 // Get a list of existing/valid sidebar-IDs.
559 $valid_sidebars = array_merge(
560 array_keys( $theme_sidebars ),
561 array_keys( self::$import_data['sidebars'] )
562 );
563
564 // =====
565 // Check for theme-sidebars that do not exist.
566 foreach ( self::$import_data['options']['modifiable'] as $id => $sb_id ) {
567 if ( ! isset( $theme_sidebars[ $sb_id ] ) ) {
568 if ( ! isset( self::$import_data['ignore']['sidebars'] ) ) {
569 self::$import_data['ignore']['sidebars'] = array();
570 }
571 self::$import_data['ignore']['sidebars'][] = $sb_id;
572 unset( self::$import_data['options']['modifiable'][ $id ] );
573 }
574 }
575
576 // =====
577 // Remove invalid sidebars from the default replacement options.
578 foreach ( array( 'post_type_single', 'post_type_archive', 'category_single', 'category_archive' ) as $key ) {
579 foreach ( self::$import_data['options'][ $key ] as $id => $list ) {
580 $list = $this->_remove_sidebar_from_list( $list, $valid_sidebars );
581 self::$import_data['options'][ $key ][ $id ] = $list;
582 }
583 }
584 foreach ( array( 'blog', 'tags', 'authors', 'search', 'date' ) as $key ) {
585 $list = self::$import_data['options'][ $key ];
586 $list = $this->_remove_sidebar_from_list( $list, $valid_sidebars );
587 self::$import_data['options'][ $key ] = $list;
588 }
589
590 // =====
591 // Check for missing/different categories.
592 foreach ( get_categories( array( 'hide_empty' => 0 ) ) as $cat ) {
593 $valid_categories[ $cat->term_id ] = $cat;
594 }
595 foreach ( self::$import_data['categories'] as $infos ) {
596 $id = $infos['term_id'];
597 if (
598 empty( $valid_categories[ $id ] ) ||
599 $valid_categories[ $id ]->slug != $infos['slug']
600 ) {
601 if ( ! isset( self::$import_data['ignore']['categories'] ) ) {
602 self::$import_data['ignore']['categories'] = array();
603 }
604 self::$import_data['ignore']['categories'][] = $infos['name'];
605 unset( self::$import_data['categories'][ $id ] );
606
607 // Remove the categories from the config array.
608 unset( self::$import_data['options']['category_posts'][ $id ] );
609 unset( self::$import_data['options']['category_pages'][ $id ] );
610 }
611 }
612
613 // =====
614 // Remove missing widgets from import data.
615 foreach ( $wp_registered_widgets as $widget ) {
616 if ( is_array( $widget['callback'] ) ) {
617 $classname = get_class( $widget['callback'][0] );
618 } else {
619 $classname = $widget['classname'];
620 }
621 $valid_widgets[ $classname ] = true;
622 }
623 foreach ( self::$import_data['widgets'] as $sb_id => $sidebar ) {
624 if ( ! is_array( $sidebar ) ) { continue; }
625 foreach ( $sidebar as $id => $widget_instance ) {
626 $version = $widget_instance['version'];
627 $instance_class = $widget_instance['classname'];
628 $exists = (true === @$valid_widgets[ $instance_class ]);
629 if ( ! $exists ) {
630 if ( ! isset( self::$import_data['ignore']['widgets'] ) ) {
631 self::$import_data['ignore']['widgets'] = array();
632 }
633 self::$import_data['ignore']['widgets'][] = $widget_instance['name'];
634 unset( $sidebar[ $id ] );
635 }
636 }
637 self::$import_data['widgets'][ $sb_id ] = $sidebar;
638 }
639 }
640
641 /**
642 * Helper function that is used by prepare_data.
643 *
644 * @since 2.0
645 */
646 private function _remove_sidebar_from_list( $list, $valid_list ) {
647 /**
648 * do not process if $list is not an array or is an empty array
649 */
650 if ( ! is_array( $list ) || empty( $list ) ) {
651 return $list;
652 }
653 foreach ( $list as $id => $value ) {
654 if ( ! in_array( $value, $valid_list ) ) {
655 unset( $list[ $id ] );
656 } else if ( ! in_array( $id, $valid_list ) ) {
657 unset( $list[ $id ] );
658 }
659 }
660 return $list;
661 }
662
663 /**
664 * Returns the contents of the uploaded import file for preview or import.
665 *
666 * @since 2.0
667 */
668 static public function get_import_data() {
669 return self::$import_data;
670 }
671
672
673 /*============================*\
674 ================================
675 == ==
676 == IMPORT ==
677 == ==
678 ================================
679 \*============================*/
680
681 /**
682 * Process the import data provided in self::$import_data.
683 * Save the configuration to database.
684 * Populates the response object.
685 *
686 * @since 2.0
687 * @param object $req Initial response object for JSON response.
688 * @return object Updated response object.
689 */
690 private function do_import( $req ) {
691 $data = $this->selected_data;
692 $msg = array();
693
694 // =====================================================================
695 // Import custom sidebars
696
697 $sidebars = self::get_custom_sidebars();
698 $sidebar_count = 0;
699 // First replace existing sidebars.
700 foreach ( $sidebars as $idx => $sidebar ) {
701 $sb_id = $sidebar['id'];
702 if ( isset( $data['sidebars'][ $sb_id ] ) ) {
703 $new_sidebar = $data['sidebars'][ $sb_id ];
704 $sidebars[ $idx ] = array(
705 'name' => @$new_sidebar['name'],
706 'id' => $sb_id,
707 'description' => @$new_sidebar['description'],
708 'before_widget' => @$new_sidebar['before_widget'],
709 'after_widget' => @$new_sidebar['after_widget'],
710 'before_title' => @$new_sidebar['before_title'],
711 'after_title' => @$new_sidebar['after_title'],
712 );
713 $sidebar_count += 1;
714 unset( $data['sidebars'][ $sb_id ] );
715 }
716 }
717 // Second add new sidebars.
718 foreach ( $data['sidebars'] as $sb_id => $new_sidebar ) {
719 $sidebars[] = array(
720 'name' => @$new_sidebar['name'],
721 'id' => $sb_id,
722 'description' => @$new_sidebar['description'],
723 'before_widget' => @$new_sidebar['before_widget'],
724 'after_widget' => @$new_sidebar['after_widget'],
725 'before_title' => @$new_sidebar['before_title'],
726 'after_title' => @$new_sidebar['after_title'],
727 );
728 $sidebar_count += 1;
729 }
730 if ( $sidebar_count > 0 ) {
731 self::set_custom_sidebars( $sidebars );
732 $msg[] = sprintf(
733 _n(
734 'Imported %d custom sidebar!',
735 'Imported %d custom sidebars!',
736 $sidebar_count,
737 'custom-sidebars'
738 ),
739 $sidebar_count
740 );
741 }
742
743 // =====================================================================
744 // Import plugin settings
745 if ( ! empty( $data['options'] ) ) {
746 self::set_options( $data['options'] );
747 $msg[] = __( 'Plugin options were imported!', 'custom-sidebars' );
748 }
749
750 // =====================================================================
751 // Import widgets
752 $widget_count = 0;
753 $def_sidebars = wp_get_sidebars_widgets();
754 $widget_list = array();
755 $orig_POST = $_POST;
756 /**
757 * First replace existing sidebars.
758 */
759 if ( isset( $data['widgets'] ) && is_array( $data['widgets'] ) ) {
760 foreach ( $data['widgets'] as $sb_id => $sidebar ) {
761 // --- 1. Remove all widgets from the sidebar
762 // @see wp-admin/includes/ajax-actions.php : function wp_ajax_save_widget()
763 // Empty the sidebar, in case it contains widgets.
764 $old_widgets = @$def_sidebars[ $sb_id ];
765 $def_sidebars[ $sb_id ] = array();
766 wp_set_sidebars_widgets( $def_sidebars );
767 // Also remove the widget-instances from wp-option table.
768 if ( ! is_array( $old_widgets ) ) {
769 $old_widgets = array();
770 }
771 foreach ( $old_widgets as $widget_id ) {
772 $id_base = preg_replace( '/-[0-9]+$/', '', $widget_id );
773 $_POST = array(
774 'sidebar' => $sb_id,
775 'widget-' . $id_base => array(),
776 'the-widget-id' => $widget_id,
777 'delete_widget' => '1',
778 );
779 $this->_refresh_widget_settings( $id_base );
780 }
781 // --- 2. Import the new widgets to the sidebar
782 foreach ( $sidebar as $class => $widget ) {
783 $widget_base = $widget['id_base'];
784 $widget_name = $this->_add_new_widget( $widget_base, $widget['settings'] );
785 if ( ! empty( $widget_name ) ) {
786 $def_sidebars[ $sb_id ][] = $widget_name;
787 $widget_count += 1;
788 }
789 }
790 }
791 }
792 $_POST = $orig_POST;
793 if ( $widget_count > 0 ) {
794 wp_set_sidebars_widgets( $def_sidebars );
795 $msg[] = sprintf(
796 _n(
797 'Imported %d widget!',
798 'Imported %d widgets!',
799 $widget_count,
800 'custom-sidebars'
801 ),
802 $widget_count
803 );
804 }
805
806 $req->message = base64_encode( implode( '<br />', $msg ) );
807
808 // We return a HTTP header to refresh the widgets page.
809 header( 'HTTP/1.1 302 Found' );
810 header( 'Location: ' . admin_url( 'widgets.php?cs-msg=' . $req->message ) );
811 die();
812 }
813
814 /**
815 * Helper function used by the "do_import()" handler.
816 * Updates the widget-data in DB.
817 *
818 * @since 2.0
819 */
820 private function _refresh_widget_settings( $id_base ) {
821 global $wp_registered_widget_updates;
822
823 foreach ( (array) $wp_registered_widget_updates as $name => $control ) {
824
825 if ( $name == $id_base ) {
826 if ( ! is_callable( $control['callback'] ) ) {
827 continue;
828 }
829
830 ob_start();
831 if ( is_object( $control['callback'] ) ) {
832 $control['callback']->updated = false;
833 }
834 call_user_func_array( $control['callback'], $control['params'] );
835 ob_end_clean();
836
837 break;
838 }
839 }
840 }
841
842 /**
843 * Helper function used by the "do_import()" handler.
844 * Updates the widget-data in DB.
845 *
846 * @since 2.0
847 */
848 private function _add_new_widget( $id_base, $instance ) {
849 global $wp_registered_widget_updates;
850 $widget_name = false;
851
852 foreach ( (array) $wp_registered_widget_updates as $name => $control ) {
853
854 if ( $name == $id_base ) {
855 if ( ! is_callable( $control['callback'] ) ) {
856 continue;
857 }
858
859 if ( is_array( $control['callback'] ) ) {
860 $obj = $control['callback'][0];
861 } else {
862 // We cannot import data from old widgets API.
863 break;
864 }
865 $obj->updated = false;
866
867 $all_instances = $obj->get_settings();
868
869 // Find out what the next free number is.
870 $new_number = 0;
871 foreach ( $all_instances as $number => $data ) {
872 $new_number = $number > $new_number ? $number : $new_number;
873 }
874 $new_number += 1;
875 $widget_name = $id_base . '-' . $new_number;
876 /**
877 * reset previous data
878 */
879 $keys = array( 'title', 'text', 'filter', 'csb_visibility', 'csb_clone' );
880 foreach ( $keys as $key ) {
881 if ( isset( $_POST[ $key ] ) ) {
882 unset( $_POST[ $key ] );
883 }
884 }
885 /**
886 * set current values
887 */
888 foreach ( $instance as $key => $value ) {
889 $_POST[ $key ] = $value;
890 }
891
892 /**
893 * Filter a widget's settings before saving.
894 *
895 * Returning false will effectively short-circuit the widget's ability
896 * to update settings.
897 *
898 * @see wp-includes/widgets.php : function "update_callback()"
899 * @since WordPress 2.8.0
900 *
901 * @param array $instance The current widget instance's settings.
902 * @param array $new_instance Array of new widget settings.
903 * @param array $old_instance Array of old widget settings.
904 * @param WP_Widget $this The current widget instance.
905 */
906 $instance = apply_filters( 'widget_update_callback', $instance, $instance, array(), $obj );
907 if ( false !== $instance ) {
908 $all_instances[ $new_number ] = $instance;
909 }
910
911 $obj->save_settings( $all_instances );
912
913 break;
914 }
915 }
916
917 return $widget_name;
918 }
919 };
920