<!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>[54112] trunk: Widgets: Store default options for uninitialized widgets.</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 { white-space: pre-line; 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/54112">54112</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/54112","name":"Review Commit"}}</script></dd>
<dt style="float: left; width: 6em; font-weight: bold">Author</dt> <dd>peterwilsoncc</dd>
<dt style="float: left; width: 6em; font-weight: bold">Date</dt> <dd>2022-09-09 02:17:33 +0000 (Fri, 09 Sep 2022)</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'>Widgets: Store default options for uninitialized widgets.
Prevent unnecessary database queries on page load by initializing widget options. On sites with uninitialized widgets, this prevents one or two database queries per uninitialized widget on each page load.
Props Chouby, mvraghavan, costdev, peterwilsoncc, spacedmonkey, mukesh27.
Fixes <a href="https://core.trac.wordpress.org/ticket/54677">#54677</a>.</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#trunksrcwpincludesclasswpwidgetphp">trunk/src/wp-includes/class-wp-widget.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="trunksrcwpincludesclasswpwidgetphp"></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/class-wp-widget.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/class-wp-widget.php 2022-09-09 02:04:18 UTC (rev 54111)
+++ trunk/src/wp-includes/class-wp-widget.php 2022-09-09 02:17:33 UTC (rev 54112)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -612,12 +612,16 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $settings = get_option( $this->option_name );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> if ( false === $settings ) {
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $settings = array();
</ins><span class="cx" style="display: block; padding: 0 10px"> if ( isset( $this->alt_option_name ) ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $settings = get_option( $this->alt_option_name );
- } else {
- // Save an option so it can be autoloaded next time.
- $this->save_settings( array() );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Get settings from alternative (legacy) option.
+ $settings = get_option( $this->alt_option_name, array() );
+
+ // Delete the alternative (legacy) option as the new option will be created using `$this->option_name`.
+ delete_option( $this->alt_option_name );
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Save an option so it can be autoloaded next time.
+ $this->save_settings( $settings );
</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"> if ( ! is_array( $settings ) && ! ( $settings instanceof ArrayObject || $settings instanceof ArrayIterator ) ) {
</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 2022-09-09 02:04:18 UTC (rev 54111)
+++ trunk/tests/phpunit/tests/widgets.php 2022-09-09 02:17:33 UTC (rev 54112)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -687,6 +687,61 @@
</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">+ * @ticket 54677
+ *
+ * @covers WP_Widget::get_settings
+ */
+ public function test_wp_widget_initializes_widget_with_alt_option() {
+ /*
+ * Emulate a new the recent posts widget.
+ *
+ * The widget contains an alternative (legacy) option so both the
+ * current and the alternative option need to be deleted.
+ */
+ delete_option( 'widget_recent-posts' );
+ delete_option( 'widget_recent_entries' );
+
+ $this->assertFalse( get_option( 'widget_recent-posts' ), 'The option widget_recent-posts was not deleted.' );
+ $this->assertFalse( get_option( 'widget_recent_entries' ), 'The option widget_recent_entries was not deleted.' );
+
+ wp_widgets_init();
+ $this->assertSameSetsWithIndex( array( '_multiwidget' => 1 ), get_option( 'widget_recent-posts' ), 'Option failed to be initialized.' );
+ $this->assertFalse( get_option( 'widget_recent_entries' ), 'Alternative option is set.' );
+ }
+
+ /**
+ * @ticket 54677
+ *
+ * @covers WP_Widget::get_settings
+ */
+ public function test_wp_widget_migrates_widget_with_alt_option() {
+ $option = array(
+ 2 => array(
+ 'title' => 'Recent Posts',
+ 'number' => 5,
+ 'show_date' => false,
+ ),
+ '_multiwidget' => 1,
+ );
+
+ /*
+ * Emulate the recent posts widget with an alternative option.
+ *
+ * The widget contains an alternative (legacy) option so the
+ * current option is deleted while the alternative option is created.
+ */
+ delete_option( 'widget_recent-posts' );
+ update_option( 'widget_recent_entries', $option );
+
+ $this->assertFalse( get_option( 'widget_recent-posts' ), 'The option widget_recent-posts was not deleted.' );
+ $this->assertSameSetsWithIndex( $option, get_option( 'widget_recent_entries' ), 'The option widget_recent_entries was not set to the default.' );
+
+ wp_widgets_init();
+ $this->assertSameSetsWithIndex( $option, get_option( 'widget_recent-posts' ), 'Option failed to be converted to new name.' );
+ $this->assertFalse( get_option( 'widget_recent_entries' ), 'Alternative option was not deleted.' );
+ }
+
+ /**
</ins><span class="cx" style="display: block; padding: 0 10px"> * @see WP_Widget::save_settings()
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> public function test_wp_widget_save_settings() {
</span></span></pre>
</div>
</div>
</body>
</html>