Skip to content
This repository was archived by the owner on Dec 11, 2021. It is now read-only.

Commit c174cb0

Browse files
committed
Add route url filtering via --route flag
1 parent e6bb539 commit c174cb0

File tree

3 files changed

+138
-56
lines changed

3 files changed

+138
-56
lines changed

README.md

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,18 +18,32 @@ composer.phar require --dev bitexpert/magerun2-list-api-endpoints
1818
This plugin adds the `api:list:endpoints` command to magerun2.
1919

2020
You are able to filter routes by their respective HTTP methods. To only
21-
see GET routes, run magerun2 like this:
21+
see `GET` routes, run magerun2 like this:
2222

2323
```
2424
magerun2 api:list:endpoints --method=get
2525
```
2626

27-
To list all GET and POST routes, pass a comma-separated list as method argument:
27+
To list all `GET` and `POST` routes, pass a comma-separated list as method argument:
2828

2929
```
3030
magerun2 api:list:endpoints --method=get,post
3131
```
3232

33+
You are able to filter routes by their url. To only see `customers` routes,
34+
run magerun2 like this:
35+
36+
```
37+
magerun2 api:list:endpoints --route=customers
38+
```
39+
40+
Both filters can be combined, to show only `customers` routes with the `GET`
41+
method, run magerun2 like this:
42+
43+
```
44+
magerun2 api:list:endpoints --route=customers --method=get
45+
```
46+
3347
## Contribute
3448

3549
Please feel free to fork and extend existing or add new features and send

src/BitExpert/Magento/ListApiEndpoints/Command/ListApiEndpoints.php

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ class ListApiEndpoints extends AbstractMagentoCommand
2323
{
2424
const OPTION_OUTPUT_FORMAT = 'output-format';
2525
const OPTION_FILTER_METHOD = 'method';
26+
const OPTION_FILTER_ROUTE = 'route';
2627

2728
/**
2829
* {@inheritdoc}
@@ -45,6 +46,13 @@ protected function configure()
4546
InputOption::VALUE_OPTIONAL,
4647
'Filters routes for given method. Pass multiple methods as comma-separated list',
4748
''
49+
)
50+
->addOption(
51+
self::OPTION_FILTER_ROUTE,
52+
'r',
53+
InputOption::VALUE_OPTIONAL,
54+
'Filters routes by given part',
55+
''
4856
);
4957
}
5058

@@ -56,7 +64,9 @@ protected function execute(InputInterface $input, OutputInterface $output)
5664
$this->detectMagento($output);
5765
if ($this->initMagento()) {
5866
$methodFilter = $input->getOption(self::OPTION_FILTER_METHOD);
59-
$services = $this->filterServices($this->getDefinedServices(), $methodFilter);
67+
$routeFilter = $input->getOption(self::OPTION_FILTER_ROUTE);
68+
$services = $this->getDefinedServices();
69+
$services = $this->filterServices($services, $methodFilter, $routeFilter);
6070

6171
$outputFormat = $input->getOption(self::OPTION_OUTPUT_FORMAT);
6272
switch ($outputFormat) {
@@ -110,16 +120,29 @@ private function printAsTable(array $services, OutputInterface $output)
110120
*
111121
* @param array $services
112122
* @param string $methodsToFilter
123+
* @param string $routesToFilter
113124
* @return array
114125
*/
115-
private function filterServices(array $services, $methodsToFilter)
126+
private function filterServices(array $services, $methodsToFilter, $routesToFilter)
116127
{
117-
if(empty($methodsToFilter)) {
128+
if(!isset($services['routes']) || !is_array($services['routes'])) {
118129
return $services;
119130
}
120131

121-
$methodsToFilterArray = explode(',', strtoupper($methodsToFilter));
122-
if(isset($services['routes']) && is_array($services['routes'])) {
132+
if(!empty($routesToFilter)) {
133+
foreach ($services['routes'] as $route => $methods) {
134+
if (strpos($route, $routesToFilter) === false) {
135+
unset($services['routes'][$route]);
136+
}
137+
}
138+
}
139+
140+
if(!empty($methodsToFilter)) {
141+
$methodsToFilterArray = explode(',', strtoupper($methodsToFilter));
142+
array_walk($methodsToFilterArray, function(&$value, $index) {
143+
$value = trim($value);
144+
});
145+
123146
foreach ($services['routes'] as $route => $methods) {
124147
foreach ($methods as $method => $config) {
125148
if(!in_array($method, $methodsToFilterArray)) {

tests/BitExpert/Magento/ListApiEndpoints/Command/ListApiEndpointsUnitTest.php

Lines changed: 94 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,14 @@
2323
*/
2424
class ListApiEndpointsUnitTest extends TestCase
2525
{
26+
/**
27+
* Number of lines rendered for a table without any data, just the table header
28+
*/
29+
const EMPTY_TABLE_OUTPUT_LINES = 3;
30+
/**
31+
* Minimum number of lines rendered for a table with data and the table header
32+
*/
33+
const TABLE_OUTPUT_LINES = 4;
2634
/**
2735
* @var InputInterface
2836
*/
@@ -74,12 +82,13 @@ public function missingOutputFormatParameterThrowsException()
7482
public function withOutputFormatParameterSetTheCommandWillRenderTableStructure()
7583
{
7684
// since no services are returned, just the table header is rendered
77-
$this->output->expects($this->exactly($this->countTableRowsToPrint()))
85+
$this->output->expects($this->exactly(self::EMPTY_TABLE_OUTPUT_LINES))
7886
->method('writeln');
7987

8088
$this->input->expects($this->any())
8189
->method('getOption')
8290
->will($this->returnValueMap([
91+
[ListApiEndpoints::OPTION_FILTER_ROUTE, ''],
8392
[ListApiEndpoints::OPTION_FILTER_METHOD, ''],
8493
[ListApiEndpoints::OPTION_OUTPUT_FORMAT, 'table'],
8594
]));
@@ -103,12 +112,13 @@ public function forEachDefinedRouteTheCommandWillRenderTableRow()
103112
]
104113
];
105114

106-
$this->output->expects($this->exactly($this->countTableRowsToPrint($services)))
115+
$this->output->expects($this->exactly(self::TABLE_OUTPUT_LINES + 1))
107116
->method('writeln');
108117

109118
$this->input->expects($this->any())
110119
->method('getOption')
111120
->will($this->returnValueMap([
121+
[ListApiEndpoints::OPTION_FILTER_ROUTE, ''],
112122
[ListApiEndpoints::OPTION_FILTER_METHOD, ''],
113123
[ListApiEndpoints::OPTION_OUTPUT_FORMAT, 'table'],
114124
]));
@@ -124,7 +134,7 @@ public function forEachDefinedRouteTheCommandWillRenderTableRow()
124134
/**
125135
* @test
126136
*/
127-
public function forEachFilteredRouteTheCommandWillRenderTableRow()
137+
public function forEachFilteredRouteByMethodTheCommandWillRenderTableRow()
128138
{
129139
$filter = 'GET';
130140
$services['routes'] = [
@@ -139,12 +149,88 @@ public function forEachFilteredRouteTheCommandWillRenderTableRow()
139149
],
140150
];
141151

142-
$this->output->expects($this->exactly($this->countTableRowsToPrint($services, $filter)))
152+
$this->output->expects($this->exactly(self::TABLE_OUTPUT_LINES + 2))
153+
->method('writeln');
154+
155+
$this->input->expects($this->any())
156+
->method('getOption')
157+
->will($this->returnValueMap([
158+
[ListApiEndpoints::OPTION_FILTER_ROUTE, ''],
159+
[ListApiEndpoints::OPTION_FILTER_METHOD, $filter],
160+
[ListApiEndpoints::OPTION_OUTPUT_FORMAT, 'table'],
161+
]));
162+
163+
/** @var ListApiEndpoints $command */
164+
$command = $this->getApiEndpointsMock();
165+
$command->method('getDefinedServices')
166+
->willReturn($services);
167+
$command->setApplication($this->application);
168+
$command->run($this->input, $this->output);
169+
}
170+
171+
/**
172+
* @test
173+
*/
174+
public function forMultipleFilteredRoutesByMethodTheCommandWillRenderTableRow()
175+
{
176+
$filter = 'GET, POST';
177+
$services['routes'] = [
178+
'/route' => [
179+
'GET' => ['resources' => '{}'],
180+
'PUT' => ['resources' => '{}']
181+
],
182+
'/other-route' => [
183+
'GET' => ['resources' => '{}'],
184+
'POST' => ['resources' => '{}'],
185+
'DELETE' => ['resources' => '{}']
186+
],
187+
];
188+
189+
$this->output->expects($this->exactly(self::TABLE_OUTPUT_LINES + 3))
190+
->method('writeln');
191+
192+
$this->input->expects($this->any())
193+
->method('getOption')
194+
->will($this->returnValueMap([
195+
[ListApiEndpoints::OPTION_FILTER_ROUTE, ''],
196+
[ListApiEndpoints::OPTION_FILTER_METHOD, $filter],
197+
[ListApiEndpoints::OPTION_OUTPUT_FORMAT, 'table'],
198+
]));
199+
200+
/** @var ListApiEndpoints $command */
201+
$command = $this->getApiEndpointsMock();
202+
$command->method('getDefinedServices')
203+
->willReturn($services);
204+
$command->setApplication($this->application);
205+
$command->run($this->input, $this->output);
206+
}
207+
208+
/**
209+
* @test
210+
*/
211+
public function forMultipleFilteredRoutesByRouteTheCommandWillRenderTableRow()
212+
{
213+
$filter = '';
214+
$route = 'other';
215+
$services['routes'] = [
216+
'/route' => [
217+
'GET' => ['resources' => '{}'],
218+
'PUT' => ['resources' => '{}']
219+
],
220+
'/other-route' => [
221+
'GET' => ['resources' => '{}'],
222+
'POST' => ['resources' => '{}'],
223+
'DELETE' => ['resources' => '{}']
224+
],
225+
];
226+
227+
$this->output->expects($this->exactly(self::TABLE_OUTPUT_LINES + 3))
143228
->method('writeln');
144229

145230
$this->input->expects($this->any())
146231
->method('getOption')
147232
->will($this->returnValueMap([
233+
[ListApiEndpoints::OPTION_FILTER_ROUTE, $route],
148234
[ListApiEndpoints::OPTION_FILTER_METHOD, $filter],
149235
[ListApiEndpoints::OPTION_OUTPUT_FORMAT, 'table'],
150236
]));
@@ -160,9 +246,10 @@ public function forEachFilteredRouteTheCommandWillRenderTableRow()
160246
/**
161247
* @test
162248
*/
163-
public function forMultipleFilteredRoutesTheCommandWillRenderTableRow()
249+
public function forMultipleFilteredRoutesByMethodAndRouteTheCommandWillRenderTableRow()
164250
{
165251
$filter = 'GET, POST';
252+
$route = 'other';
166253
$services['routes'] = [
167254
'/route' => [
168255
'GET' => ['resources' => '{}'],
@@ -175,12 +262,13 @@ public function forMultipleFilteredRoutesTheCommandWillRenderTableRow()
175262
],
176263
];
177264

178-
$this->output->expects($this->exactly($this->countTableRowsToPrint($services, $filter)))
265+
$this->output->expects($this->exactly(self::TABLE_OUTPUT_LINES + 2))
179266
->method('writeln');
180267

181268
$this->input->expects($this->any())
182269
->method('getOption')
183270
->will($this->returnValueMap([
271+
[ListApiEndpoints::OPTION_FILTER_ROUTE, $route],
184272
[ListApiEndpoints::OPTION_FILTER_METHOD, $filter],
185273
[ListApiEndpoints::OPTION_OUTPUT_FORMAT, 'table'],
186274
]));
@@ -212,47 +300,4 @@ protected function getApiEndpointsMock()
212300
->willReturn(true);
213301
return $command;
214302
}
215-
216-
/**
217-
* Helper method to count the routes in given $services array.
218-
*
219-
* @param array $services
220-
* @param string $filter
221-
* @return int
222-
*/
223-
protected function countRoutes(array $services, $filter = '')
224-
{
225-
$routesCounter = 0;
226-
$methodsToFilterArray = explode(',', strtoupper($filter));
227-
228-
if(isset($services['routes']) && is_array($services['routes'])) {
229-
foreach ($services['routes'] as $route => $methods) {
230-
foreach ($methods as $method => $config) {
231-
if(empty($filter) || in_array($method, $methodsToFilterArray)) {
232-
$routesCounter++;
233-
}
234-
}
235-
}
236-
}
237-
238-
return $routesCounter;
239-
}
240-
241-
/**
242-
* Helper method to count all the rows printed by the Symfony Console Table component
243-
* based on the given input parameters.
244-
*
245-
* @param array $services
246-
* @param string $filter
247-
* @return int
248-
*/
249-
protected function countTableRowsToPrint(array $services = [], $filter = '')
250-
{
251-
if (count($services) === 0 && empty($filter)) {
252-
// default amount of rows that Symfony Console Table component will render
253-
return 3;
254-
}
255-
256-
return 4 + $this->countRoutes($services, $filter);
257-
}
258303
}

0 commit comments

Comments
 (0)