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

src/Aspect/AbstractContractAspect.php (1 issue)

Labels
Severity

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

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
        $parameters = $invocation->getMethod()->getParameters();
43 49
        $argumentNames = array_map(function (\ReflectionParameter $parameter) {
44 48
            return $parameter->name;
45 49
        }, $parameters);
46 49
        $parameters = array_combine($argumentNames, $invocation->getArguments());
47
48 49
        return $parameters;
49
    }
50
51
    /**
52
     * Performs verification of contracts for given invocation
53
     *
54
     * @param MethodInvocation $invocation Current invocation
55
     * @param array|Annotation[] $contracts Contract annotation
56
     * @param object|string $instance Invocation instance or string for static class
57
     * @param string $scope Scope of method
58
     * @param array $args List of arguments for the method
59
     *
60
     * @throws DomainException
61
     */
62 49
    protected function ensureContracts(MethodInvocation $invocation, array $contracts, $instance, $scope, array $args)
63
    {
64 49
        static $invoker = null;
65 49
        if (!$invoker) {
66 49
            $invoker = function () {
67 49
                extract(func_get_arg(0));
0 ignored issues
show
func_get_arg(0) cannot be passed to extract() as the parameter $var_array expects a reference.
Loading history...
68
69 49
                return eval('return ' . func_get_arg(1) . '; ?>');
70 3
            };
71
        }
72
73
        $instance     = is_object($instance) ? $instance : null;
74
        $boundInvoker = $invoker->bindTo($instance, $scope);
75
76
        foreach ($contracts as $contract) {
77
            $contractExpression = $contract->value;
78
            try {
79
                $invocationResult = $boundInvoker->__invoke($args, $contractExpression);
80
81
                // we accept as a result only true or null
82
                // null may be a result of assertions from beberlei/assert which passed
83
                if ($invocationResult !== null && $invocationResult !== true) {
84
                    $errorMessage = 'Invalid return value received from the assertion body,'
85
                        . ' only boolean or void can be returned';
86
                    throw new DomainException($errorMessage);
87
                }
88
89
            } catch (\Error $internalError) {
90
                // PHP-7 friendly interceptor for fatal errors
91
                throw new ContractViolation($invocation, $contractExpression, $internalError);
92
            } catch (\Exception $internalException) {
93
                throw new ContractViolation($invocation, $contractExpression, $internalException);
94
            }
95
        }
96
    }
97
}
98