Completed
Push — unit-tests-conditions ( dc9eee...e8c03e )
by Romain
02:37
created

BooleanNode::getOperator()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
c 0
b 0
f 0
rs 10
cc 1
eloc 2
nc 1
nop 0
1
<?php
2
/*
3
 * 2017 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 $leftNode;
33
34
    /**
35
     * @var NodeInterface
36
     */
37
    protected $rightNode;
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->leftNode = $leftSide;
49
        $this->rightNode = $rightSide;
50
        $this->operator = $operator;
51
52
        $this->leftNode->setParent($this);
53
        $this->rightNode->setParent($this);
54
    }
55
56
    /**
57
     * @inheritdoc
58
     */
59
    public function along(callable $callback)
60
    {
61
        $this->leftNode->along($callback);
62
        call_user_func($callback, $this);
63
        $this->rightNode->along($callback);
64
    }
65
66
    /**
67
     * @inheritdoc
68
     */
69
    public function getCssResult()
70
    {
71
        return $this->getLogicalResult(
72
            function () {
73
                return $this->processLogicalAndCss();
74
            },
75
            function () {
76
                return $this->processLogicalOrCss();
77
            }
78
        );
79
    }
80
81
    /**
82
     * @inheritdoc
83
     */
84
    public function getJavaScriptResult()
85
    {
86
        return $this->getLogicalResult(
87
            function () {
88
                return $this->processLogicalAndJavaScript();
89
            },
90
            function () {
91
                return $this->processLogicalOrJavaScript();
92
            }
93
        );
94
    }
95
96
    /**
97
     * @inheritdoc
98
     */
99
    public function getPhpResult(PhpConditionDataObject $dataObject)
100
    {
101
        return $this->getLogicalResult(
102
            function () use ($dataObject) {
103
                return $this->processLogicalAndPhp($dataObject);
104
            },
105
            function () use ($dataObject) {
106
                return $this->processLogicalOrPhp($dataObject);
107
            }
108
        );
109
    }
110
111
    /**
112
     * Global function to get the result of a logical operation, the processor
113
     * does not matter.
114
     *
115
     * @param callable $logicalAndFunction
116
     * @param callable $logicalOrFunction
117
     * @return null
118
     * @throws \Exception
119
     */
120
    protected function getLogicalResult(callable $logicalAndFunction, callable $logicalOrFunction)
121
    {
122
        switch ($this->operator) {
123
            case ConditionParser::LOGICAL_AND:
124
                $result = call_user_func($logicalAndFunction);
125
                break;
126
            case ConditionParser::LOGICAL_OR:
127
                $result = call_user_func($logicalOrFunction);
128
                break;
129
            default:
130
                throw new \Exception('The boolean node has a wrong operator: "' . $this->operator . '".', 1458150438);
131
        }
132
133
        return $result;
134
    }
135
136
    /**
137
     * Will process a logical "and" operation on the two given nodes. The result
138
     * will be an array containing all the result of the "and" operation on
139
     * every existing results of the two nodes.
140
     *
141
     * With CSS, it means to concatenate two condition strings. Example:
142
     *
143
     * Left   = [foo="bar"]
144
     * Right  = [pet="dog"]
145
     * Result = [foo="bar"][pet="dog"]
146
     *
147
     * @return array
148
     */
149
    protected function processLogicalAndCss()
150
    {
151
        $leftResults = $this->toArray($this->leftNode->getCssResult());
152
        $rightResults = $this->toArray($this->rightNode->getCssResult());
153
154
        $result = [];
155
        foreach ($leftResults as $leftResult) {
156
            foreach ($rightResults as $rightResult) {
157
                $result[] = $leftResult . $rightResult;
158
            }
159
        }
160
161
        return $result;
162
    }
163
164
    /**
165
     * Will process a logical "or" operation on the two given nodes. The result
166
     * will be an array containing all the result of the "or" operation on
167
     * every existing results of the two nodes.
168
     *
169
     * @return array
170
     */
171
    protected function processLogicalOrCss()
172
    {
173
        return array_merge(
174
            $this->toArray($this->leftNode->getCssResult()),
175
            $this->toArray($this->rightNode->getCssResult())
176
        );
177
    }
178
179
    /**
180
     * Will process a logical "and" operation on the two given nodes. The result
181
     * will be an array containing all the result of the "and" operation on
182
     * every existing results of the two nodes.
183
     *
184
     * With JavaScript, it means adding the operator `&&` between the two
185
     * expressions.
186
     *
187
     * @return array
188
     */
189
    protected function processLogicalAndJavaScript()
190
    {
191
        $leftResults = $this->toArray($this->leftNode->getJavaScriptResult());
192
        $rightResults = $this->toArray($this->rightNode->getJavaScriptResult());
193
194
        $result = [];
195
        foreach ($leftResults as $leftResult) {
196
            foreach ($rightResults as $rightResult) {
197
                $result[] = $leftResult . ' && ' . $rightResult;
198
            }
199
        }
200
201
        return $result;
202
    }
203
204
    /**
205
     * Will process a logical "or" operation on the two given nodes. The result
206
     * will be an array containing all the result of the "or" operation on
207
     * every existing results of the two nodes.
208
     *
209
     * @return array
210
     */
211
    protected function processLogicalOrJavaScript()
212
    {
213
        return array_merge(
214
            $this->toArray($this->leftNode->getJavaScriptResult()),
215
            $this->toArray($this->rightNode->getJavaScriptResult())
216
        );
217
    }
218
219
    /**
220
     * Will process a logical "and" operation on the two given nodes. The result
221
     * will be an array containing all the result of the "and" operation on
222
     * every existing results of the two nodes.
223
     *
224
     * With JavaScript, it means that the left and the right nodes are both
225
     * true.
226
     *
227
     * @param PhpConditionDataObject $dataObject
228
     * @return bool
229
     */
230
    protected function processLogicalAndPhp(PhpConditionDataObject $dataObject)
231
    {
232
        return $this->leftNode->getPhpResult($dataObject) && $this->rightNode->getPhpResult($dataObject);
233
    }
234
235
    /**
236
     * Will process a logical "or" operation on the two given nodes.
237
     *
238
     * @param PhpConditionDataObject $dataObject
239
     * @return bool
240
     */
241
    protected function processLogicalOrPhp(PhpConditionDataObject $dataObject)
242
    {
243
        return $this->leftNode->getPhpResult($dataObject) || $this->rightNode->getPhpResult($dataObject);
244
    }
245
246
    /**
247
     * @return string
248
     */
249
    public function getOperator()
250
    {
251
        return $this->operator;
252
    }
253
}
254