Passed
Push — master ( 827600...d1e019 )
by Sebastian
04:24
created

Mailcode_Collection::addCommand()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 9
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 1
eloc 3
c 2
b 0
f 0
nc 1
nop 1
dl 0
loc 9
rs 10
1
<?php
2
/**
3
 * File containing the {@see Mailcode_Collection} class.
4
 *
5
 * @package Mailcode
6
 * @subpackage Collection
7
 * @see Mailcode_Collection
8
 */
9
10
declare(strict_types=1);
11
12
namespace Mailcode;
13
14
use AppUtils\OperationResult;
15
16
/**
17
 * Commands collection: container for commands.
18
 *
19
 * @package Mailcode
20
 * @subpackage Collection
21
 * @author Sebastian Mordziol <[email protected]>
22
 */
23
class Mailcode_Collection
24
{
25
    const ERROR_CANNOT_RETRIEVE_FIRST_ERROR = 52301;
26
    
27
   /**
28
    * @var Mailcode_Commands_Command[]
29
    */
30
    protected $commands = array();
31
    
32
    /**
33
     * @var Mailcode_Collection_Error[]
34
     */
35
    protected $errors = array();
36
    
37
   /**
38
    * @var OperationResult|NULL
39
    */
40
    protected $validationResult;
41
    
42
   /**
43
    * Adds a command to the collection.
44
    * 
45
    * @param Mailcode_Commands_Command $command
46
    * @return Mailcode_Collection
47
    */
48
    public function addCommand(Mailcode_Commands_Command $command) : Mailcode_Collection
49
    {
50
        $this->commands[] = $command;
51
        
52
        // reset the collection's validation result, since it 
53
        // depends on the commands.
54
        $this->validationResult = null;
55
        
56
        return $this;
57
    }
58
    
59
   /**
60
    * Whether there are any commands in the collection.
61
    * 
62
    * @return bool
63
    */
64
    public function hasCommands() : bool
65
    {
66
        return !empty($this->commands);
67
    }
68
    
69
   /**
70
    * Counts the amount of commands in the collection.
71
    * 
72
    * @return int
73
    */
74
    public function countCommands() : int
75
    {
76
        return count($this->commands);
77
    }
78
79
    public function addErrorMessage(string $matchedText, string $message, int $code) : void
80
    {
81
        $this->errors[] = new Mailcode_Collection_Error_Message(
82
            $matchedText,
83
            $code,
84
            $message
85
        );
86
    }
87
    
88
    public function addInvalidCommand(Mailcode_Commands_Command $command) : void
89
    {
90
        $this->errors[] = new Mailcode_Collection_Error_Command($command);
91
    }
92
    
93
   /**
94
    * @return Mailcode_Collection_Error[]
95
    */
96
    public function getErrors()
97
    {
98
        $result = $this->getValidationResult();
99
        
100
        $errors = $this->errors;
101
        
102
        if(!$result->isValid())
103
        {
104
            $errors[] = new Mailcode_Collection_Error_Message(
105
                '',
106
                $result->getCode(),
107
                $result->getErrorMessage()
108
            );
109
        }
110
        
111
        return $errors;
112
    }
113
    
114
    public function getFirstError() : Mailcode_Collection_Error
115
    {
116
        $errors = $this->getErrors();
117
        
118
        if(!empty($errors))
119
        {
120
            return array_shift($errors);
121
        }
122
        
123
        throw new Mailcode_Exception(
124
            'Cannot retrieve first error: no errors detected',
125
            null,
126
            self::ERROR_CANNOT_RETRIEVE_FIRST_ERROR
127
        );
128
    }
129
    
130
    public function isValid() : bool
131
    {
132
        $errors = $this->getErrors();
133
        
134
        return empty($errors);
135
    }
136
    
137
   /**
138
    * Retrieves all commands that were detected, in the exact order
139
    * they were found.
140
    * 
141
    * @return \Mailcode\Mailcode_Commands_Command[]
142
    */
143
    public function getCommands()
144
    {
145
       return $this->commands;
146
    }
147
    
148
   /**
149
    * Retrieves all unique commands by their matched
150
    * string hash: this ensures only commands that were
151
    * written the exact same way (including spacing)
152
    * are returned.
153
    * 
154
    * @return \Mailcode\Mailcode_Commands_Command[]
155
    */
156
    public function getGroupedByHash()
157
    {
158
        $hashes = array();
159
        
160
        foreach($this->commands as $command)
161
        {
162
            $hash = $command->getHash();
163
            
164
            if(!isset($hashes[$hash]))
165
            {
166
                $hashes[$hash] = $command;
167
            }
168
        }
169
            
170
        return array_values($hashes);
171
    }
172
173
   /**
174
    * Adds several commands at once.
175
    * 
176
    * @param Mailcode_Commands_Command[] $commands
177
    * @return Mailcode_Collection
178
    */
179
    public function addCommands(array $commands) : Mailcode_Collection
180
    {
181
        foreach($commands as $command)
182
        {
183
            $this->addCommand($command);
184
        }
185
        
186
        return $this;
187
    }
188
    
189
    public function mergeWith(Mailcode_Collection $collection) : Mailcode_Collection
190
    {
191
        $this->addCommands($collection->getCommands());
192
        
193
        return $this;
194
    }
195
    
196
    public function getVariables() : Mailcode_Variables_Collection
197
    {
198
        $collection = new Mailcode_Variables_Collection_Regular();
199
        
200
        foreach($this->commands as $command)
201
        {
202
            $collection->mergeWith($command->getVariables());
203
        }
204
        
205
        return $collection;
206
    }
207
    
208
    public function getValidationResult() : OperationResult
209
    {
210
        if($this->validationResult instanceof OperationResult)
211
        {
212
            return $this->validationResult;
213
        }
214
        
215
        $nesting = new Mailcode_Collection_NestingValidator($this);
216
        
217
        $this->validationResult = $nesting->validate(); 
218
        
219
        return $this->validationResult;
220
    }
221
    
222
    public function hasErrorCode(int $code) : bool
223
    {
224
        $errors = $this->getErrors();
225
        
226
        foreach($errors as $error)
227
        {
228
            if($error->getCode() === $code)
229
            {
230
                return true;
231
            }
232
        }
233
        
234
        return false;
235
    }
236
    
237
   /**
238
    * Retrieves only show variable commands in the collection, if any.
239
    * 
240
    * @return Mailcode_Commands_Command_ShowVariable[]
241
    */
242
    public function getShowVariableCommands()
243
    {
244
        return $this->getCommandsByClass(Mailcode_Commands_Command_ShowVariable::class);
245
    }
246
247
   /**
248
    * Retrieves only show date commands in the collection, if any.
249
    *
250
    * @return Mailcode_Commands_Command_ShowDate[]
251
    */
252
    public function getShowDateCommands() : array
253
    {
254
        return $this->getCommandsByClass(Mailcode_Commands_Command_ShowDate::class);
255
    }
256
257
    /**
258
     * @param string $className
259
     * @return Mailcode_Commands_Command[]
260
     */
261
    public function getCommandsByClass(string $className) : array
262
    {
263
        $result = array();
264
265
        foreach($this->commands as $command)
266
        {
267
            if($command instanceof $className)
268
            {
269
                $result[] = $command;
270
            }
271
        }
272
273
        return $result;
274
    }
275
    
276
    public function getFirstCommand() : ?Mailcode_Commands_Command
277
    {
278
        $commands = $this->getCommands();
279
        
280
        if(!empty($commands))
281
        {
282
            return array_shift($commands);
283
        }
284
        
285
        return null;
286
    }
287
}
288