summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/Router/Routes/Glob.php21
-rw-r--r--src/Router/UrlParsing.php4
-rw-r--r--tests/Router/Routes/GlobTest.php351
-rw-r--r--tests/RouterTest.php2
4 files changed, 238 insertions, 140 deletions
diff --git a/src/Router/Routes/Glob.php b/src/Router/Routes/Glob.php
index fcece76..4c6d93c 100644
--- a/src/Router/Routes/Glob.php
+++ b/src/Router/Routes/Glob.php
@@ -16,6 +16,18 @@ class Glob extends ArrayObject implements Routes
use UrlParsing;
/**
+ * Class constructor
+ *
+ * @param Routes[]|array|\Traversable $input
+ * @param int $flags
+ */
+ public function __construct($input = [], $flags = 0)
+ {
+ $routes = $this->createRoutes($input);
+ parent::__construct($routes, $flags);
+ }
+
+ /**
* Create a route from an assisiative array or stdClass object
*
* @param Route|\stdClass|array $value
@@ -35,14 +47,7 @@ class Glob extends ArrayObject implements Routes
throw new \InvalidArgumentException("Unable to create a Route from value " . var_export($value, true));
}
- $route = Route::create($value);
-
- if (!isset($route)) {
- throw new \InvalidArgumentException("Unable to create a Route from " . var_export($value, true) . ": "
- . "neither 'controller', 'fn' or 'file' key is defined");
- }
-
- return $route;
+ return Route::create($value);
}
/**
diff --git a/src/Router/UrlParsing.php b/src/Router/UrlParsing.php
index 5727085..ee89260 100644
--- a/src/Router/UrlParsing.php
+++ b/src/Router/UrlParsing.php
@@ -31,10 +31,6 @@ trait UrlParsing
$url = rtrim($url, '/');
}
- if (substr($url, 0, 2) == '/:') {
- $url = substr($url, 2);
- }
-
return $url;
}
}
diff --git a/tests/Router/Routes/GlobTest.php b/tests/Router/Routes/GlobTest.php
index 3ed4d21..a6767a8 100644
--- a/tests/Router/Routes/GlobTest.php
+++ b/tests/Router/Routes/GlobTest.php
@@ -3,12 +3,12 @@
namespace Jasny\Router\Routes;
use Jasny\Router\Routes\Glob;
+use Jasny\Router\Route;
use Psr\Http\Message\ServerRequestInterface;
use ArrayObject;
use BadMethodCallException;
use InvalidArgumentException;
-use AppendIterator;
class GlobTest extends \PHPUnit_Framework_TestCase
{
@@ -17,63 +17,55 @@ class GlobTest extends \PHPUnit_Framework_TestCase
*/
public function testConstructor()
{
- #Test empty constructor
$glob = new Glob();
$this->assertInstanceOf('ArrayObject', $glob, "Should be an instance of 'ArrayObject'");
$this->assertEquals(0, $glob->count(), "Default count is not empty");
$this->assertEquals(0, $glob->getFlags(), "Default flags are not empty");
$this->assertEquals('ArrayIterator', $glob->getIteratorClass(), "Default iterator class is not correct");
- #Actual check for public values
+ // Actual check for available routes
$count = 0;
foreach ($glob as $value) {
$count++;
break;
}
- $this->assertEquals(0, $count);
+ $this->assertEquals(0, $count);
}
public function testConstructorWithArguments()
{
- #Test with params
$values = [
'/foo/bar' => ['controller' => 'value1'],
'/foo/*' => ['fn' => 'value3'],
'/foo/*/bar' => ['file' => 'value5'],
];
- $glob = new Glob($values, ArrayObject::ARRAY_AS_PROPS, AppendIterator::class);
+ $glob = new Glob($values, ArrayObject::ARRAY_AS_PROPS);
- $this->assertEquals(count($values), $glob->count(), "Routes count is not match");
+ $this->assertCount(3, $glob, "Routes count do not match");
$this->assertEquals(ArrayObject::ARRAY_AS_PROPS, $glob->getFlags(), "Flags are not correct");
- $this->assertEquals(AppendIterator::class, $glob->getIteratorClass(), "Iterator class is not correct");
- foreach ($values as $pattern => $options) {
- $this->assertTrue($glob->offsetExists($pattern), "Key '$pattern' is missing");
+ foreach ($glob as $pattern => $route) {
+ $this->assertInstanceof(Route::class, $route);
+ $this->assertArrayHasKey($pattern, $values);
+ $this->assertArraysEqual($values[$pattern], (array)$route);
}
+
+ return $glob;
}
-
+
/**
- * Test ArrayObject::exchangeArray method
+ * @depends testConstructorWithArguments
*
- * @dataProvider exchangeArrayProvider
+ * @param Glob $original
*/
- public function testExchangeArray($set, $reset)
+ public function testConstructorTraversable(Glob $original)
{
- $glob = new Glob($set);
- $old = $glob->exchangeArray($reset);
-
- $this->assertEquals(count($set), count($old), "Old routes count is not match");
- $this->assertEquals(count($reset), $glob->count(), "Routes count is not match");
-
- foreach ($reset as $pattern => $options) {
- $this->assertTrue($glob->offsetExists($pattern), "Key is missing");
- }
- foreach ($set as $pattern => $options) {
- $this->assertTrue(!empty($old[$pattern]), "Old key is missing");
- $this->assertFalse($glob->offsetExists($pattern), "Key exists, but should not");
- }
+ $glob = new Glob($original);
+
+ $this->assertCount(3, $glob, "Routes count do not match");
+ $this->assertEquals($original->getArrayCopy(), $glob->getArrayCopy());
}
/**
@@ -98,70 +90,93 @@ class GlobTest extends \PHPUnit_Framework_TestCase
}
/**
- * Test ArrayObject::offsetSet method
+ * Test ArrayObject::exchangeArray method
*
- * @dataProvider offsetSetProvider
- * @param string $pattern
- * @param array $options
- * @param string $exception
+ * @dataProvider exchangeArrayProvider
*/
- public function testOffsetSet($pattern, $options, $exception)
+ public function testExchangeArray($set, $reset)
{
- if ($exception) $this->expectException($exception);
-
- $glob = new Glob();
- $glob->offsetSet($pattern, $options);
+ $glob = new Glob($set);
+ $old = $glob->exchangeArray($reset);
- if ($exception) return;
+ $this->assertEquals(count($set), count($old), "Old routes count do not match");
+ $this->assertEquals(count($reset), $glob->count(), "Routes count do not match");
- $this->assertEquals(1, $glob->count(), "Routes count is not match");
- $this->assertTrue($glob->offsetExists($pattern), "Key is missing");
-
- #Verify that value was set correctly
- $value = (array)$glob->offsetGet($pattern);
- $this->assertEmpty(array_diff($options, $value), "Route was not set correct");
+ foreach ($reset as $pattern => $options) {
+ $this->assertTrue($glob->offsetExists($pattern), "Key is missing");
+ }
+ foreach ($set as $pattern => $options) {
+ $this->assertTrue(!empty($old[$pattern]), "Old key is missing");
+ $this->assertFalse($glob->offsetExists($pattern), "Key exists, but should not");
+ }
}
+
/**
* Provide data for testOffsetSet()
*/
public function offsetSetProvider()
{
return [
- ['/foo/*', ['controller' => 'bar'], ''],
- ['/foo/*', ['fn' => 'bar'], ''],
- ['/foo/*', ['file' => 'bar'], ''],
- ['', ['controller' => 'bar'], BadMethodCallException::class],
- ['foo', 'bar', InvalidArgumentException::class],
- ['', '', BadMethodCallException::class]
+ ['/foo/*', ['controller' => 'bar']],
+ ['/foo/*', ['fn' => 'bar']],
+ ['/foo/*', ['file' => 'bar']],
+ ['/foo/*', $this->getMockBuilder(Route::class)->setConstructorArgs([['controller' => 'bar']])->getMock()]
];
}
+
+ /**
+ * Test ArrayObject::offsetSet method
+ * @dataProvider offsetSetProvider
+ *
+ * @param string $pattern
+ * @param array $options
+ */
+ public function testOffsetSet($pattern, $options)
+ {
+ $glob = new Glob();
+ $glob[$pattern] = $options;
+ $this->assertCount(1, $glob);
+ $this->assertTrue(isset($glob[$pattern]));
+
+ $route = $glob[$pattern];
+ $this->assertInstanceOf(Route::class, $route);
+
+ if ($options instanceof Route) {
+ $this->assertSame($options, $route);
+ } else {
+ $this->assertEquals([], array_diff($options, (array)$route));
+ }
+ }
+
/**
- * Test ArrayObject::append method
- *
* @expectedException BadMethodCallException
*/
- public function testAppend()
+ public function testOffsetSetInvalidPattern()
{
$glob = new Glob();
- $glob->append(['controller' => 'bar']);
+ $glob[''] = ['controller' => 'bar'];
+ }
+
+ /**
+ * @expectedException InvalidArgumentException
+ */
+ public function testOffsetSetInvalidRoute()
+ {
+ $glob = new Glob();
+ $glob['/foo'] = 'bar';
}
/**
- * Test matching of url pattern to given uri
+ * Test ArrayObject::append method
*
- * @dataProvider fnMatchProvider
- * @param string $pattern
- * @param string $uri
- * @param boolean $positive
+ * @expectedException BadMethodCallException
*/
- public function testFnMatch($pattern, $uri, $positive)
- {
+ public function testAppend()
+ {
$glob = new Glob();
-
- $this->assertEquals($positive, $glob->fnmatch($pattern, $uri),
- "Pattern and uri should " . ($positive ? "" : "not") . " match");
+ $glob->append(['controller' => 'bar']);
}
/**
@@ -205,12 +220,28 @@ class GlobTest extends \PHPUnit_Framework_TestCase
}
/**
- * Testing getting route and it's existense
+ * Test matching of url pattern to given uri
+ * @dataProvider fnMatchProvider
*
+ * @param string $pattern
+ * @param string $uri
+ * @param boolean $positive
+ */
+ public function testFnMatch($pattern, $uri, $positive)
+ {
+ $glob = new Glob();
+
+ $this->assertEquals($positive, $glob->fnmatch($pattern, $uri),
+ "Pattern and uri should " . ($positive ? "" : "not") . " match");
+ }
+
+ /**
+ * Testing getting route and it's existense
* @dataProvider getHasRouteProvider
- * @param string $uri Uri of ServerRequest
- * @param string $method Query method name
- * @param boolean $positive If the test should be positive or negative
+ *
+ * @param string $uri Uri of ServerRequest
+ * @param string $method Query method name
+ * @param boolean $positive If the test should be positive or negative
*/
public function testGetHasRoute($uri, $method, $positive)
{
@@ -241,7 +272,7 @@ class GlobTest extends \PHPUnit_Framework_TestCase
$this->assertTrue($exist, "Route not exists");
$this->assertTrue((bool)$match, "Found no match of uri with patterns");
- $this->assertEquals($values[$match]['controller'], $route['controller'], "False route obtained");
+ $this->assertEquals($values[$match]['controller'], $route->controller, "False route obtained");
}
/**
@@ -306,17 +337,36 @@ class GlobTest extends \PHPUnit_Framework_TestCase
$request = $this->getServerRequest($uri);
$route = $glob->getRoute($request);
- $this->assertEquals($route['check'], $values[$uri]['check'], "Option value is not correct");
+ $this->assertEquals($values[$uri]['check'], $route->check);
+ }
+
+ /**
+ * Provide uri's and corresponding patterns for testBindVarSingleUrlPart()
+ */
+ public function bindVarSingleUrlPartProvider()
+ {
+ return [
+ ['/*', '/test', ['check' => '$1'], 'test'],
+ ['/', '/', ['check' => '$1|test'], 'test'],
+ ['/foo/*/bar', '/foo/test/bar', ['check' => '$2'], 'test'],
+ ['/foo/bar/*', '/foo/bar/test', ['check' => '$3'], 'test'],
+ ['/foo/bar/*/zet/*', '/foo/bar/test1/zet/test2', ['check' => '$3', 'checkB' => '$5'], 'test1', 'test2'],
+ ['/foo/bar/*/zet/*', '/foo/bar/test1/zet/test2', ['check' => '~$3~/~$5~'], 'test1/test2'],
+ ['/', '/', ['check' => '$foo'], null]
+ ];
}
/**
* Test binding single url part to route option
* @dataProvider bindVarSingleUrlPartProvider
- * @param string $patter
+ *
+ * @param string $pattern
* @param string $uri
- * @param array $options Route options
+ * @param array $options Route options
+ * @param string $check Expected value for `check`
+ * @param string $checkB Expected value for `checkB`
*/
- public function testBindVarSingleUrlPart($pattern, $uri, $options)
+ public function testBindVarSingleUrlPart($pattern, $uri, $options, $check, $checkB = null)
{
$values = [$pattern => $options];
@@ -324,82 +374,138 @@ class GlobTest extends \PHPUnit_Framework_TestCase
$request = $this->getServerRequest($uri);
$route = $glob->getRoute($request);
- $this->assertTrue((bool)$route, "Route not found");
+ $this->assertNotNull($route, "Route not found");
+ $this->assertInstanceOf(Route::class, $route);
- if (!empty($options['check'])) {
- $this->assertEquals('test', $route['check'], "Single pocket did not match");
- } elseif(empty($options['check2'])) {
- $this->assertEquals('test1/test2', $route['check1'], "Single compound pocket did not match");
- } else {
- $this->assertEquals('test1', $route['check1'], "First of two pockets did not match");
- $this->assertEquals('test2', $route['check2'], "Second of two pockets did not match");
+ $this->assertEquals($check, $route->check);
+
+ if (isset($checkB)) {
+ $this->assertEquals($checkB, $route->checkB);
}
}
+
+ public function testBindVarWithObject()
+ {
+ $object = new \Exception(); // Could be anything, just not stdClass
+ $glob = new Glob(['/' => ['object' => $object]]);
+
+ $request = $this->getServerRequest('/');
+ $route = $glob->getRoute($request);
+ $this->assertNotNull($route, "Route not found");
+ $this->assertInstanceOf(Route::class, $route);
+
+ $this->assertSame($object, $route->object);
+ }
+
+ public function bindVarWithSubProvider()
+ {
+ return [
+ [['group' => ['check' => '$1']], 'array'],
+ [['group' => (object)['check' => '$1']], 'object'],
+ [['group' => ['sub' => (object)['check' => '$1']]], 'array', 'object'],
+ [['group' => (object)['sub' => ['check' => '$1']]], 'object', 'array']
+ ];
+ }
+
/**
- * Provide uri's and corresponding patterns for testBindVarSingleUrlPart()
+ * @dataProvider bindVarWithSubProvider
+ *
+ * @param array $options
+ * @param string $type
+ * @param string $subtype
*/
- public function bindVarSingleUrlPartProvider()
+ public function testBindVarWithSub(array $options, $type, $subtype = null)
+ {
+ $glob = new Glob(['/*' => $options]);
+
+ $request = $this->getServerRequest('/test');
+ $route = $glob->getRoute($request);
+
+ $this->assertNotNull($route, "Route not found");
+ $this->assertInstanceOf(Route::class, $route);
+
+ $this->assertInternalType($type, $route->group);
+
+ $group = (array)$route->group;
+
+ if (isset($subtype)) {
+ $this->assertArrayHasKey('sub', $group);
+ $this->assertInternalType($subtype, $group['sub']);
+
+ $group = (array)$group['sub'];
+ }
+
+ $this->assertEquals($group, ['check' => 'test']);
+ }
+
+
+ /**
+ * Provide uri's and corresponding patterns for testBindVarMultipleUrlParts()
+ */
+ public function bindVarMultipleUrlPartsProvider()
{
return [
- ['/*', '/test', ['controller' => 'value', 'check' => '$1']],
- ['/foo/*/bar', '/foo/test/bar', ['controller' => 'value', 'check' => '$2']],
- ['/foo/bar/*', '/foo/bar/test', ['controller' => 'value', 'check' => '$3']],
- ['/foo/bar/*/zet/*', '/foo/bar/test1/zet/test2', ['controller' => 'value', 'check1' => '$3', 'check2' => '$5']],
- ['/foo/bar/*/zet/*', '/foo/bar/test1/zet/test2', ['controller' => 'value', 'check1' => '~$3~/~$5~']]
+ ['/foo', ['check' => '$1...'], false, InvalidArgumentException::class],
+ ['/', ['check' => ['$1...']], false],
+ ['/foo', ['check' => ['$1...']], true],
+ ['/foo/bar', ['check' => ['$1...'], 'checkB' => ['$2...']],
+ InvalidArgumentException::class]
];
}
/**
* Test binding multyple url parts to route option
- *
* @dataProvider bindVarMultipleUrlPartsProvider
- * @param string $uri
- * @param array $options Route options
- * @param boolean $positive
- * @param string $exception
+ *
+ * @param string $uri
+ * @param array $options Route options
+ * @param boolean $positive
+ * @param string $exception
*/
- public function testBindVarMultipleUrlParts($uri, $options, $positive, $exception)
+ public function testBindVarMultipleUrlParts($uri, $options, $positive, $exception = false)
{
- if ($exception) $this->expectException(InvalidArgumentException::class);
-
- $values = [$uri => $options];
- $glob = new Glob($values);
+ if ($exception) {
+ $this->expectException($exception);
+ }
+
+ $glob = new Glob([$uri => $options]);
$request = $this->getServerRequest($uri);
$route = $glob->getRoute($request);
if ($exception) return;
- $values = explode('/', trim($uri, '/'));
- $this->assertTrue((bool)$route, "Route not found");
+ $this->assertNotNull($route, "Route not found");
+ $this->assertInstanceOf(Route::class, $route);
+ $values = explode('/', trim($uri, '/'));
+
$positive ?
- $this->assertArraysEqual($values, $route['check'], "Multyple url parts are not picked correctly") :
- $this->assertEmpty($route['check'], "Multyple parts element should be empty");
+ $this->assertArraysEqual($values, $route->check, "Multyple url parts are not picked correctly") :
+ $this->assertEmpty($route->check, "Multyple parts element should be empty");
- if (!empty($options['check2'])) {
+ if (!empty($options->checkB)) {
array_shift($values);
- $this->assertArraysEqual($values, $route['check2'], "Secondary multyple url parts are not picked correctly");
+ $this->assertArraysEqual($values, $route->checkB, "Secondary multyple url parts are not picked correctly");
}
}
/**
* Provide uri's and corresponding patterns for testBindVarMultipleUrlParts()
*/
- public function bindVarMultipleUrlPartsProvider()
+ public function bindVarSuperGlobalProvider()
{
return [
- ['/foo', ['controller' => 'value', 'check' => '$1...'], false, InvalidArgumentException::class],
- ['/', ['controller' => 'value', 'check' => ['$1...']], false, ''],
- ['/foo', ['controller' => 'value', 'check' => ['$1...']], true, ''],
- ['/foo/bar', ['controller' => 'value', 'check' => ['$1...'], 'check2' => ['$2...']], true, '']
+ ['/foo', ['check' => '$_GET[check]'], 'get'],
+ ['/foo', ['check' => '$_POST[check]'], 'post'],
+ ['/foo', ['check' => '$_COOKIE[check]'], 'cookie']
];
}
/**
* Test binding element of superglobal array to route option
- *
* @dataProvider bindVarSuperGlobalProvider
+ *
* @param string $uri
* @param array $options
* @param string $type ('get', 'post', 'cookie')
@@ -411,19 +517,7 @@ class GlobTest extends \PHPUnit_Framework_TestCase
$request = $this->getServerRequest($uri, 'GET', [$type => $test]);
$route = $glob->getRoute($request);
- $this->assertEquals($test['check'], $route['check'], "Did not obtaine value for superglobal '$type'");
- }
-
- /**
- * Provide uri's and corresponding patterns for testBindVarMultipleUrlParts()
- */
- public function bindVarSuperGlobalProvider()
- {
- return [
- ['/foo', ['controller' => 'value', 'check' => '$_GET[check]'], 'get'],
- ['/foo', ['controller' => 'value', 'check' => '$_POST[check]'], 'post'],
- ['/foo', ['controller' => 'value', 'check' => '$_COOKIE[check]'], 'cookie']
- ];
+ $this->assertEquals($test['check'], $route->check, "Did not obtaine value for superglobal '$type'");
}
/**
@@ -433,11 +527,14 @@ class GlobTest extends \PHPUnit_Framework_TestCase
{
$uri = '/foo/bar';
$test = 'test_header_value';
- $glob = new Glob([$uri => ['controller' => 'value', 'check' => '$HTTP_REFERER']]);
+
+ $glob = new Glob([$uri => ['check' => '$HTTP_REFERER']]);
$request = $this->getServerRequest($uri, 'GET', [], $test);
+
$route = $glob->getRoute($request);
+ $this->assertNotNull($route, "Route not found");
- $this->assertEquals($test, $route['check'], "Did not obtaine value for header");
+ $this->assertEquals($test, $route->check);
}
/**
@@ -469,7 +566,7 @@ class GlobTest extends \PHPUnit_Framework_TestCase
*/
public function assertArraysEqual(array $array1, array $array2)
{
- $this->assertEquals(count($array1), count($array2));
- $this->assertEmpty(array_diff($array1, $array2));
+ $this->assertEmpty(array_diff($array2, $array1), 'Missing items');
+ $this->assertEmpty(array_diff($array1, $array2), 'Additional items');
}
}
diff --git a/tests/RouterTest.php b/tests/RouterTest.php
index ee082b4..c036c71 100644
--- a/tests/RouterTest.php
+++ b/tests/RouterTest.php
@@ -5,7 +5,7 @@ namespace Jasny\Router;
use Jasny\Router;
use Jasny\Router\Route;
use Jasny\Router\Routes;
-use Jasny\Router\Runner\RunnerFactory;
+use Jasny\Router\RunnerFactory;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\StreamInterface;