-
Notifications
You must be signed in to change notification settings - Fork 22
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Made AbstractFetcher accept more then one annotation type * Add inherit annotation This will serve as a contract inherit flag. It will take all existing annotations (ensure, verify, invariant) and check current as well as parent classes for contracts * Update Inherit implementation - Inherit will now always inherit contracts (despite missing @inheritdoc) - provide Inherit tests - update Demo implementation - update Readme with Inherit documentation
- Loading branch information
1 parent
51150fd
commit 078ca37
Showing
18 changed files
with
376 additions
and
27 deletions.
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
/vendor/ | ||
composer.lock | ||
/tests/cache/ | ||
/demo/cache/ |
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
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
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
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
<?php | ||
/** | ||
* PHP Deal framework | ||
* | ||
* @copyright Copyright 2014, Lisachenko Alexander <lisachenko.it@gmail.com> | ||
* | ||
* This source file is subject to the license that is bundled | ||
* with this source code in the file LICENSE. | ||
*/ | ||
namespace PhpDeal\Annotation; | ||
|
||
use Doctrine\Common\Annotations\Annotation as BaseAnnotation; | ||
|
||
/** | ||
* This annotation defines a contract inheritance check, applied to the method or class | ||
* | ||
* @Annotation | ||
* @Target({"METHOD", "CLASS"}) | ||
*/ | ||
class Inherit extends BaseAnnotation | ||
{ | ||
public function __toString() | ||
{ | ||
return $this->value; | ||
} | ||
} |
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,130 @@ | ||
<?php | ||
|
||
namespace PhpDeal\Aspect; | ||
|
||
use Doctrine\Common\Annotations\Reader; | ||
use Go\Aop\Aspect; | ||
use Go\Aop\Intercept\MethodInvocation; | ||
use Go\Lang\Annotation\Around; | ||
use PhpDeal\Annotation\Ensure; | ||
use PhpDeal\Annotation\Invariant; | ||
use PhpDeal\Annotation\Verify; | ||
use PhpDeal\Contract\Fetcher\Parent\InvariantFetcher; | ||
use PhpDeal\Contract\Fetcher\Parent\MethodConditionFetcher; | ||
use PhpDeal\Exception\ContractViolation; | ||
use ReflectionClass; | ||
|
||
class InheritCheckerAspect extends AbstractContractAspect implements Aspect | ||
{ | ||
/** | ||
* @var MethodConditionFetcher | ||
*/ | ||
private $methodConditionFetcher; | ||
|
||
/** @var InvariantFetcher */ | ||
private $invariantFetcher; | ||
|
||
public function __construct(Reader $reader) | ||
{ | ||
parent::__construct($reader); | ||
$this->methodConditionFetcher = new MethodConditionFetcher([Ensure::class, Verify::class, Invariant::class], $reader); | ||
$this->invariantFetcher = new InvariantFetcher([Invariant::class], $reader); | ||
} | ||
|
||
/** | ||
* Verifies inherit contracts for the method | ||
* | ||
* @Around("@execution(PhpDeal\Annotation\Inherit)") | ||
* @param MethodInvocation $invocation | ||
* | ||
* @throws ContractViolation | ||
* @return mixed | ||
*/ | ||
public function inheritMethodContracts(MethodInvocation $invocation) | ||
{ | ||
$object = $invocation->getThis(); | ||
$args = $this->fetchMethodArguments($invocation); | ||
$class = $invocation->getMethod()->getDeclaringClass(); | ||
if ($class->isCloneable()) { | ||
$args['__old'] = clone $object; | ||
} | ||
|
||
$result = $invocation->proceed(); | ||
$args['__result'] = $result; | ||
$allContracts = $this->fetchMethodContracts($invocation); | ||
|
||
$this->ensureContracts($invocation, $allContracts, $object, $class->name, $args); | ||
|
||
return $result; | ||
} | ||
|
||
/** | ||
* @Around("@within(PhpDeal\Annotation\Inherit) && execution(public **->*(*))") | ||
* @param MethodInvocation $invocation | ||
* @return mixed | ||
*/ | ||
public function inheritClassContracts(MethodInvocation $invocation) | ||
{ | ||
$object = $invocation->getThis(); | ||
$args = $this->fetchMethodArguments($invocation); | ||
$class = $invocation->getMethod()->getDeclaringClass(); | ||
if ($class->isCloneable()) { | ||
$args['__old'] = clone $object; | ||
} | ||
|
||
$result = $invocation->proceed(); | ||
$args['__result'] = $result; | ||
|
||
$allContracts = $this->fetchClassContracts($class); | ||
$this->ensureContracts($invocation, $allContracts, $object, $class->name, $args); | ||
|
||
return $result; | ||
} | ||
|
||
/** | ||
* @param MethodInvocation $invocation | ||
* @return array | ||
*/ | ||
private function fetchMethodContracts(MethodInvocation $invocation) | ||
{ | ||
$allContracts = $this->fetchParentsMethodContracts($invocation); | ||
|
||
foreach ($invocation->getMethod()->getAnnotations() as $annotation) { | ||
$annotationClass = \get_class($annotation); | ||
|
||
if (\in_array($annotationClass, [Ensure::class, Verify::class, Invariant::class], true)) { | ||
$allContracts[] = $annotation; | ||
} | ||
} | ||
|
||
return array_unique($allContracts); | ||
} | ||
|
||
/** | ||
* @param MethodInvocation $invocation | ||
* @return array | ||
*/ | ||
private function fetchParentsMethodContracts(MethodInvocation $invocation) | ||
{ | ||
return $this->methodConditionFetcher->getConditions( | ||
$invocation->getMethod()->getDeclaringClass(), | ||
$invocation->getMethod()->name | ||
); | ||
} | ||
|
||
/** | ||
* @param ReflectionClass $class | ||
* @return array | ||
*/ | ||
private function fetchClassContracts(ReflectionClass $class) | ||
{ | ||
$allContracts = $this->invariantFetcher->getConditions($class); | ||
foreach ($this->reader->getClassAnnotations($class) as $annotation) { | ||
if ($annotation instanceof Invariant) { | ||
$allContracts[] = $annotation; | ||
} | ||
} | ||
|
||
return array_unique($allContracts); | ||
} | ||
} |
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
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
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
Oops, something went wrong.