Completed
Push — development ( 3a4e51...3956e8 )
by Romain
21:00 queued 18:45
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
use Romm\Formz\Exceptions\InvalidConfigurationException;
19
20
/**
21
 * A boolean node, which contains two sides and an operator.
22
 */
23
class BooleanNode extends AbstractNode
24
{
25
    /**
26
     * @var string
27
     */
28
    protected $operator;
29
30
    /**
31
     * @var NodeInterface
32
     */
33
    protected $leftNode;
34
35
    /**
36
     * @var NodeInterface
37
     */
38
    protected $rightNode;
39
40
    /**
41
     * Constructor.
42
     *
43
     * @param NodeInterface $leftSide  Left side of the boolean expression.
44
     * @param NodeInterface $rightSide Right side of the boolean expression.
45
     * @param string       $operator  One of the `ConditionParser::LOGICAL_*` constants.
46
     */
47
    public function __construct(NodeInterface $leftSide, NodeInterface $rightSide, $operator)
48
    {
49
        $this->leftNode = $leftSide;
50
        $this->rightNode = $rightSide;
51
        $this->operator = $operator;
52
53
        $this->leftNode->setParent($this);
54
        $this->rightNode->setParent($this);
55
    }
56
57
    /**
58
     * @inheritdoc
59
     */
60
    public function along(callable $callback)
61
    {
62
        $this->leftNode->along($callback);
63
        call_user_func($callback, $this);
64
        $this->rightNode->along($callback);
65
    }
66
67
    /**
68
     * @inheritdoc
69
     */
70
    public function getCssResult()
71
    {
72
        return $this->getLogicalResult(
73
            function () {
74
                return $this->processLogicalAndCss();
75
            },
76
            function () {
77
                return $this->processLogicalOrCss();
78
            }
79
        );
80
    }
81
82
    /**
83
     * @inheritdoc
84
     */
85
    public function getJavaScriptResult()
86
    {
87
        return $this->getLogicalResult(
88
            function () {
89
                return $this->processLogicalAndJavaScript();
90
            },
91
            function () {
92
                return $this->processLogicalOrJavaScript();
93
            }
94
        );
95
    }
96
97
    /**
98
     * @inheritdoc
99
     */
100
    public function getPhpResult(PhpConditionDataObject $dataObject)
101
    {
102
        return $this->getLogicalResult(
103
            function () use ($dataObject) {
104
                return $this->processLogicalAndPhp($dataObject);
105
            },
106
            function () use ($dataObject) {
107
                return $this->processLogicalOrPhp($dataObject);
108
            }
109
        );
110
    }
111
112
    /**
113
     * Global function to get the result of a logical operation, the processor
114
     * does not matter.
115
     *
116
     * @param callable $logicalAndFunction
117
     * @param callable $logicalOrFunction
118
     * @return null
119
     * @throws \Exception
120
     */
121
    protected function getLogicalResult(callable $logicalAndFunction, callable $logicalOrFunction)
122
    {
123
        switch ($this->operator) {
124
            case ConditionParser::LOGICAL_AND:
125
                $result = call_user_func($logicalAndFunction);
126
                break;
127
            case ConditionParser::LOGICAL_OR:
128
                $result = call_user_func($logicalOrFunction);
129
                break;
130
            default:
131
                throw InvalidConfigurationException::wrongBooleanNodeOperator($this->operator);
132
        }
133
134
        return $result;
135
    }
136
137
    /**
138
     * Will process a logical "and" operation on the two given nodes. The result
139
     * will be an array containing all the result of the "and" operation on
140
     * every existing results of the two nodes.
141
     *
142
     * With CSS, it means to concatenate two condition strings. Example:
143
     *
144
     * Left   = [foo="bar"]
145
     * Right  = [pet="dog"]
146
     * Result = [foo="bar"][pet="dog"]
147
     *
148
     * @return array
149
     */
150
    protected function processLogicalAndCss()
151
    {
152
        $leftResults = $this->toArray($this->leftNode->getCssResult());
153
        $rightResults = $this->toArray($this->rightNode->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
     * @return array
171
     */
172
    protected function processLogicalOrCss()
173
    {
174
        return array_merge(
175
            $this->toArray($this->leftNode->getCssResult()),
176
            $this->toArray($this->rightNode->getCssResult())
177
        );
178
    }
179
180
    /**
181
     * Will process a logical "and" operation on the two given nodes. The result
182
     * will be an array containing all the result of the "and" operation on
183
     * every existing results of the two nodes.
184
     *
185
     * With JavaScript, it means adding the operator `&&` between the two
186
     * expressions.
187
     *
188
     * @return array
189
     */
190
    protected function processLogicalAndJavaScript()
191
    {
192
        $leftResults = $this->toArray($this->leftNode->getJavaScriptResult());
193
        $rightResults = $this->toArray($this->rightNode->getJavaScriptResult());
194
195
        $result = [];
196
        foreach ($leftResults as $leftResult) {
197
            foreach ($rightResults as $rightResult) {
198
                $result[] = $leftResult . ' && ' . $rightResult;
199
            }
200
        }
201
202
        return $result;
203
    }
204
205
    /**
206
     * Will process a logical "or" operation on the two given nodes. The result
207
     * will be an array containing all the result of the "or" operation on
208
     * every existing results of the two nodes.
209
     *
210
     * @return array
211
     */
212
    protected function processLogicalOrJavaScript()
213
    {
214
        return array_merge(
215
            $this->toArray($this->leftNode->getJavaScriptResult()),
216
            $this->toArray($this->rightNode->getJavaScriptResult())
217
        );
218
    }
219
220
    /**
221
     * Will process a logical "and" operation on the two given nodes. The result
222
     * will be an array containing all the result of the "and" operation on
223
     * every existing results of the two nodes.
224
     *
225
     * With JavaScript, it means that the left and the right nodes are both
226
     * true.
227
     *
228
     * @param PhpConditionDataObject $dataObject
229
     * @return bool
230
     */
231
    protected function processLogicalAndPhp(PhpConditionDataObject $dataObject)
232
    {
233
        return $this->leftNode->getPhpResult($dataObject) && $this->rightNode->getPhpResult($dataObject);
234
    }
235
236
    /**
237
     * Will process a logical "or" operation on the two given nodes.
238
     *
239
     * @param PhpConditionDataObject $dataObject
240
     * @return bool
241
     */
242
    protected function processLogicalOrPhp(PhpConditionDataObject $dataObject)
243
    {
244
        return $this->leftNode->getPhpResult($dataObject) || $this->rightNode->getPhpResult($dataObject);
245
    }
246
247
    /**
248
     * @return string
249
     */
250
    public function getOperator()
251
    {
252
        return $this->operator;
253
    }
254
}
255