diff --git a/amp.php b/amp.php index 449a814ddc9..e84f62c5f5f 100644 --- a/amp.php +++ b/amp.php @@ -71,6 +71,7 @@ function amp_after_setup_theme() { } add_action( 'init', 'amp_init' ); + add_action( 'widgets_init', 'AMP_Theme_Support::register_widgets' ); add_action( 'admin_init', 'AMP_Options_Manager::register_settings' ); add_filter( 'amp_post_template_analytics', 'amp_add_custom_analytics' ); add_action( 'wp_loaded', 'amp_post_meta_box' ); diff --git a/bin/add-test-widgets-to-sidebar.php b/bin/add-test-widgets-to-sidebar.php index b84313a6e29..bd3a9e30d61 100644 --- a/bin/add-test-widgets-to-sidebar.php +++ b/bin/add-test-widgets-to-sidebar.php @@ -385,7 +385,15 @@ function amp_create_widget( $widget ) { $title = str_replace( '-', ' ', $title ); $settings['title'] = sprintf( 'Test %s Widget', ucwords( $title ) ); } - $widgets[] = $settings; + + $number = 1; + unset( $widgets['_multiwidget'] ); + if ( ! empty( $widgets ) ) { + $number = max( array_keys( $widgets ) ); + $number = max( 1, $number ); + } + $number++; + $widgets[ $number ] = $settings; update_option( $option_key, $widgets ); } diff --git a/includes/class-amp-autoloader.php b/includes/class-amp-autoloader.php index 1376d157e48..37264085486 100644 --- a/includes/class-amp-autoloader.php +++ b/includes/class-amp-autoloader.php @@ -79,6 +79,9 @@ class AMP_Autoloader { 'AMP_Image_Dimension_Extractor' => 'includes/utils/class-amp-image-dimension-extractor', 'AMP_String_Utils' => 'includes/utils/class-amp-string-utils', 'AMP_WP_Utils' => 'includes/utils/class-amp-wp-utils', + 'AMP_Widget_Archives' => 'includes/widgets/class-amp-widget-archives', + 'AMP_Widget_Categories' => 'includes/widgets/class-amp-widget-categories', + 'AMP_Widget_Recent_Comments' => 'includes/widgets/class-amp-widget-recent-comments', 'WPCOM_AMP_Polldaddy_Embed' => 'wpcom/class-amp-polldaddy-embed', 'AMP_Test_Stub_Sanitizer' => 'tests/stubs', 'AMP_Test_World_Sanitizer' => 'tests/stubs', diff --git a/includes/class-amp-theme-support.php b/includes/class-amp-theme-support.php index f7401cd9700..c85bdd9f941 100644 --- a/includes/class-amp-theme-support.php +++ b/includes/class-amp-theme-support.php @@ -196,6 +196,29 @@ public static function register_hooks() { // @todo Add character conversion. } + /** + * Register/override widgets. + * + * @global WP_Widget_Factory + * @return void + */ + public static function register_widgets() { + global $wp_widget_factory; + foreach ( $wp_widget_factory->widgets as $registered_widget ) { + $registered_widget_class_name = get_class( $registered_widget ); + if ( ! preg_match( '/^WP_Widget_(.+)$/', $registered_widget_class_name, $matches ) ) { + continue; + } + $amp_class_name = 'AMP_Widget_' . $matches[1]; + if ( ! class_exists( $amp_class_name ) || is_a( $amp_class_name, $registered_widget_class_name ) ) { + continue; + } + + unregister_widget( $registered_widget_class_name ); + register_widget( $amp_class_name ); + } + } + /** * Override $wp_styles as AMP_WP_Styles, ideally before first instantiated as WP_Styles. * @@ -463,7 +486,7 @@ public static function get_amp_component_scripts() { * * @since 0.7 * - * @param string $amp_scripts AMP Component scripts, mapping component names to component source URLs. + * @param array $amp_scripts AMP Component scripts, mapping component names to component source URLs. */ $amp_scripts = apply_filters( 'amp_component_scripts', $amp_scripts ); diff --git a/includes/widgets/class-amp-widget-archives.php b/includes/widgets/class-amp-widget-archives.php new file mode 100644 index 00000000000..0bad7cc33ea --- /dev/null +++ b/includes/widgets/class-amp-widget-archives.php @@ -0,0 +1,103 @@ +. + * More escaping. + * The dropdown is now filtered with 'wp_dropdown_cats.' + * This enables adding an 'on' attribute, with the id of the form. + * So changing the dropdown value will redirect to the category page, with valid AMP. + * + * @since 0.7.0 + * + * @param array $args Widget display data. + * @param array $instance Data for widget. + * @return void. + */ + public function widget( $args, $instance ) { + if ( ! is_amp_endpoint() ) { + parent::widget( $args, $instance ); + return; + } + + $c = ! empty( $instance['count'] ) ? '1' : '0'; + $d = ! empty( $instance['dropdown'] ) ? '1' : '0'; + + /** This filter is documented in wp-includes/widgets/class-wp-widget-pages.php */ + $title = apply_filters( 'widget_title', empty( $instance['title'] ) ? __( 'Archives', 'default' ) : $instance['title'], $instance, $this->id_base ); + echo wp_kses_post( $args['before_widget'] ); + if ( $title ) : + echo wp_kses_post( $args['before_title'] . $title . $args['after_title'] ); + endif; + + if ( $d ) : + $dropdown_id = "{$this->id_base}-dropdown-{$this->number}"; + ?> +
+ + +
+ + + . + * And the dropdown is now filtered with 'wp_dropdown_cats.' + * This enables adding an 'on' attribute, with the id of the form. + * So changing the dropdown value will redirect to the category page, with valid AMP. + * + * @since 0.7.0 + * + * @param array $args Widget display data. + * @param array $instance Data for widget. + * @return void + */ + public function widget( $args, $instance ) { + if ( ! is_amp_endpoint() ) { + parent::widget( $args, $instance ); + return; + } + + static $first_dropdown = true; + $title = ! empty( $instance['title'] ) ? $instance['title'] : __( 'Categories', 'default' ); + /** This filter is documented in wp-includes/widgets/class-wp-widget-pages.php */ + $title = apply_filters( 'widget_title', $title, $instance, $this->id_base ); + $c = ! empty( $instance['count'] ) ? '1' : '0'; + $h = ! empty( $instance['hierarchical'] ) ? '1' : '0'; + $d = ! empty( $instance['dropdown'] ) ? '1' : '0'; + echo wp_kses_post( $args['before_widget'] ); + if ( $title ) { + echo wp_kses_post( $args['before_title'] . $title . $args['after_title'] ); + } + $cat_args = array( + 'orderby' => 'name', + 'show_count' => $c, + 'hierarchical' => $h, + ); + if ( $d ) : + $form_id = sprintf( 'widget-categories-dropdown-%d', $this->number ); + printf( '
', esc_url( home_url() ), esc_attr( $form_id ) ); + $dropdown_id = ( $first_dropdown ) ? 'cat' : "{$this->id_base}-dropdown-{$this->number}"; + $first_dropdown = false; + echo ''; + $cat_args['show_option_none'] = __( 'Select Category', 'default' ); + $cat_args['id'] = $dropdown_id; + + $dropdown = wp_dropdown_categories( array_merge( + /** This filter is documented in wp-includes/widgets/class-wp-widget-categories.php */ + apply_filters( 'widget_categories_dropdown_args', $cat_args, $instance ), + array( 'echo' => false ) + ) ); + $dropdown = preg_replace( + '/(?<='; + else : + ?> + + - + diff --git a/tests/test-class-amp-theme-support.php b/tests/test-class-amp-theme-support.php index 0b15e7f1165..da03d44345b 100644 --- a/tests/test-class-amp-theme-support.php +++ b/tests/test-class-amp-theme-support.php @@ -68,6 +68,23 @@ public function test_is_paired_available() { $this->assertFalse( AMP_Theme_Support::is_paired_available() ); } + /** + * Test register_widgets(). + * + * @covers AMP_Theme_Support::register_widgets() + * @global WP_Widget_Factory $wp_widget_factory + */ + public function test_register_widgets() { + global $wp_widget_factory; + remove_all_actions( 'widgets_init' ); + $wp_widget_factory->widgets = array(); + wp_widgets_init(); + AMP_Theme_Support::register_widgets(); + + $this->assertArrayNotHasKey( 'WP_Widget_Categories', $wp_widget_factory->widgets ); + $this->assertArrayHasKey( 'AMP_Widget_Categories', $wp_widget_factory->widgets ); + } + /** * Test finish_output_buffering. * diff --git a/tests/test-class-amp-widget-archives.php b/tests/test-class-amp-widget-archives.php new file mode 100644 index 00000000000..bef6d8639ee --- /dev/null +++ b/tests/test-class-amp-widget-archives.php @@ -0,0 +1,73 @@ +widget = new AMP_Widget_Archives(); + } + + /** + * Test construct(). + * + * @see AMP_Widget_Archives::__construct(). + */ + public function test_construct() { + $this->assertEquals( 'AMP_Widget_Archives', get_class( $this->widget ) ); + $this->assertEquals( 'archives', $this->widget->id_base ); + $this->assertEquals( 'Archives', $this->widget->name ); + $this->assertEquals( 'widget_archive', $this->widget->widget_options['classname'] ); + $this->assertEquals( true, $this->widget->widget_options['customize_selective_refresh'] ); + $this->assertEquals( 'A monthly archive of your site’s Posts.', $this->widget->widget_options['description'] ); + } + + /** + * Test widget(). + * + * @see AMP_Widget_Archives::widget(). + */ + public function test_widget() { + $arguments = array( + 'before_widget' => '
', + 'after_widget' => '
', + 'before_title' => '

', + 'after_title' => '

', + ); + $instance = array( + 'title' => 'Test Archives Widget', + 'dropdown' => 1, + ); + ob_start(); + $this->widget->widget( $arguments, $instance ); + $output = ob_get_clean(); + + $this->assertContains( 'on="change:AMP.navigateTo(url=event.value)"', $output ); + $this->assertNotContains( 'onchange=', $output ); + } + +} diff --git a/tests/test-class-amp-widget-categories.php b/tests/test-class-amp-widget-categories.php new file mode 100644 index 00000000000..b79bc42dea2 --- /dev/null +++ b/tests/test-class-amp-widget-categories.php @@ -0,0 +1,73 @@ +widget = new AMP_Widget_Categories(); + } + + /** + * Test construct(). + * + * @covers AMP_Widget_Categories::__construct() + */ + public function test_construct() { + $this->assertEquals( 'AMP_Widget_Categories', get_class( $this->widget ) ); + $this->assertEquals( 'categories', $this->widget->id_base ); + $this->assertEquals( 'Categories', $this->widget->name ); + $this->assertEquals( 'widget_categories', $this->widget->widget_options['classname'] ); + $this->assertEquals( true, $this->widget->widget_options['customize_selective_refresh'] ); + $this->assertEquals( 'A list or dropdown of categories.', $this->widget->widget_options['description'] ); + } + + /** + * Test widget(). + * + * @covers AMP_Widget_Categories::widget() + */ + public function test_widget() { + $arguments = array( + 'before_widget' => '
', + 'after_widget' => '
', + 'before_title' => '

', + 'after_title' => '

', + ); + $instance = array( + 'title' => 'Test Categories Widget', + 'dropdown' => 1, + ); + ob_start(); + $this->widget->widget( $arguments, $instance ); + $output = ob_get_clean(); + + $this->assertContains( 'on="change:', $output ); + $this->assertNotContains( '