Completed
Push — master ( 26495e...cf8e72 )
by Nathan
02:19
created

BranchValidator::validateCircularReferences()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 14
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 14
rs 9.4285
c 0
b 0
f 0
cc 3
eloc 9
nc 2
nop 4
1
<?php
2
3
namespace NatePage\EasyHtmlElement;
4
5
use NatePage\EasyHtmlElement\Exception\InvalidElementException;
6
7
class BranchValidator implements BranchValidatorInterface
8
{
9
    /** @var HtmlElementInterface */
10
    private $htmlElement;
11
12
    /** @var array The options to check to valid a branch */
13
    private $checks = array('parent', 'extends', 'children');
14
15
    public function __construct(HtmlElementInterface $htmlElement)
16
    {
17
        $this->htmlElement = $htmlElement;
18
    }
19
20
    /**
21
     * Valid the current map branch.
22
     *
23
     * @param string $name     The current element name
24
     * @param array  $circular The array of elements names called in the current branch of map
25
     */
26
    public function validateBranch($name, array $circular = array())
27
    {
28
        $current = $this->htmlElement->getCurrentElement($name);
29
30
        $circular[] = $current['name'];
31
32
        $this->validateClass($current);
33
34
        foreach ($this->checks as $check) {
35
            if (isset($current[$check])) {
36
                $currentCheck = (array) $current[$check];
37
38
                $this->validateDefineHimself($current['name'], $currentCheck, $check);
39
40
                foreach ($currentCheck as $cc) {
41
                    $this->validateCircularReferences($current['name'], $cc, $check, $circular);
42
                    $this->validateBranch($cc, $circular);
43
                }
44
            }
45
        }
46
    }
47
48
    /**
49
     * Validate the current element class.
50
     *
51
     * @param array $current The current element
52
     *
53
     * @throws InvalidElementException If the current element defines a class which doesn't exist
54
     */
55
    private function validateClass(array $current)
56
    {
57
        if (isset($current['class']) && !class_exists($current['class'])) {
58
            throw new InvalidElementException(sprintf(
59
                'The element "%s" define a class which doesn\'t exist.',
60
                $current['name']
61
            ));
62
        }
63
    }
64
65
    /**
66
     * Validate himself references.
67
     *
68
     * @param string $name         The current element name
69
     * @param array  $currentCheck The current check context
70
     * @param string $check        The current check name
71
     *
72
     * @throws InvalidElementException If the current element defines himself as parent, children or extends
73
     */
74
    private function validateDefineHimself($name, array $currentCheck, $check)
75
    {
76
        if (in_array($name, $currentCheck)) {
77
            throw new InvalidElementException(sprintf(
78
                'Element "%s" cannot define himself as %s.',
79
                $name,
80
                $check
81
            ));
82
        }
83
    }
84
85
    /**
86
     * Validate circular references.
87
     *
88
     * @param string       $name         The current element name
89
     * @param string|array $currentCheck The current check context
90
     * @param string       $check        The current check name
91
     * @param array        $circular     The names of the previous elements called
92
     *
93
     * @throws InvalidElementException If the current element defines a parent, child or extends which creates circular
94
     *                                 reference
95
     */
96
    private function validateCircularReferences($name, $currentCheck, $check, array $circular)
97
    {
98
        if (!is_array($currentCheck) && in_array($currentCheck, $circular)) {
99
            $circular[] = $currentCheck;
100
101
            throw new InvalidElementException(sprintf(
102
                'Element "%s" cannot define "%s" as %s. It\'s a circular reference. [%s]',
103
                $name,
104
                $currentCheck,
105
                $check,
106
                implode(' -> ', $circular)
107
            ));
108
        }
109
    }
110
}
111