<!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>[31433] branches/4.1: In `paginate_links()`, don't override custom format arguments when setting up default 'add_args'.</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/31433">31433</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/31433","name":"Review Commit"}}</script></dd>
<dt style="float: left; width: 6em; font-weight: bold">Author</dt> <dd>dd32</dd>
<dt style="float: left; width: 6em; font-weight: bold">Date</dt> <dd>2015-02-12 02:19:44 +0000 (Thu, 12 Feb 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'>In `paginate_links()`, don't override custom format arguments when setting up default 'add_args'.

Since 4.1 <a href="https://core.trac.wordpress.org/changeset/29780">[29780]</a>, the default value of the 'add_args' argument in
paginate_links() has been determined by parsing the current URL. This change
had the side effect of overriding custom values of 'format' that changed the
pagination query var, with the result that plugins using `paginate_links()`
with a custom format generated the incorrect links unless explicitly
declaring 'add_args=false' to prevent the default values from overriding. We
fix this behavior by parsing URL query vars into the 'add_args' array only
after the explicit function params have been parsed, and by skipping the
current page's pagination query var when doing this parsing (to avoid the
override).

Props obenland.
Merges <a href="https://core.trac.wordpress.org/changeset/31203">[31203]</a>, <a href="https://core.trac.wordpress.org/changeset/31432">[31432]</a> to the 4.1 branch.
Fixes <a href="https://core.trac.wordpress.org/ticket/30831">#30831</a>.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#branches41srcwpincludesgeneraltemplatephp">branches/4.1/src/wp-includes/general-template.php</a></li>
<li><a href="#branches41testsphpunittestsgeneralpaginateLinksphp">branches/4.1/tests/phpunit/tests/general/paginateLinks.php</a></li>
</ul>

<h3>Property Changed</h3>
<ul>
<li><a href="#branches41">branches/4.1/</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<span class="cx" style="display: block; padding: 0 10px">Index: branches/4.1
</span><span class="cx" style="display: block; padding: 0 10px">===================================================================
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">--- branches/4.1 2015-02-12 01:38:26 UTC (rev 31432)
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+++ branches/4.1  2015-02-12 02:19:44 UTC (rev 31433)
</ins><a id="branches41"></a>
<div class="propset"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Property changes: branches/4.1</h4>
<pre class="diff"><span>
</span></pre></div>
<a id="svnmergeinfo"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: svn:mergeinfo</h4></div>
<span class="cx" style="display: block; padding: 0 10px"> /branches/3.1:18031
</span><span class="cx" style="display: block; padding: 0 10px"> /branches/3.3:20543
</span><span class="cx" style="display: block; padding: 0 10px"> /branches/3.4:21757
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-/trunk:18512,30801-30813,30817,30821,30823-30824,30828-30847,30849,30852-30857,30860,30865-30869,30871-30874,30879,30884-30891,30893,30896-30897,30899-30901,30903,30905,30907,30910,30912,30921,30929,30932,30944-30946,30951-30956,30961,30967,30971,30985,30991,30993,31010,31054,31071,31073,31140,31179,31197,31251,31273,31329,31339,31342,31360,31386,31390,31429
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/trunk:18512,30801-30813,30817,30821,30823-30824,30828-30847,30849,30852-30857,30860,30865-30869,30871-30874,30879,30884-30891,30893,30896-30897,30899-30901,30903,30905,30907,30910,30912,30921,30929,30932,30944-30946,30951-30956,30961,30967,30971,30985,30991,30993,31010,31054,31071,31073,31140,31179,31197,31203,31251,31273,31329,31339,31342,31360,31386,31390,31429,31432
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of property
</span><a id="branches41srcwpincludesgeneraltemplatephp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: branches/4.1/src/wp-includes/general-template.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- branches/4.1/src/wp-includes/general-template.php 2015-02-12 01:38:26 UTC (rev 31432)
+++ branches/4.1/src/wp-includes/general-template.php   2015-02-12 02:19:44 UTC (rev 31433)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2587,20 +2587,18 @@
</span><span class="cx" style="display: block; padding: 0 10px"> function paginate_links( $args = '' ) {
</span><span class="cx" style="display: block; padding: 0 10px">        global $wp_query, $wp_rewrite;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        $total        = ( isset( $wp_query->max_num_pages ) ) ? $wp_query->max_num_pages : 1;
-       $current      = ( get_query_var( 'paged' ) ) ? intval( get_query_var( 'paged' ) ) : 1;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Setting up default values based on the current URL.
</ins><span class="cx" style="display: block; padding: 0 10px">         $pagenum_link = html_entity_decode( get_pagenum_link() );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        $query_args   = array();
</del><span class="cx" style="display: block; padding: 0 10px">         $url_parts    = explode( '?', $pagenum_link );
</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 ( isset( $url_parts[1] ) ) {
-               wp_parse_str( $url_parts[1], $query_args );
-               $query_args = urlencode_deep( $query_args );
-       }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Get max pages and current page out of the current query, if available.
+       $total   = isset( $wp_query->max_num_pages ) ? $wp_query->max_num_pages : 1;
+       $current = get_query_var( 'paged' ) ? intval( get_query_var( 'paged' ) ) : 1;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        $pagenum_link = remove_query_arg( array_keys( $query_args ), $pagenum_link );
-       $pagenum_link = trailingslashit( $pagenum_link ) . '%_%';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Append the format placeholder to the base URL.
+       $pagenum_link = trailingslashit( $url_parts[0] ) . '%_%';
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        // URL base depends on permalink settings.
</ins><span class="cx" style="display: block; padding: 0 10px">         $format  = $wp_rewrite->using_index_permalinks() && ! strpos( $pagenum_link, 'index.php' ) ? 'index.php/' : '';
</span><span class="cx" style="display: block; padding: 0 10px">        $format .= $wp_rewrite->using_permalinks() ? user_trailingslashit( $wp_rewrite->pagination_base . '/%#%', 'paged' ) : '?paged=%#%';
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2616,7 +2614,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                'end_size' => 1,
</span><span class="cx" style="display: block; padding: 0 10px">                'mid_size' => 2,
</span><span class="cx" style="display: block; padding: 0 10px">                'type' => 'plain',
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                'add_args' => $query_args, // array of query args to add
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         'add_args' => array(), // array of query args to add
</ins><span class="cx" style="display: block; padding: 0 10px">                 'add_fragment' => '',
</span><span class="cx" style="display: block; padding: 0 10px">                'before_page_number' => '',
</span><span class="cx" style="display: block; padding: 0 10px">                'after_page_number' => ''
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2624,6 +2622,21 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        $args = wp_parse_args( $args, $defaults );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        if ( ! is_array( $args['add_args'] ) ) {
+               $args['add_args'] = array();
+       }
+
+       // Merge additional query vars found in the original URL into 'add_args' array.
+       if ( isset( $url_parts[1] ) ) {
+               // Find the format argument.
+               $format_query = parse_url( str_replace( '%_%', $args['format'], $args['base'] ), PHP_URL_QUERY );
+               wp_parse_str( $format_query, $format_arg );
+
+               // Remove the format argument from the array of query arguments, to avoid overwriting custom format.
+               wp_parse_str( remove_query_arg( array_keys( $format_arg ), $url_parts[1] ), $query_args );
+               $args['add_args'] = array_merge( $args['add_args'], urlencode_deep( $query_args ) );
+       }
+
</ins><span class="cx" style="display: block; padding: 0 10px">         // Who knows what else people pass in $args
</span><span class="cx" style="display: block; padding: 0 10px">        $total = (int) $args['total'];
</span><span class="cx" style="display: block; padding: 0 10px">        if ( $total < 2 ) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2638,7 +2651,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">        if ( $mid_size < 0 ) {
</span><span class="cx" style="display: block; padding: 0 10px">                $mid_size = 2;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        $add_args = is_array( $args['add_args'] ) ? $args['add_args'] : false;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $add_args = $args['add_args'];
</ins><span class="cx" style="display: block; padding: 0 10px">         $r = '';
</span><span class="cx" style="display: block; padding: 0 10px">        $page_links = array();
</span><span class="cx" style="display: block; padding: 0 10px">        $dots = false;
</span></span></pre></div>
<a id="branches41testsphpunittestsgeneralpaginateLinksphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: branches/4.1/tests/phpunit/tests/general/paginateLinks.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- branches/4.1/tests/phpunit/tests/general/paginateLinks.php        2015-02-12 01:38:26 UTC (rev 31432)
+++ branches/4.1/tests/phpunit/tests/general/paginateLinks.php  2015-02-12 02:19:44 UTC (rev 31433)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -229,4 +229,86 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        $this->assertEquals( $expected_href, $href );
</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 30831
+        */
+       function test_paginate_links_with_custom_query_args() {
+               add_filter( 'get_pagenum_link', array( $this, 'add_query_arg' ) );
+               $links = paginate_links( array(
+                       'current'  => 2,
+                       'total'    => 5,
+                       'end_size' => 1,
+                       'mid_size' => 1,
+                       'type'     => 'array',
+                       'add_args' => array(
+                               'baz' => 'qux',
+                       ),
+               ) );
+               remove_filter( 'get_pagenum_link', array( $this, 'add_query_arg' ) );
+
+               $document = new DOMDocument();
+               $document->preserveWhiteSpace = false;
+
+               $data = array(
+                       0 => home_url( '/?baz=qux&foo=bar&s=search+term' ),
+                       1 => home_url( '/?baz=qux&foo=bar&s=search+term' ),
+                       3 => home_url( '/?paged=3&baz=qux&foo=bar&s=search+term' ),
+                       5 => home_url( '/?paged=5&baz=qux&foo=bar&s=search+term' ),
+                       6 => home_url( '/?paged=3&baz=qux&foo=bar&s=search+term' ),
+               );
+
+               foreach ( $data as $index => $expected_href ) {
+                       $document->loadHTML( $links[ $index ] );
+                       $tag = $document->getElementsByTagName( 'a' )->item( 0 );
+                       $this->assertNotNull( $tag );
+
+                       $href = $tag->attributes->getNamedItem( 'href' )->value;
+                       $this->assertEquals( $expected_href, $href );
+               }
+       }
+
+       /**
+        * @ticket 30831
+        */
+       public function test_paginate_links_should_allow_non_default_format_without_add_args() {
+               // Fake the query params.
+               $request_uri = $_SERVER['REQUEST_URI'];
+               $_SERVER['REQUEST_URI'] = add_query_arg( 'foo', 3, home_url() );
+
+               $links = paginate_links( array(
+                       'base'    => add_query_arg( 'foo', '%#%' ),
+                       'format'  => '',
+                       'total'   => 5,
+                       'current' => 3,
+                       'type'    => 'array',
+               ) );
+
+               $this->assertContains( '?foo=1', $links[1] );
+               $this->assertContains( '?foo=2', $links[2] );
+               $this->assertContains( '?foo=4', $links[4] );
+               $this->assertContains( '?foo=5', $links[5] );
+
+               $_SERVER['REQUEST_URI'] = $request_uri;
+       }
+
+       /**
+        * @ticket 30831
+        */
+       public function test_paginate_links_should_allow_add_args_to_be_bool_false() {
+               // Fake the query params.
+               $request_uri = $_SERVER['REQUEST_URI'];
+               $_SERVER['REQUEST_URI'] = add_query_arg( 'foo', 3, home_url() );
+
+               $links = paginate_links( array(
+                       'add_args' => false,
+                       'base'    => add_query_arg( 'foo', '%#%' ),
+                       'format'  => '',
+                       'total'   => 5,
+                       'current' => 3,
+                       'type'    => 'array',
+               ) );
+
+               $this->assertContains( "<span class='page-numbers current'>3</span>", $links );
+       }
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span></span></pre>
</div>
</div>

</body>
</html>