InvariantCheckerAspect   A
last analyzed

Complexity

Total Complexity 7

Size/Duplication

Total Lines 57
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 4

Test Coverage

Coverage 80.95%

Importance

Changes 0
Metric Value
wmc 7
lcom 1
cbo 4
dl 0
loc 57
ccs 17
cts 21
cp 0.8095
rs 10
c 0
b 0
f 0

3 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 5 1
A invariantContract() 0 17 3
A fetchAllContracts() 0 11 3
1
<?php
2
3
/**
4
 * PHP Deal framework
5
 *
6
 * @copyright Copyright 2019, Lisachenko Alexander <[email protected]>
7
 *
8
 * This source file is subject to the license that is bundled
9
 * with this source code in the file LICENSE.
10
 */
11
12
declare(strict_types=1);
13
14
namespace PhpDeal\Aspect;
15
16
use Doctrine\Common\Annotations\Reader;
17
use Go\Aop\Aspect;
18
use Go\Aop\Intercept\MethodInvocation;
19
use PhpDeal\Annotation\Invariant;
20
use PhpDeal\Contract\Fetcher\Parent\InvariantFetcher;
21
use PhpDeal\Exception\ContractViolation;
22
use Go\Lang\Annotation\Around;
23
use ReflectionClass;
24
25
class InvariantCheckerAspect extends AbstractContractAspect implements Aspect
26
{
27
    /**
28
     * @var InvariantFetcher
29
     */
30
    private $invariantFetcher;
31
32
    public function __construct(Reader $reader)
33
    {
34
        parent::__construct($reader);
35
        $this->invariantFetcher = new InvariantFetcher([Invariant::class], $reader);
36
    }
37
38
    /**
39
     * Verifies invariants for contract class
40
     *
41
     * @Around("@within(PhpDeal\Annotation\Invariant) && execution(public **->*(*))")
42
     * @param MethodInvocation $invocation
43
     *
44
     * @throws ContractViolation
45
     * @throws \ReflectionException
46
     * @return mixed
47
     */
48 8
    public function invariantContract(MethodInvocation $invocation)
49
    {
50 8
        $object = $invocation->getThis();
51 8
        $args   = $this->fetchMethodArguments($invocation);
52 8
        $class  = $invocation->getMethod()->getDeclaringClass();
53 8
        if (\is_object($object) && $class->isCloneable()) {
54 8
            $args['__old'] = clone $object;
55
        }
56
57 8
        $result = $invocation->proceed();
58 8
        $args['__result'] = $result;
59
60 8
        $allContracts = $this->fetchAllContracts($class);
61 8
        $this->ensureContracts($invocation, $allContracts, $object, $class->name, $args);
62
63 1
        return $result;
64
    }
65
66
    /**
67
     * @param ReflectionClass $class
68
     * @return array
69
     */
70 8
    private function fetchAllContracts(ReflectionClass $class): array
71
    {
72 8
        $allContracts = $this->invariantFetcher->getConditions($class);
73 8
        foreach ($this->reader->getClassAnnotations($class) as $annotation) {
74 8
            if ($annotation instanceof Invariant) {
75 8
                $allContracts[] = $annotation;
76
            }
77
        }
78
79 8
        return \array_unique($allContracts);
80
    }
81
}
82