98 */ |
98 */ |
99 public function __construct( $manager ) { |
99 public function __construct( $manager ) { |
100 $this->manager = $manager; |
100 $this->manager = $manager; |
101 |
101 |
102 // See https://github.com/xwp/wp-customize-snapshots/blob/962586659688a5b1fd9ae93618b7ce2d4e7a421c/php/class-customize-snapshot-manager.php#L420-L449 |
102 // See https://github.com/xwp/wp-customize-snapshots/blob/962586659688a5b1fd9ae93618b7ce2d4e7a421c/php/class-customize-snapshot-manager.php#L420-L449 |
103 add_filter( 'customize_dynamic_setting_args', array( $this, 'filter_customize_dynamic_setting_args' ), 10, 2 ); |
103 add_filter( 'customize_dynamic_setting_args', array( $this, 'filter_customize_dynamic_setting_args' ), 10, 2 ); |
104 add_action( 'widgets_init', array( $this, 'register_settings' ), 95 ); |
104 add_action( 'widgets_init', array( $this, 'register_settings' ), 95 ); |
105 add_action( 'customize_register', array( $this, 'schedule_customize_register' ), 1 ); |
105 add_action( 'customize_register', array( $this, 'schedule_customize_register' ), 1 ); |
106 |
106 |
107 // Skip remaining hooks when the user can't manage widgets anyway. |
107 // Skip remaining hooks when the user can't manage widgets anyway. |
108 if ( ! current_user_can( 'edit_theme_options' ) ) { |
108 if ( ! current_user_can( 'edit_theme_options' ) ) { |
109 return; |
109 return; |
110 } |
110 } |
111 |
111 |
112 add_action( 'wp_loaded', array( $this, 'override_sidebars_widgets_for_theme_switch' ) ); |
112 add_action( 'wp_loaded', array( $this, 'override_sidebars_widgets_for_theme_switch' ) ); |
113 add_action( 'customize_controls_init', array( $this, 'customize_controls_init' ) ); |
113 add_action( 'customize_controls_init', array( $this, 'customize_controls_init' ) ); |
114 add_action( 'customize_controls_enqueue_scripts', array( $this, 'enqueue_scripts' ) ); |
114 add_action( 'customize_controls_enqueue_scripts', array( $this, 'enqueue_scripts' ) ); |
115 add_action( 'customize_controls_print_styles', array( $this, 'print_styles' ) ); |
115 add_action( 'customize_controls_print_styles', array( $this, 'print_styles' ) ); |
116 add_action( 'customize_controls_print_scripts', array( $this, 'print_scripts' ) ); |
116 add_action( 'customize_controls_print_scripts', array( $this, 'print_scripts' ) ); |
117 add_action( 'customize_controls_print_footer_scripts', array( $this, 'print_footer_scripts' ) ); |
117 add_action( 'customize_controls_print_footer_scripts', array( $this, 'print_footer_scripts' ) ); |
118 add_action( 'customize_controls_print_footer_scripts', array( $this, 'output_widget_control_templates' ) ); |
118 add_action( 'customize_controls_print_footer_scripts', array( $this, 'output_widget_control_templates' ) ); |
119 add_action( 'customize_preview_init', array( $this, 'customize_preview_init' ) ); |
119 add_action( 'customize_preview_init', array( $this, 'customize_preview_init' ) ); |
120 add_filter( 'customize_refresh_nonces', array( $this, 'refresh_nonces' ) ); |
120 add_filter( 'customize_refresh_nonces', array( $this, 'refresh_nonces' ) ); |
121 |
121 |
122 add_action( 'dynamic_sidebar', array( $this, 'tally_rendered_widgets' ) ); |
122 add_action( 'dynamic_sidebar', array( $this, 'tally_rendered_widgets' ) ); |
123 add_filter( 'is_active_sidebar', array( $this, 'tally_sidebars_via_is_active_sidebar_calls' ), 10, 2 ); |
123 add_filter( 'is_active_sidebar', array( $this, 'tally_sidebars_via_is_active_sidebar_calls' ), 10, 2 ); |
124 add_filter( 'dynamic_sidebar_has_widgets', array( $this, 'tally_sidebars_via_dynamic_sidebar_calls' ), 10, 2 ); |
124 add_filter( 'dynamic_sidebar_has_widgets', array( $this, 'tally_sidebars_via_dynamic_sidebar_calls' ), 10, 2 ); |
125 |
125 |
126 // Selective Refresh. |
126 // Selective Refresh. |
127 add_filter( 'customize_dynamic_partial_args', array( $this, 'customize_dynamic_partial_args' ), 10, 2 ); |
127 add_filter( 'customize_dynamic_partial_args', array( $this, 'customize_dynamic_partial_args' ), 10, 2 ); |
128 add_action( 'customize_preview_init', array( $this, 'selective_refresh_init' ) ); |
128 add_action( 'customize_preview_init', array( $this, 'selective_refresh_init' ) ); |
129 } |
129 } |
130 |
130 |
131 /** |
131 /** |
132 * List whether each registered widget can be use selective refresh. |
132 * List whether each registered widget can be use selective refresh. |
133 * |
133 * |
397 /* |
397 /* |
398 * Add a setting which will be supplied for the theme's sidebars_widgets |
398 * Add a setting which will be supplied for the theme's sidebars_widgets |
399 * theme_mod when the theme is switched. |
399 * theme_mod when the theme is switched. |
400 */ |
400 */ |
401 if ( ! $this->manager->is_theme_active() ) { |
401 if ( ! $this->manager->is_theme_active() ) { |
402 $setting_id = 'old_sidebars_widgets_data'; |
402 $setting_id = 'old_sidebars_widgets_data'; |
403 $setting_args = $this->get_setting_args( $setting_id, array( |
403 $setting_args = $this->get_setting_args( |
404 'type' => 'global_variable', |
404 $setting_id, |
405 'dirty' => true, |
405 array( |
406 ) ); |
406 'type' => 'global_variable', |
|
407 'dirty' => true, |
|
408 ) |
|
409 ); |
407 $this->manager->add_setting( $setting_id, $setting_args ); |
410 $this->manager->add_setting( $setting_id, $setting_args ); |
408 } |
411 } |
409 |
412 |
410 $this->manager->add_panel( 'widgets', array( |
413 $this->manager->add_panel( |
411 'type' => 'widgets', |
414 'widgets', |
412 'title' => __( 'Widgets' ), |
415 array( |
413 'description' => __( 'Widgets are independent sections of content that can be placed into widgetized areas provided by your theme (commonly called sidebars).' ), |
416 'type' => 'widgets', |
414 'priority' => 110, |
417 'title' => __( 'Widgets' ), |
415 'active_callback' => array( $this, 'is_panel_active' ), |
418 'description' => __( 'Widgets are independent sections of content that can be placed into widgetized areas provided by your theme (commonly called sidebars).' ), |
416 'auto_expand_sole_section' => true, |
419 'priority' => 110, |
417 ) ); |
420 'active_callback' => array( $this, 'is_panel_active' ), |
|
421 'auto_expand_sole_section' => true, |
|
422 ) |
|
423 ); |
418 |
424 |
419 foreach ( $sidebars_widgets as $sidebar_id => $sidebar_widget_ids ) { |
425 foreach ( $sidebars_widgets as $sidebar_id => $sidebar_widget_ids ) { |
420 if ( empty( $sidebar_widget_ids ) ) { |
426 if ( empty( $sidebar_widget_ids ) ) { |
421 $sidebar_widget_ids = array(); |
427 $sidebar_widget_ids = array(); |
422 } |
428 } |
440 // Add section to contain controls. |
446 // Add section to contain controls. |
441 $section_id = sprintf( 'sidebar-widgets-%s', $sidebar_id ); |
447 $section_id = sprintf( 'sidebar-widgets-%s', $sidebar_id ); |
442 if ( $is_active_sidebar ) { |
448 if ( $is_active_sidebar ) { |
443 |
449 |
444 $section_args = array( |
450 $section_args = array( |
445 'title' => $wp_registered_sidebars[ $sidebar_id ]['name'], |
451 'title' => $wp_registered_sidebars[ $sidebar_id ]['name'], |
446 'description' => $wp_registered_sidebars[ $sidebar_id ]['description'], |
452 'description' => $wp_registered_sidebars[ $sidebar_id ]['description'], |
447 'priority' => array_search( $sidebar_id, array_keys( $wp_registered_sidebars ) ), |
453 'priority' => array_search( $sidebar_id, array_keys( $wp_registered_sidebars ) ), |
448 'panel' => 'widgets', |
454 'panel' => 'widgets', |
449 'sidebar_id' => $sidebar_id, |
455 'sidebar_id' => $sidebar_id, |
450 ); |
456 ); |
451 |
457 |
452 /** |
458 /** |
453 * Filters Customizer widget section arguments for a given sidebar. |
459 * Filters Customizer widget section arguments for a given sidebar. |
454 * |
460 * |
461 $section_args = apply_filters( 'customizer_widgets_section_args', $section_args, $section_id, $sidebar_id ); |
467 $section_args = apply_filters( 'customizer_widgets_section_args', $section_args, $section_id, $sidebar_id ); |
462 |
468 |
463 $section = new WP_Customize_Sidebar_Section( $this->manager, $section_id, $section_args ); |
469 $section = new WP_Customize_Sidebar_Section( $this->manager, $section_id, $section_args ); |
464 $this->manager->add_section( $section ); |
470 $this->manager->add_section( $section ); |
465 |
471 |
466 $control = new WP_Widget_Area_Customize_Control( $this->manager, $setting_id, array( |
472 $control = new WP_Widget_Area_Customize_Control( |
467 'section' => $section_id, |
473 $this->manager, |
468 'sidebar_id' => $sidebar_id, |
474 $setting_id, |
469 'priority' => count( $sidebar_widget_ids ), // place 'Add Widget' and 'Reorder' buttons at end. |
475 array( |
470 ) ); |
476 'section' => $section_id, |
|
477 'sidebar_id' => $sidebar_id, |
|
478 'priority' => count( $sidebar_widget_ids ), // place 'Add Widget' and 'Reorder' buttons at end. |
|
479 ) |
|
480 ); |
471 $new_setting_ids[] = $setting_id; |
481 $new_setting_ids[] = $setting_id; |
472 |
482 |
473 $this->manager->add_control( $control ); |
483 $this->manager->add_control( $control ); |
474 } |
484 } |
475 } |
485 } |
476 |
486 |
477 // Add a control for each active widget (located in a sidebar). |
487 // Add a control for each active widget (located in a sidebar). |
478 foreach ( $sidebar_widget_ids as $i => $widget_id ) { |
488 foreach ( $sidebar_widget_ids as $i => $widget_id ) { |
479 |
489 |
480 // Skip widgets that may have gone away due to a plugin being deactivated. |
490 // Skip widgets that may have gone away due to a plugin being deactivated. |
481 if ( ! $is_active_sidebar || ! isset( $wp_registered_widgets[$widget_id] ) ) { |
491 if ( ! $is_active_sidebar || ! isset( $wp_registered_widgets[ $widget_id ] ) ) { |
482 continue; |
492 continue; |
483 } |
493 } |
484 |
494 |
485 $registered_widget = $wp_registered_widgets[$widget_id]; |
495 $registered_widget = $wp_registered_widgets[ $widget_id ]; |
486 $setting_id = $this->get_setting_id( $widget_id ); |
496 $setting_id = $this->get_setting_id( $widget_id ); |
487 $id_base = $wp_registered_widget_controls[$widget_id]['id_base']; |
497 $id_base = $wp_registered_widget_controls[ $widget_id ]['id_base']; |
488 |
498 |
489 $control = new WP_Widget_Form_Customize_Control( $this->manager, $setting_id, array( |
499 $control = new WP_Widget_Form_Customize_Control( |
490 'label' => $registered_widget['name'], |
500 $this->manager, |
491 'section' => $section_id, |
501 $setting_id, |
492 'sidebar_id' => $sidebar_id, |
502 array( |
493 'widget_id' => $widget_id, |
503 'label' => $registered_widget['name'], |
494 'widget_id_base' => $id_base, |
504 'section' => $section_id, |
495 'priority' => $i, |
505 'sidebar_id' => $sidebar_id, |
496 'width' => $wp_registered_widget_controls[$widget_id]['width'], |
506 'widget_id' => $widget_id, |
497 'height' => $wp_registered_widget_controls[$widget_id]['height'], |
507 'widget_id_base' => $id_base, |
498 'is_wide' => $this->is_wide_widget( $widget_id ), |
508 'priority' => $i, |
499 ) ); |
509 'width' => $wp_registered_widget_controls[ $widget_id ]['width'], |
|
510 'height' => $wp_registered_widget_controls[ $widget_id ]['height'], |
|
511 'is_wide' => $this->is_wide_widget( $widget_id ), |
|
512 ) |
|
513 ); |
500 $this->manager->add_control( $control ); |
514 $this->manager->add_control( $control ); |
501 } |
515 } |
502 } |
516 } |
503 |
517 |
504 if ( $this->manager->settings_previewed() ) { |
518 if ( $this->manager->settings_previewed() ) { |
706 |
720 |
707 /* |
721 /* |
708 * Gather all strings in PHP that may be needed by JS on the client. |
722 * Gather all strings in PHP that may be needed by JS on the client. |
709 * Once JS i18n is implemented (in #20491), this can be removed. |
723 * Once JS i18n is implemented (in #20491), this can be removed. |
710 */ |
724 */ |
711 $some_non_rendered_areas_messages = array(); |
725 $some_non_rendered_areas_messages = array(); |
712 $some_non_rendered_areas_messages[1] = html_entity_decode( |
726 $some_non_rendered_areas_messages[1] = html_entity_decode( |
713 __( 'Your theme has 1 other widget area, but this particular page doesn’t display it.' ), |
727 __( 'Your theme has 1 other widget area, but this particular page doesn’t display it.' ), |
714 ENT_QUOTES, |
728 ENT_QUOTES, |
715 get_bloginfo( 'charset' ) |
729 get_bloginfo( 'charset' ) |
716 ); |
730 ); |
717 $registered_sidebar_count = count( $wp_registered_sidebars ); |
731 $registered_sidebar_count = count( $wp_registered_sidebars ); |
718 for ( $non_rendered_count = 2; $non_rendered_count < $registered_sidebar_count; $non_rendered_count++ ) { |
732 for ( $non_rendered_count = 2; $non_rendered_count < $registered_sidebar_count; $non_rendered_count++ ) { |
719 $some_non_rendered_areas_messages[ $non_rendered_count ] = html_entity_decode( sprintf( |
733 $some_non_rendered_areas_messages[ $non_rendered_count ] = html_entity_decode( |
720 /* translators: %s: the number of other widget areas registered but not rendered */ |
734 sprintf( |
721 _n( |
735 /* translators: %s: the number of other widget areas registered but not rendered */ |
722 'Your theme has %s other widget area, but this particular page doesn’t display it.', |
736 _n( |
723 'Your theme has %s other widget areas, but this particular page doesn’t display them.', |
737 'Your theme has %s other widget area, but this particular page doesn’t display it.', |
724 $non_rendered_count |
738 'Your theme has %s other widget areas, but this particular page doesn’t display them.', |
|
739 $non_rendered_count |
|
740 ), |
|
741 number_format_i18n( $non_rendered_count ) |
725 ), |
742 ), |
726 number_format_i18n( $non_rendered_count ) |
743 ENT_QUOTES, |
727 ), ENT_QUOTES, get_bloginfo( 'charset' ) ); |
744 get_bloginfo( 'charset' ) |
|
745 ); |
728 } |
746 } |
729 |
747 |
730 if ( 1 === $registered_sidebar_count ) { |
748 if ( 1 === $registered_sidebar_count ) { |
731 $no_areas_shown_message = html_entity_decode( sprintf( |
749 $no_areas_shown_message = html_entity_decode( |
732 __( 'Your theme has 1 widget area, but this particular page doesn’t display it.' ) |
750 sprintf( |
733 ), ENT_QUOTES, get_bloginfo( 'charset' ) ); |
751 __( 'Your theme has 1 widget area, but this particular page doesn’t display it.' ) |
|
752 ), |
|
753 ENT_QUOTES, |
|
754 get_bloginfo( 'charset' ) |
|
755 ); |
734 } else { |
756 } else { |
735 $no_areas_shown_message = html_entity_decode( sprintf( |
757 $no_areas_shown_message = html_entity_decode( |
736 /* translators: %s: the total number of widget areas registered */ |
758 sprintf( |
737 _n( |
759 /* translators: %s: the total number of widget areas registered */ |
738 'Your theme has %s widget area, but this particular page doesn’t display it.', |
760 _n( |
739 'Your theme has %s widget areas, but this particular page doesn’t display them.', |
761 'Your theme has %s widget area, but this particular page doesn’t display it.', |
740 $registered_sidebar_count |
762 'Your theme has %s widget areas, but this particular page doesn’t display them.', |
|
763 $registered_sidebar_count |
|
764 ), |
|
765 number_format_i18n( $registered_sidebar_count ) |
741 ), |
766 ), |
742 number_format_i18n( $registered_sidebar_count ) |
767 ENT_QUOTES, |
743 ), ENT_QUOTES, get_bloginfo( 'charset' ) ); |
768 get_bloginfo( 'charset' ) |
|
769 ); |
744 } |
770 } |
745 |
771 |
746 $settings = array( |
772 $settings = array( |
747 'registeredSidebars' => array_values( $wp_registered_sidebars ), |
773 'registeredSidebars' => array_values( $wp_registered_sidebars ), |
748 'registeredWidgets' => $wp_registered_widgets, |
774 'registeredWidgets' => $wp_registered_widgets, |
749 'availableWidgets' => $available_widgets, // @todo Merge this with registered_widgets |
775 'availableWidgets' => $available_widgets, // @todo Merge this with registered_widgets |
750 'l10n' => array( |
776 'l10n' => array( |
751 'saveBtnLabel' => __( 'Apply' ), |
777 'saveBtnLabel' => __( 'Apply' ), |
752 'saveBtnTooltip' => __( 'Save and preview changes before publishing them.' ), |
778 'saveBtnTooltip' => __( 'Save and preview changes before publishing them.' ), |
753 'removeBtnLabel' => __( 'Remove' ), |
779 'removeBtnLabel' => __( 'Remove' ), |
754 'removeBtnTooltip' => __( 'Trash widget by moving it to the inactive widgets sidebar.' ), |
780 'removeBtnTooltip' => __( 'Keep widget settings and move it to the inactive widgets' ), |
755 'error' => __( 'An error has occurred. Please reload the page and try again.' ), |
781 'error' => __( 'An error has occurred. Please reload the page and try again.' ), |
756 'widgetMovedUp' => __( 'Widget moved up' ), |
782 'widgetMovedUp' => __( 'Widget moved up' ), |
757 'widgetMovedDown' => __( 'Widget moved down' ), |
783 'widgetMovedDown' => __( 'Widget moved down' ), |
758 'navigatePreview' => __( 'You can navigate to other pages on your site while using the Customizer to view and edit the widgets displayed on those pages.' ), |
784 'navigatePreview' => __( 'You can navigate to other pages on your site while using the Customizer to view and edit the widgets displayed on those pages.' ), |
759 'someAreasShown' => $some_non_rendered_areas_messages, |
785 'someAreasShown' => $some_non_rendered_areas_messages, |
795 <div class="customize-section-title"> |
821 <div class="customize-section-title"> |
796 <button class="customize-section-back" tabindex="-1"> |
822 <button class="customize-section-back" tabindex="-1"> |
797 <span class="screen-reader-text"><?php _e( 'Back' ); ?></span> |
823 <span class="screen-reader-text"><?php _e( 'Back' ); ?></span> |
798 </button> |
824 </button> |
799 <h3> |
825 <h3> |
800 <span class="customize-action"><?php |
826 <span class="customize-action"> |
|
827 <?php |
801 /* translators: ▸ is the unicode right-pointing triangle, and %s is the section title in the Customizer */ |
828 /* translators: ▸ is the unicode right-pointing triangle, and %s is the section title in the Customizer */ |
802 echo sprintf( __( 'Customizing ▸ %s' ), esc_html( $this->manager->get_panel( 'widgets' )->title ) ); |
829 echo sprintf( __( 'Customizing ▸ %s' ), esc_html( $this->manager->get_panel( 'widgets' )->title ) ); |
803 ?></span> |
830 ?> |
|
831 </span> |
804 <?php _e( 'Add a Widget' ); ?> |
832 <?php _e( 'Add a Widget' ); ?> |
805 </h3> |
833 </h3> |
806 </div> |
834 </div> |
807 <div id="available-widgets-filter"> |
835 <div id="available-widgets-filter"> |
808 <label class="screen-reader-text" for="widgets-search"><?php _e( 'Search Widgets' ); ?></label> |
836 <label class="screen-reader-text" for="widgets-search"><?php _e( 'Search Widgets' ); ?></label> |
809 <input type="text" id="widgets-search" placeholder="<?php esc_attr_e( 'Search widgets…' ) ?>" aria-describedby="widgets-search-desc" /> |
837 <input type="text" id="widgets-search" placeholder="<?php esc_attr_e( 'Search widgets…' ); ?>" aria-describedby="widgets-search-desc" /> |
810 <div class="search-icon" aria-hidden="true"></div> |
838 <div class="search-icon" aria-hidden="true"></div> |
811 <button type="button" class="clear-results"><span class="screen-reader-text"><?php _e( 'Clear Results' ); ?></span></button> |
839 <button type="button" class="clear-results"><span class="screen-reader-text"><?php _e( 'Clear Results' ); ?></span></button> |
812 <p class="screen-reader-text" id="widgets-search-desc"><?php _e( 'The search results will be updated as you type.' ); ?></p> |
840 <p class="screen-reader-text" id="widgets-search-desc"><?php _e( 'The search results will be updated as you type.' ); ?></p> |
813 </div> |
841 </div> |
814 <div id="available-widgets-list"> |
842 <div id="available-widgets-list"> |
815 <?php foreach ( $this->get_available_widgets() as $available_widget ): ?> |
843 <?php foreach ( $this->get_available_widgets() as $available_widget ) : ?> |
816 <div id="widget-tpl-<?php echo esc_attr( $available_widget['id'] ) ?>" data-widget-id="<?php echo esc_attr( $available_widget['id'] ) ?>" class="widget-tpl <?php echo esc_attr( $available_widget['id'] ) ?>" tabindex="0"> |
844 <div id="widget-tpl-<?php echo esc_attr( $available_widget['id'] ); ?>" data-widget-id="<?php echo esc_attr( $available_widget['id'] ); ?>" class="widget-tpl <?php echo esc_attr( $available_widget['id'] ); ?>" tabindex="0"> |
817 <?php echo $available_widget['control_tpl']; ?> |
845 <?php echo $available_widget['control_tpl']; ?> |
818 </div> |
846 </div> |
819 <?php endforeach; ?> |
847 <?php endforeach; ?> |
820 <p class="no-widgets-found-message"><?php _e( 'No widgets found.' ); ?></p> |
848 <p class="no-widgets-found-message"><?php _e( 'No widgets found.' ); ?></p> |
821 </div><!-- #available-widgets-list --> |
849 </div><!-- #available-widgets-list --> |
856 'capability' => 'edit_theme_options', |
884 'capability' => 'edit_theme_options', |
857 'default' => array(), |
885 'default' => array(), |
858 ); |
886 ); |
859 |
887 |
860 if ( preg_match( $this->setting_id_patterns['sidebar_widgets'], $id, $matches ) ) { |
888 if ( preg_match( $this->setting_id_patterns['sidebar_widgets'], $id, $matches ) ) { |
861 $args['sanitize_callback'] = array( $this, 'sanitize_sidebar_widgets' ); |
889 $args['sanitize_callback'] = array( $this, 'sanitize_sidebar_widgets' ); |
862 $args['sanitize_js_callback'] = array( $this, 'sanitize_sidebar_widgets_js_instance' ); |
890 $args['sanitize_js_callback'] = array( $this, 'sanitize_sidebar_widgets_js_instance' ); |
863 $args['transport'] = current_theme_supports( 'customize-selective-refresh-widgets' ) ? 'postMessage' : 'refresh'; |
891 $args['transport'] = current_theme_supports( 'customize-selective-refresh-widgets' ) ? 'postMessage' : 'refresh'; |
864 } elseif ( preg_match( $this->setting_id_patterns['widget_instance'], $id, $matches ) ) { |
892 } elseif ( preg_match( $this->setting_id_patterns['widget_instance'], $id, $matches ) ) { |
865 $args['sanitize_callback'] = array( $this, 'sanitize_widget_instance' ); |
893 $args['sanitize_callback'] = array( $this, 'sanitize_widget_instance' ); |
866 $args['sanitize_js_callback'] = array( $this, 'sanitize_widget_js_instance' ); |
894 $args['sanitize_js_callback'] = array( $this, 'sanitize_widget_js_instance' ); |
867 $args['transport'] = $this->is_widget_selective_refreshable( $matches['id_base'] ) ? 'postMessage' : 'refresh'; |
895 $args['transport'] = $this->is_widget_selective_refreshable( $matches['id_base'] ) ? 'postMessage' : 'refresh'; |
868 } |
896 } |
869 |
897 |
870 $args = array_merge( $args, $overrides ); |
898 $args = array_merge( $args, $overrides ); |
871 |
899 |
872 /** |
900 /** |
887 * |
915 * |
888 * Used as the 'sanitize_callback' for each $sidebars_widgets setting. |
916 * Used as the 'sanitize_callback' for each $sidebars_widgets setting. |
889 * |
917 * |
890 * @since 3.9.0 |
918 * @since 3.9.0 |
891 * |
919 * |
892 * @param array $widget_ids Array of widget IDs. |
920 * @param string[] $widget_ids Array of widget IDs. |
893 * @return array Array of sanitized widget IDs. |
921 * @return string[] Array of sanitized widget IDs. |
894 */ |
922 */ |
895 public function sanitize_sidebar_widgets( $widget_ids ) { |
923 public function sanitize_sidebar_widgets( $widget_ids ) { |
896 $widget_ids = array_map( 'strval', (array) $widget_ids ); |
924 $widget_ids = array_map( 'strval', (array) $widget_ids ); |
897 $sanitized_widget_ids = array(); |
925 $sanitized_widget_ids = array(); |
898 foreach ( $widget_ids as $widget_id ) { |
926 foreach ( $widget_ids as $widget_id ) { |
899 $sanitized_widget_ids[] = preg_replace( '/[^a-z0-9_\-]/', '', $widget_id ); |
927 $sanitized_widget_ids[] = preg_replace( '/[^a-z0-9_\-]/', '', $widget_id ); |
900 } |
928 } |
901 return $sanitized_widget_ids; |
929 return $sanitized_widget_ids; |
947 'widget_name' => $widget['name'], |
975 'widget_name' => $widget['name'], |
948 '_display' => 'template', |
976 '_display' => 'template', |
949 ); |
977 ); |
950 |
978 |
951 $is_disabled = false; |
979 $is_disabled = false; |
952 $is_multi_widget = ( isset( $wp_registered_widget_controls[$widget['id']]['id_base'] ) && isset( $widget['params'][0]['number'] ) ); |
980 $is_multi_widget = ( isset( $wp_registered_widget_controls[ $widget['id'] ]['id_base'] ) && isset( $widget['params'][0]['number'] ) ); |
953 if ( $is_multi_widget ) { |
981 if ( $is_multi_widget ) { |
954 $id_base = $wp_registered_widget_controls[$widget['id']]['id_base']; |
982 $id_base = $wp_registered_widget_controls[ $widget['id'] ]['id_base']; |
955 $args['_temp_id'] = "$id_base-__i__"; |
983 $args['_temp_id'] = "$id_base-__i__"; |
956 $args['_multi_num'] = next_widget_id_number( $id_base ); |
984 $args['_multi_num'] = next_widget_id_number( $id_base ); |
957 $args['_add'] = 'multi'; |
985 $args['_add'] = 'multi'; |
958 } else { |
986 } else { |
959 $args['_add'] = 'single'; |
987 $args['_add'] = 'single'; |
962 $is_disabled = true; |
990 $is_disabled = true; |
963 } |
991 } |
964 $id_base = $widget['id']; |
992 $id_base = $widget['id']; |
965 } |
993 } |
966 |
994 |
967 $list_widget_controls_args = wp_list_widget_controls_dynamic_sidebar( array( 0 => $args, 1 => $widget['params'][0] ) ); |
995 $list_widget_controls_args = wp_list_widget_controls_dynamic_sidebar( |
968 $control_tpl = $this->get_widget_control( $list_widget_controls_args ); |
996 array( |
|
997 0 => $args, |
|
998 1 => $widget['params'][0], |
|
999 ) |
|
1000 ); |
|
1001 $control_tpl = $this->get_widget_control( $list_widget_controls_args ); |
969 |
1002 |
970 // The properties here are mapped to the Backbone Widget model. |
1003 // The properties here are mapped to the Backbone Widget model. |
971 $available_widget = array_merge( $available_widget, array( |
1004 $available_widget = array_merge( |
972 'temp_id' => isset( $args['_temp_id'] ) ? $args['_temp_id'] : null, |
1005 $available_widget, |
973 'is_multi' => $is_multi_widget, |
1006 array( |
974 'control_tpl' => $control_tpl, |
1007 'temp_id' => isset( $args['_temp_id'] ) ? $args['_temp_id'] : null, |
975 'multi_number' => ( $args['_add'] === 'multi' ) ? $args['_multi_num'] : false, |
1008 'is_multi' => $is_multi_widget, |
976 'is_disabled' => $is_disabled, |
1009 'control_tpl' => $control_tpl, |
977 'id_base' => $id_base, |
1010 'multi_number' => ( $args['_add'] === 'multi' ) ? $args['_multi_num'] : false, |
978 'transport' => $this->is_widget_selective_refreshable( $id_base ) ? 'postMessage' : 'refresh', |
1011 'is_disabled' => $is_disabled, |
979 'width' => $wp_registered_widget_controls[$widget['id']]['width'], |
1012 'id_base' => $id_base, |
980 'height' => $wp_registered_widget_controls[$widget['id']]['height'], |
1013 'transport' => $this->is_widget_selective_refreshable( $id_base ) ? 'postMessage' : 'refresh', |
981 'is_wide' => $this->is_wide_widget( $widget['id'] ), |
1014 'width' => $wp_registered_widget_controls[ $widget['id'] ]['width'], |
982 ) ); |
1015 'height' => $wp_registered_widget_controls[ $widget['id'] ]['height'], |
|
1016 'is_wide' => $this->is_wide_widget( $widget['id'] ), |
|
1017 ) |
|
1018 ); |
983 |
1019 |
984 $available_widgets[] = $available_widget; |
1020 $available_widgets[] = $available_widget; |
985 } |
1021 } |
986 |
1022 |
987 return $available_widgets; |
1023 return $available_widgets; |
1007 * |
1043 * |
1008 * @param array $args Widget control arguments. |
1044 * @param array $args Widget control arguments. |
1009 * @return string Widget control form HTML markup. |
1045 * @return string Widget control form HTML markup. |
1010 */ |
1046 */ |
1011 public function get_widget_control( $args ) { |
1047 public function get_widget_control( $args ) { |
1012 $args[0]['before_form'] = '<div class="form">'; |
1048 $args[0]['before_form'] = '<div class="form">'; |
1013 $args[0]['after_form'] = '</div><!-- .form -->'; |
1049 $args[0]['after_form'] = '</div><!-- .form -->'; |
1014 $args[0]['before_widget_content'] = '<div class="widget-content">'; |
1050 $args[0]['before_widget_content'] = '<div class="widget-content">'; |
1015 $args[0]['after_widget_content'] = '</div><!-- .widget-content -->'; |
1051 $args[0]['after_widget_content'] = '</div><!-- .widget-content -->'; |
1016 ob_start(); |
1052 ob_start(); |
1017 call_user_func_array( 'wp_widget_control', $args ); |
1053 call_user_func_array( 'wp_widget_control', $args ); |
1018 $control_tpl = ob_get_clean(); |
1054 $control_tpl = ob_get_clean(); |
1019 return $control_tpl; |
1055 return $control_tpl; |
1020 } |
1056 } |
1030 * @type string $content The contents of the widget form itself. |
1066 * @type string $content The contents of the widget form itself. |
1031 * } |
1067 * } |
1032 */ |
1068 */ |
1033 public function get_widget_control_parts( $args ) { |
1069 public function get_widget_control_parts( $args ) { |
1034 $args[0]['before_widget_content'] = '<div class="widget-content">'; |
1070 $args[0]['before_widget_content'] = '<div class="widget-content">'; |
1035 $args[0]['after_widget_content'] = '</div><!-- .widget-content -->'; |
1071 $args[0]['after_widget_content'] = '</div><!-- .widget-content -->'; |
1036 $control_markup = $this->get_widget_control( $args ); |
1072 $control_markup = $this->get_widget_control( $args ); |
1037 |
1073 |
1038 $content_start_pos = strpos( $control_markup, $args[0]['before_widget_content'] ); |
1074 $content_start_pos = strpos( $control_markup, $args[0]['before_widget_content'] ); |
1039 $content_end_pos = strrpos( $control_markup, $args[0]['after_widget_content'] ); |
1075 $content_end_pos = strrpos( $control_markup, $args[0]['after_widget_content'] ); |
1040 |
1076 |
1041 $control = substr( $control_markup, 0, $content_start_pos + strlen( $args[0]['before_widget_content'] ) ); |
1077 $control = substr( $control_markup, 0, $content_start_pos + strlen( $args[0]['before_widget_content'] ) ); |
1042 $control .= substr( $control_markup, $content_end_pos ); |
1078 $control .= substr( $control_markup, $content_end_pos ); |
1043 $content = trim( substr( |
1079 $content = trim( |
1044 $control_markup, |
1080 substr( |
1045 $content_start_pos + strlen( $args[0]['before_widget_content'] ), |
1081 $control_markup, |
1046 $content_end_pos - $content_start_pos - strlen( $args[0]['before_widget_content'] ) |
1082 $content_start_pos + strlen( $args[0]['before_widget_content'] ), |
1047 ) ); |
1083 $content_end_pos - $content_start_pos - strlen( $args[0]['before_widget_content'] ) |
|
1084 ) |
|
1085 ); |
1048 |
1086 |
1049 return compact( 'control', 'content' ); |
1087 return compact( 'control', 'content' ); |
1050 } |
1088 } |
1051 |
1089 |
1052 /** |
1090 /** |
1125 /** |
1163 /** |
1126 * Communicates the sidebars that appeared on the page at the very end of the page, |
1164 * Communicates the sidebars that appeared on the page at the very end of the page, |
1127 * and at the very end of the wp_footer, |
1165 * and at the very end of the wp_footer, |
1128 * |
1166 * |
1129 * @since 3.9.0 |
1167 * @since 3.9.0 |
1130 * |
1168 * |
1131 * @global array $wp_registered_sidebars |
1169 * @global array $wp_registered_sidebars |
1132 * @global array $wp_registered_widgets |
1170 * @global array $wp_registered_widgets |
1133 */ |
1171 */ |
1134 public function export_preview_data() { |
1172 public function export_preview_data() { |
1135 global $wp_registered_sidebars, $wp_registered_widgets; |
1173 global $wp_registered_sidebars, $wp_registered_widgets; |
1136 |
1174 |
1137 $switched_locale = switch_to_locale( get_user_locale() ); |
1175 $switched_locale = switch_to_locale( get_user_locale() ); |
1138 $l10n = array( |
1176 $l10n = array( |
1139 'widgetTooltip' => __( 'Shift-click to edit this widget.' ), |
1177 'widgetTooltip' => __( 'Shift-click to edit this widget.' ), |
1140 ); |
1178 ); |
1141 if ( $switched_locale ) { |
1179 if ( $switched_locale ) { |
1142 restore_previous_locale(); |
1180 restore_previous_locale(); |
1143 } |
1181 } |
1144 |
1182 |
1145 // Prepare Customizer settings to pass to JavaScript. |
1183 // Prepare Customizer settings to pass to JavaScript. |
1146 $settings = array( |
1184 $settings = array( |
1147 'renderedSidebars' => array_fill_keys( array_unique( $this->rendered_sidebars ), true ), |
1185 'renderedSidebars' => array_fill_keys( array_unique( $this->rendered_sidebars ), true ), |
1148 'renderedWidgets' => array_fill_keys( array_keys( $this->rendered_widgets ), true ), |
1186 'renderedWidgets' => array_fill_keys( array_keys( $this->rendered_widgets ), true ), |
1149 'registeredSidebars' => array_values( $wp_registered_sidebars ), |
1187 'registeredSidebars' => array_values( $wp_registered_sidebars ), |
1150 'registeredWidgets' => $wp_registered_widgets, |
1188 'registeredWidgets' => $wp_registered_widgets, |
1151 'l10n' => $l10n, |
1189 'l10n' => $l10n, |
1152 'selectiveRefreshableWidgets' => $this->get_selective_refreshable_widgets(), |
1190 'selectiveRefreshableWidgets' => $this->get_selective_refreshable_widgets(), |
1153 ); |
1191 ); |
1154 foreach ( $settings['registeredWidgets'] as &$registered_widget ) { |
1192 foreach ( $settings['registeredWidgets'] as &$registered_widget ) { |
1155 unset( $registered_widget['callback'] ); // may not be JSON-serializeable |
1193 unset( $registered_widget['callback'] ); // may not be JSON-serializeable |
1156 } |
1194 } |
1586 } |
1623 } |
1587 |
1624 |
1588 /** |
1625 /** |
1589 * Inject selective refresh data attributes into widget container elements. |
1626 * Inject selective refresh data attributes into widget container elements. |
1590 * |
1627 * |
|
1628 * @since 4.5.0 |
|
1629 * |
1591 * @param array $params { |
1630 * @param array $params { |
1592 * Dynamic sidebar params. |
1631 * Dynamic sidebar params. |
1593 * |
1632 * |
1594 * @type array $args Sidebar args. |
1633 * @type array $args Sidebar args. |
1595 * @type array $widget_args Widget args. |
1634 * @type array $widget_args Widget args. |
1596 * } |
1635 * } |
1597 * @see WP_Customize_Nav_Menus_Partial_Refresh::filter_wp_nav_menu_args() |
1636 * @see WP_Customize_Nav_Menus::filter_wp_nav_menu_args() |
1598 * |
1637 * |
1599 * @return array Params. |
1638 * @return array Params. |
1600 */ |
1639 */ |
1601 public function filter_dynamic_sidebar_params( $params ) { |
1640 public function filter_dynamic_sidebar_params( $params ) { |
1602 $sidebar_args = array_merge( |
1641 $sidebar_args = array_merge( |
1603 array( |
1642 array( |
1604 'before_widget' => '', |
1643 'before_widget' => '', |
1605 'after_widget' => '', |
1644 'after_widget' => '', |
1606 ), |
1645 ), |
1607 $params[0] |
1646 $params[0] |
1608 ); |
1647 ); |
1609 |
1648 |
1610 // Skip widgets not in a registered sidebar or ones which lack a proper wrapper element to attach the data-* attributes to. |
1649 // Skip widgets not in a registered sidebar or ones which lack a proper wrapper element to attach the data-* attributes to. |
1611 $matches = array(); |
1650 $matches = array(); |
1612 $is_valid = ( |
1651 $is_valid = ( |
1613 isset( $sidebar_args['id'] ) |
1652 isset( $sidebar_args['id'] ) |
1614 && |
1653 && |
1615 is_registered_sidebar( $sidebar_args['id'] ) |
1654 is_registered_sidebar( $sidebar_args['id'] ) |
1616 && |
1655 && |
1626 $context = array( |
1665 $context = array( |
1627 'sidebar_id' => $sidebar_args['id'], |
1666 'sidebar_id' => $sidebar_args['id'], |
1628 ); |
1667 ); |
1629 if ( isset( $this->context_sidebar_instance_number ) ) { |
1668 if ( isset( $this->context_sidebar_instance_number ) ) { |
1630 $context['sidebar_instance_number'] = $this->context_sidebar_instance_number; |
1669 $context['sidebar_instance_number'] = $this->context_sidebar_instance_number; |
1631 } else if ( isset( $sidebar_args['id'] ) && isset( $this->sidebar_instance_count[ $sidebar_args['id'] ] ) ) { |
1670 } elseif ( isset( $sidebar_args['id'] ) && isset( $this->sidebar_instance_count[ $sidebar_args['id'] ] ) ) { |
1632 $context['sidebar_instance_number'] = $this->sidebar_instance_count[ $sidebar_args['id'] ]; |
1671 $context['sidebar_instance_number'] = $this->sidebar_instance_count[ $sidebar_args['id'] ]; |
1633 } |
1672 } |
1634 |
1673 |
1635 $attributes = sprintf( ' data-customize-partial-id="%s"', esc_attr( 'widget[' . $sidebar_args['widget_id'] . ']' ) ); |
1674 $attributes = sprintf( ' data-customize-partial-id="%s"', esc_attr( 'widget[' . $sidebar_args['widget_id'] . ']' ) ); |
1636 $attributes .= ' data-customize-partial-type="widget"'; |
1675 $attributes .= ' data-customize-partial-type="widget"'; |
1637 $attributes .= sprintf( ' data-customize-partial-placement-context="%s"', esc_attr( wp_json_encode( $context ) ) ); |
1676 $attributes .= sprintf( ' data-customize-partial-placement-context="%s"', esc_attr( wp_json_encode( $context ) ) ); |
1638 $attributes .= sprintf( ' data-customize-widget-id="%s"', esc_attr( $sidebar_args['widget_id'] ) ); |
1677 $attributes .= sprintf( ' data-customize-widget-id="%s"', esc_attr( $sidebar_args['widget_id'] ) ); |
1639 $sidebar_args['before_widget'] = preg_replace( '#^(<\w+)#', '$1 ' . $attributes, $sidebar_args['before_widget'] ); |
1678 $sidebar_args['before_widget'] = preg_replace( '#^(<\w+)#', '$1 ' . $attributes, $sidebar_args['before_widget'] ); |
1640 |
1679 |
1641 $params[0] = $sidebar_args; |
1680 $params[0] = $sidebar_args; |
1642 return $params; |
1681 return $params; |
1643 } |
1682 } |
1668 if ( ! isset( $allowed_html[ $tag_name ] ) ) { |
1707 if ( ! isset( $allowed_html[ $tag_name ] ) ) { |
1669 $allowed_html[ $tag_name ] = array(); |
1708 $allowed_html[ $tag_name ] = array(); |
1670 } |
1709 } |
1671 $allowed_html[ $tag_name ] = array_merge( |
1710 $allowed_html[ $tag_name ] = array_merge( |
1672 $allowed_html[ $tag_name ], |
1711 $allowed_html[ $tag_name ], |
1673 array_fill_keys( array( |
1712 array_fill_keys( |
1674 'data-customize-partial-id', |
1713 array( |
1675 'data-customize-partial-type', |
1714 'data-customize-partial-id', |
1676 'data-customize-partial-placement-context', |
1715 'data-customize-partial-type', |
1677 'data-customize-partial-widget-id', |
1716 'data-customize-partial-placement-context', |
1678 'data-customize-partial-options', |
1717 'data-customize-partial-widget-id', |
1679 ), true ) |
1718 'data-customize-partial-options', |
|
1719 ), |
|
1720 true |
|
1721 ) |
1680 ); |
1722 ); |
1681 } |
1723 } |
1682 return $allowed_html; |
1724 return $allowed_html; |
1683 } |
1725 } |
1684 |
1726 |