Skip to content

Commit acb9437

Browse files
author
Augusto Pascutti
committed
Make routines accept instances that are callable.
In other words, instances of classes that implement the __invoke() method. To accept class names instead of only instances we need to change the validation of callable objects in Routine\AbstractRoutine, something that would be nice to have. :) Also created a *src* directory inside tests to put classes related to tests only (stubs). Let me know if this bothers you a lot, I still think that this is better than declaring multiple namespaces on files.
1 parent 238d815 commit acb9437

8 files changed

Lines changed: 122 additions & 5 deletions

File tree

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,11 @@ Respect\Rest uses a different approach to validate route parameters:
291291
})->when(function($documentId) {
292292
return is_numeric($documentId) && $documentId > 0;
293293
});
294+
// Routines can also be called using class and method names.
295+
$r3->get('/documents/*', function($documentId) {
296+
/** do something */
297+
})->when('SomeClass_name', 'someMethod_name');
298+
// You can also pass any instance that implements the __invoke() magic method to any routine.
294299
```
295300

296301
1. This will match the route only if the callback on *when* is matched.

library/Respect/Rest/Routines/AbstractSyncedRoutine.php

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
use InvalidArgumentException;
66
use ReflectionFunction;
77
use ReflectionMethod;
8+
use ReflectionObject;
9+
use Closure;
810
use Respect\Rest\Routes\AbstractRoute;
911

1012
/** Base class for routines that sync parameters */
@@ -15,7 +17,15 @@ abstract class AbstractSyncedRoutine extends AbstractRoutine implements ParamSyn
1517

1618
public function getParameters()
1719
{
18-
return $this->getReflection()->getParameters();
20+
$reflection = $this->getReflection();
21+
if (!$reflection instanceof ReflectionObject)
22+
return $this->getReflection()->getParameters();
23+
24+
$constructorReflection = $reflection->getConstructor();
25+
if (is_null($constructorReflection))
26+
return array();
27+
else
28+
return $constructorReflection->getParameters();
1929
}
2030

2131
/** Returns a concrete ReflectionFunctionAbstract for this routine callback */
@@ -24,8 +34,10 @@ protected function getReflection()
2434
$callback = $this->getCallback();
2535
if (is_array($callback))
2636
return new ReflectionMethod($callback[0], $callback[1]);
27-
else
37+
else if ($callback instanceof Closure)
2838
return new ReflectionFunction($callback);
39+
else
40+
return new ReflectionObject($callback);
2941
}
3042

3143
}

tests/bootstrap.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
$paths[] = $path;
1313
}
1414

15+
$paths[] = realpath(__DIR__.DIRECTORY_SEPARATOR.'src');
1516
natsort($paths);
1617
array_unshift($paths, dirname(__DIR__) .'/library');
1718
set_include_path(implode(PATH_SEPARATOR, array_unique($paths)));

tests/legacy/Respect/Rest/Routines/AbstractSyncedRoutineTest.php

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
<?php
22
namespace Respect\Rest\Routines;
33

4+
use Stubs\Routines\ByClassWithInvoke;
5+
46
/**
57
* @covers Respect\Rest\Routines\ParamSynced
68
* @author Nick Lombard <github@jigsoft.co.za>
@@ -59,7 +61,7 @@ public function test_getParameters_with_an_array()
5961
->setMethods(array('getCallback'))
6062
->disableOriginalConstructor()
6163
->getMock();
62-
$stub->expects($this->once())
64+
$stub->expects($this->any())
6365
->method('getCallback')
6466
->will($this->returnValue($callback));
6567

@@ -85,7 +87,7 @@ public function test_getParameters_with_function()
8587
->setMethods(array('getCallback'))
8688
->disableOriginalConstructor()
8789
->getMock();
88-
$stub->expects($this->once())
90+
$stub->expects($this->any())
8991
->method('getCallback')
9092
->will($this->returnValue($callback));
9193

@@ -98,4 +100,30 @@ public function test_getParameters_with_function()
98100
$result
99101
);
100102
}
103+
104+
/**
105+
* @covers Respect\Rest\Routines\AbstractSyncedRoutine
106+
* @covers Respect\Rest\Routines\AbstractRoutine
107+
*/
108+
public function test_getParameters_with_callable_instance()
109+
{
110+
$stub = new ByClassWithInvoke;
111+
$this->assertTrue(
112+
is_callable($stub),
113+
'Callable instance does not pass the is_callable test.'
114+
);
115+
$class = 'Respect\Rest\Routines\AbstractSyncedRoutine';
116+
$callback = function($name) { return 'Hello '.$name; };
117+
$routine = $this->getMockBuilder($class)
118+
->setMethods(array('getCallback'))
119+
->disableOriginalConstructor()
120+
->getMock();
121+
$routine->expects($this->any())
122+
->method('getCallback')
123+
->will($this->returnValue($stub));
124+
$this->assertCount(
125+
$expected = 0,
126+
$result = $routine->getParameters()
127+
);
128+
}
101129
}

tests/legacy/Respect/Rest/Routines/ByTest.php

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
use Respect\Rest\Request,
55
Respect\Rest\Router;
6+
use Stubs\Routines\ByClassWithInvoke;
67

78
/**
89
* @covers Respect\Rest\Routines\By
@@ -55,4 +56,23 @@ public function test_by_on_a_route()
5556
(string) $router->dispatch('GET', '/')
5657
);
5758
}
59+
60+
public function test_by_with_a_callable_class_on_a_route()
61+
{
62+
$router = new Router;
63+
$routine = new ByClassWithInvoke;
64+
$router->get('/', function() { return 'route'; })
65+
->by($routine);
66+
// By does not affect the output of the route.
67+
$this->assertEquals(
68+
$expected = 'route',
69+
(string) $router->dispatch('GET', '/')
70+
);
71+
$this->assertAttributeEquals(
72+
$expected = true,
73+
'invoked',
74+
$routine,
75+
'Routine was not invoked!'
76+
);
77+
}
5878
}

tests/legacy/Respect/Rest/Routines/WhenTest.php

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
<?php
22
namespace Respect\Rest\Routines {
3-
use Respect\Rest\Request;
3+
4+
use Respect\Rest\Request,
5+
Respect\Rest\Router;
6+
use Stubs\Routines\WhenAlwaysTrue;
7+
48
/**
59
* @covers Respect\Rest\Routines\When
610
* @author Nick Lombard <github@jigsoft.co.za>
@@ -53,6 +57,25 @@ public function testWhen()
5357
$this->assertFalse($alias->when($request, $params));
5458
$this->assertArrayHasKey('HTTP/1.1 400', $header);
5559
}
60+
61+
public function test_when_with_a_callable_class_within_a_route()
62+
{
63+
$router = new Router;
64+
$routine = new WhenAlwaysTrue;
65+
$router->get('/', function() { return 'route'; })
66+
->by($routine);
67+
// By does not affect the output of the route.
68+
$this->assertEquals(
69+
$expected = 'route',
70+
(string) $router->dispatch('GET', '/')
71+
);
72+
$this->assertAttributeEquals(
73+
$expected = true,
74+
'invoked',
75+
$routine,
76+
'Routine was not invoked!'
77+
);
78+
}
5679
}
5780

5881
if (!function_exists(__NAMESPACE__.'\\header')) {
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?php
2+
3+
namespace Stubs\Routines;
4+
5+
class ByClassWithInvoke
6+
{
7+
public $invoked = false;
8+
9+
public function __invoke()
10+
{
11+
$this->invoked = true;
12+
return __CLASS__;
13+
}
14+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?php
2+
3+
namespace Stubs\Routines;
4+
5+
class WhenAlwaysTrue
6+
{
7+
public $invoked = false;
8+
9+
public function __invoke()
10+
{
11+
$this->invoked = true;
12+
return true;
13+
}
14+
}

0 commit comments

Comments
 (0)