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

Commit 87baef0

Browse files
committed
Magic method added to catch http request methods
- defined routes removed from constructor which breaks BC - __call magic method added to let router set http request methods using method call - More exceptions defined - Tests added/changed for changes
1 parent a10276c commit 87baef0

File tree

2 files changed

+121
-25
lines changed

2 files changed

+121
-25
lines changed

src/Router.php

Lines changed: 46 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
*
66
* @license https://github.com/selamiphp/router/blob/master/LICENSE (MIT License)
77
* @link https://github.com/selamiphp/router
8+
* @package router
9+
* @category library
810
*/
911

1012
declare(strict_types = 1);
@@ -13,6 +15,7 @@
1315

1416
use FastRoute;
1517
use InvalidArgumentException;
18+
use UnexpectedValueException;
1619

1720
/**
1821
* Router
@@ -93,6 +96,7 @@ final class Router
9396
/**
9497
* Valid Request Methods array.
9598
* Make sures about return type.
99+
* Index 0 is also default value.
96100
* @var array
97101
*/
98102
private static $validReturnTypes = [
@@ -107,12 +111,11 @@ final class Router
107111
* Router constructor.
108112
* Create new router.
109113
*
110-
* @param array $routes
111114
* @param string $defaultReturnType
112115
* @param string $method
113116
* @param string $requestedPath
114117
* @param string $folder
115-
* @throws InvalidArgumentException
118+
* @throws UnexpectedValueException
116119
*/
117120
public function __construct(
118121
string $defaultReturnType,
@@ -121,12 +124,12 @@ public function __construct(
121124
string $folder = ''
122125
) {
123126
if (!in_array($method, self::$validRequestMethods, true)) {
124-
$message = sprintf('%s is nat valid Http request method.', $method);
125-
throw new InvalidArgumentException($message);
127+
$message = sprintf('%s is not valid Http request method.', $method);
128+
throw new UnexpectedValueException($message);
126129
}
127130
$this->method = $method;
128131
$this->requestedPath = $this->extractFolder($requestedPath, $folder);
129-
$this->defaultReturnType = self::$translations[$defaultReturnType] ?? self::$defaultReturnType[0];
132+
$this->defaultReturnType = self::$translations[$defaultReturnType] ?? self::$validReturnTypes[0];
130133
}
131134

132135
/**
@@ -153,39 +156,64 @@ private function extractFolder(string $requestPath, string $folder)
153156
* @param string $action
154157
* @param string $returnType
155158
* @param string $alias
156-
* @return string
157159
* @throws InvalidArgumentException
160+
* @throws UnexpectedValueException
158161
*/
159162
public function add($requestMethods, string $route, string $action, string $returnType=null, string $alias=null)
160163
{
161-
$requestMethodParameterType = gettype($requestMethods);
162-
if (!in_array($requestMethodParameterType, ['array', 'string'], true)) {
163-
$message = sprintf(
164-
'Request method must be either string or array but %s given.',
165-
$requestMethodParameterType);
166-
throw new InvalidArgumentException($message);
167-
}
168164
$requestMethodsGiven = is_array($requestMethods) ? (array) $requestMethods : [0 => $requestMethods];
169-
$returnType = $returnType === null ? $this->defaultReturnType: self::$validReturnTypes[$returnType]?? $this->defaultReturnType;
165+
$returnType = $returnType === null ? $this->defaultReturnType : self::$validReturnTypes[$returnType] ?? $this->defaultReturnType;
170166
foreach ($requestMethodsGiven as $requestMethod) {
167+
$requestMethodParameterType = gettype($requestMethod);
168+
if (!in_array($requestMethodParameterType, ['array', 'string'], true)) {
169+
$message = sprintf(
170+
'Request method must be string or array but %s given.',
171+
$requestMethodParameterType);
172+
throw new InvalidArgumentException($message);
173+
}
174+
if (!in_array(strtoupper($requestMethod), self::$validRequestMethods, true)) {
175+
$message = sprintf('%s is not valid Http request method.', $requestMethod);
176+
throw new UnexpectedValueException($message);
177+
}
171178
if ($alias !== null) {
172179
$this->aliases[$alias] = $route;
173180
}
174181
$this->routes[] = [strtoupper($requestMethod), $route, $action, $returnType];
175182
}
176183
}
177184

185+
/**
186+
* @param string $method
187+
* @param array $args
188+
* @throws UnexpectedValueException
189+
*/
190+
public function __call(string $method, array $args)
191+
{
192+
if (!in_array(strtoupper($method), self::$validRequestMethods, true)) {
193+
$message = sprintf('%s is not valid Http request method.', $method);
194+
throw new UnexpectedValueException($message);
195+
}
196+
$defaults = [
197+
null,
198+
null,
199+
$this->defaultReturnType,
200+
null
201+
];
202+
list($route, $action, $returnType, $alias) = array_merge($args, $defaults);
203+
$this->add($method, $route, $action, $returnType, $alias);
204+
}
205+
178206
/**
179207
* Dispatch against the provided HTTP method verb and URI.
180208
* @return array
181209
*/
182210
private function dispatcher()
183211
{
184212
$options = [
185-
'routeParser' => 'FastRoute\\RouteParser\\Std',
186-
'dataGenerator' => 'FastRoute\\DataGenerator\\GroupCountBased',
187-
'dispatcher' => 'FastRoute\\Dispatcher\\GroupCountBased',
188-
'routeCollector' => 'FastRoute\\RouteCollector',
213+
'routeParser' => FastRoute\RouteParser\Std::class,
214+
'dataGenerator' => FastRoute\DataGenerator\GroupCountBased::class,
215+
'dispatcher' => FastRoute\Dispatcher\GroupCountBased::class,
216+
'routeCollector' => FastRoute\RouteCollector::class,
189217
];
190218
/** @var RouteCollector $routeCollector */
191219
$routeCollector = new $options['routeCollector'](

test/RouterTest.php

Lines changed: 75 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
use Selami;
66
use Zend\Diactoros\ServerRequestFactory;
77
use ReflectionObject;
8+
use UnexpectedValueException;
9+
use InvalidArgumentException;
810

911
class MyRouterClass extends \PHPUnit_Framework_TestCase
1012
{
@@ -95,7 +97,12 @@ public function shouldCorrectlyInstantiateRouter()
9597
$router->add('post', '/json', 'app/redirect', 'redirect');
9698
$router->add('get', '/alias', 'app/alias', null, 'alias');
9799
$this->assertInstanceOf('Selami\Router', $router);
98-
$this->assertAttributeContains('GET', 'method', $router, "Router didn't correctly return method as GET.");
100+
$this->assertAttributeContains(
101+
'GET',
102+
'method',
103+
$router,
104+
"Router didn't correctly return method as GET."
105+
);
99106
}
100107

101108
/**
@@ -104,16 +111,17 @@ public function shouldCorrectlyInstantiateRouter()
104111
public function shouldCorrectlyReturnRouteAndRouteAliases()
105112
{
106113
$router = new Selami\Router(
107-
$this->config['default_return_type'],
114+
'json',
108115
$this->request->getMethod(),
109116
$this->request->getUri()->getPath(),
110117
$this->config['folder']
111118
);
112119

113-
$router->add('get', '/', 'app/main',null, 'home');
114-
$router->add('get', '/json', 'app/json', 'json');
115-
$router->add('post', '/json', 'app/redirect', 'redirect');
116-
$router->add('get', '/alias', 'app/alias', null, 'alias');
120+
$router->get('/', 'app/main', null, 'home');
121+
$router->get('/json', 'app/json', 'json');
122+
$router->get('/html', 'app/json');
123+
$router->post('/json', 'app/redirect', 'redirect');
124+
$router->get('/alias', 'app/alias', null, 'alias');
117125
$routeInfo = $router->getRoute();
118126
$this->assertArrayHasKey('aliases', $routeInfo, "Router didn't correctly return route data");
119127

@@ -123,9 +131,69 @@ public function shouldCorrectlyReturnRouteAndRouteAliases()
123131
$this->assertEquals('/alias', $routeInfo['aliases']['alias'], "Router didn't correctly return aliases");
124132
$this->assertArrayHasKey('controller', $routeInfo['route'], "Router didn't correctly return route data");
125133
$this->assertEquals('app/alias', $routeInfo['route']['controller'], "Router didn't correctly return router data");
126-
$this->assertEquals('html', $routeInfo['route']['returnType'], "Router didn't correctly return router data");
134+
$this->assertEquals('json', $routeInfo['route']['returnType'], "Router didn't correctly return router data");
135+
}
136+
137+
/**
138+
* @test
139+
* @expectedException UnexpectedValueException
140+
*/
141+
public function shouldThrowUnexpectedValueExceptionFor__callMethod()
142+
{
143+
$router = new Selami\Router(
144+
$this->config['default_return_type'],
145+
$this->request->getMethod(),
146+
$this->request->getUri()->getPath(),
147+
$this->config['folder']
148+
);
149+
$router->nonAvalibleHTTPMethod('/', 'app/main',null, 'home');
150+
}
151+
152+
/**
153+
* @test
154+
* @expectedException UnexpectedValueException
155+
*/
156+
public function shouldThrowUnexpectedValueExceptionFor__constructorMethod()
157+
{
158+
$router = new Selami\Router(
159+
$this->config['default_return_type'],
160+
'UNEXPECTEDVALUE',
161+
$this->request->getUri()->getPath(),
162+
$this->config['folder']
163+
);
164+
}
165+
166+
/**
167+
* @test
168+
* @expectedException UnexpectedValueException
169+
*/
170+
public function shouldThrowUnexpectedValueExceptionForAddMethod()
171+
{
172+
$router = new Selami\Router(
173+
$this->config['default_return_type'],
174+
$this->request->getMethod(),
175+
$this->request->getUri()->getPath(),
176+
$this->config['folder']
177+
);
178+
$router->add('nonAvailableHTTPMethod','/', 'app/main',null, 'home');
127179
}
128180

181+
/**
182+
* @test
183+
* @expectedException InvalidArgumentException
184+
*/
185+
public function shouldThrowInvalidArgumentExceptionForAddMethodIfREquestMEthotIsNotStringOrArray()
186+
{
187+
$router = new Selami\Router(
188+
$this->config['default_return_type'],
189+
$this->request->getMethod(),
190+
$this->request->getUri()->getPath(),
191+
$this->config['folder']
192+
);
193+
$router->add(200,'/', 'app/main',null, 'home');
194+
}
195+
196+
129197
/**
130198
* @test
131199
*/

0 commit comments

Comments
 (0)