Completed
Push — 2.0 ( 0b0e6b...b762a1 )
by Christopher
03:26
created

DateToolbox::normalizeFormat()   B

Complexity

Conditions 3
Paths 2

Size

Total Lines 29
Code Lines 19

Duplication

Lines 4
Ratio 13.79 %

Importance

Changes 0
Metric Value
cc 3
eloc 19
nc 2
nop 1
dl 4
loc 29
rs 8.8571
c 0
b 0
f 0
1
<?php
2
/**
3
 * Licensed under The GPL-3.0 License
4
 * For full copyright and license information, please see the LICENSE.txt
5
 * Redistributions of files must retain the above copyright notice.
6
 *
7
 * @since    2.0.0
8
 * @author   Christopher Castro <[email protected]>
9
 * @link     http://www.quickappscms.org
10
 * @license  http://opensource.org/licenses/gpl-3.0.html GPL-3.0 License
11
 */
12
namespace Field\Utility;
13
14
use Cake\Datasource\EntityInterface;
15
16
/**
17
 * DateToolbox class for handling date related tasks.
18
 *
19
 */
20
class DateToolbox
21
{
22
23
    /**
24
     * Maps jQuery's datepicker format tokens to PHP's
25
     *
26
     * @var array
27
     */
28
    protected static $_map = [
29
        'date' => [
30
            'dd' => 'd',
31
            'd' => 'j',
32
            'oo' => 'z',
33
            'DD' => 'l',
34
            'D' => 'D',
35
            'mm' => 'm',
36
            'm' => 'n',
37
            'MM' => 'F',
38
            'M' => 'M',
39
            'yy' => 'Y',
40
            'y' => 'y',
41
            '@' => 'U',
42
        ],
43
        'time' => [
44
            'HH' => 'G',
45
            'H' => 'H',
46
            'hh' => 'h',
47
            'h' => 'g',
48
            'mm' => 'i',
49
            'ss' => 's',
50
            'tt' => 'a',
51
            'TT' => 'A',
52
        ]
53
    ];
54
55
    /**
56
     * Converts the given $date to a valid PHP's DateTime object using a jQuery's
57
     * date/time $format.
58
     *
59
     * @param string $format A jQuery's date/time format. e.g. `'today is:' yy-mm-dd`
60
     * @param string $date A date formatted using $format. e.g. `today is: 2015-01-30`
61
     * @return \DateTime|false Date object on success, false on error
62
     */
63
    public static function createFromFormat($format, $date)
64
    {
65
        if (preg_match_all("/'([^']+)'/", $format, $matches)) {
66
            foreach ($matches[1] as $literal) {
67
                $date = str_replace($literal, '', $date);
68
            }
69
            $date = preg_replace('/\s{2,}/', ' ', $date); // remove double spaces
70
        }
71
72
        $date = trim($date);
73
        $format = DateToolbox::normalizeFormat($format);
74
75
        return date_create_from_format($format, $date);
76
    }
77
78
    /**
79
     * Formats then given UNIX timestamp date using que given jQuery format.
80
     *
81
     *@param string $format jQuery format. e.g. `'today is:' yy-mm-dd`
82
     *@param int $timestamp Date as UNIX timestamp
83
     */
84
    public static function formatDate($format, $timestamp)
85
    {
86
        static $datesPatterns = null;
87
        static $timesPatterns = null;
88
89 View Code Duplication
        if ($datesPatterns === null || $timesPatterns === null) {
90
            $datesPatterns = "/\b(" . implode('|', array_keys(static::$_map['date'])) . ")\b(?![^']*'(?:(?:[^']*'){2})*[^']*$)/i";
91
            $timesPatterns = "/\b(" . implode('|', array_keys(static::$_map['time'])) . ")\b(?![^']*'(?:(?:[^']*'){2})*[^']*$)/i";
92
        }
93
94
        // normalize formats
95
        $result = preg_replace_callback($datesPatterns, function ($matches) use ($timestamp) {
96
            return date(static::$_map['date'][$matches[1]], $timestamp);
97
        }, trim($format));
98
99
        $result = preg_replace_callback($timesPatterns, function ($matches) use ($timestamp) {
100
            return date(static::$_map['time'][$matches[1]], $timestamp);
101
        }, $result);
102
103
        return str_replace('\'', '', $result);
104
    }
105
106
    /**
107
     * Converts jQuery's date/time format to PHP's.
108
     *
109
     * @param string $format Date format coming from jQuery's datepicker widget.
110
     *  e.g. yy-mm-dd hh:mm
111
     * @return string A valid date/time format to use with PHP
112
     */
113
    public static function normalizeFormat($format)
114
    {
115
        static $datesPatterns = null;
116
        static $timesPatterns = null;
117
118 View Code Duplication
        if ($datesPatterns === null || $timesPatterns === null) {
119
            $datesPatterns = '/(' . implode('|', array_keys(static::$_map['date'])) . ')/';
120
            $timesPatterns = '/(' . implode('|', array_keys(static::$_map['time'])) . ')/';
121
        }
122
123
        $format = trim($format);
124
        $format = preg_replace("/'([^']+)'/", '', $format); // remove quotes
125
        $format = preg_replace('/\s{2,}/', ' ', $format); // remove double spaces
126
        $format = trim($format);
127
        list($dateFormat, $timeFormat) = explode(' ', "{$format} ");
128
129
        // normalize formats
130
        $dateFormat = preg_replace_callback($datesPatterns, function ($matches) {
131
            return static::$_map['date'][$matches[1]];
132
        }, $dateFormat);
133
134
        $timeFormat = preg_replace_callback($timesPatterns, function ($matches) {
135
            return static::$_map['time'][$matches[1]];
136
        }, $timeFormat);
137
138
        $format = trim($dateFormat . ' ' . $timeFormat);
139
140
        return $format;
141
    }
142
143
    /**
144
     * Validates a date format for jQuery's datepicker widget.
145
     *
146
     * @param string $format Format to validate. e.g. yy:mm:ddQ (invalid)
147
     * @return bool
148
     */
149 View Code Duplication
    public static function validateDateFormat($format)
150
    {
151
        $format = str_replace(array_keys(static::$_map['date']), '', $format);
152
        $format = preg_replace("/'(.*)'/", '', $format); // remove quotes
153
        $format = preg_replace('/[^a-z]/i', '', $format);
154
        $format = trim($format);
155
156
        return empty($format);
157
    }
158
159
    /**
160
     * Validates a time format for jQuery's datepicker widget.
161
     *
162
     * @param string $format Format to validate. e.g. hh:mm:ssA (invalid)
163
     * @return bool
164
     */
165 View Code Duplication
    public static function validateTimeFormat($format)
166
    {
167
        $format = str_replace(array_keys(static::$_map['time']), '', $format);
168
        $format = preg_replace("/'(.*)'/", '', $format); // remove quotes
169
        $format = preg_replace('/[^a-z]/i', '', $format);
170
        $format = trim($format);
171
172
        return empty($format);
173
    }
174
175
    /**
176
     * Given a DateField instance, gets its PHP's date-format.
177
     *
178
     * @param \Cake\Datasource\EntityInterface $field DateField instance
179
     * @return string PHP date-format for later use with date() function
180
     */
181
    public static function getPHPFormat(EntityInterface $field)
182
    {
183
        $settings = $field->metadata->settings;
184
        $format = empty($settings['format']) ? 'yy-mm-dd' : $settings['format'];
185
        if ($settings['timepicker']) {
186
            $format .= ' ';
187
            if (empty($settings['time_format'])) {
188
                $format .= 'H:mm';
189
                $format .= empty($settings['time_seconds']) ?: ':ss';
190
            } else {
191
                $format .= $settings['time_format'];
192
            }
193
        }
194
195
        return static::normalizeFormat($format);
196
    }
197
}
198