1: <?php
2:
3: namespace Alpha\Model\Type;
4:
5: use Alpha\Util\Helper\Validator;
6: use Alpha\Exception\IllegalArguementException;
7: use Alpha\Util\Config\ConfigProvider;
8:
9: /**
10: * The Date complex data type.
11: *
12: * @since 1.0
13: *
14: * @author John Collins <dev@alphaframework.org>
15: * @license http://www.opensource.org/licenses/bsd-license.php The BSD License
16: * @copyright Copyright (c) 2015, John Collins (founder of Alpha Framework).
17: * All rights reserved.
18: *
19: * <pre>
20: * Redistribution and use in source and binary forms, with or
21: * without modification, are permitted provided that the
22: * following conditions are met:
23: *
24: * * Redistributions of source code must retain the above
25: * copyright notice, this list of conditions and the
26: * following disclaimer.
27: * * Redistributions in binary form must reproduce the above
28: * copyright notice, this list of conditions and the
29: * following disclaimer in the documentation and/or other
30: * materials provided with the distribution.
31: * * Neither the name of the Alpha Framework nor the names
32: * of its contributors may be used to endorse or promote
33: * products derived from this software without specific
34: * prior written permission.
35: *
36: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
37: * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
38: * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
39: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
40: * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
41: * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
42: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
43: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
44: * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
45: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
46: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
47: * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
48: * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
49: * </pre>
50: */
51: class Date extends Type implements TypeInterface
52: {
53: /**
54: * The year part.
55: *
56: * @var int
57: *
58: * @since 1.0
59: */
60: private $year;
61:
62: /**
63: * The month part.
64: *
65: * @var int
66: *
67: * @since 1.0
68: */
69: private $month;
70:
71: /**
72: * The day part.
73: *
74: * @var int
75: *
76: * @since 1.0
77: */
78: private $day;
79:
80: /**
81: * The textual version of the day, e.g. Monday.
82: *
83: * @var string
84: *
85: * @since 1.0
86: */
87: private $weekday;
88:
89: /**
90: * The validation rule (reg-ex) applied to Date values.
91: *
92: * @var string
93: *
94: * @since 1.0
95: */
96: private $validationRule;
97:
98: /**
99: * The error message returned for invalid values.
100: *
101: * @var string
102: *
103: * @since 1.0
104: */
105: protected $helper = 'Not a valid date value! A date should be in the ISO format YYYY-MM-DD.';
106:
107: /**
108: * Constructor. Leave $date param empty to default to now.
109: *
110: * @param string $date Date string in the ISO format YYYY-MM-DD.
111: *
112: * @since 1.0
113: *
114: * @throws Alpha\Exception\IllegalArguementException
115: */
116: public function __construct($date = '')
117: {
118: $config = ConfigProvider::getInstance();
119:
120: $this->validationRule = Validator::ALLOW_ALL;
121:
122: if (empty($date)) {
123: if ($config->get('app.default.datetime') == 'now') {
124: $this->year = date('Y');
125: $this->month = date('m');
126: $this->day = date('d');
127: $this->weekday = date('l');
128: } else {
129: $this->year = '0000';
130: $this->month = '00';
131: $this->day = '00';
132: }
133: } else {
134: if (preg_match($this->validationRule, $date)) {
135: $this->populateFromString($date);
136: } else {
137: throw new IllegalArguementException($this->helper);
138: }
139: }
140: }
141:
142: /**
143: * Accepts a full date string in ISO YYYY-mm-dd format and populates relevent Date attributes.
144: *
145: * @param string $date
146: *
147: * @since 1.0
148: *
149: * @throws Alpha\Exception\IllegalArguementException
150: */
151: public function setValue($date)
152: {
153: $this->populateFromString($date);
154: }
155:
156: /**
157: * Set the Date attributes to match the three values provided.
158: *
159: * @param int $year
160: * @param int $month
161: * @param int $day
162: *
163: * @throws Alpha\Exception\IllegalArguementException
164: *
165: * @since 1.0
166: */
167: public function setDateValue($year, $month, $day)
168: {
169: $valid = null;
170:
171: if (!preg_match('/^[0-9]{4}$/', $year)) {
172: $valid = 'Error: the year value '.$year.' provided is invalid!';
173: }
174: if (!isset($valid) && !preg_match('/^[0-9]{1,2}$/', $month)) {
175: $valid = 'Error: the month value '.$month.' provided is invalid!';
176: }
177: if (!isset($valid) && !preg_match('/^[0-9]{1,2}$/', $day)) {
178: $valid = 'Error: the day value '.$day.' provided is invalid!';
179: }
180: if (!isset($valid) && !checkdate($month, $day, $year)) {
181: $valid = 'Error: the day value '.$year.'-'.$month.'-'.$day.' provided is invalid!';
182: }
183:
184: if (isset($valid)) {
185: throw new IllegalArguementException($valid);
186: } else {
187: $this->year = $year;
188: $this->month = str_pad($month, 2, '0', STR_PAD_LEFT);
189: $this->day = str_pad($day, 2, '0', STR_PAD_LEFT);
190: $unixTime = mktime(0, 0, 0, $this->month, $this->day, $this->year);
191: $this->weekday = date('l', $unixTime);
192: }
193: }
194:
195: /**
196: * Get the date value as a string in the format "YYYY-MM-DD".
197: *
198: * @return string
199: *
200: * @since 1.0
201: */
202: public function getValue()
203: {
204: return $this->year.'-'.$this->month.'-'.$this->day;
205: }
206:
207: /**
208: * Return the value in UNIX timestamp format.
209: *
210: * @return int
211: *
212: * @since 1.0
213: */
214: public function getUnixValue()
215: {
216: return mktime(0, 0, 0, $this->month, $this->day, $this->year);
217: }
218:
219: /**
220: * Get the date value as a string in the format "DD/MM/YYYY".
221: *
222: * @return string
223: *
224: * @since 1.0
225: */
226: public function getEuroValue()
227: {
228: return $this->day.'/'.$this->month.'/'.mb_substr($this->year, 2, 2);
229: }
230:
231: /**
232: * Get the date value as a string in the format "MM/DD/YYYY".
233: *
234: * @return string
235: *
236: * @since 1.0
237: */
238: public function getUSValue()
239: {
240: return $this->month.'/'.$this->day.'/'.mb_substr($this->year, 2, 2);
241: }
242:
243: /**
244: * Get the year part.
245: *
246: * @return int
247: *
248: * @since 1.0
249: */
250: public function getYear()
251: {
252: return $this->year;
253: }
254:
255: /**
256: * Get the month part.
257: *
258: * @return int
259: *
260: * @since 1.0
261: */
262: public function getMonth()
263: {
264: return $this->month;
265: }
266:
267: /**
268: * Get the day part.
269: *
270: * @return int
271: *
272: * @since 1.0
273: */
274: public function getDay()
275: {
276: return $this->day;
277: }
278:
279: /**
280: * Get the textual weekday part, e.g. Monday.
281: *
282: * @return string
283: *
284: * @since 1.0
285: */
286: public function getWeekday()
287: {
288: return $this->weekday;
289: }
290:
291: /**
292: * Accepts a full date string in YYYY-MM-DD format and populates relevent Date attributes.
293: *
294: * @param string $date
295: *
296: * @throws Alpha\Exception\IllegalArguementException
297: *
298: * @since 1.0
299: */
300: public function populateFromString($date)
301: {
302: $valid = null;
303:
304: if ($date == '' || $date == '0000-00-00') {
305: $this->year = '0000';
306: $this->month = '00';
307: $this->day = '00';
308: } else {
309: // This is just here for legacy to ensure that any old time value from a Date object is ignored
310: $spilt_by_space = explode(' ', $date);
311:
312: if (isset($spilt_by_space[0])) {
313: $date = $spilt_by_space[0];
314: } else {
315: throw new IllegalArguementException('Invalid Date value ['.$date.'] provided!');
316: }
317:
318: $split_by_dash = explode('-', $date);
319:
320: // Parse for the date parts, seperated by "-"
321: if (isset($split_by_dash[0]) && isset($split_by_dash[1]) && isset($split_by_dash[2])) {
322: $year = $split_by_dash[0];
323: $month = $split_by_dash[1];
324: $day = $split_by_dash[2];
325: } else {
326: throw new IllegalArguementException('Invalid Date value ['.$date.'] provided!');
327: }
328:
329: if (!preg_match('/^[0-9]{4}$/', $year)) {
330: $valid = 'Error: the year value '.$year.' provided is invalid!';
331: }
332: if (!isset($valid) && !preg_match('/^[0-9]{1,2}$/', $month)) {
333: $valid = 'Error: the month value '.$month.' provided is invalid!';
334: }
335: if (!isset($valid) && !preg_match('/^[0-9]{1,2}$/', $day)) {
336: $valid = 'Error: the day value '.$day.' provided is invalid!';
337: }
338: if (!isset($valid) && !checkdate($month, $day, $year)) {
339: $valid = 'Error: the date value '.$year.'-'.$month.'-'.$day.' provided is invalid!';
340: }
341:
342: if (isset($valid)) {
343: throw new IllegalArguementException($valid);
344: } else {
345: $this->year = $year;
346: $this->month = str_pad($month, 2, '0', STR_PAD_LEFT);
347: $this->day = str_pad($day, 2, '0', STR_PAD_LEFT);
348: $unixTime = mktime(0, 0, 0, $this->month, $this->day, $this->year);
349: $this->weekday = date('l', $unixTime);
350: }
351: }
352: }
353:
354: /**
355: * Get the validation rule.
356: *
357: * @return string
358: *
359: * @since 1.0
360: */
361: public function getRule()
362: {
363: return $this->validationRule;
364: }
365:
366: /**
367: * Set the validation rule.
368: *
369: * @param string $rule
370: *
371: * @since 1.0
372: */
373: public function setRule($rule)
374: {
375: $this->validationRule = $rule;
376: }
377: }
378: