Completed
Push — master ( 89b65c...bde278 )
by Alexander
02:30
created

Contract::ensureContractSatisfied()   B

Complexity

Conditions 5
Paths 8

Size

Total Lines 21
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 13
CRAP Score 5

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 21
ccs 13
cts 13
cp 1
rs 8.7624
cc 5
eloc 11
nc 8
nop 4
crap 5
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\Contract;
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\Contract\Fetcher\MethodArgument;
18
use PhpDeal\Exception\ContractViolation;
19
20
abstract class Contract
21
{
22
    /**
23
     * @var Reader
24
     */
25
    protected $reader;
26
27
    /**
28
     * @param Reader $reader Annotation reader
29
     */
30
    public function __construct(Reader $reader)
31
    {
32
        $this->reader = $reader;
33
    }
34
35
    /**
36
     * @param MethodInvocation $invocation
37
     * @return array
38
     */
39 34
    protected function getMethodArguments(MethodInvocation $invocation)
40
    {
41 34
        return (new MethodArgument())->fetch($invocation);
42
    }
43
44
    /**
45
     * @param array $allContracts
46
     * @return array
47
     */
48 34
    protected function makeContractsUnique(array $allContracts)
49
    {
50 34
        return array_unique($allContracts);
51
    }
52
53
    /**
54
     * @param array $allContracts
55
     * @param object|string $instance
56
     * @param string $scope
57
     * @param array $args
58
     * @param MethodInvocation $invocation
59
     */
60 34
    protected function fulfillContracts($allContracts, $instance, $scope, array $args, MethodInvocation $invocation)
61
    {
62 34
        foreach ($allContracts as $contract) {
63
            try {
64 34
                $this->ensureContractSatisfied($instance, $scope, $args, $contract);
65 23
            } catch (\Exception $e) {
66 34
                throw new ContractViolation($invocation, $contract->value, $e);
67
            }
68
        }
69 12
    }
70
71
    /**
72
     * Returns a result of contract verification
73
     *
74
     * @param object|string $instance Invocation instance or string for static class
75
     * @param string $scope Scope of method
76
     * @param array $args List of arguments for the method
77
     * @param Annotation $annotation Contract annotation
78
     * @throws DomainException
79
     */
80 34
    public function ensureContractSatisfied($instance, $scope, array $args, $annotation)
81
    {
82 34
        static $invoker = null;
83 34
        if (!$invoker) {
84 34
            $invoker = function () {
85 34
                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...
86
87 34
                return eval('return ' . func_get_arg(1) . '; ?>');
88 3
            };
89
        }
90
91 34
        $instance = is_object($instance) ? $instance : null;
92 34
        $invocationResult = $invoker->bindTo($instance, $scope)->__invoke($args, $annotation->value);
93
94
        // we accept as a result only true or null
95
        // null may be a result of assertions from beberlei/assert which passed
96 30
        if ($invocationResult !== null && $invocationResult !== true) {
97 19
            $errorMessage = 'Invalid return value received from the assertion body, only boolean or void accepted';
98 19
            throw new DomainException($errorMessage);
99
        }
100 20
    }
101
}
102