PostconditionCheckerAspect   A
last analyzed

Complexity

Total Complexity 8

Size/Duplication

Total Lines 74
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 3

Test Coverage

Coverage 80.77%

Importance

Changes 0
Metric Value
wmc 8
lcom 1
cbo 3
dl 0
loc 74
ccs 21
cts 26
cp 0.8077
rs 10
c 0
b 0
f 0

4 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 5 1
A postConditionContract() 0 17 3
A fetchAllContracts() 0 14 3
A fetchParentsContracts() 0 7 1
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 Go\Aop\Support\AnnotatedReflectionMethod;
20
use PhpDeal\Annotation\Ensure;
21
use PhpDeal\Contract\Fetcher\Parent\MethodConditionFetcher;
22
use PhpDeal\Exception\ContractViolation;
23
use Go\Lang\Annotation\Around;
24
use ReflectionMethod;
25
26
class PostconditionCheckerAspect extends AbstractContractAspect implements Aspect
27
{
28
    /**
29
     * @var MethodConditionFetcher
30
     */
31
    private $methodConditionFetcher;
32
33
    public function __construct(Reader $reader)
34
    {
35
        parent::__construct($reader);
36
        $this->methodConditionFetcher = new MethodConditionFetcher([Ensure::class], $reader);
37
    }
38
39
    /**
40
     * Verifies post-condition contract for the method
41
     *
42
     * @Around("@execution(PhpDeal\Annotation\Ensure)")
43
     * @param MethodInvocation $invocation
44
     *
45
     * @throws ContractViolation
46
     * @throws \ReflectionException
47
     * @return mixed
48
     */
49 8
    public function postConditionContract(MethodInvocation $invocation)
50
    {
51 8
        $object = $invocation->getThis();
52 8
        $args   = $this->fetchMethodArguments($invocation);
53 8
        $class  = $invocation->getMethod()->getDeclaringClass();
54 8
        if (\is_object($object) && $class->isCloneable()) {
55 8
            $args['__old'] = clone $object;
56
        }
57
58 8
        $result = $invocation->proceed();
59 8
        $args['__result'] = $result;
60 8
        $allContracts = $this->fetchAllContracts($invocation);
61
62 8
        $this->ensureContracts($invocation, $allContracts, $object, $class->name, $args);
63
64
        return $result;
65
    }
66
67
    /**
68
     * @param MethodInvocation $invocation
69
     * @return array
70
     * @throws \ReflectionException
71
     */
72 8
    private function fetchAllContracts(MethodInvocation $invocation): array
73
    {
74 8
        $allContracts = $this->fetchParentsContracts($invocation);
75
        /** @var ReflectionMethod&AnnotatedReflectionMethod $reflectionMethod */
0 ignored issues
show
Documentation introduced by
The doc-type ReflectionMethod&AnnotatedReflectionMethod could not be parsed: Unknown type name "ReflectionMethod&AnnotatedReflectionMethod" at position 0. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
76 8
        $reflectionMethod = $invocation->getMethod();
77
78 8
        foreach ($reflectionMethod->getAnnotations() as $annotation) {
79 8
            if ($annotation instanceof Ensure) {
80 8
                $allContracts[] = $annotation;
81
            }
82
        }
83
84 8
        return \array_unique($allContracts);
85
    }
86
87
    /**
88
     * @param MethodInvocation $invocation
89
     * @return array
90
     * @throws \ReflectionException
91
     */
92 8
    private function fetchParentsContracts(MethodInvocation $invocation): array
93
    {
94 8
        return $this->methodConditionFetcher->getConditions(
95 8
            $invocation->getMethod()->getDeclaringClass(),
96 8
            $invocation->getMethod()->name
97
        );
98
    }
99
}
100