AbstractCondition   A
last analyzed

Complexity

Total Complexity 32

Size/Duplication

Total Lines 144
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 66
c 1
b 0
f 0
dl 0
loc 144
rs 9.84
wmc 32

3 Methods

Rating   Name   Duplication   Size   Complexity  
B stringValue() 0 27 7
A variableIsEqual() 0 16 5
D evaluateCondition() 0 63 20
1
<?php
2
3
/**
4
 * Platine Template
5
 *
6
 * Platine Template is a template engine that has taken a lot of inspiration from Django.
7
 *
8
 * This content is released under the MIT License (MIT)
9
 *
10
 * Copyright (c) 2020 Platine Template
11
 * Copyright (c) 2014 Guz Alexander, http://guzalexander.com
12
 * Copyright (c) 2011, 2012 Harald Hanek, http://www.delacap.com
13
 * Copyright (c) 2006 Mateo Murphy
14
 *
15
 * Permission is hereby granted, free of charge, to any person obtaining a copy
16
 * of this software and associated documentation files (the "Software"), to deal
17
 * in the Software without restriction, including without limitation the rights
18
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
19
 * copies of the Software, and to permit persons to whom the Software is
20
 * furnished to do so, subject to the following conditions:
21
 *
22
 * The above copyright notice and this permission notice shall be included in all
23
 * copies or substantial portions of the Software.
24
 *
25
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
26
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
27
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
28
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
29
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
30
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
31
 * SOFTWARE.
32
 */
33
34
/**
35
 *  @file AbstractCondition.php
36
 *
37
 *  The Base Template Condition class
38
 *
39
 *  @package    Platine\Template\Parser
40
 *  @author Platine Developers Team
41
 *  @copyright  Copyright (c) 2020
42
 *  @license    http://opensource.org/licenses/MIT  MIT License
43
 *  @link   https://www.platine-php.com
44
 *  @version 1.0.0
45
 *  @filesource
46
 */
47
48
declare(strict_types=1);
49
50
namespace Platine\Template\Parser;
51
52
use DateTime;
53
use Generator;
54
use Platine\Template\Exception\RenderException;
55
use Stringable;
56
57
/**
58
 * @class AbstractCondition
59
 * @package Platine\Template\Parser
60
 */
61
abstract class AbstractCondition extends AbstractBlock
62
{
63
    /**
64
     * The current left variable to compare
65
     * @var mixed
66
     */
67
    protected mixed $left = null;
68
69
    /**
70
     * The current right variable to compare
71
     * @var mixed
72
     */
73
    protected mixed $right = null;
74
75
    /**
76
     * Returns a string value of an array or object for comparisons
77
     * @param mixed $value
78
     * @return mixed
79
     */
80
    protected function stringValue(mixed $value): mixed
81
    {
82
        if (is_object($value)) {
83
            if (method_exists($value, '__toString') || $value instanceof Stringable) {
84
                return (string) $value;
85
            }
86
87
            if ($value instanceof Generator) {
88
                return (string) $value->valid();
89
            }
90
91
            if ($value instanceof DateTime) {
92
                return $value->format(DateTime::ATOM);
93
            }
94
95
            $class = get_class($value);
96
            throw new RenderException(sprintf(
97
                'The value of type [%s] has no "toObject" nor "__toString" methods',
98
                $class
99
            ));
100
        }
101
102
        if (is_array($value)) {
103
            return $value;
104
        }
105
106
        return $value;
107
    }
108
109
    /**
110
     * Check to see if to variables are equal in a given context
111
     * @param string|null $left
112
     * @param string|null $right
113
     * @param Context $context
114
     * @return bool
115
     */
116
    protected function variableIsEqual(?string $left, ?string $right, Context $context): bool
117
    {
118
        $leftValue = $left;
119
        $rightValue = $right;
120
        if (is_string($left) && $context->hasKey($left)) {
121
            $leftValue = $context->get($left);
122
        }
123
124
        if (is_string($right) && $context->hasKey($right)) {
125
            $rightValue = $context->get($right);
126
        }
127
128
        $leftStr = $this->stringValue($leftValue);
129
        $rightStr = $this->stringValue($rightValue);
130
131
        return $leftStr == $rightStr;
132
    }
133
134
    /**
135
     * Evaluate a comparison
136
     * @param mixed $left
137
     * @param mixed $right
138
     * @param string|null $operator
139
     * @param Context $context
140
     * @return bool
141
     */
142
    protected function evaluateCondition(
143
        mixed $left,
144
        mixed $right,
145
        ?string $operator,
146
        Context $context
147
    ): bool {
148
        if ($operator === null) {
149
            $value = $this->stringValue($context->get($left));
150
151
            return (bool) $value;
152
        }
153
154
        // values of 'empty' have a special meaning in array comparisons
155
        if ($right == 'empty' && is_array($context->get($left))) {
156
            $left = $context->get($left);
157
            $right = 0;
158
        } elseif ($left == 'empty' && is_array($context->get($right))) {
159
            $right = $context->get($right);
160
            $left = 0;
161
        } else {
162
            $leftValue = $context->get($left);
163
            $rightValue = $context->get($right);
164
165
            $left = $this->stringValue($leftValue);
166
            $right = $this->stringValue($rightValue);
167
        }
168
169
        // special rules for null values
170
        if (is_null($left) || is_null($right)) {
171
            //null == null => true
172
            if ($operator === '==' && is_null($left) && is_null($right)) {
173
                return true;
174
            }
175
176
            //null != anything other than null => true
177
            if ($operator === '!=') {
178
                return true;
179
            }
180
181
            return false;
182
        }
183
184
        //regular rules
185
        switch ($operator) {
186
            case '==':
187
                return ($left == $right);
188
            case '!=':
189
                return ($left != $right);
190
            case '>':
191
                return ($left > $right);
192
            case '<':
193
                return ($left < $right);
194
            case '>=':
195
                return ($left >= $right);
196
            case '<=':
197
                return ($left <= $right);
198
            case 'contains':
199
                return (is_array($left) ? in_array($right, $left) : (strpos($left, $right) !== false));
200
            default:
201
                throw new RenderException(sprintf(
202
                    'Error in tag [%s] - Unknown operator [%s]',
203
                    $this->getTagName(),
204
                    $operator
205
                ));
206
        }
207
    }
208
}
209