Completed
Push — master ( 088857...dfef6d )
by Alexander
02:43
created

AbstractContractAspect   A

Complexity

Total Complexity 14

Size/Duplication

Total Lines 88
Duplicated Lines 0 %

Coupling/Cohesion

Components 0
Dependencies 2

Test Coverage

Coverage 80.95%

Importance

Changes 0
Metric Value
wmc 14
lcom 0
cbo 2
dl 0
loc 88
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 4 1
B fetchMethodArguments() 0 19 5
C ensureContracts() 0 35 8
1
<?php
2
/**
3
 * PHP Deal framework
4
 *
5
 * @copyright Copyright 2014, Lisachenko Alexander <[email protected]>
6
 *
7
 * This source file is subject to the license that is bundled
8
 * with this source code in the file LICENSE.
9
 */
10
11
namespace PhpDeal\Aspect;
12
13
use Doctrine\Common\Annotations\Annotation;
14
use Doctrine\Common\Annotations\Reader;
15
use DomainException;
16
use Go\Aop\Intercept\MethodInvocation;
17
use PhpDeal\Exception\ContractViolation;
18
19
abstract class AbstractContractAspect
20
{
21
    /**
22
     * @var Reader
23
     */
24
    protected $reader;
25
26
    /**
27
     * @param Reader $reader Annotation reader
28
     */
29
    public function __construct(Reader $reader)
30
    {
31
        $this->reader = $reader;
32
    }
33
34
    /**
35
     * Returns an associative list of arguments for the method invocation
36
     *
37
     * @param MethodInvocation $invocation
38
     * @return array
39
     */
40 49
    protected function fetchMethodArguments(MethodInvocation $invocation)
41
    {
42 49
        $result         = [];
43 49
        $parameters     = $invocation->getMethod()->getParameters();
44 49
        $argumentValues = $invocation->getArguments();
45
46
        // Number of arguments can be less than number of parameters because of default values
47 49
        foreach ($parameters as $parameterIndex => $reflectionParameter) {
48 48
            $hasArgumentValue = array_key_exists($parameterIndex, $argumentValues);
49 48
            $argumentValue    = $hasArgumentValue ? $argumentValues[$parameterIndex] : null;
50 48
            if (!$hasArgumentValue && $reflectionParameter->isDefaultValueAvailable()) {
51
                $argumentValue = $reflectionParameter->getDefaultValue();
52
            }
53 48
            $result[$reflectionParameter->name] = $argumentValue;
54
0 ignored issues
show
Coding Style introduced by
Blank line found at end of control structure
Loading history...
55
        }
56
57 49
        return $result;
58
    }
59
60
    /**
61
     * Performs verification of contracts for given invocation
62
     *
63
     * @param MethodInvocation $invocation Current invocation
64
     * @param array|Annotation[] $contracts Contract annotation
65
     * @param object|string $instance Invocation instance or string for static class
66
     * @param string $scope Scope of method
67
     * @param array $args List of arguments for the method
68
     *
69
     * @throws DomainException
70
     */
71 49
    protected function ensureContracts(MethodInvocation $invocation, array $contracts, $instance, $scope, array $args)
72
    {
73 49
        static $invoker = null;
74 49
        if (!$invoker) {
75 49
            $invoker = function () {
76 49
                extract(func_get_arg(0));
0 ignored issues
show
Bug introduced by
func_get_arg(0) cannot be passed to extract() as the parameter $var_array expects a reference.
Loading history...
77
78 49
                return eval('return ' . func_get_arg(1) . '; ?>');
79 3
            };
80
        }
81
82
        $instance     = is_object($instance) ? $instance : null;
83
        $boundInvoker = $invoker->bindTo($instance, $scope);
84
85
        foreach ($contracts as $contract) {
86
            $contractExpression = $contract->value;
87
            try {
88
                $invocationResult = $boundInvoker->__invoke($args, $contractExpression);
89
90
                // we accept as a result only true or null
91
                // null may be a result of assertions from beberlei/assert which passed
92
                if ($invocationResult !== null && $invocationResult !== true) {
93
                    $errorMessage = 'Invalid return value received from the assertion body,'
94
                        . ' only boolean or void can be returned';
95
                    throw new DomainException($errorMessage);
96
                }
97
0 ignored issues
show
Coding Style introduced by
Blank line found at end of control structure
Loading history...
98
            } catch (\Error $internalError) {
0 ignored issues
show
Bug introduced by
The class Error does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
99
                // PHP-7 friendly interceptor for fatal errors
100
                throw new ContractViolation($invocation, $contractExpression, $internalError);
101
            } catch (\Exception $internalException) {
102
                throw new ContractViolation($invocation, $contractExpression, $internalException);
103
            }
104
        }
105
    }
106
}
107