[wp-trac] [WordPress Trac] #45331: 'rest_url_prefix' filter fails to impact flush_rewrite_rules() on plugin activation

WordPress Trac noreply at wordpress.org
Mon Nov 12 14:39:16 UTC 2018


#45331: 'rest_url_prefix' filter fails to impact flush_rewrite_rules() on plugin
activation
-------------------------------------------------+-------------------------
 Reporter:  KestutisIT                           |      Owner:  (none)
     Type:  defect (bug)                         |     Status:  new
 Priority:  normal                               |  Milestone:  Awaiting
                                                 |  Review
Component:  Permalinks                           |    Version:  4.9.8
 Severity:  major                                |   Keywords:  needs-patch
  Focuses:  administration, rest-api, coding-    |  ux-feedback
  standards                                      |
-------------------------------------------------+-------------------------
 'rest_url_prefix' filter fails to impact flush_rewrite_rules() on plugin
 activation
 =========================================================================

 So here is the bug - 'flush_rewrite_rules' is called on plugin activation
 after 'rest_url_prefix' filter added with new API ENDPOINT,
 but if I go to '<MY-DOMAIN>/<NEW-ENDPOINT>/' it gives me 404 error. And if
 I access '<MY-DOMAIN>/wp-json/' on Firefox Developer Edition in 'Header'
 section I see:\\
 `Link   <http://<MY-DOMAIN>/<NEW-ENDPOINT>/>; rel="https://api.w.org/"`\\
 So the header is correct here. And it will fix the issue if I go to WP
 Settings -> Permalinks -> Save.\\
 But that is a bug. As you won't have to instruct that to your plugin user,
 after his activation he will see that API is not working.\\
 \\
 Install Controller class - 'flush_rewrite_rules' is called on plugin
 activation after 'rest_url_prefix' filter added with new API ENDPOINT:
 {{{#!php
 <?php
 namespace GreatestEverManager\Controllers\Admin;
 final class InstallController
 {
     <...>

     public function setCustomWP_RestAPI_Prefix()
     {
         // NOTE: Do not forget to do the same on install with
 flush_rewrite_rules(); after it.
         add_filter('rest_url_prefix', function() { return
 ConfigurationInterface::WP_REST_API_PREFIX; }, 10, 1);

         // NOTE: As there is no custom post types or custom taxonomies
 registration later, we perform rewrite rules flush right now
         flush_rewrite_rules();
     }

     <...>
 }
 }}}
 \\
 Main Controller class:
 {{{#!php
 <?php
 namespace GreatestEverManager\Controllers;
 use SoftwareLicenseManager\Models\Configuration\ConfigurationInterface;
 <...>

 final class MainController
 {
     <...>
     public function __construct(ConfigurationInterface
 $paramConfWithoutRouting)
     {
         <...>
         if(!is_null($this->confWithoutRouting))
         {
 register_activation_hook($this->confWithoutRouting->getPluginPathWithFilename(),
 array(&$this, 'networkOrSingleActivate'));
 register_deactivation_hook($this->confWithoutRouting->getPluginPathWithFilename(),
 array(&$this, 'networkDeactivate'));
             <...>
         }
     }

     /**
      * Activate (enable+install or enable only) plugin for across the
 whole network
      * @note - 'get_sites' function requires WordPress 4.6 or newer!
      */
     public function networkOrSingleActivate()
     {
         if(is_multisite())
         {
             // A workaround until WP will get fixed
             // SHOULD be 'networkActivate' but WordPress does not yet
 support that feature,
             // so this means as long as the 'MULTISITE' constant is
 defined in wp-config, we use that method
             $this->multisiteActivate();
         } else
         {
             // A workaround until WP will get fixed
             $this->activate();
         }
     }

     public function activate()
     {
         try
         {
             <...>
             // Install plugin for single site
             $objInstaller = new
 \GreatestEverManager\Controllers\Admin\InstallController($conf, $lang,
 $conf->getBlogId());
             // Install
             <...>
             $objInstaller->setCustomWP_RestAPI_Prefix();
             <...>
         } catch (\Exception $e)
         {
             if(StaticValidator::inWPDebug())
             {
                 // In WP activation we can kill the install only via
 'trigger_error' with 'E_USER_ERROR' param
                 $error = sprintf(static::LANG_ERROR_IN_METHOD_TEXT,
 __FUNCTION__, $e->getMessage());
                 trigger_error($error, E_USER_ERROR);
             }
         }
     }

     public function run()
     {
         if($this->canProcess)
         {
             <...>
             add_filter('rest_url_prefix', function() { return
 ConfigurationInterface::WP_REST_API_PREFIX; }, 10, 1);
             add_action('rest_api_init', array(&$this,
 'frontEndAPI_Callback'), 0);
             <...>
         }
     }
     <...>
 }
 }}}
 \\
 Plugin main file (wp-
 content/plugins/GreatestEverManager/GreatestEverManager.php):
 {{{#!php
 <?php
 /**
  * Plugin Name: Greatest Ever Manager
  * <...>
  */
 namespace GreatestEverManager;

 require_once 'Models/Configuration/ConfigurationInterface.php';
 require_once 'Models/Configuration/Configuration.php';
 require_once 'Controllers/MainController.php';
 <...>

 use GreatestEverManager\Models\Configuration\Configuration;
 use GreatestEverManager\Controllers\MainController;

 if(!class_exists('GreatestEverManager\GreatestEverManager'))
 {
     final class GreatestEverManager
     {
         // Configuration
         const REQUIRED_PHP_VERSION = '5.4.0';
         const REQUIRED_WP_VERSION = 4.6;
         const OLDEST_COMPATIBLE_PLUGIN_VERSION = 6.0;
         const PLUGIN_VERSION = 6.0;

         // Settings
         private static $params = array(
             'plugin_id' => 0,
             'plugin_prefix' => 'greatest_ever_manager_',
             'plugin_api_namespace' => 'gem/v1',
             'plugin_handle_prefix' => 'greatest-ever-manager-',
             <...>
         );
         private static $objConfiguration = NULL;
         private static $objMainController = NULL;
         <...>

         /**
          * @return Configuration
          */
         public static function getConfiguration()
         {
             if(is_null(static::$objConfiguration) ||
 !(static::$objConfiguration instanceof Configuration))
             {
                 // Create an instance of plugin configuration model
                 static::$objConfiguration = new Configuration(
                     $GLOBALS['wpdb'],
                     get_current_blog_id(),
                     static::REQUIRED_PHP_VERSION, phpversion(),
                     static::REQUIRED_WP_VERSION, $GLOBALS['wp_version'],
                     static::OLDEST_COMPATIBLE_PLUGIN_VERSION,
 static::PLUGIN_VERSION,
                     __FILE__,
                     static::$params
                 );
             }
             return static::$objConfiguration;
         }

         /**
          * Creates new or returns existing instance of plugin main
 controller
          * @return MainController
          */
         public static function getMainController()
         {
             if(is_null(static::$objMainController) ||
 !(static::$objMainController instanceof MainController))
             {
                 // NOTE: This is not passing by reference!
                 static::$objMainController = new
 MainController(static::getConfiguration());
             }

             return static::$objMainController;
         }

         <...>
     }

     <...>

     // Run the plugin
     GreatestEverManager::getMainController()->run();
 }
 }}}
 \\
 The coding pattern is S.O.L.I.D. MVC, Version 6, based on PSR-4
 Autoloaders and PSR-2 Coding Standards.
 To deeply inspect load process (without the REST_API part), you can
 inspect 'Expadandable FAQ' - SolidMVC boiler-plate plugin:
 [https://wordpress.org/plugins/expandable-faq/]

-- 
Ticket URL: <https://core.trac.wordpress.org/ticket/45331>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform


More information about the wp-trac mailing list