Completed
Push — master ( f4f264...399648 )
by Antarès
03:11
created

AutomatedBehaviorTrait::assertPropertyValue()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 18
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 15
CRAP Score 4

Importance

Changes 4
Bugs 0 Features 0
Metric Value
c 4
b 0
f 0
dl 0
loc 18
ccs 15
cts 15
cp 1
rs 9.2
cc 4
eloc 11
nc 4
nop 2
crap 4
1
<?php
2
3
namespace Accessible;
4
5
use \Accessible\MethodManager\CollectionManager;
6
use \Accessible\Reader\Reader;
7
use \Accessible\Reader\ConstraintsReader;
8
9
trait AutomatedBehaviorTrait
10
{
11
    use AutoConstructTrait, AutoMethodsTrait;
12
13
    /**
14
     * The list of access rights on each property of the object.
15
     *
16
     * @var array
17
     */
18
    private $_accessProperties;
19
20
    /**
21
     * The list of collection properties and their item names.
22
     * Ex: [
23
     *   "byItemName" => "user" => ["property" => "users", "behavior" => "list", "methods" => ["add", "remove"]],
24
     *   "byProperty" => "users" => ["itemName" => "user", "behavior" => "list", "methods" => ["add", "remove"]]
25
     * ]
26
     *
27
     * @var array
28
     */
29
    private $_collectionsItemNames;
30
31
    /**
32
     * The list of associations for each property
33
     * Ex: ["products" => ["property" => "cart", "association" => "inverted"]]
34
     *
35
     * @var array
36
     */
37
    private $_associationsList;
38
39
    /**
40
     * Indicates wether the constraints validation should be enabled or not.
41
     *
42
     * @var boolean
43
     */
44
    private $_constraintsValidationEnabled;
45
46
    /**
47
     * The initial values of the properties that use Initialize and InitializeObject annotations.
48
     *
49
     * @var array
50
     */
51
    private $_initialPropertiesValues;
52
53
    /**
54
     * The arguments needed for the constructor.
55
     *
56
     * @var array
57
     */
58
    private $_initializationNeededArguments;
59
60
    /**
61
     * Indicates wether getPropertiesInfo() has been called or not.
62
     *
63
     * @var boolean
64
     */
65
    private $_automatedBehaviorInitialized = false;
66
67
    /**
68
     * Indicates if the properties constraints validation is enabled.
69
     *
70
     * @return boolean
71
     */
72
    public function isPropertiesConstraintsValidationEnabled()
73
    {
74
        return $this->_constraintsValidationEnabled;
75
    }
76
77
    /**
78
     * Enable (or disable) the properties constraints validation.
79
     *
80
     * @param boolean $enabled
81
     */
82 1
    public function setPropertiesConstraintsValidationEnabled($enabled = true)
83
    {
84 1
        $this->_constraintsValidationEnabled = $enabled;
85 1
    }
86
87
    /**
88
     * Disable (or enable) the properties constraints validation.
89
     *
90
     * @param boolean $disabled
91
     */
92 1
    public function setPropertiesConstraintsValidationDisabled($disabled = true)
93
    {
94 1
        $this->_constraintsValidationEnabled = !$disabled;
95 1
    }
96
97
    /**
98
     * Validates the given value compared to given property constraints.
99
     * If the value is not valid, an InvalidArgumentException will be thrown.
100
     *
101
     * @param  string $property The name of the reference property.
102
     * @param  mixed  $value    The value to check.
103
     *
104
     * @throws \InvalidArgumentException If the value is not valid.
105
     */
106 29
    protected function assertPropertyValue($property, $value)
107 1
    {
108 29
        $this->getPropertiesInfo();
109
110 29
        if ($this->_constraintsValidationEnabled) {
111 28
            $constraintsViolations = ConstraintsReader::validatePropertyValue($this, $property, $value);
112 28
            if ($constraintsViolations->count()) {
113 5
                $errorMessage = "Argument given is invalid; its constraints validation failed for property $property with the following messages: \"";
114 5
                $errorMessageList = array();
115 5
                foreach ($constraintsViolations as $violation) {
116 5
                    $errorMessageList[] = $violation->getMessage();
117 5
                }
118 5
                $errorMessage .= implode("\", \n\"", $errorMessageList) . "\".";
119
120 5
                throw new \InvalidArgumentException($errorMessage);
121
            }
122 27
        }
123 29
    }
124
125
    /**
126
     * Update the property associated to the given property.
127
     * You can pass the old or the new value given to the property.
128
     *
129
     * @param  string $property The property of the current class to update
130
     * @param  object $values   An array of old a new value under the following form:
131
     *                          ['oldValue' => $oldvalue, 'newValue' => $newValue]
132
     *                          If one of theses values is not given, it will simply not be updated.
133
     */
134 29
    protected function updatePropertyAssociation($property, array $values)
135
    {
136 29
        $this->getPropertiesInfo();
137
138 29
        $oldValue = empty($values['oldValue']) ? null : $values['oldValue'];
139 29
        $newValue = empty($values['newValue']) ? null : $values['newValue'];
140
141 29
        $association = $this->_associationsList[$property];
142 29
        if (!empty($association)) {
143 7
            $associatedProperty = $association['property'];
144 7
            switch ($association['association']) {
145 7
                case 'inverted':
146 5
                    $invertedGetMethod = 'get' . strtoupper(substr($associatedProperty, 0, 1)) . substr($associatedProperty, 1);
147 5
                    $invertedSetMethod = 'set' . strtoupper(substr($associatedProperty, 0, 1)) . substr($associatedProperty, 1);
148 5
                    if ($oldValue !== null && $oldValue->$invertedGetMethod() === $this) {
149 4
                        $oldValue->$invertedSetMethod(null);
150 4
                    }
151 5
                    if ($newValue !== null && $newValue->$invertedGetMethod() !== $this) {
152 5
                        $newValue->$invertedSetMethod($this);
153 5
                    }
154 5
                    break;
155
156 3
                case 'mapped':
157 3
                    $itemName = $association['itemName'];
158 3
                    $mappedGetMethod = 'get' . strtoupper(substr($associatedProperty, 0, 1)) . substr($associatedProperty, 1);
159 3
                    $mappedAddMethod = 'add' . strtoupper(substr($itemName, 0, 1)) . substr($itemName, 1);
160 3
                    $mappedRemoveMethod = 'remove' . strtoupper(substr($itemName, 0, 1)) . substr($itemName, 1);
161
162 3
                    if ($oldValue !== null && CollectionManager::collectionContains($this, $oldValue->$mappedGetMethod())) {
163 3
                        $oldValue->$mappedRemoveMethod($this);
164 3
                    }
165 3
                    if ($newValue !== null && !CollectionManager::collectionContains($this, $newValue->$mappedGetMethod())) {
166 3
                        $newValue->$mappedAddMethod($this);
167 3
                    }
168 3
                    break;
169 7
            }
170 7
        }
171 29
    }
172
173
    /**
174
     * Get every information needed from this class.
175
     */
176 29
    private function getPropertiesInfo()
177
    {
178 29
        if (!$this->_automatedBehaviorInitialized) {
179 29
            $classInfo = Reader::getClassInformation($this);
180
181 29
            $this->_accessProperties = $classInfo['accessProperties'];
182 29
            $this->_collectionsItemNames = $classInfo['collectionsItemNames'];
183 29
            $this->_associationsList = $classInfo['associationsList'];
184 29
            $this->_constraintsValidationEnabled = $classInfo['constraintsValidationEnabled'];
185 29
            $this->_initialPropertiesValues = $classInfo['initialPropertiesValues'];
186 29
            $this->_initializationNeededArguments = $classInfo['initializationNeededArguments'];
187
188 29
            $this->_automatedBehaviorInitialized = true;
189 29
        }
190 29
    }
191
}
192