[wp-trac] [WordPress Trac] #37561: Inserting rewrite rules using the filter 'option_rewrite_rules' breaks 'WP_Rewrite::flush_rules()', causing 404 errors

WordPress Trac noreply at wordpress.org
Wed Aug 10 23:17:53 UTC 2016


#37561: Inserting rewrite rules using the filter 'option_rewrite_rules' breaks
'WP_Rewrite::flush_rules()', causing 404 errors
---------------------------+------------------------------
 Reporter:  maratbn        |       Owner:
     Type:  defect (bug)   |      Status:  new
 Priority:  normal         |   Milestone:  Awaiting Review
Component:  Rewrite Rules  |     Version:
 Severity:  normal         |  Resolution:
 Keywords:  close          |     Focuses:
---------------------------+------------------------------

Comment (by maratbn):

 Replying to [comment:5 SergeyBiryukov]:
 > Replying to [comment:4 maratbn]:
 > > b/c the Jupiter theme is flushing rewrite rules inside page requests
 >
 > That sounds like a bad practice the
 [https://codex.wordpress.org/flush_rewrite_rules#Usage Codex specifically
 warns against].

 Well yeah.  Since they're doing it after their admin settings are updated,
 my guess is that doing it directly from an admin dashboard page request
 caused them some other issues and conflicts, so they switched to
 {{{wp_loaded}}} inside regular page requests, and to their credit they
 have special logic to not do it on subsequent page requests.

 Perhaps WordPress could use a kind of a non-optimal code warning feature,
 to detect if there is a call to {{{flush_rewrite_rules()}}} inside an
 incorrect action, or if some other core operation is being performed
 inside an incorrect callback, and to append a warning to a log that could
 be displayed in the admin dashboard to warn admins that they're running
 themes / plugins with non-optimal logic.  This way these problems would
 become apparent sooner, and the developers would also try harder to use
 the appropriate actions/filters, and to file bug reports when they are
 having unusual issues and conflicts using recommended callbacks.

 As far as my earlier idea regarding adding a new optional parameter to
 {{{wp_rewrite_rules()}}} that will force it to call the method
 {{{WP_Rewrite::rewrite_rules()}}} regardless of whether
 {{{get_option('rewrite_rules')}}} returns an empty list or not, and that
 optional parameter should be passed-in from
 {{{WP_Rewrite::flush_rules(...)}}}, what do you guys think about that?
 Here's what the patch for that looks like:
 {{{
 --- wp-includes/class-wp-rewrite.php--BACKUP--2016-08-02--01    2016-08-02
 14:57:51.615661000 -0700
 +++ wp-includes/class-wp-rewrite.php    2016-08-10 15:47:04.412482000
 -0700
 @@ -1468,11 +1468,23 @@
          * @since 1.5.0
          * @access public
          *
 +        * @param bool $flag_dont_check_cache Optional Whether to always
 regenerate the rewrite rules even if they already appear to be present due
 to phantom rules being inserted into the cache via the filter
 'option_rewrite_rules'.
 +        *                                             Default false.
 +        *
          * @return array Rewrite rules.
          */
 -       public function wp_rewrite_rules() {
 -               $this->rules = get_option('rewrite_rules');
 -               if ( empty($this->rules) ) {
 +       public function wp_rewrite_rules($flag_dont_check_cache = false) {
 +
 +               $flag_actually_rewrite = $flag_dont_check_cache;
 +
 +               if (!$flag_actually_rewrite) {
 +                       $this->rules = get_option('rewrite_rules');
 +                       if ( empty($this->rules) ) {
 +                               $flag_actually_rewrite = true;
 +                       }
 +               }
 +
 +               if ($flag_actually_rewrite) {
                         $this->matches = 'matches';
                         $this->rewrite_rules();
                         update_option('rewrite_rules', $this->rules);
 @@ -1810,8 +1822,7 @@
                         unset( $do_hard_later );
                 }

 -               update_option( 'rewrite_rules', '' );
 -               $this->wp_rewrite_rules();
 +               $this->wp_rewrite_rules(true);

                 /**
                  * Filter whether a "hard" rewrite rule flush should be
 performed when requested.
 }}}

 Alternatively, what about not applying {{{option_rewrite_rules}}} when
 retrieving the cached rewrite rules?  The patch for that looks like this:

 {{{
 --- wp-includes/option.php--BACKUP--2016-08-10--01      2016-08-10
 15:53:47.104482000 -0700
 +++ wp-includes/option.php      2016-08-10 16:11:32.744482000 -0700
 @@ -25,9 +25,12 @@
   *
   * @param string $option  Name of option to retrieve. Expected to not be
 SQL-escaped.
   * @param mixed  $default Optional. Default value to return if the option
 does not exist.
 + * @param bool   $flag_dont_filter
 + *                        Optional.  Don't apply filter 'option_[option
 name]'.
 + *                        Default false.
   * @return mixed Value set for the option.
   */
 -function get_option( $option, $default = false ) {
 +function get_option( $option, $default = false, $flag_dont_filter = false
 ) {
         global $wpdb;

         $option = trim( $option );
 @@ -120,6 +123,10 @@
         if ( in_array( $option, array('siteurl', 'home', 'category_base',
 'tag_base') ) )
                 $value = untrailingslashit( $value );

 +       if ($flag_dont_filter) {
 +               return maybe_unserialize( $value );
 +       }
 +
         /**
          * Filter the value of an existing option.
          *
 --- wp-includes/class-wp-rewrite.php--BACKUP--2016-08-02--01    2016-08-02
 14:57:51.615661000 -0700
 +++ wp-includes/class-wp-rewrite.php    2016-08-10 16:10:38.800482000
 -0700
 @@ -1471,7 +1471,7 @@
          * @return array Rewrite rules.
          */
         public function wp_rewrite_rules() {
 -               $this->rules = get_option('rewrite_rules');
 +               $this->rules = get_option('rewrite_rules', null, true);
                 if ( empty($this->rules) ) {
                         $this->matches = 'matches';
                         $this->rewrite_rules();
 }}}

--
Ticket URL: <https://core.trac.wordpress.org/ticket/37561#comment:6>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform


More information about the wp-trac mailing list