Skip to content

Commit 7b8b354

Browse files
authored
Conditions (#51)
* Condition Attributes * Attribute repeatable * Attribute repeatable * Target all * Construct conditions with DI * Remove init watcher * Use cubex * Share cubex as DI
1 parent ac3f51d commit 7b8b354

File tree

7 files changed

+170
-1
lines changed

7 files changed

+170
-1
lines changed

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
"packaged/config": "~1.5",
2424
"packaged/context": "^1.11",
2525
"packaged/context-i18n": "~1.0",
26-
"packaged/di-container": "~1.0",
26+
"packaged/di-container": "dev-master as 1.7",
2727
"packaged/event": "~1.2",
2828
"packaged/figlet": "~0.0",
2929
"packaged/helpers": "^2.15",
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<?php
2+
3+
namespace Cubex\Attributes;
4+
5+
use Packaged\DiContainer\DependencyInjector;
6+
7+
abstract class AbstractConditionAttribute
8+
{
9+
protected string $_class = '';
10+
protected array $_args = [];
11+
12+
public function __construct(string $class, array $args = [])
13+
{
14+
$this->_class = $class;
15+
$this->_args = $args;
16+
}
17+
18+
public function getClass(): string
19+
{
20+
return $this->_class;
21+
}
22+
23+
public function result(?DependencyInjector $di): ConditionResult
24+
{
25+
$obj = null;
26+
27+
if($di)
28+
{
29+
$obj = $di->resolve($this->_class, ...$this->_args);
30+
}
31+
else if(class_exists($this->_class))
32+
{
33+
$obj = new $this->_class(...$this->_args);
34+
}
35+
36+
if($obj instanceof ConditionResult)
37+
{
38+
return $obj;
39+
}
40+
41+
throw new \RuntimeException("Class {$this->_class} does not exist, or is not a ConditionResult");
42+
}
43+
}

src/Attributes/ConditionResult.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?php
2+
3+
namespace Cubex\Attributes;
4+
5+
use Packaged\Context\Context;
6+
7+
interface ConditionResult
8+
{
9+
// Returns null or a value to be returned from the method
10+
public function process(Context $ctx): mixed;
11+
}

src/Attributes/PreCondition.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?php
2+
3+
namespace Cubex\Attributes;
4+
5+
use Attribute;
6+
7+
#[Attribute(\Attribute::IS_REPEATABLE | \Attribute::TARGET_ALL)]
8+
class PreCondition extends AbstractConditionAttribute
9+
{
10+
}

src/Attributes/SkipCondition.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?php
2+
3+
namespace Cubex\Attributes;
4+
5+
use Attribute;
6+
7+
#[Attribute(\Attribute::IS_REPEATABLE | \Attribute::TARGET_ALL)]
8+
class SkipCondition extends AbstractConditionAttribute
9+
{
10+
}

src/Cubex.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ public function __construct($projectRoot, ClassLoader $loader = null, $global =
6363
$this->_eventChannel = new Channel('cubex');
6464
//Setup Context
6565
$this->share(ClassLoader::class, $loader);
66+
$this->share(DependencyInjector::class, $this);
6667
$this->factory(Context::class, $this->_defaultContextFactory());
6768

6869
if($global && self::$_cubex === null)

src/Routing/ConditionProcessor.php

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
<?php
2+
3+
namespace Cubex\Routing;
4+
5+
use Cubex\Attributes\PreCondition;
6+
use Cubex\Attributes\SkipCondition;
7+
use Cubex\Cubex;
8+
use Cubex\CubexAwareTrait;
9+
use Packaged\Context\ContextAwareTrait;
10+
use Packaged\DiContainer\AttributeWatcher;
11+
use Packaged\DiContainer\ReflectionInterrupt;
12+
use Packaged\DiContainer\ReflectionObserver;
13+
14+
class ConditionProcessor extends AttributeWatcher implements ReflectionInterrupt, ReflectionObserver
15+
{
16+
use ContextAwareTrait;
17+
use CubexAwareTrait;
18+
19+
public function __construct(Cubex $cubex)
20+
{
21+
$this->setCubex($cubex);
22+
$this->setContext($cubex->getContext());
23+
$this->clear();
24+
}
25+
26+
/**
27+
* @var \Cubex\Attributes\PreCondition[]
28+
*/
29+
protected array $_conditions = [];
30+
protected bool $_processed = false;
31+
32+
protected mixed $_handled = null;
33+
34+
protected function _processAttributes()
35+
{
36+
if($this->_processed)
37+
{
38+
return;
39+
}
40+
41+
$skipClasses = [];
42+
$this->_conditions = [];
43+
foreach($this->attributes() as $attribute)
44+
{
45+
if($attribute->getName() === SkipCondition::class)
46+
{
47+
$skipClasses[] = $attribute->newInstance()->getClass();
48+
}
49+
if($attribute->getName() === PreCondition::class)
50+
{
51+
/** @var \Cubex\Attributes\AbstractConditionAttribute $condition */
52+
$condition = $attribute->newInstance();
53+
$this->_conditions[$condition->getClass()] = $condition;
54+
}
55+
}
56+
57+
foreach($skipClasses as $skipClass)
58+
{
59+
if(isset($this->_conditions[$skipClass]))
60+
{
61+
unset($this->_conditions[$skipClass]);
62+
}
63+
}
64+
65+
$this->_processed = true;
66+
}
67+
68+
public function shouldInterruptMethod(): bool
69+
{
70+
$this->_processAttributes();
71+
if(empty($this->_conditions))
72+
{
73+
return false;
74+
}
75+
76+
foreach($this->_conditions as $condition)
77+
{
78+
$inst = $condition->result($this->getCubex());
79+
$res = $inst->process($this->getContext());
80+
if($res !== null)
81+
{
82+
$this->_handled = $res;
83+
return true;
84+
}
85+
}
86+
87+
return false;
88+
}
89+
90+
public function interruptMethod(): mixed
91+
{
92+
return $this->_handled;
93+
}
94+
}

0 commit comments

Comments
 (0)