1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* File containing the {@see \Mailcode\Mailcode_Commands} class. |
4
|
|
|
* |
5
|
|
|
* @package Mailcode |
6
|
|
|
* @subpackage Commands |
7
|
|
|
* @see \Mailcode\Mailcode_Commands |
8
|
|
|
*/ |
9
|
|
|
|
10
|
|
|
declare(strict_types=1); |
11
|
|
|
|
12
|
|
|
namespace Mailcode; |
13
|
|
|
|
14
|
|
|
use AppUtils\FileHelper; |
15
|
|
|
|
16
|
|
|
/** |
17
|
|
|
* Mailcode commands repository: factory for command instances, |
18
|
|
|
* and for fetching command information. |
19
|
|
|
* |
20
|
|
|
* @package Mailcode |
21
|
|
|
* @subpackage Commands |
22
|
|
|
* @author Sebastian Mordziol <[email protected]> |
23
|
|
|
*/ |
24
|
|
|
class Mailcode_Commands |
25
|
|
|
{ |
26
|
|
|
public const ERROR_COMMAND_NAME_DOES_NOT_EXIST = 45901; |
27
|
|
|
public const ERROR_COMMAND_DOES_NOT_EXIST = 45902; |
28
|
|
|
public const ERROR_INVALID_DUMMY_COMMAND_TYPE = 45903; |
29
|
|
|
public const ERROR_INVALID_COMMAND_CLASS = 45904; |
30
|
|
|
|
31
|
|
|
/** |
32
|
|
|
* @var Mailcode_Commands_Command[] |
33
|
|
|
*/ |
34
|
|
|
private array $commands = array(); |
35
|
|
|
|
36
|
|
|
/** |
37
|
|
|
* @var array<string,Mailcode_Commands_Command> |
38
|
|
|
*/ |
39
|
|
|
private static array $dummyCommands = array(); |
40
|
|
|
|
41
|
|
|
/** |
42
|
|
|
* Retrieves a list of all available command IDs. |
43
|
|
|
* |
44
|
|
|
* @return string[] |
45
|
|
|
*/ |
46
|
|
|
public function getIDs() : array |
47
|
|
|
{ |
48
|
|
|
static $ids = array(); |
49
|
|
|
|
50
|
|
|
if(empty($ids)) { |
51
|
|
|
$ids = FileHelper::createFileFinder(__DIR__.'/Commands/Command') |
|
|
|
|
52
|
|
|
->getPHPClassNames(); |
53
|
|
|
} |
54
|
|
|
|
55
|
|
|
return $ids; |
56
|
|
|
} |
57
|
|
|
|
58
|
|
|
/** |
59
|
|
|
* Retrieves a list of all available commands, sorted by label. |
60
|
|
|
* |
61
|
|
|
* NOTE: These instances are only used for information purposes. |
62
|
|
|
* |
63
|
|
|
* @return Mailcode_Commands_Command[] |
64
|
|
|
* @throws Mailcode_Factory_Exception |
65
|
|
|
*/ |
66
|
|
|
public function getAll() : array |
67
|
|
|
{ |
68
|
|
|
if(!empty($this->commands)) { |
69
|
|
|
return $this->commands; |
70
|
|
|
} |
71
|
|
|
|
72
|
|
|
$ids = $this->getIDs(); |
73
|
|
|
|
74
|
|
|
$result = array(); |
75
|
|
|
|
76
|
|
|
foreach($ids as $id) |
77
|
|
|
{ |
78
|
|
|
$result[] = $this->getDummyCommand($id); |
79
|
|
|
} |
80
|
|
|
|
81
|
|
|
usort($result, static function(Mailcode_Commands_Command $a, Mailcode_Commands_Command $b) |
82
|
|
|
{ |
83
|
|
|
return strnatcasecmp($a->getLabel(), $b->getLabel()); |
84
|
|
|
}); |
85
|
|
|
|
86
|
|
|
$this->commands = $result; |
87
|
|
|
|
88
|
|
|
return $result; |
89
|
|
|
} |
90
|
|
|
|
91
|
|
|
/** |
92
|
|
|
* Gets an available command by its ID. |
93
|
|
|
* |
94
|
|
|
* @param string $id |
95
|
|
|
* @return Mailcode_Commands_Command |
96
|
|
|
*/ |
97
|
|
|
public function getByID(string $id) : Mailcode_Commands_Command |
98
|
|
|
{ |
99
|
|
|
static $instances = array(); |
100
|
|
|
|
101
|
|
|
if(!isset($instances[$id])) |
102
|
|
|
{ |
103
|
|
|
$instances[$id] = $this->createCommand($id, '__dummy', '', ''); |
104
|
|
|
} |
105
|
|
|
|
106
|
|
|
return $instances[$id]; |
107
|
|
|
} |
108
|
|
|
|
109
|
|
|
/** |
110
|
|
|
* Retrieves the ID of a command by its name. |
111
|
|
|
* |
112
|
|
|
* @param string $name |
113
|
|
|
* @throws Mailcode_Exception |
114
|
|
|
* @return string |
115
|
|
|
* |
116
|
|
|
* @see Mailcode_Commands::ERROR_COMMAND_NAME_DOES_NOT_EXIST |
117
|
|
|
*/ |
118
|
|
|
public function getIDByName(string $name) : string |
119
|
|
|
{ |
120
|
|
|
$items = $this->getAll(); |
121
|
|
|
|
122
|
|
|
foreach($items as $item) |
123
|
|
|
{ |
124
|
|
|
if($item->getName() === $name) { |
125
|
|
|
return $item->getID(); |
126
|
|
|
} |
127
|
|
|
} |
128
|
|
|
|
129
|
|
|
throw new Mailcode_Exception( |
130
|
|
|
'No such command name', |
131
|
|
|
sprintf( |
132
|
|
|
'The command name [%1$s] does not exist.', |
133
|
|
|
$name |
134
|
|
|
), |
135
|
|
|
self::ERROR_COMMAND_NAME_DOES_NOT_EXIST |
136
|
|
|
); |
137
|
|
|
} |
138
|
|
|
|
139
|
|
|
public function idExists(string $id) : bool |
140
|
|
|
{ |
141
|
|
|
$ids = $this->getIDs(); |
142
|
|
|
|
143
|
|
|
return in_array($id, $ids); |
144
|
|
|
} |
145
|
|
|
|
146
|
|
|
/** |
147
|
|
|
* Checks whether the specified name exists. |
148
|
|
|
* |
149
|
|
|
* @param string $name For example: "showvar". |
150
|
|
|
* @return bool |
151
|
|
|
* @throws Mailcode_Factory_Exception |
152
|
|
|
*/ |
153
|
|
|
public function nameExists(string $name) : bool |
154
|
|
|
{ |
155
|
|
|
$items = $this->getAll(); |
156
|
|
|
|
157
|
|
|
foreach($items as $item) |
158
|
|
|
{ |
159
|
|
|
if($item->getName() === $name) { |
160
|
|
|
return true; |
161
|
|
|
} |
162
|
|
|
} |
163
|
|
|
|
164
|
|
|
return false; |
165
|
|
|
} |
166
|
|
|
|
167
|
|
|
/** |
168
|
|
|
* @param string $id The command ID, e.g. `ShowVar`. |
169
|
|
|
* @param string $type The command's subtype, e.g. `variable` for the `if variable` command. |
170
|
|
|
* @param string $params The parameter string |
171
|
|
|
* @param string $matchedString The original matched string of the parsed command. |
172
|
|
|
* @return Mailcode_Commands_Command |
173
|
|
|
* @throws Mailcode_Factory_Exception |
174
|
|
|
*/ |
175
|
|
|
public function createCommand(string $id, string $type, string $params, string $matchedString) : Mailcode_Commands_Command |
176
|
|
|
{ |
177
|
|
|
$class = $this->resolveClassName($id, $type); |
178
|
|
|
|
179
|
|
|
if(!class_exists($class)) |
180
|
|
|
{ |
181
|
|
|
throw new Mailcode_Factory_Exception( |
182
|
|
|
'No such command', |
183
|
|
|
sprintf( |
184
|
|
|
'The command ID [%1$s] does not exist, class [%2$s] not found.', |
185
|
|
|
$id, |
186
|
|
|
$class |
187
|
|
|
), |
188
|
|
|
self::ERROR_COMMAND_DOES_NOT_EXIST |
189
|
|
|
); |
190
|
|
|
} |
191
|
|
|
|
192
|
|
|
$command = new $class($type, $params, $matchedString); |
193
|
|
|
|
194
|
|
|
if($command instanceof Mailcode_Commands_Command) |
195
|
|
|
{ |
196
|
|
|
return $command; |
197
|
|
|
} |
198
|
|
|
|
199
|
|
|
throw new Mailcode_Factory_Exception( |
200
|
|
|
'Invalid command class', |
201
|
|
|
sprintf( |
202
|
|
|
'The class [%s] does not extend the base command class.', |
203
|
|
|
$class |
204
|
|
|
), |
205
|
|
|
self::ERROR_INVALID_COMMAND_CLASS |
206
|
|
|
); |
207
|
|
|
} |
208
|
|
|
|
209
|
|
|
protected function resolveClassName(string $id, string $type) : string |
210
|
|
|
{ |
211
|
|
|
$class = 'Mailcode\Mailcode_Commands_Command_'.$id; |
212
|
|
|
|
213
|
|
|
$dummy = $this->getDummyCommand($id); |
214
|
|
|
|
215
|
|
|
if($dummy->supportsType()) |
216
|
|
|
{ |
217
|
|
|
if(empty($type)) |
218
|
|
|
{ |
219
|
|
|
$type = $dummy->getDefaultType(); |
220
|
|
|
} |
221
|
|
|
|
222
|
|
|
$class .= '_'.$this->adjustTypeName($type); |
223
|
|
|
} |
224
|
|
|
|
225
|
|
|
return $class; |
226
|
|
|
} |
227
|
|
|
|
228
|
|
|
/** |
229
|
|
|
* Translates the command type to the expected class naming scheme. |
230
|
|
|
* |
231
|
|
|
* Example: not-empty => NotEmpty |
232
|
|
|
* |
233
|
|
|
* @param string $type |
234
|
|
|
* @return string |
235
|
|
|
*/ |
236
|
|
|
private function adjustTypeName(string $type) : string |
237
|
|
|
{ |
238
|
|
|
$type = str_replace('-', ' ', $type); |
239
|
|
|
$type = ucwords($type); |
240
|
|
|
$type = str_replace(' ', '', $type); |
241
|
|
|
|
242
|
|
|
return $type; |
243
|
|
|
} |
244
|
|
|
|
245
|
|
|
/** |
246
|
|
|
* Retrieves the dummy command of the specified type, which |
247
|
|
|
* is used to retrieve information on the command's capabilities. |
248
|
|
|
* |
249
|
|
|
* @param string $id |
250
|
|
|
* @return Mailcode_Commands_Command |
251
|
|
|
* @throws Mailcode_Factory_Exception |
252
|
|
|
*/ |
253
|
|
|
private function getDummyCommand(string $id) : Mailcode_Commands_Command |
254
|
|
|
{ |
255
|
|
|
if(isset(self::$dummyCommands[$id])) { |
256
|
|
|
return self::$dummyCommands[$id]; |
257
|
|
|
} |
258
|
|
|
|
259
|
|
|
$class = 'Mailcode\Mailcode_Commands_Command_'.$id; |
260
|
|
|
$cmd = new $class('__dummy'); |
261
|
|
|
|
262
|
|
|
if($cmd instanceof Mailcode_Commands_Command) |
263
|
|
|
{ |
264
|
|
|
self::$dummyCommands[$id] = $cmd; |
265
|
|
|
return $cmd; |
266
|
|
|
} |
267
|
|
|
|
268
|
|
|
throw new Mailcode_Factory_Exception( |
269
|
|
|
'Invalid dummy command type', |
270
|
|
|
sprintf('The stored variable type is %1$s.', gettype(self::$dummyCommands[$id])), |
271
|
|
|
self::ERROR_INVALID_DUMMY_COMMAND_TYPE |
272
|
|
|
); |
273
|
|
|
} |
274
|
|
|
|
275
|
|
|
/** |
276
|
|
|
* Retrieves all commands that can contain content |
277
|
|
|
* that is not parsed by the main parsing process. |
278
|
|
|
* |
279
|
|
|
* @return Mailcode_Interfaces_Commands_ProtectedContent[] |
280
|
|
|
* @throws Mailcode_Exception |
281
|
|
|
*/ |
282
|
|
|
public function getContentCommands() : array |
283
|
|
|
{ |
284
|
|
|
$result = array(); |
285
|
|
|
$commands = $this->getAll(); |
286
|
|
|
|
287
|
|
|
foreach($commands as $command) |
288
|
|
|
{ |
289
|
|
|
if($command instanceof Mailcode_Interfaces_Commands_ProtectedContent) |
290
|
|
|
{ |
291
|
|
|
$result[] = $command; |
292
|
|
|
} |
293
|
|
|
} |
294
|
|
|
|
295
|
|
|
return $result; |
296
|
|
|
} |
297
|
|
|
} |
298
|
|
|
|
This function has been deprecated. The supplier of the function has supplied an explanatory message.
The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.