<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[32602] trunk: Add support for `WP_Widget::get_settings()` returning `ArrayIterator`/`ArrayObject` instances.</title>
</head>
<body>
<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; }
#msg dl a { font-weight: bold}
#msg dl a:link { color:#fc3; }
#msg dl a:active { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta" style="font-size: 105%">
<dt style="float: left; width: 6em; font-weight: bold">Revision</dt> <dd><a style="font-weight: bold" href="https://core.trac.wordpress.org/changeset/32602">32602</a><script type="application/ld+json">{"@context":"http://schema.org","@type":"EmailMessage","description":"Review this Commit","action":{"@type":"ViewAction","url":"https://core.trac.wordpress.org/changeset/32602","name":"Review Commit"}}</script></dd>
<dt style="float: left; width: 6em; font-weight: bold">Author</dt> <dd>westonruter</dd>
<dt style="float: left; width: 6em; font-weight: bold">Date</dt> <dd>2015-05-26 16:50:03 +0000 (Tue, 26 May 2015)</dd>
</dl>
<pre style='padding-left: 1em; margin: 2em 0; border-left: 2px solid #ccc; line-height: 1.25; font-size: 105%; font-family: sans-serif'>Add support for `WP_Widget::get_settings()` returning `ArrayIterator`/`ArrayObject` instances.
Plugins can use `pre_option_widget_{$id_base}` filters to return `ArrayIterator`/`ArrayObject` instances instead of primitive arrays. This makes possible for widget instance data to be drawn from somewhere else than `wp_options`, such as a custom post type.
Add unit tests for widgets.
Fixes <a href="https://core.trac.wordpress.org/ticket/32474">#32474</a>.</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#trunksrcwpincludeswidgetsphp">trunk/src/wp-includes/widgets.php</a></li>
<li><a href="#trunktestsphpunittestswidgetsphp">trunk/tests/phpunit/tests/widgets.php</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunksrcwpincludeswidgetsphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/widgets.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/widgets.php 2015-05-25 22:08:08 UTC (rev 32601)
+++ trunk/src/wp-includes/widgets.php 2015-05-26 16:50:03 UTC (rev 32602)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -214,20 +214,24 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $settings = $this->get_settings();
</span><span class="cx" style="display: block; padding: 0 10px"> $empty = true;
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if ( is_array($settings) ) {
- foreach ( array_keys($settings) as $number ) {
- if ( is_numeric($number) ) {
- $this->_set($number);
- $this->_register_one($number);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // When $settings is an array-like object, get an intrinsic array for use with array_keys().
+ if ( $settings instanceof ArrayObject || $settings instanceof ArrayIterator ) {
+ $settings = $settings->getArrayCopy();
+ }
+
+ if ( is_array( $settings ) ) {
+ foreach ( array_keys( $settings ) as $number ) {
+ if ( is_numeric( $number ) ) {
+ $this->_set( $number );
+ $this->_register_one( $number );
</ins><span class="cx" style="display: block; padding: 0 10px"> $empty = false;
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> if ( $empty ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- // If there are none, we register the widget's existence with a
- // generic template
- $this->_set(1);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // If there are none, we register the widget's existence with a generic template.
+ $this->_set( 1 );
</ins><span class="cx" style="display: block; padding: 0 10px"> $this->_register_one();
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -294,15 +298,16 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * }
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> public function display_callback( $args, $widget_args = 1 ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if ( is_numeric($widget_args) )
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( is_numeric( $widget_args ) ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> $widget_args = array( 'number' => $widget_args );
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $widget_args = wp_parse_args( $widget_args, array( 'number' => -1 ) );
</span><span class="cx" style="display: block; padding: 0 10px"> $this->_set( $widget_args['number'] );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $instance = $this->get_settings();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $instances = $this->get_settings();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if ( array_key_exists( $this->number, $instance ) ) {
- $instance = $instance[$this->number];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( isset( $instances[ $this->number ] ) ) {
+ $instance = $instances[ $this->number ];
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * Filter the settings for a particular widget instance.
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -424,6 +429,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @access public
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @param int|array $widget_args Widget instance number or array of widget arguments.
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @return string|null
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> public function form_callback( $widget_args = 1 ) {
</span><span class="cx" style="display: block; padding: 0 10px"> if ( is_numeric($widget_args) )
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -516,20 +522,22 @@
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> public function get_settings() {
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $settings = get_option($this->option_name);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $settings = get_option( $this->option_name );
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if ( false === $settings && isset($this->alt_option_name) )
- $settings = get_option($this->alt_option_name);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( false === $settings && isset( $this->alt_option_name ) ) {
+ $settings = get_option( $this->alt_option_name );
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if ( !is_array($settings) )
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( ! is_array( $settings ) && ! ( $settings instanceof ArrayObject || $settings instanceof ArrayIterator ) ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> $settings = array();
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if ( !empty($settings) && !array_key_exists('_multiwidget', $settings) ) {
- // old format, convert if single widget
- $settings = wp_convert_widget_settings($this->id_base, $this->option_name, $settings);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( ! empty( $settings ) && ! isset( $settings['_multiwidget'] ) ) {
+ // Old format, convert if single widget.
+ $settings = wp_convert_widget_settings( $this->id_base, $this->option_name, $settings );
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- unset($settings['_multiwidget'], $settings['__i__']);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ unset( $settings['_multiwidget'], $settings['__i__'] );
</ins><span class="cx" style="display: block; padding: 0 10px"> return $settings;
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span></span></pre></div>
<a id="trunktestsphpunittestswidgetsphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/tests/phpunit/tests/widgets.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/widgets.php 2015-05-25 22:08:08 UTC (rev 32601)
+++ trunk/tests/phpunit/tests/widgets.php 2015-05-26 16:50:03 UTC (rev 32602)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,33 +1,48 @@
</span><span class="cx" style="display: block; padding: 0 10px"> <?php
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Test widget template tags
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Test functions and classes for widgets and sidebars.
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @group widgets
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> class Tests_Widgets extends WP_UnitTestCase {
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function test_register_widget_core_widget() {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function clean_up_global_scope() {
+ global $wp_widget_factory, $wp_registered_sidebars, $wp_registered_widgets, $wp_registered_widget_controls, $wp_registered_widget_updates;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- global $wp_widget_factory;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $wp_registered_sidebars = array();
+ $wp_registered_widgets = array();
+ $wp_registered_widget_controls = array();
+ $wp_registered_widget_updates = array();
+ $wp_widget_factory->widgets = array();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- unregister_widget( 'WP_Widget_Search' );
- register_widget( 'WP_Widget_Search' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ parent::clean_up_global_scope();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $this->assertTrue( isset( $wp_widget_factory->widgets['WP_Widget_Search'] ) );
-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function tearDown() {
+ global $wp_customize;
+ $wp_customize = null;
+ parent::tearDown();
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function test_unregister_widget_core_widget() {
-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * @see register_widget()
+ * @see unregister_widget()
+ */
+ function test_register_and_unregister_widget_core_widget() {
</ins><span class="cx" style="display: block; padding: 0 10px"> global $wp_widget_factory;
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- unregister_widget( 'WP_Widget_Search' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $widget_class = 'WP_Widget_Search';
+ register_widget( $widget_class );
+ $this->assertArrayHasKey( $widget_class, $wp_widget_factory->widgets );
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $this->assertFalse( isset( $wp_widget_factory->widgets['WP_Widget_Search'] ) );
-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ unregister_widget( $widget_class );
+ $this->assertArrayNotHasKey( $widget_class, $wp_widget_factory->widgets );
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * @see register_sidebars()
+ */
</ins><span class="cx" style="display: block; padding: 0 10px"> function test_register_sidebars_single() {
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> global $wp_registered_sidebars;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -38,41 +53,244 @@
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * @see register_sidebars()
+ */
</ins><span class="cx" style="display: block; padding: 0 10px"> function test_register_sidebars_multiple() {
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> global $wp_registered_sidebars;
</span><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $result = array();
</ins><span class="cx" style="display: block; padding: 0 10px"> $num = 3;
</span><span class="cx" style="display: block; padding: 0 10px"> $id_base = 'WP Unit Test';
</span><span class="cx" style="display: block; padding: 0 10px"> register_sidebars( $num, array( 'name' => $id_base . ' %d' ) );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $names = wp_list_pluck( $wp_registered_sidebars, 'name' );
</span><span class="cx" style="display: block; padding: 0 10px"> for ( $i = 1; $i <= $num; $i++ ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if ( in_array( "$id_base $i", $names ) )
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( in_array( "$id_base $i", $names ) ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> $result[] = true;
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ }
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertEquals( $num, count( $result ) );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function test_register_sidebar() {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * @see register_sidebar
+ * @see unregister_sidebar
+ */
+ function test_register_and_unregister_sidebar() {
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> global $wp_registered_sidebars;
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- register_sidebar( array( 'id' => 'wp-unit-test' ) );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $sidebar_id = 'wp-unit-test';
+ register_sidebar( array( 'id' => $sidebar_id ) );
+ $this->assertArrayHasKey( $sidebar_id, $wp_registered_sidebars );
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $this->assertTrue( isset( $wp_registered_sidebars['wp-unit-test'] ) );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ unregister_sidebar( $sidebar_id );
+ $this->assertArrayNotHasKey( 'wp-unit-test', $wp_registered_sidebars );
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * @see WP_Widget_Search::form()
+ */
+ function test_wp_widget_search_form() {
+ $widget = new WP_Widget_Search( 'foo', 'Foo' );
+ ob_start();
+ $args = array(
+ 'before_widget' => '<section>',
+ 'after_widget' => "</section>\n",
+ 'before_title' => '<h2>',
+ 'after_title' => "</h2>\n",
+ );
+ $instance = array( 'title' => 'Buscar' );
+ $widget->_set( 2 );
+ $widget->widget( $args, $instance );
+ $output = ob_get_clean();
+ $this->assertNotContains( 'no-options-widget', $output );
+ $this->assertContains( '<h2>Buscar</h2>', $output );
+ $this->assertContains( '<section>', $output );
+ $this->assertContains( '</section>', $output );
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- function test_unregister_sidebar() {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * @see WP_Widget::form()
+ */
+ function test_wp_widget_form() {
+ $widget = new WP_Widget( 'foo', 'Foo' );
+ ob_start();
+ $retval = $widget->form( array() );
+ $output = ob_get_clean();
+ $this->assertEquals( 'noform', $retval );
+ $this->assertContains( 'no-options-widget', $output );
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- global $wp_registered_sidebars;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * @see WP_Widget::__construct()
+ */
+ function test_wp_widget_constructor() {
+ $id_base = 'foo';
+ $name = 'Foo';
+ $foo_widget = new WP_Widget( $id_base, $name );
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- unregister_sidebar( 'sidebar-1' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $this->assertEquals( $id_base, $foo_widget->id_base );
+ $this->assertEquals( $name, $foo_widget->name );
+ $this->assertEquals( "widget_{$id_base}", $foo_widget->option_name );
+ $this->assertArrayHasKey( 'classname', $foo_widget->widget_options );
+ $this->assertEquals( "widget_{$id_base}", $foo_widget->widget_options['classname'] );
+ $this->assertArrayHasKey( 'id_base', $foo_widget->control_options );
+ $this->assertEquals( $id_base, $foo_widget->control_options['id_base'] );
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $this->assertFalse( isset( $wp_registered_sidebars['sidebar-1'] ) );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $id_base = 'bar';
+ $name = 'Bar';
+ $widget_options = array(
+ 'classname' => 'bar_classname',
+ );
+ $control_options = array(
+ 'id_base' => 'bar_id_base',
+ );
+ $bar_widget = new WP_Widget( $id_base, $name, $widget_options, $control_options );
+ $this->assertEquals( $widget_options['classname'], $bar_widget->widget_options['classname'] );
+ $this->assertEquals( $control_options['id_base'], $bar_widget->control_options['id_base'] );
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * @see WP_Widget::get_field_name()
+ */
+ function test_wp_widget_get_field_name() {
+ $widget = new WP_Widget( 'foo', 'Foo' );
+ $widget->_set( 2 );
+ $this->assertEquals( 'widget-foo[2][title]', $widget->get_field_name( 'title' ) );
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+ /**
+ * @see WP_Widget::get_field_id()
+ */
+ function test_wp_widget_get_field_id() {
+ $widget = new WP_Widget( 'foo', 'Foo' );
+ $widget->_set( 2 );
+ $this->assertEquals( 'widget-foo-2-title', $widget->get_field_id( 'title' ) );
+ }
+
+ /**
+ * @see WP_Widget::_register()
+ */
+ function test_wp_widget__register() {
+ global $wp_registered_widgets;
+
+ $settings = get_option( 'widget_search' );
+ unset( $settings['_multiwidget'] );
+ $this->assertArrayHasKey( 2, $settings );
+
+ $this->assertEmpty( $wp_registered_widgets );
+ wp_widgets_init();
+
+ // Note: We cannot use array_keys() here because $settings could be an ArrayIterator
+ foreach ( $settings as $widget_number => $instance ) {
+ $widget_id = "search-$widget_number";
+ $this->assertArrayHasKey( $widget_id, $wp_registered_widgets );
+ }
+ }
+
+ // @todo test WP_Widget::display_callback()
+
+ /**
+ * @see WP_Widget::is_preview()
+ */
+ function test_wp_widget_is_preview() {
+ global $wp_customize;
+
+ $widget = new WP_Widget( 'foo', 'Foo' );
+
+ $this->assertEmpty( $wp_customize );
+ $this->assertFalse( $widget->is_preview() );
+
+ wp_set_current_user( $this->factory->user->create( array( 'role' => 'administrator' ) ) );
+ require_once ABSPATH . WPINC . '/class-wp-customize-manager.php';
+ $wp_customize = new WP_Customize_Manager();
+ $wp_customize->start_previewing_theme();
+
+ $this->assertTrue( $widget->is_preview() );
+ }
+
+ // @todo test WP_Widget::update_callback()
+ // @todo test WP_Widget::form_callback()
+ // @todo test WP_Widget::_register_one()
+
+ /**
+ * @see WP_Widget::get_settings()
+ */
+ function test_wp_widget_get_settings() {
+ global $wp_registered_widgets;
+
+ $option_value = get_option( 'widget_search' );
+ $this->assertArrayHasKey( '_multiwidget', $option_value );
+ $this->assertEquals( 1, $option_value['_multiwidget'] );
+ $this->assertArrayHasKey( 2, $option_value );
+ $instance = $option_value[2];
+ $this->assertInternalType( 'array', $instance );
+ $this->assertArrayHasKey( 'title', $instance );
+ unset( $option_value['_multiwidget'] );
+
+ wp_widgets_init();
+ $wp_widget_search = $wp_registered_widgets['search-2']['callback'][0];
+
+ $settings = $wp_widget_search->get_settings();
+ // @todo $this->assertArrayNotHasKey( '_multiwidget', $settings ); ?
+ $this->assertArrayHasKey( 2, $settings );
+
+ foreach ( $option_value as $widget_number => $instance ) {
+ $this->assertEquals( $settings[ $widget_number ], $option_value[ $widget_number ] );
+ }
+ }
+
+ /**
+ * @see WP_Widget::save_settings()
+ */
+ function test_wp_widget_save_settings() {
+ global $wp_registered_widgets;
+
+ wp_widgets_init();
+ $wp_widget_search = $wp_registered_widgets['search-2']['callback'][0];
+
+ $settings = $wp_widget_search->get_settings();
+ $overridden_title = 'Unit Tested';
+
+ /*
+ * Note that if a plugin is filtering $settings to be an ArrayIterator,
+ * then doing this:
+ * $settings[2]['title'] = $overridden_title;
+ * Will fail with this:
+ * > Indirect modification of overloaded element of X has no effect.
+ * So this is why the value must be obtained.
+ */
+ $instance = $settings[2];
+ $instance['title'] = $overridden_title;
+ $settings[2] = $instance;
+
+ $wp_widget_search->save_settings( $settings );
+
+ $option_value = get_option( $wp_widget_search->option_name );
+ $this->assertArrayHasKey( '_multiwidget', $option_value );
+ $this->assertEquals( $overridden_title, $option_value[2]['title'] );
+ }
+
+ /**
+ * @see WP_Widget::save_settings()
+ */
+ function test_wp_widget_save_settings_delete() {
+ global $wp_registered_widgets;
+
+ wp_widgets_init();
+ $wp_widget_search = $wp_registered_widgets['search-2']['callback'][0];
+
+ $settings = $wp_widget_search->get_settings();
+ $this->assertArrayHasKey( 2, $settings );
+ unset( $settings[2] );
+ $wp_widget_search->save_settings( $settings );
+ $option_value = get_option( $wp_widget_search->option_name );
+ $this->assertArrayNotHasKey( 2, $option_value );
+ }
+
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span></span></pre>
</div>
</div>
</body>
</html>