Completed
Branch unit-test-asset-handler-connec... (029d08)
by Romain
01:55
created

BooleanNode   A

Complexity

Total Complexity 20

Size/Duplication

Total Lines 235
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 2

Importance

Changes 0
Metric Value
wmc 20
lcom 1
cbo 2
dl 0
loc 235
rs 10
c 0
b 0
f 0

12 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 9 1
A along() 0 5 1
A getCssResult() 0 11 1
A getJavaScriptResult() 0 11 1
A getPhpResult() 0 11 1
A getLogicalResult() 0 15 3
A processLogicalAndCss() 0 14 3
A processLogicalOrCss() 0 7 1
A processLogicalAndJavaScript() 0 14 3
A processLogicalOrJavaScript() 0 7 1
A processLogicalAndPhp() 0 4 2
A processLogicalOrPhp() 0 4 2
1
<?php
2
/*
3
 * 2016 Romain CANON <[email protected]>
4
 *
5
 * This file is part of the TYPO3 Formz project.
6
 * It is free software; you can redistribute it and/or modify it
7
 * under the terms of the GNU General Public License, either
8
 * version 3 of the License, or any later version.
9
 *
10
 * For the full copyright and license information, see:
11
 * http://www.gnu.org/licenses/gpl-3.0.html
12
 */
13
14
namespace Romm\Formz\Condition\Parser\Node;
15
16
use Romm\Formz\Condition\Parser\ConditionParser;
17
use Romm\Formz\Condition\Processor\DataObject\PhpConditionDataObject;
18
19
/**
20
 * A boolean node, which contains two sides and an operator.
21
 */
22
class BooleanNode extends AbstractNode
23
{
24
    /**
25
     * @var string
26
     */
27
    protected $operator;
28
29
    /**
30
     * @var NodeInterface
31
     */
32
    protected $leftSide;
33
34
    /**
35
     * @var NodeInterface
36
     */
37
    protected $rightSide;
38
39
    /**
40
     * Constructor.
41
     *
42
     * @param NodeInterface $leftSide  Left side of the boolean expression.
43
     * @param NodeInterface $rightSide Right side of the boolean expression.
44
     * @param string       $operator  One of the `ConditionParser::LOGICAL_*` constants.
45
     */
46
    public function __construct(NodeInterface $leftSide, NodeInterface $rightSide, $operator)
47
    {
48
        $this->leftSide = $leftSide;
49
        $this->rightSide = $rightSide;
50
        $this->operator = $operator;
51
52
        $this->leftSide->setParent($this);
53
        $this->rightSide->setParent($this);
54
    }
55
56
    /**
57
     * @inheritdoc
58
     */
59
    public function along(callable $callback)
60
    {
61
        $this->leftSide->along($callback);
62
        $this->rightSide->along($callback);
63
    }
64
65
    /**
66
     * @inheritdoc
67
     */
68
    public function getCssResult()
69
    {
70
        return $this->getLogicalResult(
71
            function() {
72
                return $this->processLogicalAndCss($this->leftSide, $this->rightSide);
73
            },
74
            function() {
75
                return $this->processLogicalOrCss($this->leftSide, $this->rightSide);
76
            }
77
        );
78
    }
79
80
    /**
81
     * @inheritdoc
82
     */
83
    public function getJavaScriptResult()
84
    {
85
        return $this->getLogicalResult(
86
            function() {
87
                return $this->processLogicalAndJavaScript($this->leftSide, $this->rightSide);
88
            },
89
            function() {
90
                return $this->processLogicalOrJavaScript($this->leftSide, $this->rightSide);
91
            }
92
        );
93
    }
94
95
    /**
96
     * @inheritdoc
97
     */
98
    public function getPhpResult(PhpConditionDataObject $dataObject)
99
    {
100
        return $this->getLogicalResult(
101
            function() use ($dataObject) {
102
                return $this->processLogicalAndPhp($this->leftSide, $this->rightSide, $dataObject);
103
            },
104
            function() use ($dataObject) {
105
                return $this->processLogicalOrPhp($this->leftSide, $this->rightSide, $dataObject);
106
            }
107
        );
108
    }
109
110
    /**
111
     * Global function to get the result of a logical operation, the processor
112
     * does not matter.
113
     *
114
     * @param callable $logicalAndFunction
115
     * @param callable $logicalOrFunction
116
     * @return null
117
     * @throws \Exception
118
     */
119
    protected function getLogicalResult(callable $logicalAndFunction, callable $logicalOrFunction)
120
    {
121
        switch ($this->operator) {
122
            case ConditionParser::LOGICAL_AND:
123
                $result = call_user_func($logicalAndFunction);
124
                break;
125
            case ConditionParser::LOGICAL_OR:
126
                $result = call_user_func($logicalOrFunction);
127
                break;
128
            default:
129
                throw new \Exception('The boolean node has a wrong operator: "' . $this->operator . '".', 1458150438);
130
        }
131
132
        return $result;
133
    }
134
135
    /**
136
     * Will process a logical "and" operation on the two given nodes. The result
137
     * will be an array containing all the result of the "and" operation on
138
     * every existing results of the two nodes.
139
     *
140
     * With CSS, it means to concatenate two condition strings. Example:
141
     *
142
     * Left   = [foo="bar"]
143
     * Right  = [pet="dog"]
144
     * Result = [foo="bar"][pet="dog"]
145
     *
146
     * @param NodeInterface $left  Left node instance.
147
     * @param NodeInterface $right Right node instance.
148
     * @return array
149
     */
150
    protected function processLogicalAndCss(NodeInterface $left, NodeInterface $right)
151
    {
152
        $leftResults = $this->toArray($left->getCssResult());
153
        $rightResults = $this->toArray($right->getCssResult());
154
155
        $result = [];
156
        foreach ($leftResults as $leftResult) {
157
            foreach ($rightResults as $rightResult) {
158
                $result[] = $leftResult . $rightResult;
159
            }
160
        }
161
162
        return $result;
163
    }
164
165
    /**
166
     * Will process a logical "or" operation on the two given nodes. The result
167
     * will be an array containing all the result of the "or" operation on
168
     * every existing results of the two nodes.
169
     *
170
     * @param NodeInterface $left  Left node instance.
171
     * @param NodeInterface $right Right node instance.
172
     * @return array
173
     */
174
    protected function processLogicalOrCss(NodeInterface $left, NodeInterface $right)
175
    {
176
        return array_merge(
177
            $this->toArray($left->getCssResult()),
178
            $this->toArray($right->getCssResult())
179
        );
180
    }
181
182
    /**
183
     * Will process a logical "and" operation on the two given nodes. The result
184
     * will be an array containing all the result of the "and" operation on
185
     * every existing results of the two nodes.
186
     *
187
     * With JavaScript, it means adding the operator `&&` between the two
188
     * expressions.
189
     *
190
     * @param NodeInterface $left  Left node instance.
191
     * @param NodeInterface $right Right node instance.
192
     * @return array
193
     */
194
    protected function processLogicalAndJavaScript(NodeInterface $left, NodeInterface $right)
195
    {
196
        $leftResults = $this->toArray($left->getJavaScriptResult());
197
        $rightResults = $this->toArray($right->getJavaScriptResult());
198
199
        $result = [];
200
        foreach ($leftResults as $leftResult) {
201
            foreach ($rightResults as $rightResult) {
202
                $result[] = $leftResult . ' && ' . $rightResult;
203
            }
204
        }
205
206
        return $result;
207
    }
208
209
    /**
210
     * Will process a logical "or" operation on the two given nodes. The result
211
     * will be an array containing all the result of the "or" operation on
212
     * every existing results of the two nodes.
213
     *
214
     * @param NodeInterface $left  Left node instance.
215
     * @param NodeInterface $right Right node instance.
216
     * @return array
217
     */
218
    protected function processLogicalOrJavaScript(NodeInterface $left, NodeInterface $right)
219
    {
220
        return array_merge(
221
            $this->toArray($left->getJavaScriptResult()),
222
            $this->toArray($right->getJavaScriptResult())
223
        );
224
    }
225
226
    /**
227
     * Will process a logical "and" operation on the two given nodes. The result
228
     * will be an array containing all the result of the "and" operation on
229
     * every existing results of the two nodes.
230
     *
231
     * With JavaScript, it means that the left and the right nodes are both
232
     * true.
233
     *
234
     * @param NodeInterface          $left  Left node instance.
235
     * @param NodeInterface          $right Right node instance.
236
     * @param PhpConditionDataObject $dataObject
237
     * @return bool
238
     */
239
    protected function processLogicalAndPhp(NodeInterface $left, NodeInterface $right, PhpConditionDataObject $dataObject)
240
    {
241
        return ($left->getPhpResult($dataObject) && $right->getPhpResult($dataObject));
242
    }
243
244
    /**
245
     * Will process a logical "or" operation on the two given nodes.
246
     *
247
     * @param NodeInterface          $left  Left node instance.
248
     * @param NodeInterface          $right Right node instance.
249
     * @param PhpConditionDataObject $dataObject
250
     * @return bool
251
     */
252
    protected function processLogicalOrPhp(NodeInterface $left, NodeInterface $right, PhpConditionDataObject $dataObject)
253
    {
254
        return ($left->getPhpResult($dataObject) || $right->getPhpResult($dataObject));
255
    }
256
}
257