Skip to content

Commit

Permalink
update
Browse files Browse the repository at this point in the history
  • Loading branch information
ncou committed Jun 30, 2019
1 parent ec8107d commit bb01d98
Show file tree
Hide file tree
Showing 16 changed files with 420 additions and 276 deletions.
4 changes: 4 additions & 0 deletions src/Chiron/Provider/RouterServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
use Chiron\Kernel;
use Chiron\Routing\Resolver\ControllerResolver;
use Chiron\Routing\Router;
use Chiron\Routing\RouteCollector;
use Chiron\Routing\RouterInterface;
use Chiron\Routing\Strategy\HtmlStrategy;
use Psr\Container\ContainerInterface;
Expand Down Expand Up @@ -62,6 +63,9 @@ public function register(Container $container): void
// TODO : aller chercher la controllerResolver directement dans le container plutot que de faire un new !!!! ca permettra de faire un override de cette classe si l'utilisateur souhaite redéfinir le resolver.
$router->setStrategy(new HtmlStrategy($container->get('kernel')));

//$collector = new RouteCollector();
//$router->setRouteCollector($collector);

return $router;
});

Expand Down
11 changes: 7 additions & 4 deletions src/Chiron/Routing/Dispatcher.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,15 @@

class Dispatcher extends GroupCountBasedDispatcher
{
private $routes;
//private $routes;

// mixed[] $data
/*
public function __construct(array $routes, array $data)
{
$this->routes = $routes;
parent::__construct($data);
}
}*/

/**
* Dispatch the current route.
Expand Down Expand Up @@ -60,8 +61,10 @@ private function marshalFailedRoute(array $result): RouteResult
// TODO : attention le paramétre $method n'est pas utilisé !!!! => https://github.com/zendframework/zend-expressive-fastroute/blob/master/src/FastRouteRouter.php#L397
private function marshalMatchedRoute(array $result): RouteResult
{
$identifier = $result[1];
$route = $this->routes[$identifier];
//$identifier = $result[1];
//$route = $this->routes[$identifier];

$route = $result[1];
$params = $result[2];

return RouteResult::fromRoute($route, $params);
Expand Down
145 changes: 145 additions & 0 deletions src/Chiron/Routing/RouteCollector.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
<?php

declare(strict_types=1);

namespace Chiron\Routing;

use Chiron\Routing\Traits\MiddlewareAwareInterface;
use Chiron\Routing\Traits\MiddlewareAwareTrait;
use Chiron\Routing\Traits\RouteConditionHandlerInterface;
use Chiron\Routing\Traits\RouteCollectionTrait;
use Chiron\Routing\Traits\StrategyAwareInterface;
use Chiron\Routing\Traits\StrategyAwareTrait;
use InvalidArgumentException;
use ArrayIterator;

// TODO : voir si on doit pas ajouyer une méthode pour initialiser la strategy par défaut quand on appel la méthode getIterator() cela éviterai de faire cette alimentation de la strategy de la route si elle est vide dans la classe router.
// TODO : virer la partie middleware de cette classe.
class RouteCollector implements RouteCollectorInterface
{
use RouteCollectionTrait;

/**
* @var \Chiron\Routing\Route[]
*/
private $routes = [];

/**
* @var \Chiron\Routing\RouteGroup[]
*/
private $groups = [];

/**
* {@inheritdoc}
*/
public function map(string $path, $handler): Route
{
// TODO : il faudrait peut etre remonter ce controle durectement dans l'objet Route() non ????
if (! is_string($handler) && ! is_callable($handler)) {
throw new InvalidArgumentException('Route Handler should be a callable or a string (service name in the container or class name).');
}

// TODO : attention vérifier si cette modification du path avec un slash n'est pas en doublon avec celle qui est faite dans la classe Route !!!!
$path = sprintf('/%s', ltrim($path, '/'));
$route = new Route($path, $handler);

// TODO : créer une méthode public "addRoute(RouteInterface $route)" ??????
//$this->routes[uniqid('UID_', true)] = $route;
$this->routes[] = $route;

return $route;
}

/**
* Add a group of routes to the collection.
*
* @param string $prefix
* @param callable $group
*
* @return \Chiron\Routing\RouteGroup
*/
// TODO : vérifier si on pas plutot utiliser un Closure au lieu d'un callable pour le typehint.
// TODO : il semble pôssible dans Slim de passer une string, ou un callable. Vérifier l'utilité de cette possibilité d'avoir un string !!!!
public function group(string $prefix, callable $callback): RouteGroup
{
$group = new RouteGroup($prefix, $callback, $this);

$this->groups[] = $group;

return $group;
}

/**
* Process all groups.
*/
// A voir si cette méthode ne devrait pas être appellée directement dans la méthode ->group() pour préparer les routes dés qu'on ajoute un group !!!!
// https://github.com/slimphp/Slim/blob/4.x/Slim/Routing/RouteCollector.php#L255
private function processGroups(): void
{
// TODO : vérifier si il ne faut pas faire un array_reverse lorsqu'on execute les groups. Surtout dans le cas ou on ajoute des middlewares au group et qui seront propagés à la route.
//https://github.com/slimphp/Slim/blob/4.x/Slim/Routing/Route.php#L350

// Call the $group by reference because in the case : group of group the size of the array is modified because a new group is added in the group() function.
foreach ($this->groups as $key => &$group) {
// TODO : déplacer le unset aprés la méthode invoke ou collectroute du group. Voir si c'est pas plus ^propre de remplacer le unset par un array_pop ou un array_shift !!!!
unset($this->groups[$key]);
// TODO : créer une méthode ->collectRoutes() dans la classe RouteGroup, au lieu d'utiliser le invoke() on utilisera cette méthode, c'est plus propre !!!!
$group();
//array_pop($this->groups);
//array_shift($this->routeGroups);
}
}

/**
* Get route objects.
*
* @return Route[]
*/
public function getRoutes(): array
{
//return array_values($this->toArray());
//return iterator_to_array($this->getIterator());


$this->processGroups();

return $this->routes;
}

/**
* Get a named route.
*
* @param string $name Route name
*
* @throws \InvalidArgumentException If named route does not exist
*
* @return \Chiron\Routing\Route
*/
public function getNamedRoute(string $name): Route
{
foreach ($this->getRoutes() as $route) {
if ($route->getName() === $name) {
return $route;
}
}

throw new InvalidArgumentException('Named route does not exist for name: ' . $name);
}

/**
* Remove named route.
*
* @param string $name Route name
*
* @throws \InvalidArgumentException If named route does not exist
*/
public function removeNamedRoute(string $name): void
{
$route = $this->getNamedRoute($name);
// no exception, route exists, now remove by id
//unset($this->routes[$route->getIdentifier()]);
// no exception so far so the route exists we can remove the object safely.
unset($this->routes[array_search($route, $this->routes)]);
}

}
39 changes: 39 additions & 0 deletions src/Chiron/Routing/RouteCollectorInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?php

declare(strict_types=1);

namespace Chiron\Routing;

use Chiron\Routing\Traits\RouteCollectionInterface;
use Psr\Http\Message\ServerRequestInterface;
use IteratorAggregate;

interface RouteCollectorInterface extends RouteCollectionInterface
{
/**
* Get route objects.
*
* @return Route[]
*/
public function getRoutes(): array;

/**
* Get a named route.
*
* @param string $name Route name
*
* @throws \InvalidArgumentException If named route does not exist
*
* @return \Chiron\Routing\Route
*/
public function getNamedRoute(string $name): Route;

/**
* Remove named route.
*
* @param string $name Route name
*
* @throws \InvalidArgumentException If named route does not exist
*/
public function removeNamedRoute(string $name): void;
}
1 change: 1 addition & 0 deletions src/Chiron/Routing/RouteGroup.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ class RouteGroup implements MiddlewareAwareInterface, RouteCollectionInterface,
*/
// TODO : vérifier si on pas plutot utiliser un Closure au lieu d'un callable pour le typehint
// TODO : permettre de passer un callback null, dans ce cas on initialisera avec une fonction vide !!! il faudrait que cela soit géré dans la fonction "group" de la routeCollecitonInterface
// TODO : passer en paramétre un RouteCollectorInterface et non pas un RouteCollectionInterface. non ????
public function __construct(string $prefix, callable $callback, RouteCollectionInterface $collection)
{
$this->callback = $callback;
Expand Down
60 changes: 12 additions & 48 deletions src/Chiron/Routing/RouteUrlGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,12 @@

class RouteUrlGenerator
{
/** @var FastRoute\RouteParser\Std */
private $parser;

private $router;

/**
* Characters that should not be URL encoded.
*
* @var array
*/
private $dontEncode = [
private static $dontEncode = [
'%2F' => '/',
'%40' => '@',
'%3A' => ':',
Expand All @@ -39,42 +34,10 @@ class RouteUrlGenerator
'%25' => '%',
];

// TODO : lui passer plutot un routeCollector en paramétre !!!!
public function __construct(Router $router)
{
// build parent route collector
$this->parser = new Std();
$this->router = $router;
}

/**
* Build the path for a named route including the base path.
*
* @param string $routeName Route name
* @param array $substitutions Named argument replacement data
* @param array $queryParams Optional query string parameters
*
* @throws InvalidArgumentException If named route does not exist
* @throws InvalidArgumentException If required data not provided
*
* @return string
*/
//https://github.com/illuminate/routing/blob/master/RouteUrlGenerator.php#L77
public function urlFor(string $routeName, array $substitutions = [], array $queryParams = []): string
{
$url = $this->relativeUrlFor($routeName, $substitutions, $queryParams);

if ($basePath = $this->router->getBasePath()) {
$url = $basePath . $url;
}

return $url;
}

/**
* Build the path for a named route excluding the base path.
*
* @param string $routeName Route name
* @param string $routePath Route path pattern
* @param array $substitutions Named argument replacement data
* @param array $queryParams Optional query string parameters
*
Expand All @@ -88,11 +51,12 @@ public function urlFor(string $routeName, array $substitutions = [], array $quer
// TODO ; utiliser ce bout de code : https://github.com/slimphp/Slim/blob/4.x/Slim/Routing/RouteParser.php#L42
// TODO : améliorer le code avec cette partie là => https://github.com/illuminate/routing/blob/master/RouteUrlGenerator.php#L77
// https://github.com/zendframework/zend-expressive-fastroute/blob/master/src/FastRouteRouter.php#L239
public function relativeUrlFor(string $routeName, array $substitutions = [], array $queryParams = []): string
//https://github.com/illuminate/routing/blob/master/RouteUrlGenerator.php#L77
public static function generate(string $routePath, array $substitutions = [], array $queryParams = []): string
{
$route = $this->router->getNamedRoute($routeName);
$pattern = $route->getPath();
$routeDatas = $this->parser->parse($pattern);
$parser = new Std();
$routeDatas = $parser->parse($routePath);

// $routeDatas is an array of all possible routes that can be made. There is
// one routedata for each optional parameter plus one for no optional parameters.
//
Expand Down Expand Up @@ -150,11 +114,11 @@ public function relativeUrlFor(string $routeName, array $substitutions = [], arr
if ($queryParams) {
// TODO : améliorer le code avec ca : https://github.com/illuminate/routing/blob/master/RouteUrlGenerator.php#L255 et ca : https://github.com/illuminate/support/blob/master/Arr.php#L599
//$url .= '?' . http_build_query($queryParams);
$url = $this->addQueryString($url, $queryParams);
$url = self::addQueryString($url, $queryParams);
}

// We will encode the URI and prepare it for returning to the developer.
$url = strtr(rawurlencode($url), $this->dontEncode);
$url = strtr(rawurlencode($url), self::$dontEncode);

return $url;
}
Expand All @@ -167,15 +131,15 @@ public function relativeUrlFor(string $routeName, array $substitutions = [], arr
*
* @return mixed|string
*/
protected function addQueryString(string $url, array $parameters): string
private static function addQueryString(string $url, array $parameters): string
{
// If the URI has a fragment we will move it to the end of this URI since it will
// need to come after any query string that may be added to the URL else it is
// not going to be available. We will remove it then append it back on here.
if (! is_null($fragment = parse_url($url, PHP_URL_FRAGMENT))) {
$url = preg_replace('/#.*/', '', $url);
}
$url .= $this->getRouteQueryString($parameters);
$url .= self::getRouteQueryString($parameters);

return is_null($fragment) ? $url : $url . "#{$fragment}";
}
Expand All @@ -187,7 +151,7 @@ protected function addQueryString(string $url, array $parameters): string
*
* @return string
*/
protected function getRouteQueryString(array $parameters): string
private static function getRouteQueryString(array $parameters): string
{
$query = http_build_query($parameters, '', '&', PHP_QUERY_RFC3986);

Expand Down
Loading

0 comments on commit bb01d98

Please sign in to comment.