CaseTag   A
last analyzed

Complexity

Total Complexity 13

Size/Duplication

Total Lines 124
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 50
c 1
b 0
f 0
dl 0
loc 124
rs 10
wmc 13

5 Methods

Rating   Name   Duplication   Size   Complexity  
A pushNodeList() 0 4 2
A unknownTag() 0 28 4
A __construct() 0 11 2
A render() 0 24 4
A endTag() 0 3 1
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 CaseTag.php
36
 *
37
 *  The "case" Template tag class
38
 *
39
 *  @package    Platine\Template\Tag
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\Tag;
51
52
use Platine\Template\Exception\ParseException;
53
use Platine\Template\Parser\AbstractCondition;
54
use Platine\Template\Parser\AbstractTag;
55
use Platine\Template\Parser\Context;
56
use Platine\Template\Parser\Lexer;
57
use Platine\Template\Parser\Parser;
58
use Platine\Template\Parser\Token;
59
use Platine\Template\Parser\Variable;
60
61
/**
62
 * @class CaseTag
63
 * @package Platine\Template\Tag
64
 */
65
class CaseTag extends AbstractCondition
66
{
67
    /**
68
     * Stack of node list
69
     * @var array<int, array<int, mixed>>
70
     */
71
    protected array $nodeLists = [];
72
73
    /**
74
     * The node list for the "else"
75
     * @var AbstractTag[]|Variable[]|string[]
76
     */
77
    protected array $elseNodeList = [];
78
79
    /**
80
     * Left value to compare
81
     * @var mixed
82
     */
83
    protected mixed $left = null;
84
85
    /**
86
     * Right value to compare
87
     * @var mixed
88
     */
89
    protected mixed $right = null;
90
91
    /**
92
    * {@inheritdoc}
93
    */
94
    public function __construct(string $markup, array &$tokens, Parser $parser)
95
    {
96
        parent::__construct($markup, $tokens, $parser);
97
98
        $lexer = new Lexer('/' . Token::QUOTED_FRAGMENT . '/');
99
        if ($lexer->match($markup)) {
100
            $this->left = $lexer->getStringMatch(0);
101
        } else {
102
            throw new ParseException(sprintf(
103
                'Syntax Error in "%s" - Valid syntax: case [condition]',
104
                'case'
105
            ));
106
        }
107
    }
108
109
    /**
110
    * {@inheritdoc}
111
    */
112
    protected function endTag(): void
113
    {
114
        $this->pushNodeList();
115
    }
116
117
    /**
118
    * {@inheritdoc}
119
    */
120
    protected function unknownTag(string $tag, string $param, array $tokens): void
121
    {
122
        $whenLexer = new Lexer('/' . Token::QUOTED_FRAGMENT . '/');
123
        switch ($tag) {
124
            case 'when':
125
                // push the current node list onto
126
                // the stack and prepare for a new one
127
                if ($whenLexer->match($param)) {
128
                    $this->pushNodeList();
129
                    $this->right = $whenLexer->getMixedMatch(0);
130
                    $this->nodeList = [];
131
                } else {
132
                    throw new ParseException(sprintf(
133
                        'Syntax Error in "%s" - Valid "when" condition: when [condition]',
134
                        'case'
135
                    ));
136
                }
137
                break;
138
            case 'else':
139
                // push the last node list onto the stack
140
                // and prepare to receive the else nodes
141
                $this->pushNodeList();
142
                $this->right = null;
143
                $this->elseNodeList = &$this->nodeList;
144
                $this->nodeList = [];
145
                break;
146
            default:
147
                parent::unknownTag($tag, $param, $tokens);
148
        }
149
    }
150
151
    /**
152
    * {@inheritdoc}
153
    */
154
    public function render(Context $context): string
155
    {
156
        $output = '';
157
        $runElseBlock = true;
158
159
        foreach ($this->nodeLists as $data) {
160
            list($right, $nodeList) = $data;
161
162
            if ($this->variableIsEqual($this->left, $right, $context)) {
163
                $runElseBlock = false;
164
165
                $context->push();
166
                $output .= $this->renderAll($nodeList, $context);
167
                $context->pop();
168
            }
169
        }
170
171
        if ($runElseBlock) {
172
            $context->push();
173
            $output .= $this->renderAll($this->elseNodeList, $context);
174
            $context->pop();
175
        }
176
177
        return $output;
178
    }
179
180
    /**
181
     * Pushes the current right value and node list
182
     * into the node list stack
183
     * @return void
184
     */
185
    protected function pushNodeList(): void
186
    {
187
        if ($this->right !== null) {
188
            $this->nodeLists[] = [$this->right, $this->nodeList];
189
        }
190
    }
191
}
192