Skip to content

Commit

Permalink
feat(upgrade): use multiple routes (#70)
Browse files Browse the repository at this point in the history
* feat(upgrade): use multiple routes
* feat(upgrade): re add route param as deprecated
  • Loading branch information
raf262 authored Aug 30, 2022
1 parent c406a5b commit e187c68
Show file tree
Hide file tree
Showing 16 changed files with 402 additions and 69 deletions.
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,29 +45,34 @@ m6_web_log_bridge:
filters:
get_article_error:
route: get_article
routes: ['get_article']
method: ['GET']
status: [422, 500]
level: 'error'
options:
response_body: true # from add Response body content (with DefaultFormatter)
post_article_all:
route: post_article
routes: ['post_article']
method: ~ # from all methods
status: ~ # from all status
get_article_not_found:
route: get_article
routes: ['get_article']
method: ['GET']
status: [404]
level: 'warning'
edit_category:
route: get_category
routes: ['get_category']
method: ['POST', 'PUT']
status: [400-422, ^510, !530-550]
level: 'error'
options:
post_parameters: true # From add post parameters in response content (with DefaultFormatter)
all_error: # All route, all method in error
route: ~
routes: ~
method: ~
status: [31*, 4*, 5*]
level: 'critical'
Expand All @@ -79,6 +84,13 @@ m6_web_log_bridge:
channel: my_channel_to_log # monolog channel, optional, default 'log_bridge'
```
Routes support multiples formats :
```yaml
routes: ['my_route'] # Add only this route
routes: ['my_route', 'another_route'] # Add multiples routes
routes: ['!excluded_one', '!excluded_two'] # Add all routes except the excluded
```
*By default, `level` is `info`*

You can declare all the options you want.
Expand Down
14 changes: 14 additions & 0 deletions src/M6Web/Bundle/LogBridgeBundle/Config/Filter.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ class Filter
{
private ?string $route = null;

private ?array $routes = [];

/** @var string[]|null */
private ?array $method = null;

Expand Down Expand Up @@ -43,6 +45,18 @@ public function getRoute(): ?string
return $this->route;
}

public function setRoutes(?array $routes): self
{
$this->routes = $routes;

return $this;
}

public function getRoutes(): ?array
{
return $this->routes;
}

/**
* @param string[]|null $method
*/
Expand Down
61 changes: 58 additions & 3 deletions src/M6Web/Bundle/LogBridgeBundle/Config/FilterParser.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,17 @@ protected function isRoute(string $name): bool
return $this->router?->getRouteCollection()->get($name) !== null;
}

protected function getAllRoutes(): array
{
$routesCollection = $this->router?->getRouteCollection()->all();

return array_keys($routesCollection);
}

/**
* @param array{
* route?: string,
* routes?: string[],
* method?: string[],
* status?: int[],
* level?: string,
Expand All @@ -59,11 +67,15 @@ protected function isRoute(string $name): bool
public function parse(string $name, array $config): Filter
{
if (
!array_key_exists('route', $config) ||
(!array_key_exists('route', $config) && !array_key_exists('routes', $config)) ||
!array_key_exists('method', $config) ||
!array_key_exists('status', $config)
) {
throw new ParseException(sprintf('Undefined "route", "method" or "status" parameter from filter "%s"', $name));
throw new ParseException(sprintf('Undefined "route(s)", "method" or "status" parameter from filter "%s"', $name));
}

if (array_key_exists('route', $config) && array_key_exists('routes', $config)) {
throw new ParseException(sprintf('You can\'t use both "route" and "routes" parameter from filter "%s"', $name));
}

if (!array_key_exists('level', $config)) {
Expand All @@ -74,7 +86,14 @@ public function parse(string $name, array $config): Filter
->setMethod($config['method'])
->setStatus($config['status']);

$this->parseRoute($filter, $config['route']);
if (array_key_exists('route', $config)) {
$this->parseRoute($filter, $config['route']);
}

if (array_key_exists('routes', $config)) {
$this->parseRoutes($filter, $config['routes'] ?? []);
}

$this->parseLevel($filter, $config['level']);

return $filter->setOptions($config['options'] ?? []);
Expand All @@ -89,6 +108,42 @@ protected function parseRoute(Filter $filter, ?string $route): void
$filter->setRoute($route);
}

protected function parseRoutes(Filter $filter, ?array $routes): void
{
if (empty($routes)) {
$filter->setRoutes(['all']);

return;
}

// Find and keep excluded routes
$excludedRoutes = array_filter($routes, function (string $route) {
return str_starts_with($route, '!');
});

// Create an array with routes not excluded
$routes = array_diff_key($routes, $excludedRoutes);

// Check that the route's name exist
foreach ($routes as $route) {
if (!$this->isRoute($route)) {
throw new ParseException(sprintf('Undefined route "%s" from router service', $route));
}
}

// If empty routes, return all routes except the excluded ones
if (empty($routes)) {
$existingRoutes = $this->getAllRoutes();
$excludedRoutes = array_map(function (string $route) {
return ltrim($route, '!');
}, $excludedRoutes);

$routes = array_values(array_diff($existingRoutes, $excludedRoutes));
}

$filter->setRoutes($routes);
}

protected function parseLevel(Filter $filter, ?string $level): void
{
if (!in_array($level, $this->allowedLevels, true)) {
Expand Down
2 changes: 2 additions & 0 deletions src/M6Web/Bundle/LogBridgeBundle/Config/Parser.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ public function __construct(private RouterInterface $router)
/**
* @param array<string, array{
* route?: string,
* routes?: string[],
* method?: string[],
* status?: int[],
* level?: string,
Expand All @@ -43,6 +44,7 @@ protected function createFilterCollection(array $filters): FilterCollection
* @param array{
* filters?: array<string, array{
* route?: string,
* routes?: string[],
* method?: string[],
* status?: int[],
* level?: string,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,17 @@ public function getConfigTreeBuilder(): TreeBuilder
->useAttributeAsKey('name')
->prototype('array')
->children()
->scalarNode('route')->defaultNull()->end()
->scalarNode('route')
->defaultNull()
->setDeprecated(
'm6web/log-bridge-bundle',
'10.1',
'The "route" option is deprecated. Use "routes" instead.'
)
->end()
->arrayNode('routes')
->prototype('scalar')->end()
->end()
->arrayNode('method')
->prototype('scalar')->end()
->end()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public function getLogContent(Request $request, Response $response, array $optio
/**
* @param array<string, bool|string> $options
*
* @return array<string, string|int>
* @return array<string, array|int|string>
*/
public function getLogContext(Request $request, Response $response, array $options): array;
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ interface BuilderInterface
/**
* @param array<string, array{
* route?: string,
* routes?: string[],
* method?: string[],
* status?: int[],
* level?: string,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -258,9 +258,25 @@ private function compileFilter(Filter $filter): array
{
$compiledKeys = [];
$compiled = [];
/** @var array $routesPrefix */
$routesPrefix = $filter->getRoutes();
/** @var string $prefix */
$prefix = is_null($filter->getRoute()) ? 'all' : $filter->getRoute();

$compiledKeys = isset($routesPrefix) ?
$this->compileFilterRoutes($filter, $routesPrefix, $compiledKeys) :
$this->compileFilterRoute($filter, $prefix, $compiledKeys);

foreach ($compiledKeys as $key) {
$compiled[$key]['options'] = $filter->getOptions();
$compiled[$key]['level'] = $filter->getLevel();
}

return $compiled;
}

private function compileFilterRoute(Filter $filter, string $prefix, array $compiledKeys): array
{
if (empty($filter->getMethod())) {
$prefix = sprintf('%s.all', $prefix);
$compiledKeys = $this->compileFilterStatus($prefix, $filter);
Expand All @@ -271,18 +287,34 @@ private function compileFilter(Filter $filter): array
}
}

foreach ($compiledKeys as $key) {
$compiled[$key]['options'] = $filter->getOptions();
$compiled[$key]['level'] = $filter->getLevel();
return $compiledKeys;
}

private function compileFilterRoutes(Filter $filter, ?array $routesPrefix, array $compiledKeys): array
{
if (empty($filter->getMethod())) {
foreach ($routesPrefix as $routePrefix) {
$prefix = sprintf('%s.all', $routePrefix);
$compiledKeys = array_merge($compiledKeys, $this->compileFilterStatus($prefix, $filter));
}

return $compiledKeys;
}

return $compiled;
foreach ($filter->getMethod() as $method) {
foreach ($routesPrefix as $routePrefix) {
$methodPrefix = sprintf('%s.%s', $routePrefix, $method);
$compiledKeys = array_merge($compiledKeys, $this->compileFilterStatus($methodPrefix, $filter));
}
}

return $compiledKeys;
}

/**
* @return string[]
*/
private function compileFilterStatus(string $prefix, Filter $filter): array
private function compileFilterStatus(?string $prefix, Filter $filter): array
{
$compiled = [];
/** @var string[]|null $filterStatusList */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,39 +6,49 @@ active_filters:

filters:
get_clip_all_status:
route: get_clip
routes: ['get_clip']
method: ['GET', 'PUT']
status: ~
options:
response_body: true
post_parameters: true

put_clip_form_all_200:
route: put_clips_form
routes: ['put_clips_form']
method: ['PUT']
status: [!^240, 2*]

delete_clip_500_all_hundred_without_580_to_590:
route: delete_clip
routes: ['delete_clip']
method: ['DELETE']
status: [5*, !58*]

edit_clip_5*_30*_without_550_549:
route: edit_clip
routes: ['edit_clip']
method: ['PATH']
status: [5*, !550, !549, 30*]

edit_clip_404_to_410:
route: edit_clip
routes: ['edit_clip']
method: ['POST']
status: [404-410]

delete_clip_450_more_without_452_to_458:
route: delete_clip
routes: ['delete_clip']
method: ['DELETE']
status: [^450, !452-458]

get_program_200_hundred_without_290_more:
route: get_program
routes: ['get_program']
method: ['GET']
status: [2*, !^290]
status: [2*, !^290]

get_program_200_hundred_without_route_no_filter:
routes: [ 'get_program', '!no_filter' ]
method: [ 'GET' ]
status: [ 2*, !^290 ]

get_program_200_hundred_with_simple_route:
route: 'get_program'
method: [ 'GET' ]
status: [ 2*, !^290 ]
5 changes: 5 additions & 0 deletions src/M6Web/Bundle/LogBridgeBundle/Tests/Units/BaseTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ protected function getMockedRouterCollection(): object
{
$collection = new \mock\Symfony\Component\Routing\RouteCollection();
$collection->getMockController()->get = fn($name) => $name != 'invalid_route' ? new Route('/path') : null;
$collection->getMockController()->all = [
'fake_url' => new Route('/fake_url'),
'fake_second_url' => new Route('/fake_second_url'),
'excluded_route' => new Route('/excluded_route')
];

return $collection;
}
Expand Down
Loading

0 comments on commit e187c68

Please sign in to comment.