Skip to content

Commit

Permalink
Merge pull request #870 from Automattic/add/864-native-widget-support
Browse files Browse the repository at this point in the history
Add native WordPress widget support
  • Loading branch information
westonruter authored Jan 24, 2018
2 parents b8af86a + 0e26178 commit 070930a
Show file tree
Hide file tree
Showing 12 changed files with 502 additions and 3 deletions.
1 change: 1 addition & 0 deletions amp.php
Original file line number Diff line number Diff line change
Expand Up @@ -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' );
Expand Down
10 changes: 9 additions & 1 deletion bin/add-test-widgets-to-sidebar.php
Original file line number Diff line number Diff line change
Expand Up @@ -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 );
}

Expand Down
3 changes: 3 additions & 0 deletions includes/class-amp-autoloader.php
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down
25 changes: 24 additions & 1 deletion includes/class-amp-theme-support.php
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*
Expand Down Expand Up @@ -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 );

Expand Down
103 changes: 103 additions & 0 deletions includes/widgets/class-amp-widget-archives.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
<?php
/**
* Class AMP_Widget_Archives
*
* @since 0.7.0
* @package AMP
*/

/**
* Class AMP_Widget_Archives
*
* @since 0.7.0
* @package AMP
*/
class AMP_Widget_Archives extends WP_Widget_Archives {

/**
* Echoes the markup of the widget.
*
* Mainly copied from WP_Widget_Archives::widget()
* Changes include:
* An id for the <form>.
* 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}";
?>
<form action="<?php echo esc_url( home_url() ); ?>" method="get" target="_top">
<label class="screen-reader-text" for="<?php echo esc_attr( $dropdown_id ); ?>"><?php echo esc_html( $title ); ?></label>
<select id="<?php echo esc_attr( $dropdown_id ); ?>" name="archive-dropdown" on="change:AMP.navigateTo(url=event.value)">
<?php

/** This filter is documented in wp-includes/widgets/class-wp-widget-archives.php */
$dropdown_args = apply_filters( 'widget_archives_dropdown_args', array(
'type' => 'monthly',
'format' => 'option',
'show_post_count' => $c,
) );

switch ( $dropdown_args['type'] ) {
case 'yearly':
$label = __( 'Select Year', 'default' );
break;
case 'monthly':
$label = __( 'Select Month', 'default' );
break;
case 'daily':
$label = __( 'Select Day', 'default' );
break;
case 'weekly':
$label = __( 'Select Week', 'default' );
break;
default:
$label = __( 'Select Post', 'default' );
break;
}
?>
<option value=""><?php echo esc_attr( $label ); ?></option>
<?php wp_get_archives( $dropdown_args ); ?>
</select>
</form>
<?php else : ?>
<ul>
<?php

/** This filter is documented in wp-includes/widgets/class-wp-widget-archives.php */
wp_get_archives( apply_filters( 'widget_archives_args', array(
'type' => 'monthly',
'show_post_count' => $c,
) ) );
?>
</ul>
<?php
endif;
echo wp_kses_post( $args['after_widget'] );
}

}
91 changes: 91 additions & 0 deletions includes/widgets/class-amp-widget-categories.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
<?php
/**
* Class AMP_Widget_Categories
*
* @since 0.7.0
* @package AMP
*/

/**
* Class AMP_Widget_Categories
*
* @since 0.7.0
* @package AMP
*/
class AMP_Widget_Categories extends WP_Widget_Categories {

/**
* Echoes the markup of the widget.
*
* Mainly copied from WP_Widget_Categories::widget()
* There's now an id for the <form>.
* 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( '<form action="%s" method="get" target="_top" id="%s">', esc_url( home_url() ), esc_attr( $form_id ) );
$dropdown_id = ( $first_dropdown ) ? 'cat' : "{$this->id_base}-dropdown-{$this->number}";
$first_dropdown = false;
echo '<label class="screen-reader-text" for="' . esc_attr( $dropdown_id ) . '">' . esc_html( $title ) . '</label>';
$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(
'/(?<=<select\b)/',
sprintf( '<select on="change:%s.submit"', esc_attr( $form_id ) ),
$dropdown,
1
);
echo $dropdown; // WPCS: XSS OK.
echo '</form>';
else :
?>
<ul>
<?php
$cat_args['title_li'] = '';

/** This filter is documented in wp-includes/widgets/class-wp-widget-categories.php */
wp_list_categories( apply_filters( 'widget_categories_args', $cat_args, $instance ) );
?>
</ul>
<?php
endif;
echo wp_kses_post( $args['after_widget'] );
}

}
38 changes: 38 additions & 0 deletions includes/widgets/class-amp-widget-recent-comments.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?php
/**
* Class AMP_Widget_Recent_Comments
*
* @since 0.7.0
* @package AMP
*/

/**
* Class AMP_Widget_Recent_Comments
*
* @since 0.7.0
* @package AMP
*/
class AMP_Widget_Recent_Comments extends WP_Widget_Recent_Comments {

/**
* Instantiates the widget, and prevents inline styling.
*
* @since 0.7.0
*/
public function __construct() {
parent::__construct();
add_filter( 'wp_head', array( $this, 'remove_head_style_in_amp' ), 0 );
}

/**
* Prevent recent comments widget style from printing in AMP,
*
* @since 0.7.0
*/
public function remove_head_style_in_amp() {
if ( is_amp_endpoint() ) {
add_filter( 'show_recent_comments_widget_style', '__return_false' );
}
}

}
2 changes: 1 addition & 1 deletion phpcs.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

<rule ref="WordPress.WP.I18n">
<properties>
<property name="text_domain" value="amp" />
<property name="text_domain" value="amp,default" />
</properties>
</rule>

Expand Down
17 changes: 17 additions & 0 deletions tests/test-class-amp-theme-support.php
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*
Expand Down
Loading

0 comments on commit 070930a

Please sign in to comment.