Issues (92)

src/Mailcode/Variables/Variable.php (2 issues)

1
<?php
2
/**
3
 * File containing the {@see Mailcode_Variables_Variable} class.
4
 *
5
 * @package Mailcode
6
 * @subpackage Variables
7
 * @see Mailcode_Variables_Variable
8
 */
9
10
declare(strict_types=1);
11
12
namespace Mailcode;
13
14
use AppUtils\OperationResult;
15
16
/**
17
 * Simple container for a single variable name occurrence: used
18
 * to store information on variable names used in commands, with
19
 * the possibility to retrieve the actual matched text among other
20
 * things.
21
 *
22
 * @package Mailcode
23
 * @subpackage Variables
24
 * @author Sebastian Mordziol <[email protected]>
25
 */
26
class Mailcode_Variables_Variable
27
{
28
    public const ERROR_MISSING_VALIDATION_METHOD = 48601;
29
    
30
    public const VALIDATION_ERROR_PATH_NUMERIC = 48201;
31
    public const VALIDATION_ERROR_NAME_NUMERIC = 48202;
32
    public const VALIDATION_ERROR_PATH_UNDERSCORE = 48203;
33
    public const VALIDATION_ERROR_NAME_UNDERSCORE = 48204;
34
    
35
   /**
36
    * @var string
37
    */
38
    protected string $path;
39
    
40
   /**
41
    * @var string
42
    */
43
    protected string $name;
44
    
45
   /**
46
    * @var string
47
    */
48
    protected string $matchedText;
49
    
50
   /**
51
    * @var string
52
    */
53
    protected string $hash = '';
54
    
55
   /**
56
    * @var OperationResult|NULL
57
    */
58
    protected ?OperationResult $validationResult = null;
59
    
60
   /**
61
    * @var array<string>
62
    */
63
    protected array $validations = array(
64
        'number_path',
65
        'number_name',
66
        'underscore_path',
67
        'underscore_name'
68
    );
69
70
    /**
71
     * @var Mailcode_Commands_Command|null
72
     */
73
    private ?Mailcode_Commands_Command $command;
74
75
    public function __construct(string $path, string $name, string $matchedText, ?Mailcode_Commands_Command $sourceCommand=null)
76
    {
77
        $this->path = $path;
78
        $this->name = $name;
79
        $this->matchedText = $matchedText;
80
        $this->command = $sourceCommand;
81
    }
82
83
    /**
84
     * Retrieves the source command of the variable, if any.
85
     * The string parser automatically sets the variable's
86
     * command, but if it was created via other means it will
87
     * not have one.
88
     *
89
     * @return Mailcode_Commands_Command|null
90
     */
91
    public function getSourceCommand() : ?Mailcode_Commands_Command
92
    {
93
        return $this->command;
94
    }
95
    
96
    public function getFullName() : string
97
    {
98
        if(empty($this->path))
99
        {
100
            return dollarize($this->name);
101
        }
102
        
103
        return dollarize($this->path.'.'.$this->name);
104
    }
105
106
    /**
107
     * Retrieves the name of the variable with a suffix that
108
     * uniquely identifies it together with the command it
109
     * came from. Used for grouping identical variables.
110
     *
111
     * @return string
112
     * @throws Mailcode_Exception
113
     */
114
    public function getUniqueName() : string
115
    {
116
        if(isset($this->command))
117
        {
118
            return $this->getFullName().'/'.$this->command->getHash();
0 ignored issues
show
The method getHash() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

118
            return $this->getFullName().'/'.$this->command->/** @scrutinizer ignore-call */ getHash();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
119
        }
120
121
        return $this->getFullName();
122
    }
123
    
124
    public function getName() : string
125
    {
126
        return $this->name;
127
    }
128
    
129
    public function getPath() : string
130
    {
131
        return $this->path;
132
    }
133
    
134
    public function getMatchedText() : string
135
    {
136
        return $this->matchedText;
137
    }
138
    
139
    public function getHash() : string
140
    {
141
        if(empty($this->hash))
142
        {
143
            $this->hash = md5($this->matchedText);
144
        }
145
        
146
        return $this->hash;
147
    }
148
    
149
    public function isValid() : bool
150
    {
151
        return $this->getValidationResult()->isValid();
152
    }
153
154
    /**
155
     * @return OperationResult
156
     * @throws Mailcode_Exception
157
     */
158
    public function getValidationResult() : OperationResult
159
    {
160
        if(isset($this->validationResult))
161
        {
162
            return $this->validationResult;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->validationResult could return the type null which is incompatible with the type-hinted return AppUtils\OperationResult. Consider adding an additional type-check to rule them out.
Loading history...
163
        }
164
165
        $result = new OperationResult($this);
166
        $this->validationResult = $result;
167
        $this->validate($result);
168
169
        return $result;
170
    }
171
172
    protected function validate(OperationResult $result) : void
173
    {
174
        foreach($this->validations as $validation)
175
        {
176
            $method = 'validate_'.$validation;
177
            
178
            if(!method_exists($this, $method))
179
            {
180
                throw new Mailcode_Exception(
181
                    'Unknown validation method',
182
                    sprintf(
183
                        'The method [%s] is missing in class [%s].',
184
                        $method,
185
                        get_class($this)
186
                    ),
187
                    self::ERROR_MISSING_VALIDATION_METHOD
188
                );
189
            }
190
            
191
            $this->$method();
192
193
            /*
194
            if(!$result->isValid())
195
            {
196
                return;
197
            }*/
198
        }
199
    }
200
201
    public function hasPath() : bool
202
    {
203
        return $this->getPath() !== '';
204
    }
205
206
    protected function validate_number_path() : void
207
    {
208
        $this->validateNumber($this->path, self::VALIDATION_ERROR_PATH_NUMERIC);
209
    }
210
    
211
    protected function validate_number_name() : void
212
    {
213
        $this->validateNumber($this->name, self::VALIDATION_ERROR_NAME_NUMERIC);
214
    }
215
    
216
    protected function validate_underscore_path() : void
217
    {
218
        $this->validateUnderscore($this->path, self::VALIDATION_ERROR_PATH_UNDERSCORE);
219
    }
220
    
221
    protected function validate_underscore_name() : void
222
    {
223
        $this->validateUnderscore($this->name, self::VALIDATION_ERROR_NAME_UNDERSCORE);
224
    }
225
    
226
    protected function validateNumber(string $value, int $errorCode) : void
227
    {
228
        if(empty($value) || !is_numeric($value[0]))
229
        {
230
            return;
231
        }
232
        
233
        $this->getValidationResult()->makeError(
234
            t(
235
                'The %1$s in variable %2$s must begin with a letter.',
236
                $value,
237
                $this->getFullName()
238
            ),
239
            $errorCode
240
        );
241
    }
242
    
243
    protected function validateUnderscore(string $value, int $errorCode) : void
244
    {
245
        // allow empty paths
246
        if(empty($value))
247
        {
248
            return;
249
        }
250
        
251
        $length = strlen($value);
252
        
253
        // trimming underscores does not change the length: no underscores at start or end of string.
254
        if(strlen(trim($value, '_')) === $length)
255
        {
256
            return;
257
        }
258
        
259
        $this->getValidationResult()->makeError(
260
            t(
261
                'The %1$s in variable %2$s may not start or end with an underscore.',
262
                $value,
263
                $this->getFullName()
264
            ),
265
            $errorCode
266
        );
267
    }
268
}
269