Passed
Push — master ( af11e6...9ff364 )
by Sebastian
03:46
created

CommandDef   A

Complexity

Total Complexity 17

Size/Duplication

Total Lines 163
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 62
c 0
b 0
f 0
dl 0
loc 163
rs 10
wmc 17

15 Methods

Rating   Name   Duplication   Size   Complexity  
A getName() 0 3 1
A addEscapeError() 0 16 1
A getReplacementCommand() 0 7 1
A getContent() 0 3 1
A getStartPos() 0 3 1
A toArray() 0 11 1
A getLength() 0 3 1
A __construct() 0 6 1
A extractContent() 0 10 1
A getContentID() 0 3 1
A validateContent() 0 17 3
A getParams() 0 3 1
A getClosingText() 0 3 1
A setContentID() 0 4 1
A getOpeningText() 0 3 1
1
<?php
2
/**
3
 * File containing the class {@see \Mailcode\Parser\PreParser\CommandDef}.
4
 *
5
 * @package Mailcode
6
 * @subpackage Parser
7
 * @see \Mailcode\Parser\PreParser\CommandDef
8
 */
9
10
declare(strict_types=1);
11
12
namespace Mailcode\Parser\PreParser;
13
14
use Mailcode\Mailcode_Collection;
15
use Mailcode\Mailcode_Commands_CommonConstants;
16
use Mailcode\Parser\PreParser;
17
use function AppUtils\sb;
18
19
/**
20
 * Command definition for a protected content command
21
 * detected by the pre-parser: Used to store all necessary
22
 * information on the command.
23
 *
24
 * This class does the following things:
25
 *
26
 * - Extract and store the command's content
27
 * - Determine the ID of the content
28
 * - Generate the inline command for the main parser
29
 *
30
 * @package Mailcode
31
 * @subpackage Parser
32
 * @author Sebastian Mordziol <[email protected]>
33
 */
34
class CommandDef
35
{
36
    private string $name;
37
    private string $openingText;
38
    private string $params;
39
    private string $closingText;
40
    private int $contentID = 0;
41
    private int $length = 0;
42
    private int $startPos = 0;
43
44
    public function __construct(string $name, string $openingText, string $params, string $closingText)
45
    {
46
        $this->name = $name;
47
        $this->openingText = $openingText;
48
        $this->params = $params;
49
        $this->closingText = $closingText;
50
    }
51
52
    /**
53
     * @return string
54
     */
55
    public function getName() : string
56
    {
57
        return $this->name;
58
    }
59
60
    /**
61
     * @return string
62
     */
63
    public function getOpeningText() : string
64
    {
65
        return $this->openingText;
66
    }
67
68
    /**
69
     * @return string
70
     */
71
    public function getParams() : string
72
    {
73
        return $this->params;
74
    }
75
76
    /**
77
     * @return string
78
     */
79
    public function getClosingText() : string
80
    {
81
        return $this->closingText;
82
    }
83
84
    /**
85
     * @param int $id
86
     * @return $this
87
     */
88
    public function setContentID(int $id) : self
89
    {
90
        $this->contentID = $id;
91
        return $this;
92
    }
93
94
    /**
95
     * @return int
96
     */
97
    public function getContentID() : int
98
    {
99
        return $this->contentID;
100
    }
101
102
    /**
103
     * @return int
104
     */
105
    public function getLength() : int
106
    {
107
        return $this->length;
108
    }
109
110
    /**
111
     * @return int
112
     */
113
    public function getStartPos() : int
114
    {
115
        return $this->startPos;
116
    }
117
118
    public function getReplacementCommand() : string
119
    {
120
        return sprintf(
121
            '{%s: %s %s}',
122
            $this->getName(),
123
            $this->getContentID(),
124
            $this->getParams()
125
        );
126
    }
127
128
    public function getContent() : string
129
    {
130
        return PreParser::getContent($this->getContentID());
131
    }
132
133
    public function extractContent(string $subject) : void
134
    {
135
        $this->startPos = (int)strpos($subject, $this->openingText);
136
        $posContent = $this->startPos + strlen($this->openingText);
137
        $posEnd = (int)strpos($subject, $this->closingText);
138
        $this->length = ($posEnd + strlen($this->closingText)) - $this->startPos;
139
140
        // Extract the content, and store it
141
        $content = substr($subject, $posContent, $posEnd - $posContent);
142
        $this->contentID = PreParser::storeContent($content);
143
    }
144
145
    /**
146
     * @return array{openingCommand:string,params:string,closingCommand:string,content:string,contentID:int,replacementCommand:string,startPosition:int,length:int}
147
     */
148
    public function toArray() : array
149
    {
150
        return array(
151
            'openingCommand' => $this->getOpeningText(),
152
            'params' => $this->getParams(),
153
            'closingCommand' => $this->getClosingText(),
154
            'content' => $this->getContent(),
155
            'contentID' => $this->getContentID(),
156
            'replacementCommand' => $this->getReplacementCommand(),
157
            'startPosition' => $this->getStartPos(),
158
            'length' => $this->getLength()
159
        );
160
    }
161
162
    public function validateContent(PreParser $parser, Mailcode_Collection $collection) : bool
163
    {
164
        $commands = $parser->getCommands();
165
        $content = $this->getContent();
166
167
        foreach($commands as $command)
168
        {
169
            $string = $command->getOpeningText();
170
171
            if(strpos($content, $string) !== false)
172
            {
173
                $this->addEscapeError($command, $collection);
174
                return false;
175
            }
176
        }
177
178
        return true;
179
    }
180
181
    private function addEscapeError(CommandDef $command, Mailcode_Collection $collection) : void
182
    {
183
        $collection->addErrorMessage(
184
            $command->getOpeningText(),
185
            (string)sb()
186
                ->t('Command nesting error:')
187
                ->t(
188
                    'The %1$s command contains a nested %2$s command.',
189
                    $this->getName(),
190
                    $command->getName()
191
                )
192
                ->t('Nesting commands that contain text within each other is allowed, but they must be escaped.')
193
                ->t('To solve this issue, please escape the nested command\'s brackets.')
194
                ->t('For example:')
195
                ->sf('\{%s\}', $command->getName()),
196
            Mailcode_Commands_CommonConstants::VALIDATION_UNESCAPED_NESTED_COMMAND
197
        );
198
    }
199
}
200