-
Notifications
You must be signed in to change notification settings - Fork 383
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Issue #864: Native WordPress widget support, including subclasses #870
Changes from 1 commit
3faab47
be58d02
436722d
44287d8
c7268bf
16caae9
9bd0815
fb9b451
cbdbd4a
6ee75ee
e703850
a355243
99dd862
74d727b
fc48208
da6cee6
dc3f5b4
28b5cdd
a0b9848
6053f9a
e0456e1
40a73c6
62a924f
c28578c
6f82cc7
2081ab0
0a78830
0e26178
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
<?php | ||
/** | ||
* Class AMP_Widget_Archives | ||
* | ||
* @package AMP | ||
*/ | ||
|
||
/** | ||
* Class AMP_Widget_Archives | ||
* | ||
* @package AMP | ||
*/ | ||
class AMP_Widget_Archives extends WP_Widget_Archives { | ||
|
||
/** | ||
* Echoes the markup of the widget. | ||
* | ||
* @todo filter $output, to strip the onchange attribute | ||
* @see https://github.com/Automattic/amp-wp/issues/864 | ||
* @param array $args Widget display data. | ||
* @param array $instance Data for widget. | ||
* @return void. | ||
*/ | ||
public function widget( $args, $instance ) { | ||
ob_start(); | ||
parent::widget( $args, $instance ); | ||
$output = ob_get_clean(); | ||
echo $output; // WPCS: XSS ok. | ||
} | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
<?php | ||
/** | ||
* Class AMP_Widget_Categories | ||
* | ||
* @package AMP | ||
*/ | ||
|
||
/** | ||
* Class AMP_Widget_Categories | ||
* | ||
* @package AMP | ||
*/ | ||
class AMP_Widget_Categories extends WP_Widget_Categories { | ||
|
||
/** | ||
* Echoes the markup of the widget. | ||
* | ||
* @todo filter $output, to strip the <script> tag. | ||
* @see https://github.com/Automattic/amp-wp/issues/864 | ||
* @param array $args Widget display data. | ||
* @param array $instance Data for widget. | ||
* @return void. | ||
*/ | ||
public function widget( $args, $instance ) { | ||
ob_start(); | ||
parent::widget( $args, $instance ); | ||
$output = ob_get_clean(); | ||
echo $output; // WPCS: XSS ok. | ||
} | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
<?php | ||
/** | ||
* Register widgets, and add actions. | ||
* | ||
* @package AMP | ||
*/ | ||
|
||
/** | ||
* Register the widgets. | ||
*/ | ||
class AMP_Widgets { | ||
|
||
/** | ||
* Add the actions. | ||
* | ||
* @return void. | ||
*/ | ||
public function init() { | ||
add_action( 'widgets_init', array( $this, 'register_widgets' ) ); | ||
add_action( 'show_recent_comments_widget_style', '__return_false' ); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Actually There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hi @westonruter,
I initially used
But wouldn't this be enough to prevent outputting the styling:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The subclass looks good. |
||
add_action( 'wp_footer', array( $this, 'dequeue_scripts' ) ); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Per below, this shouldn't be necessary. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks, this commit deletes this |
||
} | ||
|
||
/** | ||
* Add the filters. | ||
* | ||
* @return void. | ||
*/ | ||
public function register_widgets() { | ||
$widgets = self::get_widgets(); | ||
foreach ( $widgets as $native_wp_widget => $amp_widget ) { | ||
unregister_widget( $native_wp_widget ); | ||
register_widget( $amp_widget ); | ||
} | ||
} | ||
|
||
/** | ||
* Get the widgets to unregister and register. | ||
* | ||
* @return array $widgets An associative array, with the previous WP widget mapped to the new AMP widget. | ||
*/ | ||
public function get_widgets() { | ||
return array( | ||
'WP_Widget_Archives' => 'AMP_Widget_Archives', | ||
'WP_Widget_Categories' => 'AMP_Widget_Categories', | ||
); | ||
} | ||
|
||
/** | ||
* Dequeue widget scripts and styles, which aren't allowed in AMP. | ||
* | ||
* Uses the action 'wp_footer' in order to prevent | ||
* 'wp_print_footer_scripts' from outputting the scripts. | ||
* | ||
* @return void. | ||
*/ | ||
public function dequeue_scripts() { | ||
wp_dequeue_script( 'wp-mediaelement' ); | ||
wp_dequeue_script( 'mediaelement-vimeo' ); | ||
wp_dequeue_style( 'wp-mediaelement' ); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think this is necessary. The plugin is already unhooking There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks, @westonruter. This commit deletes |
||
} | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
<?php | ||
/** | ||
* Tests for class AMP_Widget_Archives. | ||
* | ||
* @package AMP | ||
*/ | ||
|
||
/** | ||
* Tests for class AMP_Widget_Archives. | ||
* | ||
* @package WidgetLiveEditor | ||
*/ | ||
class Test_AMP_Widget_Archives extends WP_UnitTestCase { | ||
/** | ||
* Instance of the widget. | ||
* | ||
* @var object | ||
*/ | ||
public $instance; | ||
|
||
/** | ||
* Setup. | ||
* | ||
* @inheritdoc | ||
*/ | ||
public function setUp() { | ||
parent::setUp(); | ||
$amp_widgets = new AMP_Widgets(); | ||
$amp_widgets->register_widgets(); | ||
$this->instance = new AMP_Widget_Archives(); | ||
} | ||
|
||
/** | ||
* Test construct(). | ||
* | ||
* @see AMP_Widget_Archives::__construct(). | ||
*/ | ||
public function test_construct() { | ||
global $wp_widget_factory; | ||
$amp_archives = $wp_widget_factory->widgets['AMP_Widget_Archives']; | ||
$this->assertEquals( 'AMP_Widget_Archives', get_class( $amp_archives ) ); | ||
$this->assertEquals( 'archives', $amp_archives->id_base ); | ||
$this->assertEquals( 'Archives', $amp_archives->name ); | ||
$this->assertEquals( 'widget_archive', $amp_archives->widget_options['classname'] ); | ||
$this->assertEquals( true, $amp_archives->widget_options['customize_selective_refresh'] ); | ||
$this->assertEquals( 'A monthly archive of your site’s Posts.', $amp_archives->widget_options['description'] ); | ||
} | ||
|
||
/** | ||
* Test widget(). | ||
* | ||
* @see AMP_Widget_Archives::widget(). | ||
*/ | ||
public function test_widget() { | ||
$arguments = array( | ||
'before_widget' => '<div>', | ||
'after_widget' => '</div>', | ||
'before_title' => '<h2>', | ||
'after_title' => '</h2>', | ||
); | ||
$instance = array( | ||
'title' => 'Test Archives Widget', | ||
'dropdown' => 1, | ||
); | ||
ob_start(); | ||
$this->instance->widget( $arguments, $instance ); | ||
$output = ob_get_clean(); | ||
|
||
$this->assertFalse( strpos( $output, 'onchange=' ) ); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
<?php | ||
/** | ||
* Tests for class AMP_Widget_Categories. | ||
* | ||
* @package AMP | ||
*/ | ||
|
||
/** | ||
* Tests for class AMP_Widget_Categories. | ||
* | ||
* @package WidgetLiveEditor | ||
*/ | ||
class Test_AMP_Widget_Categories extends WP_UnitTestCase { | ||
/** | ||
* Instance of the widget. | ||
* | ||
* @var object | ||
*/ | ||
public $instance; | ||
|
||
/** | ||
* Setup. | ||
* | ||
* @inheritdoc | ||
*/ | ||
public function setUp() { | ||
parent::setUp(); | ||
$amp_widgets = new AMP_Widgets(); | ||
$amp_widgets->register_widgets(); | ||
$this->instance = new AMP_Widget_Categories(); | ||
} | ||
|
||
/** | ||
* Test construct(). | ||
* | ||
* @see AMP_Widget_Categories::__construct(). | ||
*/ | ||
public function test_construct() { | ||
global $wp_widget_factory; | ||
$amp_categories = $wp_widget_factory->widgets['AMP_Widget_Categories']; | ||
$this->assertEquals( 'AMP_Widget_Categories', get_class( $amp_categories ) ); | ||
$this->assertEquals( 'categories', $amp_categories->id_base ); | ||
$this->assertEquals( 'Categories', $amp_categories->name ); | ||
$this->assertEquals( 'widget_categories', $amp_categories->widget_options['classname'] ); | ||
$this->assertEquals( true, $amp_categories->widget_options['customize_selective_refresh'] ); | ||
$this->assertEquals( 'A list or dropdown of categories.', $amp_categories->widget_options['description'] ); | ||
} | ||
|
||
/** | ||
* Test widget(). | ||
* | ||
* @see AMP_Widget_Categories::widget(). | ||
*/ | ||
public function test_widget() { | ||
$arguments = array( | ||
'before_widget' => '<div>', | ||
'after_widget' => '</div>', | ||
'before_title' => '<h2>', | ||
'after_title' => '</h2>', | ||
); | ||
$instance = array( | ||
'title' => 'Test Categories Widget', | ||
'dropdown' => 1, | ||
); | ||
ob_start(); | ||
$this->instance->widget( $arguments, $instance ); | ||
$output = ob_get_clean(); | ||
|
||
$this->assertFalse( strpos( $output, '<script type=' ) ); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
<?php | ||
/** | ||
* Tests for class AMP_Widgets. | ||
* | ||
* @package AMP | ||
*/ | ||
|
||
/** | ||
* Tests for class AMP_Widgets. | ||
*/ | ||
class Test_AMP_Widgets extends WP_UnitTestCase { | ||
/** | ||
* Instance of AMP_Widgets. | ||
* | ||
* @var object | ||
*/ | ||
public $instance; | ||
|
||
/** | ||
* Setup. | ||
* | ||
* @inheritdoc | ||
*/ | ||
public function setUp() { | ||
parent::setUp(); | ||
$this->instance = new AMP_Widgets(); | ||
} | ||
|
||
/** | ||
* Test init(). | ||
* | ||
* @see AMP_Widgets::init(). | ||
*/ | ||
public function test_init() { | ||
$this->instance->init(); | ||
$this->assertEquals( 10, has_filter( 'widgets_init', array( $this->instance, 'register_widgets' ) ) ); | ||
$this->assertEquals( 10, has_filter( 'show_recent_comments_widget_style', '__return_false' ) ); | ||
$this->assertEquals( 10, has_action( 'wp_footer', array( $this->instance, 'dequeue_scripts' ) ) ); | ||
} | ||
|
||
/** | ||
* Test register_widgets(). | ||
* | ||
* @covers AMP_Widgets::get_widgets(). | ||
* @see AMP_Widgets::register_widgets(). | ||
*/ | ||
public function test_register_widgets() { | ||
global $wp_widget_factory; | ||
$this->instance->register_widgets(); | ||
$this->assertFalse( isset( $wp_widget_factory->widgets['WP_Widget_Archives'] ) ); | ||
$this->assertEquals( 'AMP_Widget_Archives', get_class( $wp_widget_factory->widgets['AMP_Widget_Archives'] ) ); | ||
$this->assertFalse( isset( $wp_widget_factory->widgets['WP_Widget_Categories'] ) ); | ||
$this->assertEquals( 'AMP_Widget_Categories', get_class( $wp_widget_factory->widgets['AMP_Widget_Categories'] ) ); | ||
} | ||
|
||
/** | ||
* Test dequeue_scripts(). | ||
* | ||
* @see AMP_Widgets::dequeue_scripts(). | ||
*/ | ||
public function test_dequeue_scripts() { | ||
$this->assertFalse( wp_script_is( 'wp-mediaelement' ) ); | ||
$this->assertFalse( wp_script_is( 'mediaelement-vimeo' ) ); | ||
$this->assertFalse( wp_style_is( 'wp-mediaelement' ) ); | ||
} | ||
|
||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@kienstra Here we need to handle the dropdown behavior. I think this should strip out the
script
tag here via regex:And then what it needs to do is inject two additional things:
id
attribute to the<form>
with a random value, or an auto-incremented one:widget-categories-dropdown-%d
, e.g.widget-categories-dropdown-123
on
attribute onto the<select>
element likeon="change:widget-categories-dropdown-123.submit"
.Reference: https://www.ampproject.org/docs/reference/components/amp-form#input-events
👉 N.B. WordPress 4.9 first introduced the
<form>
element here: WordPress/wordpress-develop@b7c70caSo if no
<form>
is present, then it should wrap the<select>
with one.On second thought, instead of output-buffering the output and modifying it, just copy the existing logic from
\WP_Widget_Categories::widget()
in WP 4.9 and modify it here to be valid AMP.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Applied Suggestion
Thanks For The Explanation
Hi @westonruter,
Thanks for your great explanation of how to make the dropdown work with AMP. How does this commit look?
It mainly copies
\WP_Widget_Categories::widget()
from 4.9, and makes the changes you suggested.It's worked locally, with valid AMP. There are still Travis errors that I need to fix, not directly related to the commit.