Passed
Push — master ( 174259...689687 )
by Sebastian
04:01
created

Mailcode_Date_FormatInfo   A

Complexity

Total Complexity 16

Size/Duplication

Total Lines 188
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 68
c 1
b 0
f 0
dl 0
loc 188
rs 10
wmc 16

8 Methods

Rating   Name   Duplication   Size   Complexity  
A getInstance() 0 8 2
A getDefaultFormat() 0 3 1
A initCharacters() 0 29 2
A setDefaultFormat() 0 3 1
A getCharactersList() 0 3 1
A getCharactersGrouped() 0 32 4
A validateFormat() 0 36 4
A __construct() 0 3 1
1
<?php
2
/**
3
 * File containing the {@see Mailcode_Date_FormatInfo} class.
4
 *
5
 * @package Mailcode
6
 * @subpackage Commands
7
 * @see Mailcode_Date_FormatInfo
8
 */
9
10
declare(strict_types=1);
11
12
namespace Mailcode;
13
14
use AppUtils\ConvertHelper;
15
use AppUtils\OperationResult;
16
17
/**
18
 * Main hub for information all around the date format strings
19
 * that can be used in the ShowDate command.
20
 *
21
 * @package Mailcode
22
 * @subpackage Commands
23
 * @author Sebastian Mordziol <[email protected]>
24
 */
25
class Mailcode_Date_FormatInfo
26
{
27
    const VALIDATION_INVALID_FORMAT_CHARACTER = 55801;
28
    const VALIDATION_EMPTY_FORMAT_STRING = 55802;
29
    
30
    const CHARTYPE_DATE = 'date';
31
    const CHARTYPE_TIME = 'time';
32
    const CHARTYPE_PUNCTUATION = 'punctuation';
33
    
34
   /**
35
    * @var string
36
    */
37
    private $defaultFormat = "Y/m/d";
38
    
39
   /**
40
    * @var Mailcode_Date_FormatInfo_Character[]
41
    */
42
    private $formatChars = array();
43
    
44
   /**
45
    * @var string[]
46
    */
47
    private $allowedChars = array();
48
    
49
   /**
50
    * @var Mailcode_Date_FormatInfo|NULL
51
    */
52
    private static $instance;
53
    
54
    private function __construct()
55
    {
56
        $this->initCharacters();
57
    }
58
    
59
    public static function getInstance() : Mailcode_Date_FormatInfo
60
    {
61
        if(!isset(self::$instance))
62
        {
63
            self::$instance = new Mailcode_Date_FormatInfo();
64
        }
65
        
66
        return self::$instance;
67
    }
68
69
   /**
70
    * Initialized the list of allowed date formatting
71
    * characters. This is done only once per request
72
    * by storing them statically for performance reasons.
73
    */
74
    private function initCharacters() : void
75
    {
76
        $chars = array(
77
            array(self::CHARTYPE_DATE, 'd', t('Day of the month, 2 digits with leading zeros')),
78
            array(self::CHARTYPE_DATE, 'm', t('Month number, with leading zeros')),
79
            array(self::CHARTYPE_DATE, 'Y', t('Year, 4 digits')),
80
            array(self::CHARTYPE_DATE, 'y', t('Year, 2 digits')),
81
            
82
            array(self::CHARTYPE_TIME, 'H', t('Hour, 24-hour format with leading zeros')),
83
            array(self::CHARTYPE_TIME, 'i', t('Minutes with leading zeros')),
84
            array(self::CHARTYPE_TIME, 's', t('Seconds with leading zeros')),
85
            
86
            array(self::CHARTYPE_PUNCTUATION, '.', t('Dot')),
87
            array(self::CHARTYPE_PUNCTUATION, '/', t('Slash')),
88
            array(self::CHARTYPE_PUNCTUATION, '-', t('Hyphen')),
89
            array(self::CHARTYPE_PUNCTUATION, ':', t('Colon')),
90
            array(self::CHARTYPE_PUNCTUATION, ' ', t('Space'))
91
        );
92
        
93
        foreach($chars as $def)
94
        {
95
            $char = new Mailcode_Date_FormatInfo_Character(
96
                $def[0],
97
                $def[1],
98
                $def[2]
99
            );
100
            
101
            $this->formatChars[] = $char;
102
            $this->allowedChars[] = $char->getChar();
103
        }
104
    }
105
    
106
    public function getDefaultFormat() : string
107
    {
108
        return $this->defaultFormat;
109
    }
110
    
111
    public function setDefaultFormat(string $formatString) : void
112
    {
113
        $this->defaultFormat = $formatString;
114
    }
115
    
116
   /**
117
    * Validates the date format string, by ensuring that
118
    * all the characters it is composed of are known.
119
    *
120
    * @param string $formatString
121
    * @return OperationResult
122
    * 
123
    * @see Mailcode_Commands_Command_ShowDate::VALIDATION_EMPTY_FORMAT_STRING
124
    * @see Mailcode_Commands_Command_ShowDate::VALIDATION_INVALID_FORMAT_CHARACTER
125
    */
126
    public function validateFormat(string $formatString) : OperationResult
127
    {
128
        $result = new OperationResult($this);
129
        
130
        $trimmed = trim($formatString);
131
        
132
        if(empty($trimmed))
133
        {
134
            $result->makeError(
135
                t('Empty date format.'),
136
                self::VALIDATION_EMPTY_FORMAT_STRING
137
            );
138
            
139
            return $result;
140
        }
141
        
142
        $chars = ConvertHelper::string2array($formatString);
143
        $total = count($chars);
144
        
145
        for($i=0; $i < $total; $i++)
146
        {
147
            $char = $chars[$i];
148
            
149
            if(!in_array($char, $this->allowedChars))
150
            {
151
                $result->makeError(
152
                    t('Invalid character in date format:').' '.
153
                    t('%1$s at position %2$s.', '<code>'.$char.'</code>', $i+1),
154
                    self::VALIDATION_INVALID_FORMAT_CHARACTER
155
                );
156
                
157
                return $result;
158
            }
159
        }
160
        
161
        return $result;
162
    }
163
    
164
   /**
165
    * Retrieves all characters that are allowed to
166
    * be used in a date format string, with information
167
    * on each.
168
    *
169
    * @return Mailcode_Date_FormatInfo_Character[]
170
    */
171
    public function getCharactersList() : array
172
    {
173
        return $this->formatChars;
174
    }
175
    
176
   /**
177
    * Retrieves the characters list, grouped by type label.
178
    * 
179
    * @return array<string, array>
180
    */
181
    public function getCharactersGrouped() : array
182
    {
183
        $grouped = array();
184
        
185
        foreach($this->formatChars as $char)
186
        {
187
            $type = $char->getTypeLabel();
188
            
189
            if(!isset($grouped[$type]))
190
            {
191
                $grouped[$type] = array();
192
            }
193
            
194
            $grouped[$type][] = $char;
195
        }
196
197
        $groups = array_keys($grouped);
198
        
199
        foreach($groups as $group)
200
        {
201
            usort($grouped[$group], function(Mailcode_Date_FormatInfo_Character $a, Mailcode_Date_FormatInfo_Character $b)
202
            {
203
                return strnatcasecmp($a->getChar(), $b->getChar());
204
            });
205
        }
206
        
207
        uksort($grouped, function(string $a, string $b) 
208
        {
209
            return strnatcasecmp($a, $b);
210
        });
211
        
212
        return $grouped;
213
    }
214
}
215