From 427f4fe063897e73869f2486d31346c025d9bdc9 Mon Sep 17 00:00:00 2001 From: Scott Taylor Date: Wed, 30 Sep 2015 01:10:03 +0000 Subject: [PATCH] Rewrite: allow `add_rewrite_rule|WP_Rewrite::add_rule()` to accept an associative array for the value of `$redirect` instead of requiring a query string. Adds unit tests. Props scribu, DrewAPicture. Fixes #16840. git-svn-id: https://develop.svn.wordpress.org/trunk@34708 602fd350-edb4-49c9-b593-d223f7449a82 --- src/wp-includes/class-wp-rewrite.php | 38 +++++++++++------- src/wp-includes/rewrite-functions.php | 16 ++++---- tests/phpunit/tests/rewrite.php | 57 +++++++++++++++++++++++++++ 3 files changed, 90 insertions(+), 21 deletions(-) diff --git a/src/wp-includes/class-wp-rewrite.php b/src/wp-includes/class-wp-rewrite.php index 5f7bbb2340..84a57c8107 100644 --- a/src/wp-includes/class-wp-rewrite.php +++ b/src/wp-includes/class-wp-rewrite.php @@ -1510,24 +1510,34 @@ class WP_Rewrite { * the top of the rules. * * @since 2.1.0 + * @since 4.4.0 Array support was added to the `$redirect` parameter. * @access public * - * @param string $regex Regular expression to match against request. - * @param string $redirect URL regex redirects to when regex matches request. - * @param string $after Optional, default is bottom. Location to place rule. + * @param string $regex Regular expression to match against request. + * @param string|array $redirect URL regex redirects to when regex matches request, or array + * of query vars and values. + * @param string $after Optional, default is bottom. Location to place rule. */ - public function add_rule($regex, $redirect, $after = 'bottom') { - //get everything up to the first ? - $index = (strpos($redirect, '?') === false ? strlen($redirect) : strpos($redirect, '?')); - $front = substr($redirect, 0, $index); - if ( $front != $this->index ) { //it doesn't redirect to WP's index.php - $this->add_external_rule($regex, $redirect); + public function add_rule( $regex, $redirect, $after = 'bottom' ) { + if ( is_array( $redirect ) ) { + $external = false; + $redirect = add_query_arg( $redirect, 'index.php' ); } else { - if ( 'bottom' == $after) - $this->extra_rules = array_merge($this->extra_rules, array($regex => $redirect)); - else - $this->extra_rules_top = array_merge($this->extra_rules_top, array($regex => $redirect)); - //$this->extra_rules[$regex] = $redirect; + $index = false === strpos( $redirect, '?' ) ? strlen( $redirect ) : strpos( $redirect, '?' ); + $front = substr( $redirect, 0, $index ); + + $external = $front != $this->index; + } + + // "external" = it doesn't redirect to index.php + if ( $external ) { + $this->add_external_rule( $regex, $redirect ); + } else { + if ( 'bottom' == $after ) { + $this->extra_rules = array_merge( $this->extra_rules, array( $regex => $redirect ) ); + } else { + $this->extra_rules_top = array_merge( $this->extra_rules_top, array( $regex => $redirect ) ); + } } } diff --git a/src/wp-includes/rewrite-functions.php b/src/wp-includes/rewrite-functions.php index ed085b7c22..9b5a4f90df 100644 --- a/src/wp-includes/rewrite-functions.php +++ b/src/wp-includes/rewrite-functions.php @@ -7,19 +7,21 @@ */ /** - * Add a straight rewrite rule. + * Adds a straight rewrite rule. * * @since 2.1.0 + * @since 4.4.0 Array support was added to the `$redirect` parameter. * - * @global WP_Rewrite $wp_rewrite + * @global WP_Rewrite $wp_rewrite WordPress Rewrite Component. * - * @param string $regex Regular Expression to match request against. - * @param string $redirect Page to redirect to. - * @param string $after Optional, default is 'bottom'. Where to add rule, can also be 'top'. + * @param string $regex Regular Expression to match request against. + * @param string|array $redirect Page to redirect to, or array of query vars and values. + * @param string $after Optional, default is 'bottom'. Where to add rule, can also be 'top'. */ -function add_rewrite_rule($regex, $redirect, $after = 'bottom') { +function add_rewrite_rule( $regex, $redirect, $after = 'bottom' ) { global $wp_rewrite; - $wp_rewrite->add_rule($regex, $redirect, $after); + + $wp_rewrite->add_rule( $regex, $redirect, $after ); } /** diff --git a/tests/phpunit/tests/rewrite.php b/tests/phpunit/tests/rewrite.php index d31a6d36b8..0813c3d29a 100644 --- a/tests/phpunit/tests/rewrite.php +++ b/tests/phpunit/tests/rewrite.php @@ -31,6 +31,63 @@ class Tests_Rewrite extends WP_UnitTestCase { parent::tearDown(); } + /** + * @ticket 16840 + */ + public function test_add_rule() { + global $wp_rewrite; + + $pattern = 'path/to/rewrite/([^/]+)/?$'; + $redirect = 'index.php?test_var1=$matches[1]&test_var2=1'; + + $wp_rewrite->add_rule( $pattern, $redirect ); + + $wp_rewrite->flush_rules(); + + $rewrite_rules = $wp_rewrite->rewrite_rules(); + + $this->assertSame( $redirect, $rewrite_rules[ $pattern ] ); + } + + /** + * @ticket 16840 + */ + public function test_add_rule_redirect_array() { + global $wp_rewrite; + + $pattern = 'path/to/rewrite/([^/]+)/?$'; + $redirect = 'index.php?test_var1=$matches[1]&test_var2=1'; + + $wp_rewrite->add_rule( $pattern, array( + 'test_var1' => '$matches[1]', + 'test_var2' => '1' + ) ); + + $wp_rewrite->flush_rules(); + + $rewrite_rules = $wp_rewrite->rewrite_rules(); + + $this->assertSame( $redirect, $rewrite_rules[ $pattern ] ); + } + + /** + * @ticket 16840 + */ + public function test_add_rule_top() { + global $wp_rewrite; + + $pattern = 'path/to/rewrite/([^/]+)/?$'; + $redirect = 'index.php?test_var1=$matches[1]&test_var2=1'; + + $wp_rewrite->add_rule( $pattern, $redirect, 'top' ); + + $wp_rewrite->flush_rules(); + + $extra_rules_top = $wp_rewrite->extra_rules_top; + + $this->assertContains( $redirect, $extra_rules_top[ $pattern ] ); + } + function test_url_to_postid() { $id = $this->factory->post->create();