PageRenderTime 27ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/library/spoon/form/date.php

https://github.com/bet0x/forkcms
PHP | 432 lines | 193 code | 68 blank | 171 comment | 48 complexity | 31a08c971b48d87a001ef43611ad7599 MD5 | raw file
  1. <?php
  2. /**
  3. * Spoon Library
  4. *
  5. * This source file is part of the Spoon Library. More information,
  6. * documentation and tutorials can be found @ http://www.spoon-library.com
  7. *
  8. * @package spoon
  9. * @subpackage form
  10. *
  11. *
  12. * @author Davy Hellemans <davy@spoon-library.com>
  13. * @since 0.1.1
  14. */
  15. /**
  16. * Creates an html textfield (date field)
  17. *
  18. * @package spoon
  19. * @subpackage form
  20. *
  21. *
  22. * @author Davy Hellemans <davy@spoon-library.com>
  23. * @author Dieter Vanden Eynde <dieter@dieterve.be>
  24. * @since 0.1.1
  25. */
  26. class SpoonFormDate extends SpoonFormInput
  27. {
  28. /**
  29. * Input mask (every item may only occur once)
  30. *
  31. * @var string
  32. */
  33. protected $mask = 'd-m-Y';
  34. /**
  35. * The value needed to base the mask on
  36. *
  37. * @var int
  38. */
  39. private $defaultValue;
  40. /**
  41. * Class constructor.
  42. *
  43. * @param string $name The name.
  44. * @param mixed[optional] $value The initial value.
  45. * @param string[optional] $mask The mask to use.
  46. * @param string[optional] $class The CSS-class to be used.
  47. * @param string[optional] $classError The CSS-class to be used when there is an error.
  48. */
  49. public function __construct($name, $value = null, $mask = null, $class = 'inputDatefield', $classError = 'inputDatefieldError')
  50. {
  51. // obligated fields
  52. $this->attributes['id'] = SpoonFilter::toCamelCase($name, '_', true);
  53. $this->attributes['name'] = (string) $name;
  54. /**
  55. * The input mask defines the maxlength attribute, therefor
  56. * this needs to be set anyhow. The mask needs to be updated
  57. * before the value is set, or the old mask (in case it differs)
  58. * will automatically be used.
  59. */
  60. $this->setMask(($mask !== null) ? $mask : $this->mask);
  61. /**
  62. * The value will be filled based on the default input mask
  63. * if no value has been defined.
  64. */
  65. $this->defaultValue = ($value !== null) ? (($value !== '') ? (int) $value : '') : time();
  66. $this->setValue($this->defaultValue);
  67. // custom optional fields
  68. $this->attributes['class'] = (string) $class;
  69. $this->classError = (string) $classError;
  70. // update reserved attributes
  71. $this->reservedAttributes[] = 'maxlength';
  72. }
  73. /**
  74. * Retrieve the initial value.
  75. *
  76. * @return string
  77. */
  78. public function getDefaultValue()
  79. {
  80. return $this->value;
  81. }
  82. /**
  83. * Retrieve the input mask.
  84. *
  85. * @return string
  86. */
  87. public function getMask()
  88. {
  89. return $this->mask;
  90. }
  91. /**
  92. * Returns a timestamp based on mask & optional fields.
  93. *
  94. * @return int
  95. * @param int[optional] $year The year to use.
  96. * @param int[optional] $month The month to use.
  97. * @param int[optional] $day The day to use.
  98. * @param int[optional] $hour The hour to use.
  99. * @param int[optional] $minute The minutes to use.
  100. * @param int[optional] $second The seconds to use.
  101. */
  102. public function getTimestamp($year = null, $month = null, $day = null, $hour = null, $minute = null, $second = null)
  103. {
  104. // field has been filled in
  105. if($this->isFilled())
  106. {
  107. // post/get data
  108. $data = $this->getMethod(true);
  109. // valid field
  110. if($this->isValid())
  111. {
  112. // define long mask
  113. $longMask = str_replace(array('d', 'm', 'Y'), array('dd', 'mm', 'yyyy'), $this->mask);
  114. // year found
  115. if(strpos($longMask, 'yyyy') !== false && $year === null)
  116. {
  117. // redefine year
  118. $year = substr($data[$this->attributes['name']], strpos($longMask, 'yyyy'), 4);
  119. }
  120. // month found
  121. if(strpos($longMask, 'mm') !== false && $month === null)
  122. {
  123. // redefine month
  124. $month = substr($data[$this->attributes['name']], strpos($longMask, 'mm'), 2);
  125. }
  126. // day found
  127. if(strpos($longMask, 'dd') !== false && $day === null)
  128. {
  129. // redefine day
  130. $day = substr($data[$this->attributes['name']], strpos($longMask, 'dd'), 2);
  131. }
  132. }
  133. // init vars
  134. $year = ($year !== null) ? (int) $year : (int) date('Y');
  135. $month = ($month !== null) ? (int) $month : (int) date('n');
  136. $day = ($day !== null) ? (int) $day : (int) date('j');
  137. $hour = ($hour !== null) ? (int) $hour : (int) date('H');
  138. $minute = ($minute !== null) ? (int) $minute : (int) date('i');
  139. $second = ($second !== null) ? (int) $second : (int) date('s');
  140. }
  141. // create (default) time
  142. return mktime($hour, $minute, $second, $month, $day, $year);
  143. }
  144. /**
  145. * Retrieve the initial or submitted value.
  146. *
  147. * @return string
  148. */
  149. public function getValue()
  150. {
  151. // redefine html & value
  152. $value = $this->value;
  153. // added to form
  154. if($this->isSubmitted())
  155. {
  156. // post/get data
  157. $data = $this->getMethod(true);
  158. // submitted by post (may be empty)
  159. if(isset($data[$this->attributes['name']]))
  160. {
  161. // value
  162. $value = $data[$this->attributes['name']];
  163. }
  164. }
  165. return $value;
  166. }
  167. /**
  168. * Checks if this field has any content (except spaces).
  169. *
  170. * @return bool
  171. * @param string[optional] $error The errormessage to set.
  172. */
  173. public function isFilled($error = null)
  174. {
  175. // form submitted
  176. if($this->isSubmitted())
  177. {
  178. // post/get data
  179. $data = $this->getMethod(true);
  180. // check filled status
  181. if(!(isset($data[$this->getName()]) && trim($data[$this->getName()]) != ''))
  182. {
  183. if($error !== null) $this->setError($error);
  184. return false;
  185. }
  186. }
  187. return true;
  188. }
  189. /**
  190. * Checks if this field is correctly submitted.
  191. *
  192. * @return bool
  193. * @param string[optional] $error The errormessage to set.
  194. */
  195. public function isValid($error = null)
  196. {
  197. // field has been filled in
  198. if($this->isFilled())
  199. {
  200. // post/get data
  201. $data = $this->getMethod(true);
  202. // maxlength checks out (needs to be equal)
  203. if(strlen($data[$this->attributes['name']]) == $this->attributes['maxlength'])
  204. {
  205. // define long mask
  206. $longMask = str_replace(array('d', 'm', 'y', 'Y'), array('dd', 'mm', 'yy', 'yyyy'), $this->mask);
  207. // init vars
  208. $year = (int) date('Y');
  209. $month = (int) date('m');
  210. $day = (int) date('d');
  211. // validate year (yyyy)
  212. if(strpos($longMask, 'yyyy') !== false)
  213. {
  214. // redefine year
  215. $year = substr($data[$this->attributes['name']], strpos($longMask, 'yyyy'), 4);
  216. // not an int
  217. if(!SpoonFilter::isInteger($year))
  218. {
  219. if($error !== null) $this->setError($error);
  220. return false;
  221. }
  222. // invalid year
  223. if(!checkdate(1, 1, $year))
  224. {
  225. if($error !== null) $this->setError($error);
  226. return false;
  227. }
  228. }
  229. // validate year (yy)
  230. if(strpos($longMask, 'yy') !== false && strpos($longMask, 'yyyy') === false)
  231. {
  232. // redefine year
  233. $year = substr($data[$this->attributes['name']], strpos($longMask, 'yy'), 2);
  234. // not an int
  235. if(!SpoonFilter::isInteger($year))
  236. {
  237. if($error !== null) $this->setError($error);
  238. return false;
  239. }
  240. // invalid year
  241. if(!checkdate(1, 1, '19' . $year))
  242. {
  243. if($error !== null) $this->setError($error);
  244. return false;
  245. }
  246. }
  247. // validate month (mm)
  248. if(strpos($longMask, 'mm') !== false)
  249. {
  250. // redefine month
  251. $month = substr($data[$this->attributes['name']], strpos($longMask, 'mm'), 2);
  252. // not an int
  253. if(!SpoonFilter::isInteger($month))
  254. {
  255. if($error !== null) $this->setError($error);
  256. return false;
  257. }
  258. // invalid month
  259. if(!checkdate($month, 1, $year))
  260. {
  261. if($error !== null) $this->setError($error);
  262. return false;
  263. }
  264. }
  265. // validate day (dd)
  266. if(strpos($longMask, 'dd') !== false)
  267. {
  268. // redefine day
  269. $day = substr($data[$this->attributes['name']], strpos($longMask, 'dd'), 2);
  270. // not an int
  271. if(!SpoonFilter::isInteger($day))
  272. {
  273. if($error !== null) $this->setError($error);
  274. return false;
  275. }
  276. // invalid day
  277. if(!checkdate($month, $day, $year))
  278. {
  279. if($error !== null) $this->setError($error);
  280. return false;
  281. }
  282. }
  283. }
  284. // maximum length doesn't check out
  285. else
  286. {
  287. if($error !== null) $this->setError($error);
  288. return false;
  289. }
  290. }
  291. // not filled out
  292. else
  293. {
  294. if($error !== null) $this->setError($error);
  295. return false;
  296. }
  297. /**
  298. * When the code reaches the point, it means no errors have occured
  299. * and truth will out!
  300. */
  301. return true;
  302. }
  303. /**
  304. * Parses the html for this date field.
  305. *
  306. * @return string
  307. * @param SpoonTemplate[optional] $template The template to parse the element in.
  308. */
  309. public function parse(SpoonTemplate $template = null)
  310. {
  311. // name is required
  312. if($this->attributes['name'] == '') throw new SpoonFormException('A name is required for a date field. Please provide a valid name.');
  313. // start html generation
  314. $output = '<input type="text" value="' . $this->getValue() . '"';
  315. // add attributes
  316. $output .= $this->getAttributesHTML(array('[id]' => $this->attributes['id'], '[name]' => $this->attributes['name'], '[value]' => $this->getValue())) . ' />';
  317. // template
  318. if($template !== null)
  319. {
  320. $template->assign('txt' . SpoonFilter::toCamelCase($this->attributes['name']), $output);
  321. $template->assign('txt' . SpoonFilter::toCamelCase($this->attributes['name']) . 'Error', ($this->errors != '') ? '<span class="formError">' . $this->errors . '</span>' : '');
  322. }
  323. return $output;
  324. }
  325. /**
  326. * Set the input mask.
  327. *
  328. * @return SpoonFormDate
  329. * @param string[optional] $mask The date-mask.
  330. */
  331. public function setMask($mask = null)
  332. {
  333. // redefine mask
  334. $mask = ($mask !== null) ? (string) $mask : $this->mask;
  335. // allowed characters
  336. $aCharachters = array('.', '-', '/', 'd', 'm', 'y', 'Y');
  337. // new mask
  338. $maskCorrected = '';
  339. // loop all elements
  340. for($i = 0; $i < strlen($mask); $i++)
  341. {
  342. // char allowed
  343. if(in_array(substr($mask, $i, 1), $aCharachters)) $maskCorrected .= substr($mask, $i, 1);
  344. }
  345. // new mask
  346. $this->mask = $maskCorrected;
  347. // define maximum length for this element
  348. $maskCorrected = str_replace(array('d', 'm', 'y', 'Y'), array('dd', 'mm', 'yy', 'yyyy'), $maskCorrected);
  349. // update maxium length
  350. $this->attributes['maxlength'] = strlen($maskCorrected);
  351. // update value
  352. if($this->defaultValue !== null) $this->setValue($this->defaultValue);
  353. return $this;
  354. }
  355. /**
  356. * Set the value attribute for this date field.
  357. *
  358. * @param mixed $value The new value.
  359. */
  360. private function setValue($value)
  361. {
  362. $this->value = ($value === '' ? '' : date($this->mask, (int) $value));
  363. }
  364. }