Created
February 17, 2015 20:34
-
-
Save ircmaxell/292aa7e31e093c0efb06 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
trait VerifyPrecondition { | |
protected $parent; | |
protected function verifyPrecondition($method, array $args) { | |
$objs = [new ReflectionMethod($this->parent, $method)]; | |
foreach ((new ReflectionObject($this->parent))->getInterfaces() as $iface) { | |
if ($iface->hasMethod($method)) { | |
$objs[] = $iface; | |
} | |
$parent = $objs[0]->getDeclaringClass()->getParentClass(); | |
while ($parent) { | |
if ($parent->hasMethod($method)) { | |
$rm = $parent->getMethod($method); | |
$objs[] = $rm; | |
$parent = $rm->getDeclaringClass()->getParentClass(); | |
} else { | |
$parent = false; | |
} | |
} | |
while ($r = array_shift($objs)) { | |
$r = new ReflectionMethod($obj, $method); | |
$scope = []; | |
foreach ($r->getParameters() as $arg) { | |
// add additional checks here | |
$scope[$arg->getName()] = isset($args[$arg->getPosition()]) ? $args[$arg->getPosition()] : $arg->getDefaultValue(); | |
} | |
foreach ($r->getAnnotations("precondition") as $annotation) { | |
if (!$annotation->getValue($scope, $this->parent)) { | |
throw new ConstraintViolationException(...); | |
} | |
} | |
} | |
} | |
} | |
interface Foo { | |
<precondition($a > 0)> | |
<precondition($div > 0)> | |
public function getRemainder(int $a, int $div): int; | |
} | |
class FooImpl implements Foo{ | |
public function getRemainder(int $a, int $div): int { | |
return $a % $div; | |
} | |
} | |
class FooImpl2 implements Foo { | |
<precondition($a != $div)> | |
public function getRemainder(int $a, int $div): int { | |
return $a % $div; | |
} | |
} | |
class PreconditionVerifierForFoo implements Foo { | |
use VerifyPrecondition; | |
public function __construct(Foo $foo) { | |
$this->parent = $foo; | |
} | |
public function getRemainder(int $a, int $div): int { | |
$this->verifyPreconditions(__METHOD__, func_get_args()); | |
return $this->parent->getRemainder($a, $div); | |
} | |
} | |
$foo = new FooImpl; | |
$foo->getRemainder(5, 0); // 0 | |
$verifiedFoo = new PreconditionVerifierForFoo($foo); | |
$verifiedFoo->getRemainder(5, 5); // 0 | |
$verifiedFoo->getRemainder(5, 0); // ConstraintViolationException | |
$verifiedFoo2 = new PreconditionVerifierForFoo(new Foo2); | |
$verifiedFoo2->getRemainder(5, 5); // ConstraintViolationException |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
class ReflectionAnnotation { | |
/** | |
* Get the name of the annotation | |
*/ | |
public function getName(): string {} | |
/** | |
* Executes the expression using the supplied scope and object context | |
*/ | |
public function getValue(array $scope = [], object $context = null): mixed {} | |
/** | |
* Get the raw AST in array form | |
*/ | |
public function getAst(): array {} | |
} | |
$r = new ReflectionMethod($obj, $method); | |
$annotations = $r->getAnnotations(); // return all | |
$annotations = $r->getAnnotations($name); // return all named $name |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment