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

/lib/clonefish/element.selectdate.php

https://github.com/dodyrw/framework
PHP | 433 lines | 310 code | 50 blank | 73 comment | 14 complexity | c344adac1393456a994c3c624ff56cd5 MD5 | raw file
  1. <?php
  2. /**
  3. * Clonefish form generator class
  4. * (c) phpformclass.com, Dots Amazing
  5. * All rights reserved.
  6. *
  7. * @copyright 2010 Dots Amazing
  8. * @link http://phpformclass.com
  9. * @package clonefish
  10. * @subpackage elements
  11. */
  12. /*
  13. * Element
  14. * @package clonefish
  15. * @subpackage elements
  16. */
  17. class selectDate extends element {
  18. var $value;
  19. var $layout = '%Y %M %D';
  20. // we use % here to avoid problems with Y, M and D letters
  21. // in the layout string.
  22. // eg. if you'd like to use a select like
  23. // Year: [ ] Month: [ ] Day: [ ]
  24. // you should specify:
  25. // $layout = 'Year: %Y Month: %M Day: %D'
  26. var $format = '%Y-%M-%D';
  27. // format is used to specify the 'compiled' result of
  28. // the selects returned by getValue
  29. var $padding = true;
  30. // store month, day, with two digits,
  31. // (01..12, 01..31 ), year with 4 digits (leading zeroes) or not.
  32. // Affects only compiled result ($this->format),
  33. // does not affect display.
  34. var $showpaddinghours = false;
  35. // Show zeropadded hours (00..23) or not (default: false).
  36. // Compiled ('stored') format is always padded disregarding this attribute.
  37. var $showpaddingmins = true;
  38. // Show zeropadded minutes (00..59) or not (default: true).
  39. // Compiled ('stored') format is always padded disregarding this attribute.
  40. var $showpaddingsecs = true;
  41. // Show zeropadded seconds (00..59) or not (default: true).
  42. // Compiled ('stored') format is always padded disregarding this attribute.
  43. var $null = Array( '' => '' );
  44. // if $null is not false, but an array, it is used
  45. // for enabling empty dates. You may set it like:
  46. // Array( '' => '-- choose --' ) and combine
  47. // the element with a date validation.
  48. var $yearfrom = false; // if ===false, will be set to current year in constructor
  49. var $yearuntil = 1900; // if ===false, will be set to current year in constructor
  50. // if $yearfrom is larger than $yearuntil, you'll get a
  51. // decrementing list of years, which is more natural to the users
  52. var $months = Array(
  53. 1 => CF_STR_MONTH_01, 2 => CF_STR_MONTH_02, 3 => CF_STR_MONTH_03, 4 => CF_STR_MONTH_04,
  54. 5 => CF_STR_MONTH_05, 6 => CF_STR_MONTH_06, 7 => CF_STR_MONTH_07, 8 => CF_STR_MONTH_08,
  55. 9 => CF_STR_MONTH_09, 10 => CF_STR_MONTH_10, 11 => CF_STR_MONTH_11, 12 => CF_STR_MONTH_12
  56. );
  57. // you'll find the months defined in messages_XX.php
  58. // You can still override the month array by
  59. // the 'months' setting of your element.
  60. var $onbeforechange;
  61. var $onafterchange;
  62. // should you need to update anything when the dropdowns change,
  63. // just include your JS code here (trailing ";" required)
  64. // private variables
  65. var $year = null;
  66. var $month = null;
  67. var $day = null;
  68. var $hour = null;
  69. var $min = null;
  70. var $sec = null;
  71. // --------------------------------------------------------------------------
  72. function selectDate( $name, $configvalues ) {
  73. $this->name = $name;
  74. foreach ( $configvalues as $key => $value )
  75. if ( $key != 'value' )
  76. $this->$key = $value;
  77. if ( $this->yearfrom === false )
  78. $this->yearfrom = date("Y");
  79. if ( $this->yearuntil === false )
  80. $this->yearuntil = date("Y");
  81. if ( isset( $configvalues['value'] ) )
  82. $this->setValue( $configvalues['value'], 0 );
  83. }
  84. // --------------------------------------------------------------------------
  85. function setValue( $value, $magic_quotes_gpc ) {
  86. // besides the date value, we also maintain
  87. // private variables - $year, $month, $day -
  88. // which are needed to reload the selects
  89. // with selected values
  90. $value = $this->_prepareInput( $value, $magic_quotes_gpc );
  91. // $this->value = $value;
  92. //
  93. // we don't set value unless it's a date than can
  94. // be processed by strtotime. setting value is done
  95. // by $this->createStoredFormat()
  96. if ( class_exists( 'DateTime' ) ) {
  97. // above PHP 5.2, we have the DateTime object
  98. // also supporting historical dates, and better
  99. // date support
  100. if ( preg_match( '/^([^\d]|0)+$/', $value ) )
  101. // 0000-00-00 type dates are convenient
  102. // database values instead of NULLs, which are
  103. // converted to Nov 30, -0001 by PHP, so we
  104. // need to have a workaround here instead.
  105. // It will never break date compatibility, as it's
  106. // a wrong date format (zero month and day).
  107. $time = false;
  108. else {
  109. $time = new DateTime( $value );
  110. if ( is_object( $time ) ) {
  111. $year = $time->format("Y");
  112. $month = $time->format("m");
  113. $day = $time->format("d");
  114. $hour = $time->format("H");
  115. $min = $time->format("i");
  116. $sec = $time->format("s");
  117. }
  118. }
  119. }
  120. else {
  121. $time = strtotime( $value );
  122. if ( $time ) {
  123. $year = date("Y", $time );
  124. $month = date("m", $time );
  125. $day = date("d", $time );
  126. $hour = date("H", $time );
  127. $min = date("i", $time );
  128. $sec = date("s", $time );
  129. }
  130. }
  131. if ( $time ) {
  132. // we now have valid time parts, but
  133. // are the values between yearfrom/yearuntil?
  134. return $this->createStoredFormat(
  135. $year, $month, $day, $hour, $min, $sec, 0
  136. );
  137. }
  138. else
  139. return false;
  140. }
  141. // --------------------------------------------------------------------------
  142. function getHTML() {
  143. $selects = Array();
  144. $years = $this->_createrange( $this->yearfrom, $this->yearuntil );
  145. $months = $this->months;
  146. $days = $this->_createrange( 1, 31 );
  147. $hours =
  148. $this->showpaddinghours ?
  149. $this->_createrange( 0, 23, '0', 2 ) :
  150. $this->_createrange( 0, 23 );
  151. $mins =
  152. $this->showpaddingmins ?
  153. $this->_createrange( 0, 59, '0', 2 ) :
  154. $this->_createrange( 0, 59 );
  155. $secs =
  156. $this->showpaddingsecs ?
  157. $this->_createrange( 0, 59, '0', 2 ) :
  158. $this->_createrange( 0, 59 );
  159. if ( is_array( $this->null ) && count( $this->null ) ) {
  160. $years = $this->null + $years;
  161. $months = $this->null + $months;
  162. $days = $this->null + $days;
  163. $hours = $this->null + $hours;
  164. $mins = $this->null + $mins;
  165. $secs = $this->null + $secs;
  166. }
  167. $parts['%Y'] = $this->makeSelect( $this->_getHTMLId() . 'year', $years, $this->year );
  168. $parts['%M'] = $this->makeSelect( $this->_getHTMLId() . 'month', $months, $this->month );
  169. $parts['%D'] = $this->makeSelect( $this->_getHTMLId() . 'day', $days, $this->day );
  170. $parts['%h'] = $this->makeSelect( $this->_getHTMLId() . 'hour', $hours, $this->hour );
  171. $parts['%m'] = $this->makeSelect( $this->_getHTMLId() . 'min', $mins, $this->min );
  172. $parts['%s'] = $this->makeSelect( $this->_getHTMLId() . 'sec', $secs, $this->sec );
  173. // $parts['%T'] = $this->makeInput( $this->_getHTMLId() . 'timeshort', $this->timeshort, 5 );
  174. $out = strtr( $this->layout, $parts );
  175. // the hidden input is a helper field containing
  176. // the current date in a 'compiled' form (according to
  177. // 'format' setting)
  178. return
  179. '<input type="hidden" ' . $this->html .
  180. ' id="' . $this->_getHTMLId() . '"' .
  181. ' value="' . $this->value . '"' .
  182. ' name="' . $this->name . '" />' . "\n" .
  183. $out . "\n"
  184. ;
  185. }
  186. // -------------------------------------------------------------------------
  187. function makeInput( $name, $value, $length ) {
  188. return
  189. '<input name="' . $name . '" id="' . $name . '" ' .
  190. 'maxlength="' . $length . '" size="' . $length . '" type="text" ' .
  191. 'value="' . htmlspecialchars( $value ) . '" ' .
  192. 'onchange="' . $this->onbeforechange . 'clonefishSelectDateStoredFormat( ' .
  193. 'document.forms[\'' . $this->form->name . '\'], ' .
  194. '\'' . $this->_getHTMLId() . '\', ' .
  195. '\'' . $this->format . '\', ' .
  196. '\'' . $this->padding . '\' ' .
  197. ');' . $this->onafterchange .
  198. "\" />\n";
  199. }
  200. // -------------------------------------------------------------------------
  201. function makeSelect( $name, $options, $value ) {
  202. $out = '';
  203. foreach ( $options as $key => $avalue ) {
  204. if ( (string)$key == (string)$value )
  205. $out .= '<option selected="selected" value="' .
  206. htmlspecialchars( $key ) .
  207. '">';
  208. else
  209. $out .= '<option value="' . htmlspecialchars( $key ) . '">';
  210. $out .= htmlspecialchars( $avalue ) . "</option>\n";
  211. }
  212. return
  213. "<select " .
  214. "onchange=\"" . $this->onbeforechange . "clonefishSelectDateStoredFormat( " .
  215. "document.forms['" . $this->form->name . "'], " .
  216. "'" . $this->_getHTMLId() . "', ".
  217. "'" . $this->format . "', ".
  218. "'" . $this->padding . "' ".
  219. ");" . $this->onafterchange .
  220. "\" name=\"" . $name . "\">\n" . $out . "</select>\n";
  221. }
  222. // -------------------------------------------------------------------------
  223. function createStoredFormat( $year, $month, $day, $hour, $min, $sec, $magic_quotes_gpc ) {
  224. // used by $clonefish->addElements(): the values of the received
  225. // date part selects are compiled also on the server side
  226. // to support server-side validation (we cannot rely purely on JS)
  227. //
  228. // also used by $this->setValue(): when a formatted date is
  229. // received, it's being split using strtotime(), and
  230. // the element value is set to the stored format, this
  231. // way we can always match with the format settings, even
  232. // when unnecessary date elements (eg. seconds) are
  233. // passed from a database query as a value.
  234. $year = $this->_prepareInput( $year, $magic_quotes_gpc );
  235. $month = $this->_prepareInput( $month, $magic_quotes_gpc );
  236. $day = $this->_prepareInput( $day, $magic_quotes_gpc );
  237. $hour = $this->_prepareInput( $hour, $magic_quotes_gpc );
  238. $min = $this->_prepareInput( $min, $magic_quotes_gpc );
  239. $sec = $this->_prepareInput( $sec, $magic_quotes_gpc );
  240. $partMap = Array(
  241. '%Y' => $year,
  242. '%M' => $month,
  243. '%D' => $day,
  244. '%h' => $hour,
  245. '%m' => $min,
  246. '%s' => $sec
  247. );
  248. $out = '';
  249. $isYearPresent = false;
  250. for ( $i = 0; $i < strlen( $this->format ); $i++ ) {
  251. $part = substr( $this->format, $i, 2 );
  252. switch ( $part ) {
  253. case '%Y':
  254. case '%M':
  255. case '%D':
  256. case '%h':
  257. case '%m':
  258. case '%s':
  259. if ( $part == '%Y' )
  260. $isYearPresent = true;
  261. // padding the appropriate date part
  262. // if it has length and padding is needed
  263. if (
  264. strlen( $partMap[ $part ] ) &&
  265. ( $this->padding || in_array( $part, Array( '%h', '%m', '%s' ) ) )
  266. ) {
  267. $padLength = 1;
  268. if ( $this->padding || in_array( $part, Array( '%h', '%m', '%s' ) ) )
  269. $padLength = $part == '%Y' ? 4 : 2;
  270. $value = str_pad( $partMap[ $part ], $padLength, '0', STR_PAD_LEFT );
  271. $out .= $value;
  272. // padded values back to properties
  273. switch ( $part ) {
  274. case '%h': $hour = $value; break;
  275. case '%m': $min = $value; break;
  276. case '%s': $sec = $value; break;
  277. }
  278. }
  279. else
  280. $out .= $partMap[ $part ];
  281. $i++; // skip another char in format string
  282. break;
  283. default:
  284. $out .= substr( $this->format, $i, 1 );
  285. break;
  286. }
  287. }
  288. $reverse = $this->yearfrom > $this->yearuntil;
  289. if (
  290. $isYearPresent &&
  291. (
  292. (
  293. ( $this->yearfrom !== false ) &&
  294. (
  295. ( !$reverse && ( $year < $this->yearfrom ) ) ||
  296. ( $reverse && ( $year > $this->yearfrom ) )
  297. )
  298. )
  299. ||
  300. (
  301. ( $this->yearuntil !== false ) &&
  302. (
  303. ( !$reverse && ( $year > $this->yearuntil ) ) ||
  304. ( $reverse && ( $year < $this->yearuntil ) )
  305. )
  306. )
  307. )
  308. ) {
  309. // invalid date passed, out of year range
  310. return false;
  311. }
  312. else {
  313. $this->value = $out;
  314. $this->year = $year;
  315. $this->month = $month;
  316. $this->day = $day;
  317. $this->hour = $hour;
  318. $this->min = $min;
  319. $this->sec = $sec;
  320. return true;
  321. }
  322. }
  323. // -------------------------------------------------------------------------
  324. function _createRange( $from, $until, $padchar = false, $padlength = false ) {
  325. $range = Array();
  326. for (
  327. $i = $from;
  328. $from < $until ? $i <= $until : $i >= $until;
  329. $from < $until ? $i++ : $i--
  330. ) {
  331. if ( is_string( $padchar ) && $padlength ) {
  332. $padded = (string) str_pad( $i, $padlength, $padchar, STR_PAD_LEFT );
  333. $range[ $padded ] = $padded;
  334. }
  335. else
  336. $range[ $i ] = $i;
  337. }
  338. return $range;
  339. }
  340. }
  341. ?>