Passed
Push — master ( 2f714f...1c67eb )
by Sebastian
02:15
created

Mailcode_Commands_Command::getParams()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 3
rs 10
1
<?php
2
/**
3
 * File containing the {@see Mailcode_Commands_Command} class.
4
 *
5
 * @package Mailcode
6
 * @subpackage Commands
7
 * @see Mailcode_Commands_Command
8
 */
9
10
declare(strict_types=1);
11
12
namespace Mailcode;
13
14
/**
15
 * Base command class with the common functionality for all commands.
16
 *
17
 * @package Mailcode
18
 * @subpackage Commands
19
 * @author Sebastian Mordziol <[email protected]>
20
 */
21
abstract class Mailcode_Commands_Command
22
{
23
    const ERROR_NON_DUMMY_OPERATION = 46001;
24
    const ERROR_NO_VALIDATION_RESULT_AVAILABLE = 46002;
25
    const ERROR_MISSING_VALIDATION_METHOD = 46003;
26
    
27
    const VALIDATION_MISSING_PARAMETERS = 48301;
28
    const VALIDATION_ADDONS_NOT_SUPPORTED = 48302;
29
    const VALIDATION_ADDON_NOT_SUPPORTED = 48303;
30
    const VALIDATION_UNKNOWN_COMMAND_NAME = 48304;
31
    const VALIDATION_INVALID_PARAMS_STATEMENT = 48305;
32
33
   /**
34
    * @var string
35
    */
36
    protected $type = '';
37
38
   /**
39
    * @var string
40
    */
41
    protected $paramsString = '';
42
    
43
   /**
44
    * @var string
45
    */
46
    protected $matchedText = '';
47
48
   /**
49
    * @var string
50
    */
51
    protected $hash = '';
52
    
53
   /**
54
    * @var \AppUtils\OperationResult
55
    */
56
    protected $validationResult = null;
57
    
58
   /**
59
    * @var \Mailcode\Mailcode
60
    */
61
    protected $mailcode;
62
    
63
   /**
64
    * @var \Mailcode\Mailcode_Parser_Statement
65
    */
66
    protected $params;
67
68
   /**
69
    * @var string[] 
70
    */
71
    protected $validations = array(
72
        'params',
73
        'type_supported',
74
        'type_unsupported'
75
    );
76
    
77
    public function __construct(string $type='', string $paramsString='', string $matchedText='')
78
    {
79
        $this->type = $type;
80
        $this->paramsString = $paramsString;
81
        $this->matchedText = $matchedText;
82
        $this->mailcode = Mailcode::create();
83
        
84
        $this->init();
85
    }
86
    
87
    protected function init() : void
88
    {
89
        
90
    }
91
    
92
   /**
93
    * @return string The ID of the command = the name of the command class file.
94
    */
95
    public function getID() : string
96
    {
97
        $tokens = explode('_', get_class($this));
98
        return array_pop($tokens);
99
    }
100
    
101
   /**
102
    * Checks whether this is a dummy command, which is only
103
    * used to access information on the command type. It cannot
104
    * be used as an actual live command.
105
    * 
106
    * @return bool
107
    */
108
    public function isDummy() : bool
109
    {
110
        return $this->type === '__dummy';
111
    }
112
    
113
   /**
114
    * Retrieves a hash of the actual matched command string,
115
    * which is used in collections to detect duplicate commands.
116
    * 
117
    * @return string
118
    */
119
    public function getHash() : string
120
    {
121
        $this->requireNonDummy();
122
        
123
        if($this->hash === '') {
124
            $this->hash = md5($this->matchedText);
125
        }
126
        
127
        return $this->hash;
128
    }
129
    
130
    protected function requireNonDummy() : void
131
    {
132
        if(!$this->isDummy())
133
        {
134
            return;
135
        }
136
        
137
        throw new Mailcode_Exception(
138
            'Operation not allowed with dummy commands',
139
            null,
140
            self::ERROR_NON_DUMMY_OPERATION
141
        );
142
    }
143
    
144
    public function isValid() : bool
145
    {
146
        return $this->validate()->isValid();
147
    }
148
    
149
    protected function validate() : \AppUtils\OperationResult
150
    {
151
        $this->requireNonDummy();
152
        
153
        if(isset($this->validationResult)) 
154
        {
155
            return $this->validationResult;
156
        }
157
        
158
        $this->validationResult = new \AppUtils\OperationResult($this);
159
160
        $this->validateSyntax();
161
        
162
        return $this->validationResult;
163
    }
164
    
165
    public function getValidationResult() :  \AppUtils\OperationResult
166
    {
167
        if(isset($this->validationResult)) 
168
        {
169
            return $this->validationResult;
170
        }
171
        
172
        throw new Mailcode_Exception(
173
            'No validation result available',
174
            'The command has no validation error, the validation result cannot be accessed.',
175
            self::ERROR_NO_VALIDATION_RESULT_AVAILABLE
176
        );
177
    }
178
    
179
    protected function validateSyntax() : void
180
    {
181
        $validations = array_merge($this->validations, $this->getValidations());
182
        
183
        foreach($validations as $validation)
184
        {
185
            $method = 'validateSyntax_'.$validation;
186
            
187
            if(!method_exists($this, $method))
188
            {
189
                throw new Mailcode_Exception(
190
                    'Missing validation method',
191
                    sprintf(
192
                        'The method [%s] is missing from class [%s].',
193
                        $method,
194
                        get_class($this)
195
                    ),
196
                    self::ERROR_MISSING_VALIDATION_METHOD
197
                );
198
            }
199
            
200
            $this->$method();
201
            
202
            // break off at the first validation issue
203
            if(!$this->validationResult->isValid())
204
            {
205
                return;
206
            }
207
        }
208
    }
209
    
210
   /**
211
    * @return string[]
212
    */
213
    abstract protected function getValidations() : array;
214
    
215
    protected function validateSyntax_params() : void
216
    {
217
        if(!$this->requiresParameters())
218
        {
219
            return;
220
        }
221
        
222
        if(empty($this->paramsString))
223
        {
224
            $this->validationResult->makeError(
225
                t('Parameters have to be specified.'),
226
                self::VALIDATION_MISSING_PARAMETERS
227
            );
228
            return;
229
        }
230
        
231
        $this->params = $this->mailcode->getParser()->createStatement($this->paramsString);
232
        
233
        if(!$this->params->isValid())
234
        {
235
            $error = $this->params->getValidationResult();
236
            
237
            $this->validationResult->makeError(
238
                t('Invalid parameters:').' '.$error->getErrorMessage(), 
239
                self::VALIDATION_INVALID_PARAMS_STATEMENT
240
            );
241
        }
242
    }
243
    
244
    protected function validateSyntax_type_supported() : void
245
    {
246
        if(!$this->supportsType() || empty($this->type))
247
        {
248
            return;
249
        }
250
        
251
        $types = $this->getSupportedTypes();
252
253
        if(!in_array($this->type, $types))
254
        {
255
            $this->validationResult->makeError(
256
                t('The command addon %1$s is not supported.', $this->type).' '.
257
                t('Valid addons are %1$s.', implode(', ', $types)),
258
                self::VALIDATION_ADDON_NOT_SUPPORTED
259
            );
260
            
261
            return;
262
        }
263
    }
264
    
265
    protected function validateSyntax_type_unsupported() : void
266
    {
267
        if($this->supportsType() || empty($this->type))
268
        {
269
            return;
270
        }
271
        
272
        $this->validationResult->makeError(
273
            t('Command addons are not supported (the %1$s part).', $this->type),
274
            self::VALIDATION_ADDONS_NOT_SUPPORTED
275
        );
276
    }
277
    
278
    public function hasType() : bool
279
    {
280
        return $this->supportsType() && !empty($this->type);
281
    }
282
    
283
    public function getType() : string
284
    {
285
        if($this->supportsType())
286
        {
287
            return $this->type;
288
        }
289
        
290
        return '';
291
    }
292
    
293
    public function hasParameters() : bool
294
    {
295
        return $this->requiresParameters() && !empty($this->paramsString);
296
    }
297
    
298
    public function getMatchedText() : string
299
    {
300
        return $this->matchedText;
301
    }
302
    
303
    public function getHighlighted() : string
304
    {
305
        if(!$this->isValid())
306
        {
307
            return '';
308
        }
309
        
310
        $highlighter = new Mailcode_Commands_Highlighter($this);
311
        return $highlighter->highlight();
312
    }
313
    
314
    public function getParamsString() : string
315
    {
316
        if($this->requiresParameters())
317
        {
318
            return $this->paramsString;
319
        }
320
        
321
        return '';
322
    }
323
    
324
    public function getParams() : ?Mailcode_Parser_Statement
325
    {
326
        return $this->params;
327
    }
328
    
329
    abstract public function getName() : string;
330
    
331
    abstract public function getLabel() : string;
332
    
333
    abstract public function requiresParameters() : bool;
334
    
335
    abstract public function supportsType() : bool;
336
    
337
    abstract public function generatesContent() : bool;
338
339
    abstract public function getCommandType() : string;
340
    
341
    public function getNormalized() : string
342
    {
343
        if(!$this->isValid())
344
        {
345
            return '';
346
        }
347
        
348
        $parts = array();
349
        $parts[] = '{'.$this->getName();
350
        
351
        if($this->supportsType() && $this->hasType())
352
        {
353
            $parts[] = ' '.$this->getType();
354
        }
355
        
356
        if($this->requiresParameters() && isset($this->params))
357
        {
358
            $parts[] = ': ';
359
            $parts[] = $this->params->getNormalized();
360
        }
361
        
362
        $parts[] = '}';
363
        
364
        return implode('', $parts);
365
    }
366
    
367
   /**
368
    * Retrieves the names of all the command's supported types: the part
369
    * between the command name and the colon. Example: {command type: params}.
370
    * 
371
    * @return string[]
372
    */
373
    public function getSupportedTypes() : array
374
    {
375
        return array();
376
    }
377
    
378
    public function getVariables() : Mailcode_Variables_Collection_Regular
379
    {
380
        return Mailcode::create()->findVariables($this->paramsString);
381
    }
382
}
383