Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions Bonder/Collections/Map.php
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,17 @@ public function get($key, $default = null) {
public function set($key, $value) {
$this->values[$key] = $value;
}

/**
* Sets all the values from the $otherMap.
*
* @param Map $otherMap the other map.
*/
public function setAll(Map $otherMap) {
foreach ($otherMap->values as $key => &$value) {
$this->set($key, $value);
}
}

/**
* Removes the specified key from the map.
Expand Down
7 changes: 7 additions & 0 deletions Bonder/Controller.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,11 @@ interface Controller {
*/
public function service(\Bonder\Request $request);

/** Returns the Filters configuration. Should return an array
* mapping alias names to filter classes.
*
* @return array An array (alias => filter class name).
*/
public function getFilters();

}
10 changes: 9 additions & 1 deletion Bonder/Controllers/FixedResponseController.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,13 @@ public function __construct(\Bonder\Response $response) {
public function service(\Bonder\Request $request) {
return $this->response;
}


/** Returns the Filters configuration. Should return an array
* mapping alias names to filter classes.
*
* @return array An array (alias => filter class name).
*/
public function getFilters() {
return array();
}
}
10 changes: 9 additions & 1 deletion Bonder/Controllers/LambdaController.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,13 @@ public function service(\Bonder\Request $request) {
$function = $this->lambda;
return $function($request);
}


/** Returns the Filters configuration. Should return an array
* mapping alias names to filter classes.
*
* @return array An array (alias => filter class name).
*/
public function getFilters() {
return array();
}
}
14 changes: 8 additions & 6 deletions Bonder/Filters/ConfiguredFiltersProvider.php
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
<?php

namespace Bonder\Filters;
use Bonder\Controller;
use Bonder\Filters\FiltersProvider;

/**
* Decorates a filters provider, configuring the filter instances.
*
* @author hbandura
*/
final class ConfiguredFiltersProvider
implements \Bonder\Filters\FiltersProvider {
implements FiltersProvider {

/**
* @var \Bonder\Filters\FiltersProvider
* @var FiltersProvider
*/
private $wrappedProvider;

Expand All @@ -23,12 +25,12 @@ final class ConfiguredFiltersProvider
/**
* Creates a new ConfiguredFiltersProvider with the arguments given.
*
* @param \Bonder\Filters\FiltersProvider $wrappedProvider the wrapped
* @param FiltersProvider $wrappedProvider the wrapped
* provider.
* @param \Bonder\Util\Configurator $configurator the configurator.
*/
public function __construct(
\Bonder\Filters\FiltersProvider $wrappedProvider,
FiltersProvider $wrappedProvider,
\Bonder\Util\Configurator $configurator) {
$this->wrappedProvider = $wrappedProvider;
$this->configurator = $configurator;
Expand All @@ -38,8 +40,8 @@ public function __construct(
* (non-PHPdoc)
* @see Bonder\Filters.FiltersProvider::getFilters()
*/
public function getFilters($uri) {
$result = $this->wrappedProvider->getFilters($uri);
public function getFilters($uri, Controller $controller) {
$result = $this->wrappedProvider->getFilters($uri, $controller);
$configurator = $this->configurator;
array_walk($result, function($filter) use ($configurator) {
$configurator->configure($filter);
Expand Down
2 changes: 1 addition & 1 deletion Bonder/Filters/CrafterFilterChainProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public function __construct(
*/
public function get($uri) {
$controllerResult = $this->controllerProvider->getResult($uri);
$filters = $this->filtersProvider->getFilters($uri);
$filters = $this->filtersProvider->getFilters($uri, $controllerResult->getController());
return new \Bonder\Filters\FilterChainProviderResult(
new \Bonder\Filters\SimpleFilterChain($filters, $controllerResult->getController()),
$controllerResult->getUriVariables());
Expand Down
2 changes: 1 addition & 1 deletion Bonder/Filters/FilterChain.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,6 @@ public function getFilters();
* @param \Bonder\Request $request the request.
* @return \Bonder\Response the response.
*/
public function call(\Bonder\Request $request);
public function execute(\Bonder\Request $request);

}
11 changes: 6 additions & 5 deletions Bonder/Filters/FiltersProvider.php
Original file line number Diff line number Diff line change
@@ -1,20 +1,21 @@
<?php

namespace Bonder\Filters;
use Bonder\Controller;

/**
* Provides the filters to be used by a given uri.
* Provides the filters to be used by a given uri and controller.
*
* @author hbandura
*/
interface FiltersProvider {

/**
* Returns the filters for the given uri.
* Returns the filters for the given uri (global) and the controller.
*
* @param string $uri the uri.
* @return \Bonder\Filter[] the filters.
* @return \Bonder\Filter[] the filters, as an array of alias => filter.
*/
public function getFilters($uri);
public function getFilters($uri, Controller $controller);

}
16 changes: 10 additions & 6 deletions Bonder/Filters/LambdaFilter.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
<?php

namespace Bonder\Filters;
use Bonder\Filters\NextFilterCaller;
use Bonder\Request;

/**
* Closure / lambda-function filter.
Expand All @@ -10,24 +12,26 @@
final class LambdaFilter implements \Bonder\Filter {

/**
* @var function
* Callable function.
*
* @var callable
*/
private $lambda;

/**
* Creates a new LambdaFilter with the lambda function given.
*
* @param function $lambda function.
* @param mixed $lambda function.
*/
public function __construct($lambda) {
$this->lambda = $lambda;
if (!is_callable($lambda)) {
throw new \Bonder\Exceptions\Exception("Argument lambda is not callable");
if (!is_callable($lambda)) {
throw new \Bonder\Exceptions\Exception("Argument lambda is not callable");
}
}

public function filter(\Bonder\Request $request,
\Bonder\Filters\NextFilterCaller $next) {
public function filter(Request $request,
NextFilterCaller $next) {
$lambda = $this->lambda;
return $lambda($request, $next);
}
Expand Down
13 changes: 8 additions & 5 deletions Bonder/Filters/NextFilterCaller.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

namespace Bonder\Filters;

use Bonder\Request;

/**
* Caller for the next filter in the chain.
*
Expand All @@ -11,11 +13,12 @@
interface NextFilterCaller {

/**
* Calls the next filter.
*
* @param \Bonder\Request $request the request.
* Calls the next filter, passing along the processed
* variable values as an array (varname => value).
*
* @param Request $request the request.
* @param array $variables the variables.
* @return \Bonder\Response the response.
*/
public function call(\Bonder\Request $request);

public function call(Request $request, Array $variables = array());
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Used to send the processed variables from the current filter. They could then be retrieved in the controller with something like $context->getFilterVariables(FilterClass)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FilterClass string or we'll use the alias?

}
83 changes: 69 additions & 14 deletions Bonder/Filters/SimpleFilterChain.php
Original file line number Diff line number Diff line change
@@ -1,41 +1,51 @@
<?php

namespace Bonder\Filters;
use Bonder\Collections\Map;
use Bonder\Controller;
use Bonder\Request;

/**
* A filter chain used in a request dispatch.
*
* @author hbandura
*/
final class SimpleFilterChain implements
\Bonder\Filters\FilterChain,
\Bonder\Filters\NextFilterCaller {
\Bonder\Filters\FilterChain {

/**
* @var \Bonder\Filter[]
*/
private $filters;

/**
* @var Array(alias, \Bonder\Filter) []
*/
private $filtersList;

/**
* @var \Bonder\Controller
* @var Controller
*/
private $controller;

/**
* Creates a new FilterChain.
*
* @param \Bonder\Filter[] $filters the filters, in order.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we reflect the 'alias' => 'filter' feature in the comment? Something like:

  • @param \Bonder\Filter[] $filters 'alias' => 'filter', in order of execution.

* @param \Bonder\Controller $controller the controller, the end of the chain.
* @param Controller $controller the controller, the end of the chain.
*/
public function __construct(Array $filters, \Bonder\Controller $controller) {
public function __construct(Array $filters, Controller $controller) {
$this->filters = $filters;
$this->controller = $controller;
foreach ($this->filters as $alias => $filter) {
$this->filtersList[] = array($alias, $filter);
}
}

/**
* Returns the controller.
*
* @return \Bonder\Controller the controller.
* @return Controller the controller.
*/
public function getController() {
return $this->controller;
Expand All @@ -54,17 +64,62 @@ public function getFilters() {
* Executes the first filter in the chain. If no filters are available,
* calls the controller.
*
* @param \Bonder\Request $request the request.
* @param Request $request the request.
* @return \Bonder\Response the response.
*/
public function call(\Bonder\Request $request) {
if (empty($this->filters)) {
public function execute(Request $request) {
return $this->executeStep($request, 0);
}

/**
* Recursion entry point for next filter callers. Public because PHP lacks private inner classes.
*
* @param Request $request
* @param $step
* @param Map $filterVariables
* @return mixed
*/
public function executeStep(Request $request, $step) {
if ($step < count($this->filtersList)) {
list($alias, $filter) = $this->filtersList[$step];
return $filter->filter($request, new SimpleFilterChainNextCaller($this, $step + 1, $alias));
}
if ($step == count($this->filtersList)) {
return $this->controller->service($request);
}
$nextFilter = reset($this->filters);
$nextFilters = array_slice($this->filters, 1);
return $nextFilter->filter($request,
new SimpleFilterChain($nextFilters, $this->controller));
throw new \InvalidArgumentException("Step can't be higher than the filters amount + 1");
}

}

/** Utility class to simplify filter chain recursion. */
final class SimpleFilterChainNextCaller implements NextFilterCaller {

/**
* @var SimpleFilterChain
*/
private $filterChain;

/**
* @var int
*/
private $step;

/**
* @var string
*/
private $alias;

public function __construct(SimpleFilterChain $filterChain, $step, $alias) {
$this->filterChain = $filterChain;
$this->step = $step;
$this->alias = $alias;
}

public function call(Request $request, Array $variables = array()) {
if (!is_numeric($this->alias)) {
$request->getFilterVariables()->set($this->alias, Map::fromArray($variables));
}
return $this->filterChain->executeStep($request, $this->step);
}

}
8 changes: 6 additions & 2 deletions Bonder/Filters/ValueFinderFiltersProvider.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<?php

namespace Bonder\Filters;
use Bonder\Controller;

/**
* Filters provider implementation using a value finder.
Expand Down Expand Up @@ -28,11 +29,14 @@ public function __construct(\Bonder\Util\ValueFinder $valueFinder) {
* (non-PHPdoc)
* @see Bonder\Filters.FiltersProvider::getFilters()
*/
public function getFilters($uri) {
public function getFilters($uri, Controller $controller) {
$results = $this->valueFinder->getAllValues($uri);
return array_map(function(\Bonder\Util\ValueFinderResult $r) {
$global = array_map(function(\Bonder\Util\ValueFinderResult $r) {
return $r->getValue();
}, $results);
$cFilters = $controller->getFilters();
$allFilters = array_merge($global, $cFilters);
return $allFilters;
}

}
5 changes: 5 additions & 0 deletions Bonder/Http/HttpController.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ abstract class HttpController implements \Bonder\Controller, \Bonder\ContextAwar
*/
private $context;

public function getFilters() {
// No filters in the default implementation.
return array();
}

public function setContext(\Bonder\Context $context) {
$this->context = $context;
}
Expand Down
Loading