Skip to content

Commit a0a8ec4

Browse files
author
Augusto Pascutti
committed
Accept routines passed as callable class names.
- Creates an execute() method in AbstractSyncedRoutine; - Creates test for Respect\Rest\Routines\AbstractRoutine: - Add provider for valid constructor arguments - Add assert for getCallback() method on AbstractRoutine.
1 parent acb9437 commit a0a8ec4

8 files changed

Lines changed: 144 additions & 16 deletions

File tree

library/Respect/Rest/Routines/AbstractRoutine.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,6 @@
33
namespace Respect\Rest\Routines;
44

55
use InvalidArgumentException;
6-
use ReflectionFunction;
7-
use ReflectionMethod;
8-
use Respect\Rest\Routes\AbstractRoute;
96

107
/** Base class for callback routines */
118
abstract class AbstractRoutine implements Routinable
@@ -15,14 +12,17 @@ abstract class AbstractRoutine implements Routinable
1512

1613
public function __construct($callback)
1714
{
15+
if (is_string($callback) && class_exists($callback) && method_exists($callback, '__invoke'))
16+
return $this->callback = $callback;
17+
1818
if (!is_callable($callback))
1919
throw new InvalidArgumentException('Routine callback must be... guess what... callable!');
20+
2021
$this->callback = $callback;
2122
}
2223

2324
protected function getCallback()
2425
{
2526
return $this->callback;
2627
}
27-
2828
}

library/Respect/Rest/Routines/AbstractSyncedRoutine.php

Lines changed: 38 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,36 +6,65 @@
66
use ReflectionFunction;
77
use ReflectionMethod;
88
use ReflectionObject;
9+
use ReflectionClass;
910
use Closure;
10-
use Respect\Rest\Routes\AbstractRoute;
11+
use Respect\Rest\Routes\AbstractRoute,
12+
Respect\Rest\Request;
1113

1214
/** Base class for routines that sync parameters */
1315
abstract class AbstractSyncedRoutine extends AbstractRoutine implements ParamSynced
1416
{
15-
17+
/**
18+
* @var Reflector
19+
*/
1620
protected $reflection;
1721

22+
/**
23+
* Return parameters that can be used with the routine.
24+
*
25+
* @return array
26+
*/
1827
public function getParameters()
1928
{
2029
$reflection = $this->getReflection();
21-
if (!$reflection instanceof ReflectionObject)
30+
if (!$reflection instanceof ReflectionObject && !$reflection instanceof ReflectionClass)
2231
return $this->getReflection()->getParameters();
2332

24-
$constructorReflection = $reflection->getConstructor();
25-
if (is_null($constructorReflection))
26-
return array();
27-
else
28-
return $constructorReflection->getParameters();
33+
return array();
34+
}
35+
36+
/**
37+
* Executes the routine and return its result.
38+
*
39+
* @param Respect\Rest\Request $request
40+
* @param array $params
41+
* @return mixed
42+
*/
43+
public function execute(Request $request, $params)
44+
{
45+
$callback = $this->getCallback();
46+
if (is_string($callback)) {
47+
$reflection = $this->getReflection();
48+
$routineInstance = $reflection->newInstanceArgs($params);
49+
return $routineInstance();
50+
}
51+
return call_user_func_array($callback, $params);
2952
}
3053

31-
/** Returns a concrete ReflectionFunctionAbstract for this routine callback */
54+
/**
55+
* Returns a concrete ReflectionFunctionAbstract for this routine callback.
56+
*
57+
* @return Reflector
58+
*/
3259
protected function getReflection()
3360
{
3461
$callback = $this->getCallback();
3562
if (is_array($callback))
3663
return new ReflectionMethod($callback[0], $callback[1]);
3764
else if ($callback instanceof Closure)
3865
return new ReflectionFunction($callback);
66+
else if (is_string($callback))
67+
return new ReflectionClass($callback);
3968
else
4069
return new ReflectionObject($callback);
4170
}

library/Respect/Rest/Routines/By.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ class By extends AbstractSyncedRoutine implements ProxyableBy
1010

1111
public function by(Request $request, $params)
1212
{
13-
return call_user_func_array($this->callback, $params);
13+
return $this->execute($request, $params);
1414
}
1515

1616
}

library/Respect/Rest/Routines/Through.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ class Through extends AbstractSyncedRoutine implements ProxyableThrough
1010

1111
public function through(Request $request, $params)
1212
{
13-
return call_user_func_array($this->callback, $params);
13+
return $this->execute($request, $params);
1414
}
1515

1616
}

library/Respect/Rest/Routines/When.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ class When extends AbstractSyncedRoutine implements ProxyableWhen
1010

1111
public function when(Request $request, $params)
1212
{
13-
$valid = call_user_func_array($this->callback, $params);
13+
$valid = $this->execute($request, $params);
1414

1515
if (!$valid)
1616
header('HTTP/1.1 400');

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

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ public function test_by_with_an_anonymous_function()
4444

4545
/**
4646
* @covers Respect\Rest\Routines\By
47+
* @covers Respect\Rest\Routines\AbstractSyncedRoutine
4748
*/
4849
public function test_by_on_a_route()
4950
{
@@ -57,6 +58,26 @@ public function test_by_on_a_route()
5758
);
5859
}
5960

61+
/**
62+
* @covers Respect\Rest\Routines\By
63+
* @covers Respect\Rest\Routines\AbstractSyncedRoutine
64+
*/
65+
public function test_by_on_a_route_with_classname()
66+
{
67+
$router = new Router();
68+
$router->get('/', function() { return 'route'; })
69+
->by('Stubs\Routines\ByClassWithInvoke');
70+
// By does not affect the output of the route.
71+
$this->assertEquals(
72+
$expected = 'route',
73+
(string) $router->dispatch('GET', '/')
74+
);
75+
}
76+
77+
/**
78+
* @covers Respect\Rest\Routines\By
79+
* @covers Respect\Rest\Routines\AbstractSyncedRoutine
80+
*/
6081
public function test_by_with_a_callable_class_on_a_route()
6182
{
6283
$router = new Router;
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
<?php
2+
3+
namespace Respect\Rest\Routines;
4+
5+
use InvalidArgumentException;
6+
use ReflectionFunction;
7+
use ReflectionMethod;
8+
use Stubs\Routines\AbstractRoutine as Stub;
9+
use Stubs\Routines\WhenAlwaysTrue as InstanceWithInvoke;
10+
11+
/** Test an AbstractRoutine (abstract class) instantiation through a stub class. */
12+
class AbstractRoutineTest extends \PHPUnit_Framework_TestCase
13+
{
14+
/**
15+
* @dataProvider provide_valid_constructor_arguments
16+
* @covers Respect\Rest\Routines\AbstractRoutine
17+
*/
18+
public function test_valid_constructor_arguments($argument)
19+
{
20+
$this->assertInstanceOf(
21+
'Respect\Rest\Routines\AbstractRoutine',
22+
$result = new Stub($argument)
23+
);
24+
$this->assertSame(
25+
$expected = $argument,
26+
$result = $result->getCallback()
27+
);
28+
}
29+
30+
public function provide_valid_constructor_arguments()
31+
{
32+
return array(
33+
array(function() { return 'Hello'; }), // an anonymous function
34+
array(array('DateTime', 'createFromFormat')), // a class-method callable pair
35+
array(new InstanceWithInvoke), // instance of a callable class
36+
array('Stubs\Routines\WhenAlwaysTrue') // a callable class name
37+
);
38+
}
39+
40+
/**
41+
* @dataProvider provide_invalid_constructor_arguments
42+
* @covers Respect\Rest\Routines\AbstractRoutine
43+
* @expectedException InvalidArgumentException
44+
* @expectedExceptionMessage Routine callback must be... guess what... callable!
45+
*/
46+
public function test_invalid_constructor_arguments($argument)
47+
{
48+
$result = new Stub($argument);
49+
}
50+
51+
public function provide_invalid_constructor_arguments()
52+
{
53+
return array(
54+
array('this_function_name_does_not_exist'),
55+
array(new \StdClass), // an instance that is not callable
56+
);
57+
}
58+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?php
2+
3+
namespace Stubs\Routines;
4+
5+
use Respect\Rest\Routines\AbstractRoutine as RestAbstractRoutine;
6+
use InvalidArgumentException;
7+
use ReflectionFunction;
8+
use ReflectionMethod;
9+
use Respect\Rest\Routes\AbstractRoute;
10+
11+
/**
12+
* Concrete stub class for AbstractRoutines.
13+
*/
14+
class AbstractRoutine extends RestAbstractRoutine
15+
{
16+
public function getCallback()
17+
{
18+
return $this->callback;
19+
}
20+
}

0 commit comments

Comments
 (0)