forked from zendframework/zend-navigation
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Test for zend-expressive support (without changing existing files)
- Loading branch information
1 parent
2356160
commit 02190ac
Showing
4 changed files
with
345 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
<?php | ||
|
||
namespace Zend\Navigation\Middleware; | ||
|
||
use RecursiveIteratorIterator; | ||
use Zend\Navigation\Page\ExpressivePage; | ||
use Psr\Http\Message\ResponseInterface; | ||
use Psr\Http\Message\ServerRequestInterface; | ||
use Zend\Expressive\Router\RouteResult; | ||
use Zend\Navigation\Navigation; | ||
|
||
/** | ||
* Pipeline middleware for injecting a Navigation with a RouteResult. | ||
*/ | ||
class NavigationMiddleware | ||
{ | ||
/** | ||
* @var Navigation | ||
*/ | ||
private $navigation; | ||
|
||
/** | ||
* @param Navigation $navigation | ||
*/ | ||
public function __construct(Navigation $navigation) | ||
{ | ||
$this->navigation = $navigation; | ||
} | ||
|
||
/** | ||
* @param ServerRequestInterface $request | ||
* @param ResponseInterface $response | ||
* @param callable $next | ||
* @return ResponseInterface | ||
*/ | ||
public function __invoke( | ||
ServerRequestInterface $request, | ||
ResponseInterface $response, | ||
callable $next | ||
) { | ||
$routeResult = $request->getAttribute(RouteResult::class, false); | ||
|
||
if ($routeResult instanceof RouteResult) { | ||
$iterator = new RecursiveIteratorIterator( | ||
$this->navigation, | ||
RecursiveIteratorIterator::SELF_FIRST | ||
); | ||
|
||
foreach ($iterator as $page) { | ||
if ($page instanceof ExpressivePage) { | ||
$page->setRouteResult($routeResult); | ||
} | ||
} | ||
} | ||
|
||
return $next($request, $response); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
<?php | ||
|
||
namespace Zend\Navigation\Middleware; | ||
|
||
use Interop\Container\ContainerInterface; | ||
use Zend\Navigation\Exception\DomainException; | ||
use Zend\Navigation\Navigation; | ||
|
||
class NavigationMiddlewareFactory | ||
{ | ||
public function __invoke(ContainerInterface $container) | ||
{ | ||
if (! $container->has(Navigation::class)) { | ||
throw new DomainException( | ||
sprintf( | ||
'%s requires a %s service at instantiation; none found', | ||
NavigationMiddleware::class, | ||
Navigation::class | ||
) | ||
); | ||
} | ||
|
||
return new NavigationMiddleware($container->get(Navigation::class)); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,178 @@ | ||
<?php | ||
|
||
namespace Zend\Navigation\Page; | ||
|
||
use Zend\Expressive\Router\Exception\RuntimeException as RouterException; | ||
use Zend\Expressive\Router\RouteResult; | ||
use Zend\Expressive\Router\RouterInterface; | ||
use Zend\Navigation\Exception; | ||
|
||
/** | ||
* Class ExpressivePage | ||
*/ | ||
class ExpressivePage extends AbstractPage | ||
{ | ||
/** | ||
* Route name | ||
* | ||
* @var string | ||
*/ | ||
private $routeName; | ||
|
||
/** | ||
* Route parameters | ||
* | ||
* @var array | ||
*/ | ||
private $routeParams = []; | ||
|
||
/** | ||
* @var array | ||
*/ | ||
private $queryParams = []; | ||
|
||
/** | ||
* @var RouteResult | ||
*/ | ||
private $routeResult; | ||
|
||
/** | ||
* @var RouterInterface | ||
*/ | ||
private $router; | ||
|
||
/** | ||
* @var string | ||
*/ | ||
private $hrefCache; | ||
|
||
/** | ||
* @inheritdoc | ||
*/ | ||
public function isActive($recursive = false) | ||
{ | ||
if (! $this->active && $this->routeName !== null | ||
&& $this->routeResult instanceof RouteResult | ||
) { | ||
$intersectionOfParams = array_intersect_assoc( | ||
$this->routeResult->getMatchedParams(), | ||
$this->routeParams | ||
); | ||
|
||
$matchedRouteName = $this->routeResult->getMatchedRouteName(); | ||
|
||
if ($matchedRouteName === $this->routeName | ||
&& count($intersectionOfParams) === count($this->routeParams) | ||
) { | ||
$this->active = true; | ||
|
||
return $this->active; | ||
} | ||
} | ||
|
||
return parent::isActive($recursive); | ||
} | ||
|
||
/** | ||
* @inheritdoc | ||
*/ | ||
public function getHref() | ||
{ | ||
// User cache? | ||
if ($this->hrefCache) { | ||
return $this->hrefCache; | ||
} | ||
|
||
if ($this->routeName === null) { | ||
return $this->generateUriFromResult( | ||
$this->routeParams, | ||
$this->routeResult | ||
); | ||
} | ||
|
||
// Generate the route | ||
$href = $this->router->generateUri( | ||
$this->routeName, | ||
$this->routeParams | ||
); | ||
|
||
// Append query parameters if there are any | ||
if (count($this->queryParams) > 0) { | ||
$href .= '?' . http_build_query($this->queryParams); | ||
} | ||
|
||
// Append the fragment identifier | ||
if ($this->getFragment() !== null) { | ||
$href .= '#' . $this->getFragment(); | ||
} | ||
|
||
return $href; | ||
} | ||
|
||
/** | ||
* @param string|null $route | ||
*/ | ||
public function setRoute($route) | ||
{ | ||
if (null !== $route && (! is_string($route) || empty($route))) { | ||
throw new Exception\InvalidArgumentException( | ||
'Invalid argument: $route must be a non-empty string or null' | ||
); | ||
} | ||
|
||
$this->routeName = $route; | ||
$this->hrefCache = null; | ||
} | ||
|
||
/** | ||
* @param array|null $params | ||
*/ | ||
public function setParams(array $params = null) | ||
{ | ||
$this->routeParams = empty($params) ? [] : $params; | ||
$this->hrefCache = null; | ||
} | ||
|
||
/** | ||
* @param array|null $query | ||
*/ | ||
public function setQuery(array $query = null) | ||
{ | ||
$this->queryParams = empty($query) ? [] : $query; | ||
$this->hrefCache = null; | ||
} | ||
|
||
/** | ||
* @param RouteResult $routeResult | ||
*/ | ||
public function setRouteResult(RouteResult $routeResult) | ||
{ | ||
$this->routeResult = $routeResult; | ||
} | ||
|
||
/** | ||
* @param RouterInterface $router | ||
*/ | ||
public function setRouter(RouterInterface $router) | ||
{ | ||
$this->router = $router; | ||
} | ||
|
||
/** | ||
* @param array $params | ||
* @param RouteResult $result | ||
* @return string | ||
*/ | ||
private function generateUriFromResult(array $params, RouteResult $result) | ||
{ | ||
if ($result->isFailure()) { | ||
throw new RouterException( | ||
'Attempting to use matched result when routing failed; aborting' | ||
); | ||
} | ||
$name = $result->getMatchedRouteName(); | ||
$params = array_merge($result->getMatchedParams(), $params); | ||
|
||
return $this->router->generateUri($name, $params); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
<?php | ||
|
||
namespace Zend\Navigation\Service; | ||
|
||
use Zend\Navigation\Page\ExpressivePage; | ||
use Interop\Container\ContainerInterface; | ||
use Zend\Expressive\Router\RouterInterface; | ||
use Zend\Navigation\Exception; | ||
use Zend\Navigation\Service\DefaultNavigationFactory as BaseDefaultNavigationFactory; | ||
|
||
/** | ||
* Class ExpressiveNavigationFactory | ||
*/ | ||
class ExpressiveNavigationFactory extends BaseDefaultNavigationFactory | ||
{ | ||
/** | ||
* @inheritdoc | ||
*/ | ||
protected function preparePages(ContainerInterface $container, $pages) | ||
{ | ||
// Get router | ||
/** @var RouterInterface $router */ | ||
$router = $container->get(RouterInterface::class); | ||
|
||
return $this->injectComponents($pages, null, $router, null); | ||
} | ||
|
||
/** | ||
* @inheritdoc | ||
*/ | ||
protected function injectComponents( | ||
array $pages, | ||
$routeMatch = null, | ||
$router = null, | ||
$request = null | ||
) { | ||
$this->validateRouter($router); | ||
|
||
foreach ($pages as &$page) { | ||
if (isset($page['route'])) { | ||
// Set Expressive page as page type | ||
$page['type'] = ExpressivePage::class; | ||
|
||
// Set router if exists | ||
if ($router !== null && ! isset($page['router'])) { | ||
$page['router'] = $router; | ||
} | ||
} | ||
|
||
if (isset($page['pages'])) { | ||
$page['pages'] = $this->injectComponents( | ||
$page['pages'], $routeMatch, $router, $request | ||
); | ||
} | ||
} | ||
|
||
return $pages; | ||
} | ||
|
||
/** | ||
* Validate that a router argument provided to injectComponents is valid. | ||
* | ||
* @param null|RouterInterface | ||
* @return void | ||
* @throws Exception\InvalidArgumentException | ||
*/ | ||
private function validateRouter($router) | ||
{ | ||
if (null === $router) { | ||
return; | ||
} | ||
|
||
if (! $router instanceof RouterInterface) { | ||
throw new Exception\InvalidArgumentException( | ||
sprintf( | ||
'%s expected by %s::injectComponents; received %s', | ||
RouterInterface::class, | ||
__CLASS__, | ||
(is_object($router) ? get_class($router) : gettype($router)) | ||
) | ||
); | ||
} | ||
} | ||
} |