Skip to content

Commit c204943

Browse files
committed
ExecuteAsyncTask instance support & arguments type hinting
1 parent acf6916 commit c204943

File tree

2 files changed

+109
-14
lines changed

2 files changed

+109
-14
lines changed

models/AsyncExecuteTask.php

Lines changed: 56 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,40 +3,60 @@
33

44
/**
55
* Class AsyncExecuteTask
6+
*
7+
* @property object $instance Class instance to execute against
8+
* @property string $class Class to call. Not required if [[instance]] specified
9+
* @property string $method Class or instance method to call
10+
* @property array $arguments Associative array of method's arguments
611
*/
712
class AsyncExecuteTask extends AsyncTask
813
{
9-
function __sleep()
10-
{
11-
return $this->attributeNames();
12-
}
13-
14+
public $instance;
1415
public $class;
1516
public $method;
1617
public $arguments = [];
1718

1819
public function rules()
1920
{
2021
return array(
21-
[['class', 'method', 'arguments'], 'required'],
22+
[['instance'], 'validateInstance'],
23+
[['class', 'method'], 'required'],
2224
[['class', 'method'], 'string'],
2325
[['class'], 'validateClass'],
2426
[['method'], 'validateMethod'],
2527
[['arguments'], 'validateArguments'],
2628
);
2729
}
2830

31+
private function getIsClassValid()
32+
{
33+
return class_exists($this->class);
34+
}
35+
36+
public function validateInstance($attribute, $params)
37+
{
38+
if (empty($this->$attribute)) {
39+
return;
40+
}
41+
42+
if (!is_object($this->$attribute)) {
43+
$this->addError($attribute, "Instance should be an object, not a " . gettype($this->$attribute));
44+
return;
45+
}
46+
47+
$this->class = get_class($this->$attribute);
48+
}
49+
2950
public function validateClass($attribute, $params)
3051
{
31-
if (!class_exists($this->$attribute)) {
52+
if (!$this->getIsClassValid()) {
3253
$this->addError($attribute, "Class {$this->$attribute} does not exist");
3354
}
3455
}
3556

3657
public function validateMethod($attribute, $params)
3758
{
38-
if (!class_exists($this->class)) {
39-
$this->addError($attribute, "Class {$this->$attribute} does not exist");
59+
if (!$this->getIsClassValid()) {
4060
return;
4161
}
4262

@@ -50,8 +70,7 @@ public function validateMethod($attribute, $params)
5070

5171
public function validateArguments($attribute, $params)
5272
{
53-
if (!class_exists($this->class)) {
54-
$this->addError($attribute, "Class {$this->$attribute} does not exist");
73+
if (!$this->getIsClassValid()) {
5574
return;
5675
}
5776

@@ -69,6 +88,21 @@ public function validateArguments($attribute, $params)
6988
foreach ($refFunc->getParameters() as $param) {
7089
if (!$param->isOptional() && !in_array($param->getName(), $userArguments)) {
7190
$missingArguments[] = $param->getName();
91+
} else {
92+
// Type hint
93+
// Notice that array hinting is not supported yet
94+
if ($param->getClass()
95+
&& (
96+
!is_object($this->{$attribute}[$param->getName()])
97+
|| get_class($this->{$attribute}[$param->getName()]) !== $param->getClass()->name
98+
)
99+
) {
100+
$this->addError(
101+
$attribute,
102+
"Method `{$this->method}` param `{$param->getName()}` " .
103+
"expects type `{$param->getClass()->name}` but got " . gettype($this->{$attribute}[$param->getName()])
104+
);
105+
}
72106
}
73107
}
74108

@@ -90,6 +124,7 @@ public function validateArguments($attribute, $params)
90124
public function attributeNames()
91125
{
92126
return [
127+
'instance',
93128
'class',
94129
'method',
95130
'arguments'
@@ -103,6 +138,15 @@ static function nope($return)
103138

104139
public function execute()
105140
{
106-
return call_user_func_array(array($this->class, $this->method), $this->arguments);
141+
if ($this->instance) {
142+
return call_user_func_array(array($this->instance, $this->method), $this->arguments);
143+
} else {
144+
return call_user_func_array(array($this->class, $this->method), $this->arguments);
145+
}
146+
}
147+
148+
function __sleep()
149+
{
150+
return $this->attributeNames();
107151
}
108152
}

tests/unit/BaseTestClass.php

Lines changed: 53 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,16 @@ public static function run($param)
2525
{
2626
throw new TestException($param);
2727
}
28+
29+
public static function hintArray(array $array)
30+
{
31+
32+
}
33+
34+
public static function hintClass(TestTask $param)
35+
{
36+
37+
}
2838
}
2939

3040
class BaseTestClass extends \yii\codeception\TestCase
@@ -74,7 +84,7 @@ public function testLifeCycle()
7484
$this->assertFalse($this->async->receiveTask(TestTask::$queueName));
7585
}
7686

77-
public function testAsyncExecuteTask()
87+
public function testAsyncExecuteTaskAgainstClass()
7888
{
7989
$aTask = new AsyncExecuteTask();
8090
$aTask->setAttributes(
@@ -101,7 +111,48 @@ public function testAsyncExecuteTask()
101111
$this->fail('BlackHole method wasn\'t called.');
102112
}
103113

104-
public function testArgumentsValidation()
114+
public function testAsyncExecuteTaskAgainstInstance()
115+
{
116+
$instance = new TestTask(['id' => 1]);
117+
118+
$aTask = new AsyncExecuteTask();
119+
$aTask->setAttributes(
120+
[
121+
'instance' => $instance,
122+
'method' => 'execute',
123+
]
124+
);
125+
126+
$this->async->sendTask($aTask);
127+
128+
$rTask = $this->async->receiveTask($aTask::$queueName);
129+
$this->assertInstanceOf('bazilio\async\models\AsyncExecuteTask', $rTask);
130+
131+
132+
$this->assertEquals(1, $rTask->execute());
133+
}
134+
135+
public function testArgumentsTypeHintingArrayValidation() {
136+
$this->markTestSkipped('Scalar type hint reflection is not available yet.');
137+
}
138+
139+
public function testArgumentsTypeHintingClassValidation() {
140+
$aTask = new AsyncExecuteTask();
141+
$aTask->setAttributes(
142+
[
143+
'class' => 'bazilio\async\tests\unit\BlackHole',
144+
'method' => 'hintClass',
145+
'arguments' => ['param' => 0]
146+
]
147+
);
148+
149+
$this->assertFalse($aTask->validate());
150+
$this->assertEquals(
151+
$aTask->errors['arguments'][0],
152+
'Method `hintClass` param `param` expects type `bazilio\async\tests\unit\TestTask` but got integer'
153+
);
154+
}
155+
public function testMissingArgumentsValidation()
105156
{
106157
$aTask = new AsyncExecuteTask();
107158
$aTask->setAttributes(

0 commit comments

Comments
 (0)