PHPonTrax
[ class tree: PHPonTrax ] [ index: PHPonTrax ] [ all elements ]

Source for file date_helper.php

Documentation is available at date_helper.php

  1. <?php
  2. /**
  3. * File containing the DateHelper class and support functions
  4. *
  5. * (PHP 5)
  6. *
  7. * @package PHPonTrax
  8. * @version $Id$
  9. * @copyright (c) 2005 John Peterson
  10. *
  11. * Permission is hereby granted, free of charge, to any person obtaining
  12. * a copy of this software and associated documentation files (the
  13. * "Software"), to deal in the Software without restriction, including
  14. * without limitation the rights to use, copy, modify, merge, publish,
  15. * distribute, sublicense, and/or sell copies of the Software, and to
  16. * permit persons to whom the Software is furnished to do so, subject to
  17. * the following conditions:
  18. *
  19. * The above copyright notice and this permission notice shall be
  20. * included in all copies or substantial portions of the Software.
  21. *
  22. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  23. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  24. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  25. * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  26. * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  27. * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  28. * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  29. */
  30.  
  31. /**
  32. * Utility to help build HTML pulldown menus for date and time
  33. */
  34. class DateHelper extends Helpers {
  35.  
  36. /**
  37. * Year values parsed from $_REQUEST
  38. *
  39. * Set by {@link check_request_for_value()}. An array whose keys
  40. * are the names of attributes of the {@link ActiveRecord}
  41. * subclass named by {@link $object_name}, and whose values are
  42. * the strings parsed from $_REQUEST.
  43. * @var string[]
  44. */
  45. public $request_years;
  46.  
  47. /**
  48. * Month values parsed from $_REQUEST
  49. *
  50. * Set by {@link check_request_for_value()}. An array whose keys
  51. * are the names of attributes of the {@link ActiveRecord}
  52. * subclass named by {@link $object_name}, and whose values are
  53. * the strings parsed from $_REQUEST.
  54. * @var string[]
  55. */
  56. public $request_months = array();
  57.  
  58. /**
  59. * Day of month values parsed from $_REQUEST
  60. *
  61. * Set by {@link check_request_for_value()}. An array whose keys
  62. * are the names of attributes of the {@link ActiveRecord}
  63. * subclass named by {@link $object_name}, and whose values are
  64. * the strings parsed from $_REQUEST.
  65. * @var string[]
  66. */
  67. public $request_days;
  68.  
  69. /**
  70. * Hour values parsed from $_REQUEST
  71. *
  72. * Set by {@link check_request_for_value()}. An array whose keys
  73. * are the names of attributes of the {@link ActiveRecord}
  74. * subclass named by {@link $object_name}, and whose values are
  75. * the strings parsed from $_REQUEST.
  76. * @var string[]
  77. */
  78. public $request_hours;
  79.  
  80. /**
  81. * Minute values parsed from $_REQUEST
  82. *
  83. * Set by {@link check_request_for_value()}. An array whose keys
  84. * are the names of attributes of the {@link ActiveRecord}
  85. * subclass named by {@link $object_name}, and whose values are
  86. * the strings parsed from $_REQUEST.
  87. * @var string[]
  88. */
  89. public $request_minutes;
  90.  
  91. /**
  92. * Second values parsed from $_REQUEST
  93. *
  94. * Set by {@link check_request_for_value()}. An array whose keys
  95. * are the names of attributes of the {@link ActiveRecord}
  96. * subclass named by {@link $object_name}, and whose values are
  97. * the strings parsed from $_REQUEST.
  98. * @var string[]
  99. */
  100. public $request_seconds;
  101.  
  102. /**
  103. * <b>FIXME:</b> Dead code?
  104. */
  105. public $selected_years = array();
  106.  
  107. /**
  108. * Constructor
  109. *
  110. * Construct an instance of Helpers with the same arguments
  111. * @param string Name of an ActiveRecord subclass
  112. * @param string Name of an attribute of $object
  113. */
  114. function __construct($object_name = null, $attribute_name = null) {
  115. parent::__construct($object_name, $attribute_name);
  116. }
  117. /**
  118. * Check whether $_REQUEST holds value for this attribute
  119. *
  120. * Called with the name of an ActiveRecord subclass in
  121. * $this->object_name and the name of one of its attributes in
  122. * $this->attribute_name. Check whether $_REQUEST contains a
  123. * value for this attribute; if so return it.
  124. * @return mixed String value if attribute was found in
  125. * $_REQUEST, otherwise false
  126. * @uses attribute_name
  127. * @uses object_name
  128. * @uses request_years
  129. * @uses request_months
  130. * @uses request_days
  131. * @uses request_hours
  132. * @uses request_minutes
  133. * @uses request_seconds
  134. */
  135. private function check_request_for_value() {
  136. //error_log("check_request_for_value(). object name='"
  137. // . $this->object_name ."' attribute name = '"
  138. // . $this->attribute_name ."'");
  139.  
  140. // If $_REQUEST[$this->object_name] does not exist,
  141. // return false immediately
  142. if (!isset($_REQUEST) || !is_array($_REQUEST)
  143. || !array_key_exists($this->object_name, $_REQUEST)) {
  144. return false;
  145. }
  146.  
  147. // $_REQUEST[$this->object_name] exists.
  148. // Look for the requested attribute
  149. if (array_key_exists($this->attribute_name,
  150. $_REQUEST[$this->object_name])) {
  151.  
  152. // Requested attribute found, return it
  153. return $_REQUEST[$this->object_name][$this->attribute_name];
  154. }
  155.  
  156. // There is an element $_REQUEST[$this->object_name] but not
  157. // $_REQUEST[$this->object_name][$this->attribute_name] so
  158. // check for the individual components of a date/time
  159.  
  160. // Keep track of whether we find any components
  161. $found = false;
  162.  
  163. // Check for year component
  164. if (array_key_exists($this->attribute_name."(1i)",
  165. $_REQUEST[$this->object_name])) {
  166. $this->request_years[$this->attribute_name] =
  167. $_REQUEST[$this->object_name][$this->attribute_name."(1i)"];
  168. $found = true;
  169. }
  170.  
  171. // Check for month component
  172. if (array_key_exists($this->attribute_name."(2i)",
  173. $_REQUEST[$this->object_name])) {
  174. $this->request_months[$this->attribute_name] =
  175. $_REQUEST[$this->object_name][$this->attribute_name."(2i)"];
  176. $found = true;
  177. }
  178.  
  179. // Check for day component
  180. if (array_key_exists($this->attribute_name."(3i)",
  181. $_REQUEST[$this->object_name])) {
  182. $this->request_days[$this->attribute_name] =
  183. $_REQUEST[$this->object_name][$this->attribute_name."(3i)"];
  184. $found = true;
  185. }
  186.  
  187. // Check for hour component
  188. if (array_key_exists($this->attribute_name."(4i)",
  189. $_REQUEST[$this->object_name])) {
  190. $this->request_hours[$this->attribute_name] =
  191. $_REQUEST[$this->object_name][$this->attribute_name."(4i)"];
  192. $found = true;
  193. }
  194.  
  195. // Check for minute component
  196. if (array_key_exists($this->attribute_name."(5i)",
  197. $_REQUEST[$this->object_name])) {
  198. $this->request_minutes[$this->attribute_name] =
  199. $_REQUEST[$this->object_name][$this->attribute_name."(5i)"];
  200. $found = true;
  201. }
  202.  
  203. // Check for second component
  204. if (array_key_exists($this->attribute_name."(6i)",
  205. $_REQUEST[$this->object_name])) {
  206. $this->request_seconds[$this->attribute_name] =
  207. $_REQUEST[$this->object_name][$this->attribute_name."(6i)"];
  208. $found = true;
  209. }
  210. return $found;
  211. }
  212.  
  213. /**
  214. * Generate HTML/XML for select to enclose option list
  215. *
  216. * @param string Name attribute for <samp><select name=... ></samp>
  217. * @param string <samp><option>...</option><samp> list
  218. * @param string Prefix of name attribute, to be enclosed in
  219. * square brackets
  220. * @param boolean Whether to include a blank in the list of
  221. * select options
  222. * @param boolean Whether to discard the type
  223. * @return string Generated HTML
  224. */
  225. private function select_html($type, $options, $prefix = null,
  226. $include_blank = false,
  227. $discard_type = false) {
  228. $select_html = "<select name=\"$prefix";
  229. if(!$discard_type) {
  230. if($prefix) $select_html .= "[";
  231. $select_html .= $type;
  232. if($prefix) $select_html .= "]";
  233. }
  234. $select_html .= "\">\n";
  235. if($include_blank) $select_html .= "<option value=\"\"></option>\n";
  236. $select_html .= $options;
  237. $select_html .= "</select>\n";
  238. return $select_html;
  239. }
  240.  
  241. /**
  242. * Prefix a leading zero to single digit numbers
  243. * @param string A number
  244. * @return string Number with zero prefix if value <= 9
  245. */
  246. private function leading_zero_on_single_digits($number) {
  247. return $number > 9 ? $number : "0$number";
  248. }
  249.  
  250. /**
  251. * Get attribute value from $_REQUEST if there, otherwise from database
  252. *
  253. * When called, {@link $object_name} describes the
  254. * {@link ActiveRecord} subclass and {@link $attribute_name}
  255. * describes the attribute whose value is desired.
  256. *
  257. * An attempt is made to find the value in $_REQUEST, where it
  258. * would be found after the browser POSTed a form. If no value
  259. * is found there, then the database is accessed for the value.
  260. * When accessing the database, the assumption is made that the
  261. * {@link ActionController} object refers to a single
  262. * {@link ActiveRecord} subclass object which correctly
  263. * identifies the table and record containing the attribute
  264. * value.
  265. * @return mixed Attribute value if found
  266. * @uses check_request_for_value()
  267. * @uses attribute_name
  268. * @uses object()
  269. * @uses ActiveRecord::send()
  270. */
  271. protected function value() {
  272. //error_log("DateHelper::value() object name={$this->object_name}"
  273. // . " attribute name={$this->attribute_name}");
  274.  
  275. // First try to get attribute value from $_REQUEST
  276. if(!$value = $this->check_request_for_value()) {
  277.  
  278. // Value not found in $_REQUEST so we need to
  279. // go to the database. Assume that the controller
  280. // points to the right ActiveRecord object
  281. $object = $this->object();
  282. if(is_object($object) && $this->attribute_name) {
  283. $value = $object->send($this->attribute_name);
  284. }
  285. }
  286. return $value;
  287. }
  288. /**
  289. * Call to_expiration_date_select_tag()
  290. *
  291. * Alias for {@link to_expiration_date_select_tag()}
  292. * @param mixed[] Output format options
  293. * @return string Generated HTML
  294. * @uses to_expiration_date_select_tag()
  295. */
  296. function expiration_date_select($options = array()) {
  297. return $this->to_expiration_date_select_tag($options);
  298. }
  299. /**
  300. * Call to_datetime_select_tag()
  301. *
  302. * Alias for {@link to_datetime_select_tag()}
  303. * @param mixed[] Output format options
  304. * @return string Generated HTML
  305. * @uses to_datetime_select_tag()
  306. */
  307. function datetime_select($options = array()) {
  308. return $this->to_datetime_select_tag($options);
  309. }
  310. /**
  311. * Call to_date_select_tag()
  312. *
  313. * Alias for {@link to_date_select_tag()}
  314. * @param mixed[] Output format options
  315. * @return string Generated HTML
  316. * @uses to_date_select_tag()
  317. */
  318. function date_select($options = array()) {
  319. //error_log("date_select() object=$this->object_name"
  320. // . " attribute=$this->attribute_name");
  321. return $this->to_date_select_tag($options);
  322. }
  323. /**
  324. * Generate HTML/XML for expiration month and year selector
  325. * pulldowns
  326. *
  327. * Generates HTML for a month and year pulldown. The year
  328. * pulldown has a range of years from the initially selected year
  329. * to seven years after.
  330. *
  331. * When called, $_REQUEST[] may have initial date values in
  332. * fields with default names of 'expiration_month' and
  333. * 'expiration_year'. If these values exist they override the
  334. * first parameter.
  335. * @param string Date to display as initially selected if none
  336. * was found in $_REQUEST[]. If omitted, default value is the
  337. * current calendar date.<b>FIXME:</b> this doesn't work
  338. * @param mixed[] Output format options:
  339. * <ul>
  340. * <li><samp>'field_separator' => '</samp><i>somestring</i><samp>'</samp><br />
  341. * String to insert between the month and year selectors. If
  342. * none is specified, default value is <samp>' / '</samp></li>
  343. * <li><samp>'month_before_year' => 'false'<br />
  344. * Output year selector first, then month selector.
  345. * If option not specified, the month selector will be output
  346. * first.</li>
  347. * <li><samp>'month_name' =>'</samp><i>somestring</i><samp>'</samp><br />
  348. * Set the name of the generated month selector to
  349. * <i>somestring</i>. If option not specified, default name is
  350. * <samp>expiration_month</samp></li>
  351. * <li><samp>'year_name' => '</samp><i>somestring</i><samp>'</samp><br />
  352. * Set the name of the generated year selector to
  353. * <i>somestring</i>. If option not specified, default name is
  354. * <samp>expiration_year</samp></li>
  355. * </ul>
  356. * @return string Generated HTML
  357. * @uses select_html()
  358. * @uses select_month()
  359. * @uses select_year()
  360. */
  361. function select_expiration_date($date = null, $options = array()) {
  362. // error_log("select_expiration_date('"
  363. // . (is_null($date) ? 'null' : $date)
  364. // ."', " . var_export($options,true));
  365. $options['month_before_year'] = true;
  366. $options['use_month_numbers'] = true;
  367. $options['start_year'] = date("Y");
  368. $options['end_year'] = date("Y") + 7;
  369. $options['field_separator'] = " / ";
  370.  
  371. // Find name and initial value of year field,
  372. // then generate year selector pulldown
  373. $options['field_name'] = array_key_exists('year_name',$options)
  374. ? $options['year_name'] : "expiration_year";
  375. $date = array_key_exists($options['field_name'], $_REQUEST)
  376. ? date("Y-m-d",
  377. strtotime($_REQUEST[$options['field_name']]."-01-01"))
  378. : date("Y-m-d");
  379. $year_select = $this->select_year($date, $options);
  380.  
  381. // Find name and initial value of month field,
  382. // then generate year selector pulldown
  383. $options['field_name'] = array_key_exists('month_name',$options)
  384. ? $options['month_name'] : "expiration_month";
  385. $date = array_key_exists($options['field_name'], $_REQUEST)
  386. ? date("Y-m-d",
  387. strtotime("2006-".$_REQUEST[$options['field_name']]."-01"))
  388. : date("Y-m-d");
  389. $month_select = $this->select_month($date, $options);
  390.  
  391. // Output month and year selectors in desired order
  392. if($options['month_before_year']) {
  393. $select_html = $month_select . $options['field_separator']
  394. . $year_select;
  395. } else {
  396. $select_html = $year_select . $options['field_separator']
  397. . $month_select;
  398. }
  399. return $select_html;
  400. }
  401.  
  402. /**
  403. * Generate HTML/XML for year, month and day selector pull-down menus
  404. *
  405. * Returns <samp><select>...</select></samp> HTML with options
  406. * for a number of years, months and days. The first argument,
  407. * if present, specifies the initially selected date. The second
  408. * argument controls the format of the generated HTML.
  409. *
  410. * Examples:
  411. * <ul>
  412. * <li><samp>select_date();</samp><br /> Generates a group of
  413. * three pulldown menus in the order year, month and day with
  414. * the current date initially selected.</li>
  415. * <li>
  416. * <samp>select_date('August 4, 1998');</samp><br /> Generates a
  417. * group of three pulldown menus in the order year, month and
  418. * day with the date August 4, 1998 initially selected.</li>
  419. * </ul>
  420. *
  421. * @param string Date to display as initially selected if none
  422. * was found in
  423. * {@link $request_years}[{@link $attribute_name}],
  424. * {@link $request_months}[{@link $attribute_name}] and
  425. * {@link $request_days}[{@link $attribute_name}].
  426. * Character string is any US English date representation
  427. * supported by {@link strtotime()}. If omitted, the
  428. * current date is initially selected.
  429. *
  430. * @param mixed[] Output format options are all of the options of
  431. * {@link select_year()}, {@link select_month()} and
  432. * {@link select_day()}.
  433. * @return string Generated HTML
  434. * @uses select_day()
  435. * @uses select_month()
  436. * @uses select_year()
  437. */
  438. function select_date($date = null, $options = array()) {
  439. $date = is_null($date) ? date("Y-m-d") : $date;
  440. return $this->select_year($date, $options) .
  441. $this->select_month($date, $options) .
  442. $this->select_day($date, $options);
  443. }
  444.  
  445. /**
  446. * Generate HTML/XML for year-month-day-hour-minute selector pulldowns
  447. *
  448. * Returns <samp><select>...</select></samp> HTML with options
  449. * for a number of years, months, days, hours and minutes. The
  450. * first argument, if present, specifies the initially selected
  451. * date. The second argument controls the format of the
  452. * generated HTML.
  453. *
  454. * Examples:
  455. * <ul>
  456. * <li><samp>select_datetime();</samp><br /> Generates a group of
  457. * five pulldown menus in the order year, month, day, hour and
  458. * minute with the current date and time initially
  459. * selected.</li>
  460. * <li>
  461. * <samp>select_datetime('1998-04-08 13:21:17');</samp><br />
  462. * Generates a group of five pulldown menus in the order year,
  463. * month, day, hour and minute with the date/time
  464. * 1998 August 4 13:21 initially selected.</li>
  465. * </ul>
  466. *
  467. * @param string Date/time to display as initially selected.
  468. * Character string is any US English date representation
  469. * supported by {@link strtotime()}. If omitted, the
  470. * current date/time is initially selected.
  471. *
  472. * @param mixed[] Output format options are all of the options of
  473. * {@link select_year()}, {@link select_month()},
  474. * {@link select_day()}, {@link select_hour()} and
  475. * {@link select_minute()}.
  476. * @return string Generated HTML
  477. * @uses select_day()
  478. * @uses select_hour()
  479. * @uses select_minute()
  480. * @uses select_month()
  481. * @uses select_year()
  482. */
  483. function select_datetime($datetime = null, $options = array()) {
  484. $datetime = is_null($datetime) ? date("Y-m-d H:i:s") : $datetime;
  485. return $this->select_year($datetime, $options) .
  486. $this->select_month($datetime, $options) .
  487. $this->select_day($datetime, $options) .
  488. $this->select_hour($datetime, $options) .
  489. $this->select_minute($datetime, $options);
  490. }
  491.  
  492. /**
  493. * Generate HTML/XML for hour, minute and second selector pull-down menus
  494. *
  495. * Returns <samp><select>...</select></samp> HTML with options
  496. * for a number of hours, minutes and seconds. The first argument,
  497. * if present, specifies the initially selected time. The second
  498. * argument controls the format of the generated HTML.
  499. *
  500. * Examples:
  501. * <ul>
  502. * <li><samp>select_time();</samp><br /> Generates two pulldown
  503. * menus in the order hour : minute with
  504. * the current time initially selected.</li>
  505. * <li>
  506. * <samp>select_time('August 4, 1998 8:12');</samp><br /> Generates
  507. * two pulldown menus in the order hour : minute with the
  508. * time 8:12 initially selected.</li>
  509. * </ul>
  510. *
  511. * @param string Time to display as initially selected if none
  512. * was found in
  513. * {@link $request_hours}[{@link $attribute_name}],
  514. * {@link $request_minutes}[{@link $attribute_name}] and
  515. * {@link $request_seconds}[{@link $attribute_name}].
  516. * Character string is any US English date/time representation
  517. * supported by {@link strtotime()}. If omitted, the
  518. * current time is initially selected.
  519. *
  520. * @param mixed[] Output format options are all of the options of
  521. * {@link select_hour()}, {@link select_minute()} and
  522. * {@link select_second()}.
  523. * @return string Generated HTML
  524. * @uses select_hour()
  525. * @uses select_minute()
  526. * @uses select_second()
  527. */
  528. function select_time($datetime = null, $options = array()) {
  529. $datetime = is_null($datetime) ? date("Y-m-d H:i:s") : $datetime;
  530. return $this->select_hour($datetime, $options) .
  531. $this->select_minute($datetime, $options) .
  532. (array_key_exists('include_seconds', $options)
  533. && $options['include_seconds']
  534. ? $this->select_second($datetime, $options) : '');
  535. }
  536.  
  537. /**
  538. * Generate HTML/XML for second selector pull-down menu
  539. *
  540. * Returns <samp><select>...</select></samp> HTML with an option
  541. * for each of the sixty seconds. The first argument, if
  542. * present, specifies the initially selected second. The second
  543. * argument controls the format of the generated HTML.
  544. *
  545. * Examples:
  546. * <ul>
  547. * <li><samp>select_second();</samp><br />
  548. * Generates menu '00', '01', ..., '59'. Initially selected
  549. * second is the second in
  550. * {@link $request_seconds}[{@link $attribute_name}], or if that
  551. * is not defined, the current second.</li>
  552. * <li><samp>select_second(null,array('include_blank' => true));</samp>
  553. * <br />Generates menu ' ', '00', '01',..., '59'. Initially
  554. * selected second same as above.</li>
  555. * </ul>
  556. *
  557. * @param string Initially selected second as two-digit number.
  558. * If a value for this field is specified in
  559. * {@link $request_seconds}[{@link $attribute_name}], then that second
  560. * is initially selected regardless of the value of this argument.
  561. * Otherwise, if the first argument is present and is a character
  562. * string of two decimal digits with a value in the range
  563. * '00'..'59' then that second is initially selected. If this
  564. * argument is absent or invalid, the current second is
  565. * initially selected.
  566. * @param mixed[] Output format options:
  567. * <ul>
  568. * <li><samp>'include_blank' => true</samp> Show a blank
  569. * as the first option.</li>
  570. * <li><samp>'field_name' => '</samp><i>somestring</i><samp>'</samp>
  571. * Generate output<br />
  572. * <samp><select name="</samp><i>somestring</i><samp>">...</select></samp> .
  573. * <br />If absent, generate output<br />
  574. * <samp><select name="second">...</select></samp>.</li>
  575. * <li><samp>'discard_type' => ???</samp> FIXME</li>
  576. * <li><samp>'prefix' => ???</samp> FIXME</li>
  577. * </ul>
  578. *
  579. * @return string Generated HTML
  580. * @uses attribute_name
  581. * @uses leading_zero_on_single_digits()
  582. * @uses request_seconds
  583. * @uses select_html()
  584. */
  585. function select_second($datetime=null, $options = array()) {
  586. //error_log("select_second() \$datetime=$datetime \$options="
  587. // .var_export($options,true));
  588. $second_options = "";
  589. if($this->request_seconds[$this->attribute_name]) {
  590. $datetime_sec = $this->request_seconds[$this->attribute_name];
  591. } elseif(strlen($datetime) == 2 && is_numeric($datetime)) {
  592. $datetime_sec = $datetime;
  593. } else {
  594. $datetime = $datetime ? $datetime : date("Y-m-d H:i:s");
  595. $datetime_sec = date("s",strtotime($datetime));
  596. }
  597. for($second = 0; $second <= 59; $second++) {
  598. $second_options .= ($datetime && ($datetime_sec == $second)) ?
  599. "<option value=\"".$this->leading_zero_on_single_digits($second)."\" selected=\"selected\">".$this->leading_zero_on_single_digits($second)."</option>\n" :
  600. "<option value=\"".$this->leading_zero_on_single_digits($second)."\">".$this->leading_zero_on_single_digits($second)."</option>\n";
  601. }
  602. $field_name = array_key_exists('field_name',$options)
  603. ? $options['field_name'] : 'second';
  604. return $this->select_html($field_name, $second_options,
  605. array_key_exists('prefix',$options)
  606. ? $options['prefix'] : null,
  607. array_key_exists('include_blank',$options)
  608. ? $options['include_blank'] : false,
  609. array_key_exists('discard_type',$options)
  610. ? $options['discard_type'] : false);
  611. }
  612.  
  613. /**
  614. * Generate HTML/XML for minute selector pull-down menu
  615. *
  616. * Returns <samp><select>...</select></samp> HTML with an option
  617. * for each of the sixty minutes. The first argument, if
  618. * present, specifies the initially selected minute. The second
  619. * argument controls the format of the generated HTML.
  620. *
  621. * Examples:
  622. * <ul>
  623. * <li><samp>select_minute();</samp><br />
  624. * Generates menu '00', '01', ..., '59'. Initially selected
  625. * minute is the minute in
  626. * {@link $request_minutes}[{@link $attribute_name}], or if that
  627. * is not defined, the current minute.</li>
  628. * <li><samp>select_minute(null,array('include_blank' => true));</samp>
  629. * <br />Generates menu ' ', '00', '01',..., '59'. Initially
  630. * selected minute same as above.</li>
  631. * </ul>
  632. *
  633. * @param string Initially selected minute as two-digit number.
  634. * If a value for this field is specified in
  635. * {@link $request_minutes}[{@link $attribute_name}], then that minute
  636. * is initially selected regardless of the value of this argument.
  637. * Otherwise, if the first argument is present and is a character
  638. * string of two decimal digits with a value in the range
  639. * '00'..'59' then that minute is initially selected. If this
  640. * argument is absent or invalid, the current minute is
  641. * initially selected.
  642. * @param mixed[] Output format options:
  643. * <ul>
  644. * <li><samp>'include_blank' => true</samp> Show a blank
  645. * as the first option.</li>
  646. * <li><samp>'field_name' => '</samp><i>somestring</i><samp>'</samp>
  647. * Generate output<br />
  648. * <samp><select name="</samp><i>somestring</i><samp>">...</select></samp> .
  649. * <br />If absent, generate output<br />
  650. * <samp><select name="minute">...</select></samp>.</li>
  651. * <li><samp>'discard_type' => ???</samp> FIXME</li>
  652. * <li><samp>'prefix' => ???</samp> FIXME</li>
  653. * </ul>
  654. *
  655. * @return string Generated HTML
  656. * @uses attribute_name
  657. * @uses leading_zero_on_single_digits()
  658. * @uses request_minutes
  659. * @uses select_html()
  660. */
  661. function select_minute($datetime=null, $options = array()) {
  662. $minute_options = "";
  663. if($this->request_minutes[$this->attribute_name]) {
  664. $datetime_min = $this->request_minutes[$this->attribute_name];
  665. } elseif(strlen($datetime) == 2 && is_numeric($datetime)) {
  666. $datetime_min = $datetime;
  667. } else {
  668. $datetime = $datetime ? $datetime : date("Y-m-d H:i:s");
  669. $datetime_min = date("i",strtotime($datetime));
  670. }
  671. for($minute = 0; $minute <= 59; $minute++) {
  672. $minute_options .= ($datetime && ($datetime_min == $minute)) ?
  673. "<option value=\"".$this->leading_zero_on_single_digits($minute)."\" selected=\"selected\">".$this->leading_zero_on_single_digits($minute)."</option>\n" :
  674. "<option value=\"".$this->leading_zero_on_single_digits($minute)."\">".$this->leading_zero_on_single_digits($minute)."</option>\n";
  675. }
  676. $field_name = array_key_exists('field_name', $options)
  677. ? $options['field_name'] : 'minute';
  678. return $this->select_html($field_name, $minute_options,
  679. array_key_exists('prefix', $options)
  680. ? $options['prefix'] : null,
  681. array_key_exists('include_blank', $options)
  682. ? $options['include_blank'] : false,
  683. array_key_exists('discard_type', $options)
  684. ? $options['discard_type'] : false);
  685. }
  686.  
  687. /**
  688. * Generate HTML/XML for hour selector pull-down menu
  689. *
  690. * Returns <samp><select>...</select></samp> HTML with an option
  691. * for each of the twenty-four hours. The first argument, if
  692. * present, specifies the initially selected hour. The second
  693. * argument controls the format of the generated HTML.
  694. *
  695. * Examples:
  696. * <ul>
  697. * <li><samp>select_hour();</samp><br />
  698. * Generates menu '00', '01', ..., '23'. Initially selected
  699. * hour is the hour in
  700. * {@link $request_hours}[{@link $attribute_name}], or if that
  701. * is not defined, the current hour.</li>
  702. * <li><samp>select_hour(null,array('include_blank' => true));</samp>
  703. * <br />Generates menu ' ', '00', '01',..., '23'. Initially
  704. * selected hour same as above.</li>
  705. * </ul>
  706. *
  707. * @param string Initially selected hour as two-digit number.
  708. * If a value for this field is specified in
  709. * {@link $request_hours}[{@link $attribute_name}], then that hour
  710. * is initially selected regardless of the value of this argument.
  711. * Otherwise, if the first argument is present and is a character
  712. * string of two decimal digits with a value in the range
  713. * '00'..'23' then that hour is initially selected. If this
  714. * argument is absent or invalid, the current hour is
  715. * initially selected.
  716. * @param mixed[] Output format options:
  717. * <ul>
  718. * <li><samp>'include_blank' => true</samp> Show a blank
  719. * as the first option.</li>
  720. * <li><samp>'field_name' => '</samp><i>somestring</i><samp>'</samp>
  721. * Generate output<br />
  722. * <samp><select name="</samp><i>somestring</i><samp>">...</select></samp> .
  723. * <br />If absent, generate output<br />
  724. * <samp><select name="hour">...</select></samp>.</li>
  725. * <li><samp>'discard_type' => ???</samp> FIXME</li>
  726. * <li><samp>'prefix' => ???</samp> FIXME</li>
  727. * </ul>
  728. *
  729. * @return string Generated HTML
  730. * @uses attribute_name
  731. * @uses leading_zero_on_single_digits()
  732. * @uses request_hours
  733. * @uses select_html()
  734. */
  735. function select_hour($datetime=null, $options = array()) {
  736. //error_log("DateTime::select_hour() \$datetime=$datetime \$options="
  737. // .var_export($options,true));
  738. $hour_options = "";
  739. // If a value for this attribute was parsed from $_REQUEST,
  740. // use it as initially selected and ignore first argument
  741. if($this->request_hours[$this->attribute_name]) {
  742. $datetime_hour = $this->request_hours[$this->attribute_name];
  743. }
  744.  
  745. // No value in $_REQUEST so look at the first argument.
  746. // If it is valid use it as initially selected
  747. elseif(strlen($datetime) == 2 && is_numeric($datetime)) {
  748. $datetime_hour = $datetime;
  749. }
  750.  
  751. // First argument is missing or invalid,
  752. // initially select current hour
  753. else {
  754. $datetime = $datetime ? $datetime : date("Y-m-d H:i:s");
  755. $datetime_hour = date("H",strtotime($datetime));
  756. }
  757.  
  758. // Generate <option>...</option> HTML for each hour
  759. for($hour = 0; $hour <= 23; $hour++) {
  760. $hour_options .= ($datetime && ($datetime_hour == $hour)) ?
  761. "<option value=\"".$this->leading_zero_on_single_digits($hour)."\" selected=\"selected\">".$this->leading_zero_on_single_digits($hour)."</option>\n" :
  762. "<option value=\"".$this->leading_zero_on_single_digits($hour)."\">".$this->leading_zero_on_single_digits($hour)."</option>\n";
  763. }
  764.  
  765. // Return finished HTML
  766. $field_name = array_key_exists('field_name', $options)
  767. ? $options['field_name'] : 'hour';
  768. return $this->select_html($field_name, $hour_options,
  769. array_key_exists('prefix', $options)
  770. ? $options['prefix'] : null,
  771. array_key_exists('include_blank', $options)
  772. ? $options['include_blank'] : false,
  773. array_key_exists('discard_type', $options)
  774. ? $options['discard_type'] : false);
  775. }
  776.  
  777. /**
  778. * Generate HTML/XML for day selector pull-down menu
  779. *
  780. * Returns <samp><select>...</select></samp> HTML with an option
  781. * for each of the thirty-one days. The first argument, if
  782. * present, specifies the initially selected day. The second
  783. * argument controls the format of the generated HTML.
  784. *
  785. *
  786. * Examples:
  787. * <ul>
  788. * <li><samp>select_day();</samp><br />
  789. * Generates menu '01', '02', ..., '31'. Initially selected
  790. * day is the day in
  791. * {@link $request_days}[{@link $attribute_name}], or if that
  792. * is not defined, the current calendar day.</li>
  793. * <li><samp>select_day(null,array('include_blank' => true));</samp>
  794. * <br />Generates menu ' ', '01', '02',..., '31'. Initially
  795. * selected day same as above.</li>
  796. * </ul>
  797. *
  798. * @param string Initially selected day as two-digit number.
  799. * If a value for this field is specified in
  800. * {@link $request_days}[{@link $attribute_name}], then that day
  801. * is initially selected regardless of the value of this argument.
  802. * Otherwise, if the first argument is present and is a character
  803. * string of two decimal digits with a value in the range
  804. * '01'..'31' then that day is initially selected. Otherwise, if
  805. * the first argument is a date in some US English date format,
  806. * the day of the month from that date is initially selected. If
  807. * this argument is absent or invalid, the current calendar day
  808. * is initially selected.
  809. * @param mixed[] Output format options:
  810. * <ul>
  811. * <li><samp>'include_blank' => true</samp> Show a blank
  812. * as the first option.</li>
  813. * <li><samp>'field_name' => '</samp><i>somestring</i><samp>'</samp>
  814. * Generate output<br />
  815. * <samp><select name="</samp><i>somestring</i><samp>">...</select></samp> .
  816. * <br />If absent, generate output<br />
  817. * <samp><select name="day">...</select></samp>.</li>
  818. * <li><samp>'discard_type' => ???</samp> FIXME</li>
  819. * <li><samp>'prefix' => ???</samp> FIXME</li>
  820. * </ul>
  821. *
  822. * @return string Generated HTML
  823. * @uses attribute_name
  824. * @uses leading_zero_on_single_digits()
  825. * @uses request_days
  826. * @uses select_html()
  827. */
  828. function select_day($datetime=null, $options = array()) {
  829. $day_options = "";
  830. // If a value for this attribute was parsed from $_REQUEST,
  831. // use it as initially selected and ignore first argument
  832. if($this->request_days[$this->attribute_name]) {
  833. $datetime_day = $this->request_days[$this->attribute_name];
  834. }
  835.  
  836. // No value in $_REQUEST so look at the first argument.
  837. // If it is valid use it as initially selected
  838. elseif(strlen($datetime) == 2 && is_numeric($datetime)) {
  839. $datetime_day = $datetime;
  840. }
  841.  
  842. // First argument is missing or invalid,
  843. // initially select current day
  844. else {
  845. $datetime = $datetime ? $datetime : date("Y-m-d H:i:s");
  846. $datetime_day = date("d",strtotime($datetime));
  847. }
  848. // Generate <option>...</option> HTML for each day
  849. for($day = 1; $day <= 31; $day++) {
  850. $day_options .= ($datetime && ($datetime_day == $day)) ?
  851. "<option value=\"".$this->leading_zero_on_single_digits($day)."\" selected=\"selected\">".$this->leading_zero_on_single_digits($day)."</option>\n" :
  852. "<option value=\"".$this->leading_zero_on_single_digits($day)."\">".$this->leading_zero_on_single_digits($day)."</option>\n";
  853. }
  854.  
  855. // Return finished HTML
  856. $field_name = array_key_exists('field_name', $options)
  857. ? $options['field_name'] : 'day';
  858. return $this->select_html($field_name, $day_options,
  859. array_key_exists('prefix',$options)
  860. ? $options['prefix'] : null,
  861. array_key_exists('include_blank', $options)
  862. ? $options['include_blank'] : false,
  863. array_key_exists('discard_type', $options)
  864. ? $options['discard_type'] : false);
  865. }
  866.  
  867. /**
  868. * Generate HTML/XML for month selector pull-down menu
  869. *
  870. * Returns <samp><select>...</select></samp> HTML with an option
  871. * for each of the twelve months. The first argument, if
  872. * present, specifies the initially selected month. The second
  873. * argument controls the format of the generated HTML.
  874. *
  875. *
  876. * Examples:
  877. * <ul>
  878. * <li><samp>select_month();</samp> Generates menu January,
  879. * February etc.</li>
  880. * <li><samp>select_month(null,array('use_month_number' => true));</samp>
  881. * Generates menu 1, 2 etc.</li>
  882. * <li><samp>select_month(null,array('add_month_number' => true));</samp>
  883. * Generates menu 1 - January, 2 - February etc.</li>
  884. * </ul>
  885. *
  886. * @param string Initially selected month as two-digit number.
  887. * If a value for this field is specified in
  888. * {@link $request_months}[{@link $attribute_name}], then that month
  889. * is initially selected regardless of the value of this argument.
  890. * Otherwise, if the first argument is present and is a character
  891. * string of two decimal digits with a value in the range
  892. * '01'..'12' then that month is initially selected. Otherwise,
  893. * if the first argument is a date in some US English date
  894. * format, the month from that date is initially selected. If
  895. * this argument is absent or invalid, the current calendar month
  896. * is initially selected.
  897. * @param mixed[] Output format options:
  898. * <ul>
  899. * <li><samp>'include_blank' => true</samp> Show a blank
  900. * as the first option.</li>
  901. * <li><samp>'use_month_number' => true</samp> Show months in
  902. * the menu by their month number (1, 2 ...). Default is to
  903. * show English month name (January, February ...).</li>
  904. * <li><samp>'add_month_number' => true</samp> Show both month
  905. * number and month name in the menu.</li>
  906. * <li><samp>'field_name' => '</samp><i>somestring</i><samp>'</samp>
  907. * Generate output<br />
  908. * <samp><select name="</samp><i>somestring</i><samp>">...</select></samp> .
  909. * <br />If absent, generate output<br />
  910. * <samp><select name="month">...</select></samp>.</li>
  911. * <li><samp>'discard_type' => ???</samp> FIXME</li>
  912. * <li><samp>'prefix' => ???</samp> FIXME</li>
  913. * </ul>
  914. * In all cases the value sent to the server is the two digit
  915. * month number in the range '01'..'12'.
  916. *
  917. * @return string Generated HTML
  918. * @uses attribute_name
  919. * @uses leading_zero_on_single_digits()
  920. * @uses request_months
  921. * @uses select_html
  922. */
  923. function select_month($date = null, $options = array()) {
  924. $month_options = ""; // will accumulate <option>s
  925. // If a value for this attribute was parsed from $_REQUEST,
  926. // use it as initially selected and ignore first argument
  927. if(array_key_exists($this->attribute_name,$this->request_months)) {
  928. $date_month = $this->request_months[$this->attribute_name];
  929. }
  930.  
  931. // No value in $_REQUEST so look at the first argument.
  932. // If it is valid use it as initially selected
  933. elseif(strlen($date) == 2 && is_numeric($date)
  934. && $date >=1 && $date <= 12 ) {
  935. $date_month = $date;
  936. }
  937.  
  938. // Parse initially selected month from US English description
  939. // in first argument if present, otherwise select current month
  940. else {
  941. $date = $date ? $date : date("Y-m-d H:i:s");
  942. $date_month = date("m",strtotime($date));
  943. }
  944. // Generate <option>...</option> HTML for each month
  945. for($month_number = 1; $month_number <= 12; $month_number++) {
  946. if(array_key_exists('use_month_numbers',$options)) {
  947. $month_name = $month_number;
  948. } elseif(array_key_exists('add_month_numbers',$options)) {
  949. $month_name = $month_number. ' - '
  950. . date("F",strtotime("2005-" . $month_number
  951. . "-01"));
  952. } else {
  953. $month_name = date("F",strtotime("2005-" . $month_number
  954. ."-01"));
  955. }
  956.  
  957. $month_options .= ($date_month == $month_number ?
  958. "<option value=\""
  959. .$this->leading_zero_on_single_digits($month_number)
  960. ."\" selected=\"selected\">$month_name</option>\n" :
  961. "<option value=\""
  962. .$this->leading_zero_on_single_digits($month_number)
  963. ."\">$month_name</option>\n");
  964. }
  965.  
  966. // Return finished HTML
  967. $field_name = array_key_exists('field_name', $options)
  968. ? $options['field_name'] : 'month';
  969. return $this->select_html($field_name, $month_options,
  970. array_key_exists('prefix', $options)
  971. ? $options['prefix'] : null,
  972. array_key_exists('include_blank', $options)
  973. ? $options['include_blank'] : false,
  974. array_key_exists('discard_type', $options)
  975. ? $options['discard_type'] : false);
  976. }
  977.  
  978. /**
  979. * Generate HTML/XML for year selector pull-down menu
  980. *
  981. * Returns <samp><select>...</select></samp> HTML with options
  982. * for a number of years. The first argument, if present,
  983. * specifies the initially selected year. The second
  984. * argument controls the format of the generated HTML.
  985. *
  986. * Examples:
  987. * <ul>
  988. * <li><samp>select_year();</samp><br /> Generates a pulldown menu with
  989. * with a range of +/- five years. If a year is specified in
  990. * {@link $request_years}[{@link $attribute_name}] then it is
  991. * selected initially, otherwise the current calendar year is
  992. * selected.</li>
  993. * <li>
  994. * <samp>select_year(null,array('start_year' => '1900));</samp><br />
  995. * Generates year options from 1900 to five years after the
  996. * initially selected year, which is chosen as in the previous
  997. * example.</li>
  998. * <li><samp>select_year(null,array('start_year'=>date('Y')+5, 'end_year'=>date('Y')-5);</samp><br />
  999. * Generates year options starting five years after the current year,
  1000. * ending five years before the current year.
  1001. * </ul>
  1002. *
  1003. * @param string Year to display as initially selected if none
  1004. * was found in {@link $request_years}[{@link $attribute_name}].
  1005. * Character string is either exactly four decimal
  1006. * digits or some English date representation. If omitted, the
  1007. * current year is initially selected.
  1008. *
  1009. * @param mixed[] Output format options:
  1010. * <ul>
  1011. * <li><samp>'start_year'=>'</samp><i>startyear</i><samp>'</samp>
  1012. * If specified, <i>startyear</i> will be the first year in
  1013. * the output menu, otherwise the first year in the menu will
  1014. * be five years before the initially selected year.</li>
  1015. * <li><samp>'end_year'=>'</samp><i>endyear</i><samp>'</samp>
  1016. * If specified, <i>endyear</i> will be the last year in
  1017. * the output menu, otherwise the last year in the menu will
  1018. * be five years after the initially selected year.</li>
  1019. * <li><samp>'field_name' => '</samp><i>somestring</i><samp>'</samp>
  1020. * Generate output<br />
  1021. * <samp><select name="</samp><i>somestring</i><samp>">...</select></samp> .
  1022. * <br />If absent, generate output<br />
  1023. * <samp><select name="year">...</select></samp>.</li>
  1024. * <li><samp>'discard_type' => ???</samp> FIXME</li>
  1025. * <li><samp>'prefix' => ???</samp> FIXME</li>
  1026. * </ul>
  1027. * To generate a list with most recent year first, define that
  1028. * year as the start year and the oldest year as the end year.
  1029. * @return string Generated HTML
  1030. * @uses attribute_name
  1031. * @uses request_years
  1032. * @uses select_html
  1033. * @uses year_option()
  1034. */
  1035. function select_year($date=null, $options = array()) {
  1036. //error_log("select_year('" . (is_null($date) ? 'null' : $date)
  1037. // ."', " . var_export($options,true));
  1038. //error_log('request_years='
  1039. // .var_export($this->request_years[$this->attribute_name],true));
  1040. $year_options = "";
  1041.  
  1042. // Find the year to display.
  1043. if($this->request_years[$this->attribute_name]) {
  1044.  
  1045. // There was a value for this attribute in $_REQUEST
  1046. // so display it as the initial choice
  1047. $date_year = $this->request_years[$this->attribute_name];
  1048. } elseif(strlen($date) == 4 && is_numeric($date)) {
  1049.  
  1050. // The first argument is exactly four decimal digits
  1051. // so interpret that as a year
  1052. $date_year = $date;
  1053. } else {
  1054.  
  1055. // If a first argument was specified, assume that it is
  1056. // some English date representation and convert it for
  1057. // use as the initial value.
  1058. // If first argument was null, use the current year for
  1059. // the initial value.
  1060. $date_year = $date ? date("Y",strtotime($date)) : date("Y");
  1061. }
  1062.  
  1063. // Set first year to appear in the option list
  1064. $start_year = array_key_exists('start_year',$options)
  1065. ? $options['start_year'] : $date_year - 5;
  1066.  
  1067. // Set last year to appear in the option list
  1068. $end_year = array_key_exists('end_year',$options)
  1069. ? $options['end_year'] : $date_year + 5;
  1070.  
  1071. if ($start_year < $end_year) {
  1072. for($year = $start_year; $year <= $end_year; $year++) {
  1073. $year_options .= $this->year_option($year, $date_year);
  1074. }
  1075. } else {
  1076. for($year = $start_year; $year >= $end_year; $year--) {
  1077. $year_options .= $this->year_option($year, $date_year);
  1078. }
  1079. }
  1080.  
  1081. $field_name = array_key_exists('field_name',$options)
  1082. ? $options['field_name'] : 'year';
  1083. return $this->select_html($field_name, $year_options,
  1084. array_key_exists('prefix',$options)
  1085. ? $options['prefix'] : null,
  1086. array_key_exists('include_blank',$options)
  1087. ? $options['include_blank'] : false,
  1088. array_key_exists('discard_type',$options)
  1089. ? $options['discard_type'] : false);
  1090.  
  1091. }
  1092.  
  1093. /**
  1094. * Return one HTML/XML year option, selected if so specified
  1095. * @param integer Year to put in the option
  1096. * @param integer Year that should be selected
  1097. * @return string HTML for one year option
  1098. */
  1099. function year_option($year, $date_year) {
  1100. return "<option value=\"$year\""
  1101. . (($date_year == $year) ? " selected=\"selected\">" : ">")
  1102. . "$year</option>\n";
  1103. }
  1104.  
  1105. /**
  1106. * Generate HTML/XML for day/month/year selector pull-down menus
  1107. *
  1108. * When called, {@link $object_name} describes the
  1109. * {@link ActiveRecord} subclass and {@link $attribute_name}
  1110. * describes the attribute whose value will be set by the
  1111. * generated pull-down menus. The value to be displayed
  1112. * initially in each menu is from $_REQUEST if present, otherwise
  1113. * from the database.
  1114. *
  1115. * @param mixed[] Output format options
  1116. * <ul>
  1117. * <li><samp>'discard_day' => true</samp> Don't show a day of
  1118. * month menu. If absent or false, day menu will be output.</li>
  1119. * <li><samp>'discard_month' => true</samp> Don't show a month
  1120. * or day of the month menu. If absent or false, month menu
  1121. * will be output.</li>
  1122. * <li><samp>'discard_type' => true</samp> (true is the
  1123. * default) Don't show name of individual field, for example
  1124. * <samp>[year]</samp>, as part of the <samp>name</samp> value
  1125. * of the generated <samp><select ...></samp>. The
  1126. * information to identify the field is available as a suffix
  1127. * <samp>(</samp><i>n</i><samp>i)</samp> of the attribute
  1128. * name.</li>
  1129. * <li><samp>'discard_year' => true</samp> Don't show a year
  1130. * menu. If absent or false, year menu will be output.</li>
  1131. * <li><samp>'field_separator' => '</samp><i>string</i><samp>'</samp>
  1132. * String to insert between the submenus in the output. If
  1133. * absent, one blank will be inserted.</li>
  1134. * <li><samp>'include_blank' => true</samp> Initially show a blank
  1135. * selection in the menu. If absent or false, the current
  1136. * date will be shown as the initial selection. If a value
  1137. * was parsed from $_REQUEST, it will be used for the initial
  1138. * selection regardless of this option.</li>
  1139. * <li><samp>'month_before_year' => true</samp> Equivalent to
  1140. * <samp>'order' => array('month', 'day', 'year')</samp></li>
  1141. * <li><samp>'order' => array(</samp><i>elements</i><samp>)</samp>
  1142. * A list of the elements <samp>'month', 'day'</samp> and
  1143. * <samp>'year'</samp> in the order in which the menus should
  1144. * appear in the output. Default is
  1145. * <samp>'year', 'month', 'day'</samp></li>
  1146. * <li><b>Also:</b> options provided by {@link select_month()},
  1147. * {@link select_day()} and {@link select_year()}
  1148. * </ul>
  1149. * @return string Generated HTML
  1150. * @uses select_day()
  1151. * @uses select_month()
  1152. * @uses select_year()
  1153. * @uses value()
  1154. */
  1155. function to_date_select_tag($options = array()) {
  1156. // error_log("to_date_select_tag() object='$this->object_name'"
  1157. // . " attribute='$this->attribute_name'");
  1158. // error_log("options=".var_export($options,true));
  1159.  
  1160. // Handle historically misspelled options
  1161. if (array_key_exists('field_seperator', $options)) {
  1162. $options['field_separator'] = $options['field_seperator'];
  1163. unset($options['field_seperator']);
  1164. }
  1165. $defaults = array('discard_type' => true);
  1166. $options = array_merge($defaults, $options);
  1167. $options_with_prefix = array();
  1168.  
  1169. // Set the name of each submenu in the form
  1170. for($i=1 ; $i <= 3 ; $i++) {
  1171. $options_with_prefix[$i] = array_merge($options, array('prefix' =>
  1172. "{$this->object_name}[{$this->attribute_name}({$i}i)]"));
  1173. }
  1174. // Test for output option 'include_blank' == true
  1175. if(array_key_exists('include_blank', $options)
  1176. && $options['include_blank']) {
  1177.  
  1178. // 'include_blank' is present so if no value for this
  1179. // attribute was parsed from $_REQUEST, show blank initially
  1180. // FIXME: this doesn't actually work
  1181. $value = $this->value();
  1182. $date = $value ? $value : null;
  1183. } else {
  1184.  
  1185. // 'include_blank' is not present so if no value for this
  1186. // attribute was parsed from $_REQUEST, show today's date
  1187. // initially
  1188. $value = $this->value();
  1189. $date = $value ? $value : date("Y-m-d");
  1190. }
  1191.  
  1192. // Test for output option 'month_before_year' == true
  1193. $date_select = array();
  1194. if(array_key_exists('month_before_year', $options)
  1195. && $options['month_before_year']) {
  1196.  
  1197. // 'month_before_year' is present so set the default
  1198. // ordering of output menus accordingly
  1199. $options['order'] = array('month', 'year', 'day');
  1200. } elseif(!array_key_exists('order',$options)
  1201. ||!$options['order']) {
  1202.  
  1203. // If 'order' option not present set order from default
  1204. $options['order'] = array('year', 'month', 'day');
  1205. }
  1206.  
  1207. $position = array('year' => 1, 'month' => 2, 'day' => 3);
  1208.  
  1209. // Evaluate 'discard_field' options to see which fields
  1210. // should not be represented by menus in the output
  1211. $discard = array();
  1212. if(array_key_exists('discard_year',$options)
  1213. && $options['discard_year']) $discard['year'] = true;
  1214. if(array_key_exists('discard_month',$options)
  1215. && $options['discard_month']) $discard['month'] = true;
  1216. if( (array_key_exists('discard_day',$options)
  1217. &&$options['discard_day'])
  1218. || (array_key_exists('discard_month',$options)
  1219. && $options['discard_month'])) $discard['day'] = true;
  1220.  
  1221. // Build HTML for menus in the order determined above,
  1222. // except for fields to be discarded.
  1223. foreach($options['order'] as $param) {
  1224. if(!array_key_exists($param,$discard) || !$discard[$param]) {
  1225. $date_select[] = call_user_func(array($this, "select_$param"),
  1226. $date, $options_with_prefix[$position[$param]]);
  1227. }
  1228. }
  1229. // HTML for each menu is in an element of $date_select[].
  1230. // Join the pieces of HTML with an optional field separator
  1231. // (default blank)
  1232. if(count($date_select)) {
  1233. $separator = array_key_exists('field_separator',$options)
  1234. ? $options['field_separator'] : " ";
  1235. $date_select = implode($separator, $date_select);
  1236. }
  1237.  
  1238. return $date_select;
  1239. }
  1240.  
  1241. /**
  1242. * Generate HTML/XML for date/time pulldown menus
  1243. *
  1244. * Returns <samp><select>...</select></samp> HTML with options
  1245. * for a number of years, months, days, hours and minutes. The
  1246. * first argument, if present, specifies the initially selected
  1247. * date. The second argument controls the format of the
  1248. * generated HTML.
  1249. *
  1250. * Examples:
  1251. * <ul>
  1252. * <li><samp>to_datetime_select_tag();</samp><br /> Generates a
  1253. * group of five pulldown menus in the order year, month, day,
  1254. * hour and minute with the current date and time initially
  1255. * selected.</li>
  1256. * <li>
  1257. * <li><samp>to_datetime_select_tag(array('discard_second' => false);</samp><br />
  1258. * Generates a group of six pulldown menus in the order year,
  1259. * month, day, hour, minute and second with the current date
  1260. * and time initially selected.</li>
  1261. * <li>
  1262. * <samp>to_datetime_select_tag('1998-04-08 13:21:17');</samp><br />
  1263. * Generates a group of five pulldown menus in the order year,
  1264. * month, day, hour and minute with the date/time
  1265. * 1998 August 4 13:21 initially selected.</li>
  1266. * </ul>
  1267. *
  1268. * @param string Date/time to display as initially selected.
  1269. * Character string is any US English date representation
  1270. * supported by {@link strtotime()}. If omitted, the
  1271. * current date/time is initially selected.
  1272. *
  1273. * @param mixed[] Output format options:
  1274. * <ul>
  1275. * <li><samp>'discard_month' => true</samp><br />
  1276. * Output selector for only the year.</li>
  1277. * <li><samp>'discard_day' => true</samp><br />
  1278. * Output selector for only the year and month.</li>
  1279. * <li><samp>'discard_hour' => true</samp><br />
  1280. * Output selector for only the year, month and day.</li>
  1281. * <li><samp>'discard_minute' => true</samp><br />
  1282. * Output selector for only the year, month, day and
  1283. * hour.</li>
  1284. * <li><samp>'discard_second' => false</samp><br />
  1285. * Output selector for year, month, day, hour, minute and
  1286. * second.</li>
  1287. * </ul>
  1288. * @return string Generated HTML
  1289. * @uses request_days
  1290. * @uses request_hours
  1291. * @uses request_minutes
  1292. * @uses request_months
  1293. * @uses request_seconds
  1294. * @uses request_years
  1295. * @uses select_day()
  1296. * @uses select_hour()
  1297. * @uses select_minute()
  1298. * @uses select_month()
  1299. * @uses select_second()
  1300. * @uses select_year()
  1301. * @uses value()
  1302. */
  1303. function to_datetime_select_tag($options = array()) {
  1304. $defaults = array('discard_type' => true,
  1305. 'discard_second' => true);
  1306. $options = array_merge($defaults, $options);
  1307. $options_with_prefix = array();
  1308. for($i=1 ; $i <= 6 ; $i++) {
  1309. $options_with_prefix[$i] =
  1310. array_merge($options, array('prefix' =>
  1311. "{$this->object_name}[{$this->attribute_name}({$i}i)]"));
  1312. }
  1313.  
  1314. // FIXME: this doesn't work
  1315. if(array_key_exists('include_blank', $options)
  1316. && $options['include_blank']) {
  1317. $value = $this->value();
  1318. $datetime = $value ? $value : null;
  1319. } else {
  1320. $value = $this->value();
  1321. $datetime = $value ? $value : date("Y-m-d H:i:s");
  1322. }
  1323. // Generate year pulldown
  1324. $datetime_select = $this->select_year($datetime,
  1325. $options_with_prefix[1]);
  1326.  
  1327. // Generate month pulldown if not discarded
  1328. if(!array_key_exists('discard_month', $options)
  1329. || !$options['discard_month']) {
  1330. $datetime_select .= $this->select_month($datetime,
  1331. $options_with_prefix[2]);
  1332.  
  1333. // Generate day pulldown if not discarded
  1334. if(!array_key_exists('discard_day', $options)
  1335. || !($options['discard_day'] || $options['discard_month'])) {
  1336. $datetime_select .= $this->select_day($datetime,
  1337. $options_with_prefix[3]);
  1338.  
  1339. // Generate hour pulldown if not discarded
  1340. if(!array_key_exists('discard_hour', $options)
  1341. || !$options['discard_hour']) {
  1342. $datetime_select .= ' &mdash; '
  1343. . $this->select_hour($datetime,
  1344. $options_with_prefix[4]);
  1345.  
  1346. // Generate minute pulldown if not discarded
  1347. if(!array_key_exists('discard_minute', $options)
  1348. || !$options['discard_minute']) {
  1349. $datetime_select .= ' : '
  1350. . $this->select_minute($datetime,
  1351. $options_with_prefix[5]);
  1352.  
  1353. // Generate second pulldown if not discarded
  1354. if(!array_key_exists('discard_second', $options)
  1355. || !$options['discard_second']) {
  1356. $datetime_select .= ' : '
  1357. . $this->select_second($datetime,
  1358. $options_with_prefix[6]);
  1359. } // second
  1360. } // minute
  1361. } // hour
  1362. } // day
  1363. } // month
  1364. return $datetime_select;
  1365. }
  1366. /**
  1367. * Generate HTML/XML for expiration month and year pulldown.
  1368. *
  1369. * Calls {@link to_date_select_tag()} with options for month with
  1370. * number, followed by year starting this year and going seven
  1371. * years in the future.
  1372. * @param mixed[] Output format options
  1373. * @return string Generated HTML
  1374. * @uses to_date_select_tag()
  1375. */
  1376. function to_expiration_date_select_tag($options = array()) {
  1377. $options['discard_day'] = true;
  1378. $options['month_before_year'] = true;
  1379. $options['use_month_numbers'] = true;
  1380. $options['start_year'] = date("Y");
  1381. $options['end_year'] = date("Y") + 7;
  1382. $options['field_separator'] = " / ";
  1383. return $this->to_date_select_tag($options);
  1384. }
  1385.  
  1386. /**
  1387. * Generate HTML/XML for time pulldown
  1388. *
  1389. * When called, {@link $object_name} describes the
  1390. * {@link ActiveRecord} subclass and {@link $attribute_name}
  1391. * describes the attribute whose value will be set by the
  1392. * generated pull-down menu. The value to be displayed initially
  1393. * is from $_REQUEST if present, otherwise from the database.
  1394. *
  1395. * @param mixed[] Output format options
  1396. * @return string Generated HTML
  1397. * @uses request_hours
  1398. * @uses request_minutes
  1399. * @uses request_seconds
  1400. * @uses select_time()
  1401. * @uses value()
  1402. */
  1403. function time_select($options=array()) {
  1404. $defaults = array('discard_type' => true,
  1405. 'discard_second' => true);
  1406. $options = array_merge($defaults,$options);
  1407. $options_with_prefix = array();
  1408. for($i=4 ; $i <= 6 ; $i++) {
  1409. $options_with_prefix[$i] =
  1410. array_merge($options, array('prefix' =>
  1411. "{$this->object_name}[{$this->attribute_name}({$i}i)]"));
  1412. }
  1413.  
  1414. // If no value for this attribute found in $_REQUEST
  1415. // or the model, show current time initially
  1416. $time = $this->value();
  1417. $time = $time ? $time : date('H:i:s');
  1418.  
  1419. // Generate HTML for hour
  1420. $time_select = $this->select_hour($time, $options_with_prefix[4]);
  1421.  
  1422. // Generate HTML for minute if not discarded
  1423. if (!(array_key_exists('discard_minute', $options)
  1424. && $options['discard_minute'])) {
  1425. $time_select .= ' : '
  1426. . $this->select_minute($time, $options_with_prefix[5]);
  1427.  
  1428. // Generate HTML for second if not discarded
  1429. if (!(array_key_exists('discard_second', $options)
  1430. && $options['discard_second'])) {
  1431. $time_select .= ' : '
  1432. . $this->select_second($time, $options_with_prefix[6]);
  1433. }
  1434. }
  1435. return $time_select;
  1436. }
  1437.  
  1438. /**
  1439. * Generate HTML/XML for year pulldown
  1440. *
  1441. * When called, {@link $object_name} describes the
  1442. * {@link ActiveRecord} subclass and {@link $attribute_name}
  1443. * describes the attribute whose value will be set by the
  1444. * generated pull-down menu. The value to be displayed initially
  1445. * is from $_REQUEST if present, otherwise from the database.
  1446. *
  1447. * @param mixed[] Output format options
  1448. * @return string Generated HTML
  1449. * @uses select_year()
  1450. * @uses value()
  1451. */
  1452. function year_select($options=array()) {
  1453. $defaults = array('discard_type' => true,
  1454. 'prefix' =>
  1455. "{$this->object_name}[{$this->attribute_name}(1i)]");
  1456. $options = array_merge($defaults,$options);
  1457.  
  1458. // If no value for this attribute found in $_REQUEST
  1459. // or the model, show today's date initially
  1460. $year = $this->value();
  1461. if (!$year) {
  1462. $year =
  1463. (is_array($this->request_years)
  1464. && array_key_exists($this->attribute_name,$this->request_years))
  1465. ? $this->request_years[$this->attribute_name]
  1466. : date("Y");
  1467. }
  1468. return $this->select_year($year.'-01-01',$options);
  1469. }
  1470. }
  1471.  
  1472. /**
  1473. * Make a new DateHelper object and call its select_date() method
  1474. * @uses DateHelper::select_date()
  1475. */
  1476. function select_date() {
  1477. $date_helper = new DateHelper();
  1478. $args = func_get_args();
  1479. return call_user_func_array(array($date_helper, 'select_date'), $args);
  1480. }
  1481.  
  1482. /**
  1483. * Make a new DateHelper object and call its select_datetime() method
  1484. * @uses DateHelper::select_datetime()
  1485. */
  1486. function select_datetime() {
  1487. $date_helper = new DateHelper();
  1488. $args = func_get_args();
  1489. return call_user_func_array(array($date_helper, 'select_datetime'), $args);
  1490. }
  1491.  
  1492. /**
  1493. * Make a new DateHelper object and call its select_expiration_date() method
  1494. * @uses DateHelper::select_expiration_date()
  1495. */
  1496. function select_expiration_date() {
  1497. $date_helper = new DateHelper();
  1498. $args = func_get_args();
  1499. return call_user_func_array(array($date_helper, 'select_expiration_date'), $args);
  1500. }
  1501.  
  1502. /**
  1503. * Make a new DateHelper object and call its datetime_select() method
  1504. * @param string Name of an ActiveRecord subclass
  1505. * @param string Name of an attribute of $object
  1506. * @param mixed[] Format options
  1507. * @uses DateHelper::datetime_select()
  1508. * @see ActiveRecordHelper::to_scaffold_tag()
  1509. */
  1510. function datetime_select($object, $attribute, $options = array()) {
  1511. $date_helper = new DateHelper($object, $attribute);
  1512. return $date_helper->datetime_select($options);
  1513. }
  1514.  
  1515. /**
  1516. * Make a new DateHelper object and call its date_select() method
  1517. * @param string Name of an ActiveRecord subclass
  1518. * @param string Name of an attribute of $object
  1519. * @param mixed[] Output format options
  1520. * @return string Generated HTML
  1521. * @uses DateHelper::date_select()
  1522. * @see ActiveRecordHelper::to_scaffold_tag()
  1523. */
  1524. function date_select($object, $attribute, $options = array()) {
  1525. $date_helper = new DateHelper($object, $attribute);
  1526. return $date_helper->date_select($options);
  1527. }
  1528.  
  1529. /**
  1530. * Make a new DateHelper object and call its year_select() method
  1531. * @param string Name of an ActiveRecord subclass
  1532. * @param string Name of an attribute of $object
  1533. * @param mixed[] Format options
  1534. * @uses DateHelper::year_select()
  1535. * @see ActiveRecordHelper::to_scaffold_tag()
  1536. */
  1537. function year_select($object, $attribute, $options = array()) {
  1538. $date_helper = new DateHelper($object, $attribute);
  1539. return $date_helper->year_select($options);
  1540. }
  1541.  
  1542. /**
  1543. * Make a new DateHelper object and call its select_time() method
  1544. * @param string Name of an ActiveRecord subclass
  1545. * @param string Name of an attribute of $object
  1546. * @param mixed[] Format options
  1547. * @uses DateHelper::select_time()
  1548. * @see ActiveRecordHelper::to_scaffold_tag()
  1549. */
  1550. function time_select($object, $attribute, $options = array()) {
  1551. $date_helper = new DateHelper($object, $attribute);
  1552. return $date_helper->time_select($options);
  1553. }
  1554.  
  1555. /**
  1556. * Make a new DateHelper object and call its expiration_date_select() method
  1557. * @param string Name of an ActiveRecord subclass
  1558. * @param string Name of an attribute of $object
  1559. * @param mixed[] Format options
  1560. * @uses DateHelper::expiration_date_select()
  1561. */
  1562. function expiration_date_select($object, $attribute, $options = array()) {
  1563. $date_helper = new DateHelper($object, $attribute);
  1564. return $date_helper->expiration_date_select($options);
  1565. }
  1566.  
  1567. /**
  1568. * Make a new DateHelper object and call its select_month() method
  1569. *
  1570. * Generate HTML/XML for month selector pull-down menu using only
  1571. * explicit month specification.<br />
  1572. * <b>NB:</b> An attempt to get value of an attribute will always
  1573. * fail because there is no way to set
  1574. * {@link DateHelper::object_name} and
  1575. * {@link DateHelper::attribute_name}.
  1576. * @uses DateHelper::select_month()
  1577. */
  1578. function select_month() {
  1579. $date_helper = new DateHelper();
  1580. $args = func_get_args();
  1581. return call_user_func_array(array($date_helper, 'select_month'), $args);
  1582. }
  1583.  
  1584. /**
  1585. * Make a new DateHelper object and call its select_day() method
  1586. * @uses DateHelper::select_day()
  1587. */
  1588. function select_day() {
  1589. $date_helper = new DateHelper();
  1590. $args = func_get_args();
  1591. return call_user_func_array(array($date_helper, 'select_day'), $args);
  1592. }
  1593.  
  1594. // -- set Emacs parameters --
  1595. // Local variables:
  1596. // tab-width: 4
  1597. // c-basic-offset: 4
  1598. // c-hanging-comment-ender-p: nil
  1599. // indent-tabs-mode: nil
  1600. // End:

Documentation generated on Thu, 04 May 2006 19:47:26 -0600 by phpDocumentor 1.3.0RC4