[ Index ]

PHP Cross Reference of Joomla 4.2.2 documentation

title

Body

[close]

/libraries/src/Router/ -> ApiRouter.php (source)

   1  <?php
   2  
   3  /**
   4   * Joomla! Content Management System
   5   *
   6   * @copyright  (C) 2019 Open Source Matters, Inc. <https://www.joomla.org>
   7   * @license    GNU General Public License version 2 or later; see LICENSE.txt
   8   */
   9  
  10  namespace Joomla\CMS\Router;
  11  
  12  use Joomla\CMS\Application\CMSApplicationInterface;
  13  use Joomla\CMS\Router\Exception\RouteNotFoundException;
  14  use Joomla\CMS\Uri\Uri;
  15  use Joomla\Router\Route;
  16  use Joomla\Router\Router;
  17  
  18  // phpcs:disable PSR1.Files.SideEffects
  19  \defined('_JEXEC') or die;
  20  // phpcs:enable PSR1.Files.SideEffects
  21  
  22  /**
  23   * Joomla! API Router class
  24   *
  25   * @since  4.0.0
  26   */
  27  class ApiRouter extends Router
  28  {
  29      /**
  30       * The application object
  31       *
  32       * @var    CMSApplicationInterface
  33       * @since  4.0.0
  34       */
  35      protected $app;
  36  
  37      /**
  38       * Constructor.
  39       *
  40       * @param   CMSApplicationInterface  $app   The application object
  41       * @param   array                    $maps  An optional array of route maps
  42       *
  43       * @since   1.0
  44       */
  45      public function __construct(CMSApplicationInterface $app, array $maps = [])
  46      {
  47          $this->app = $app;
  48  
  49          parent::__construct($maps);
  50      }
  51  
  52      /**
  53       * Creates routes map for CRUD
  54       *
  55       * @param   string  $baseName    The base name of the component.
  56       * @param   string  $controller  The name of the controller that contains CRUD functions.
  57       * @param   array   $defaults    An array of default values that are used when the URL is matched.
  58       * @param   bool    $publicGets  Allow the public to make GET requests.
  59       *
  60       * @return  void
  61       *
  62       * @since   4.0.0
  63       */
  64      public function createCRUDRoutes($baseName, $controller, $defaults = [], $publicGets = false)
  65      {
  66          $getDefaults = array_merge(['public' => $publicGets], $defaults);
  67  
  68          $routes = [
  69              new Route(['GET'], $baseName, $controller . '.displayList', [], $getDefaults),
  70              new Route(['GET'], $baseName . '/:id', $controller . '.displayItem', ['id' => '(\d+)'], $getDefaults),
  71              new Route(['POST'], $baseName, $controller . '.add', [], $defaults),
  72              new Route(['PATCH'], $baseName . '/:id', $controller . '.edit', ['id' => '(\d+)'], $defaults),
  73              new Route(['DELETE'], $baseName . '/:id', $controller . '.delete', ['id' => '(\d+)'], $defaults),
  74          ];
  75  
  76          $this->addRoutes($routes);
  77      }
  78  
  79      /**
  80       * Parse the given route and return the name of a controller mapped to the given route.
  81       *
  82       * @param   string  $method  Request method to match. One of GET, POST, PUT, DELETE, HEAD, OPTIONS, TRACE or PATCH
  83       *
  84       * @return  array   An array containing the controller and the matched variables.
  85       *
  86       * @since   4.0.0
  87       * @throws  \InvalidArgumentException
  88       */
  89      public function parseApiRoute($method = 'GET')
  90      {
  91          $method = strtoupper($method);
  92  
  93          $validMethods = ["GET", "POST", "PUT", "DELETE", "HEAD", "TRACE", "PATCH"];
  94  
  95          if (!\in_array($method, $validMethods)) {
  96              throw new \InvalidArgumentException(sprintf('%s is not a valid HTTP method.', $method));
  97          }
  98  
  99          // Get the path from the route and remove and leading or trailing slash.
 100          $routePath = $this->getRoutePath();
 101  
 102          $query = Uri::getInstance()->getQuery(true);
 103  
 104          // Iterate through all of the known routes looking for a match.
 105          foreach ($this->routes as $route) {
 106              if (\in_array($method, $route->getMethods())) {
 107                  if (preg_match($route->getRegex(), ltrim($routePath, '/'), $matches)) {
 108                      // If we have gotten this far then we have a positive match.
 109                      $vars = $route->getDefaults();
 110  
 111                      foreach ($route->getRouteVariables() as $i => $var) {
 112                          $vars[$var] = $matches[$i + 1];
 113                      }
 114  
 115                      $controller = preg_split("/[.]+/", $route->getController());
 116                      $vars       = array_merge($vars, $query);
 117  
 118                      return [
 119                          'controller' => $controller[0],
 120                          'task'       => $controller[1],
 121                          'vars'       => $vars
 122                      ];
 123                  }
 124              }
 125          }
 126  
 127          throw new RouteNotFoundException(sprintf('Unable to handle request for route `%s`.', $routePath));
 128      }
 129  
 130      /**
 131       * Get the path from the route and remove and leading or trailing slash.
 132       *
 133       * @return string
 134       *
 135       * @since 4.0.0
 136       */
 137      public function getRoutePath()
 138      {
 139          // Get the path from the route and remove and leading or trailing slash.
 140          $uri  = Uri::getInstance();
 141          $path = urldecode($uri->getPath());
 142  
 143          /**
 144           * In some environments (e.g. CLI we can't form a valid base URL). In this case we catch the exception thrown
 145           * by URI and set an empty base URI for further work.
 146           * @todo: This should probably be handled better
 147           */
 148          try {
 149              $baseUri = Uri::base(true);
 150          } catch (\RuntimeException $e) {
 151              $baseUri = '';
 152          }
 153  
 154          // Remove the base URI path.
 155          $path = substr_replace($path, '', 0, \strlen($baseUri));
 156  
 157          // Transform the route
 158          $path = $this->removeIndexPhpFromPath($path);
 159  
 160          return $path;
 161      }
 162  
 163      /**
 164       * Removes the index.php from the route's path.
 165       *
 166       * @param   string  $path  The path
 167       *
 168       * @return  string
 169       *
 170       * @since   4.0.0
 171       */
 172      private function removeIndexPhpFromPath(string $path): string
 173      {
 174          // Normalize the path
 175          $path = ltrim($path, '/');
 176  
 177          // We can only remove index.php if it's present in the beginning of the route
 178          if (strpos($path, 'index.php') !== 0) {
 179              return $path;
 180          }
 181  
 182          // Edge case: the route is index.php without a trailing slash. Bad idea but we can still map it to a null route.
 183          if ($path === 'index.php') {
 184              return '';
 185          }
 186  
 187          // Remove the "index.php/" part of the route and return the result.
 188          return substr($path, 10);
 189      }
 190  
 191      /**
 192       * Extract routes matching current route from all known routes.
 193       *
 194       * @return \Joomla\Router\Route[]
 195       *
 196       * @since 4.0.0
 197       */
 198      public function getMatchingRoutes()
 199      {
 200          $routePath = $this->getRoutePath();
 201  
 202          // Extract routes matching $routePath from all known routes.
 203          return array_filter(
 204              $this->routes,
 205              function ($route) use ($routePath) {
 206                  return preg_match($route->getRegex(), ltrim($routePath, '/')) === 1;
 207              }
 208          );
 209      }
 210  }


Generated: Wed Sep 7 05:41:13 2022 Chilli.vc Blog - For Webmaster,Blog-Writer,System Admin and Domainer