Passed
Push — master ( 77b992...62880d )
by Sebastian
02:14
created

Mailcode_Commands_Command::validateSyntax()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 27
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 1
Metric Value
cc 4
eloc 14
c 2
b 0
f 1
nc 4
nop 0
dl 0
loc 27
rs 9.7998
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
    
25
    const ERROR_NO_VALIDATION_RESULT_AVAILABLE = 46002;
26
    
27
    const ERROR_MISSING_VALIDATION_METHOD = 46003;
28
    
29
    const VALIDATION_MISSING_PARAMETERS = 48301;
30
    
31
    const VALIDATION_ADDONS_NOT_SUPPORTED = 48302;
32
    
33
    const VALIDATION_ADDON_NOT_SUPPORTED = 48303;
34
    
35
    const VALIDATION_UNKNOWN_COMMAND_NAME = 48304;
36
    
37
   /**
38
    * @var string
39
    */
40
    protected $type = '';
41
42
   /**
43
    * @var string
44
    */
45
    protected $paramsString = '';
46
    
47
   /**
48
    * @var string
49
    */
50
    protected $matchedText = '';
51
52
   /**
53
    * @var string
54
    */
55
    protected $hash = '';
56
    
57
   /**
58
    * @var \AppUtils\OperationResult
59
    */
60
    protected $validationResult = null;
61
    
62
    public function __construct(string $type='', string $paramsString='', string $matchedText='')
63
    {
64
        $this->type = $type;
65
        $this->paramsString = $paramsString;
66
        $this->matchedText = $matchedText;
67
    }
68
    
69
   /**
70
    * @return string The ID of the command = the name of the command class file.
71
    */
72
    public function getID() : string
73
    {
74
        $tokens = explode('_', get_class($this));
75
        return array_pop($tokens);
76
    }
77
    
78
   /**
79
    * Checks whether this is a dummy command, which is only
80
    * used to access information on the command type. It cannot
81
    * be used as an actual live command.
82
    * 
83
    * @return bool
84
    */
85
    public function isDummy() : bool
86
    {
87
        return $this->type === '__dummy';
88
    }
89
    
90
   /**
91
    * Retrieves a hash of the actual matched command string,
92
    * which is used in collections to detect duplicate commands.
93
    * 
94
    * @return string
95
    */
96
    public function getHash() : string
97
    {
98
        $this->requireNonDummy();
99
        
100
        if($this->hash === '') {
101
            $this->hash = md5($this->matchedText);
102
        }
103
        
104
        return $this->hash;
105
    }
106
    
107
    protected function requireNonDummy() : void
108
    {
109
        if(!$this->isDummy())
110
        {
111
            return;
112
        }
113
        
114
        throw new Mailcode_Exception(
115
            'Operation not allowed with dummy commands',
116
            null,
117
            self::ERROR_NON_DUMMY_OPERATION
118
        );
119
    }
120
    
121
    public function isValid() : bool
122
    {
123
        return $this->validate()->isValid();
124
    }
125
    
126
    protected function validate() : \AppUtils\OperationResult
127
    {
128
        $this->requireNonDummy();
129
        
130
        if(isset($this->validationResult)) 
131
        {
132
            return $this->validationResult;
133
        }
134
        
135
        $this->validationResult = new \AppUtils\OperationResult($this);
136
137
        $this->validateSyntax();
138
        
139
        return $this->validationResult;
140
    }
141
    
142
    public function getValidationResult() :  \AppUtils\OperationResult
143
    {
144
        if(isset($this->validationResult)) 
145
        {
146
            return $this->validationResult;
147
        }
148
        
149
        throw new Mailcode_Exception(
150
            'No validation result available',
151
            'The command has no validation error, the validation result cannot be accessed.',
152
            self::ERROR_NO_VALIDATION_RESULT_AVAILABLE
153
        );
154
    }
155
    
156
    protected $validations = array(
157
        'params',
158
        'type_supported',
159
        'type_unsupported',
160
        'variables'
161
    );
162
    
163
    protected function validateSyntax() : void
164
    {
165
        $validations = array_merge($this->validations, $this->getValidations());
166
        
167
        foreach($validations as $validation)
168
        {
169
            $method = 'validateSyntax_'.$validation;
170
            
171
            if(!method_exists($this, $method))
172
            {
173
                throw new Mailcode_Exception(
174
                    'Missing validation method',
175
                    sprintf(
176
                        'The method [%s] is missing from class [%s].',
177
                        $method,
178
                        get_class($this)
179
                    ),
180
                    self::ERROR_MISSING_VALIDATION_METHOD
181
                );
182
            }
183
            
184
            $this->$method();
185
            
186
            // break off at the first validation issue
187
            if(!$this->validationResult->isValid())
188
            {
189
                return;
190
            }
191
        }
192
    }
193
    
194
    abstract protected function getValidations() : array;
195
    
196
    protected function validateSyntax_params()
197
    {
198
        if($this->requiresParameters() && empty($this->paramsString))
199
        {
200
            $this->validationResult->makeError(
201
                t('Parameters have to be specified.'),
202
                self::VALIDATION_MISSING_PARAMETERS
203
            );
204
            return;
205
        }
206
    }
207
    
208
    protected function validateSyntax_type_supported()
209
    {
210
        if(!$this->supportsType() || empty($this->type))
211
        {
212
            return;
213
        }
214
        
215
        $types = $this->getSupportedTypes();
216
217
        if(!in_array($this->type, $types))
218
        {
219
            $this->validationResult->makeError(
220
                t('The command addon %1$s is not supported.', $this->type).' '.
221
                t('Valid addons are %1$s.', implode(', ', $types)),
222
                self::VALIDATION_ADDON_NOT_SUPPORTED
223
            );
224
            
225
            return;
226
        }
227
    }
228
    
229
    protected function validateSyntax_type_unsupported()
230
    {
231
        if($this->supportsType() || empty($this->type))
232
        {
233
            return;
234
        }
235
        
236
        $this->validationResult->makeError(
237
            t('Command addons are not supported (the %1$s part).', $this->type),
238
            self::VALIDATION_ADDONS_NOT_SUPPORTED
239
        );
240
    }
241
    
242
    protected function validateSyntax_variables()
243
    {
244
        $vars = $this->getVariables();
245
        
246
        if(!$vars->hasInvalid()) 
247
        {
248
            return;
249
        }
250
        
251
        $error = $vars->getInvalid()->getFirstError();
252
        
253
        $this->validationResult->makeError(
254
            $error->getErrorMessage(),
255
            $error->getCode()
256
        );
257
    }
258
    
259
    public function hasType() : bool
260
    {
261
        return $this->supportsType() && !empty($this->type);
262
    }
263
    
264
    public function getType() : string
265
    {
266
        if($this->supportsType())
267
        {
268
            return $this->type;
269
        }
270
        
271
        return '';
272
    }
273
    
274
    public function hasParameters() : bool
275
    {
276
        return $this->requiresParameters() && !empty($this->paramsString);
277
    }
278
    
279
    public function getMatchedText() : string
280
    {
281
        return $this->matchedText;
282
    }
283
    
284
    public function getHighlighted() : string
285
    {
286
        $highlighter = new Mailcode_Commands_Highlighter($this);
287
        return $highlighter->highlight();
288
    }
289
    
290
    public function getParamsString() : string
291
    {
292
        if($this->requiresParameters())
293
        {
294
            return $this->paramsString;
295
        }
296
        
297
        return '';
298
    }
299
    
300
    abstract public function getName() : string;
301
    
302
    abstract public function getLabel() : string;
303
    
304
    abstract public function requiresParameters() : bool;
305
    
306
    abstract public function supportsType() : bool;
307
    
308
    abstract public function generatesContent() : bool;
309
    
310
    public function getSupportedTypes() : array
311
    {
312
        return array();
313
    }
314
    
315
    public function getVariables() : Mailcode_Variables_Collection_Regular
316
    {
317
        return Mailcode::create()->findVariables($this->paramsString);
318
    }
319
}
320