PageRenderTime 43ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/lib/form/dateselector.php

http://github.com/moodle/moodle
PHP | 306 lines | 161 code | 22 blank | 123 comment | 33 complexity | bbb635f7804d717c1b2553f2fbb1fc8f MD5 | raw file
Possible License(s): MIT, AGPL-3.0, MPL-2.0-no-copyleft-exception, LGPL-3.0, GPL-3.0, Apache-2.0, LGPL-2.1, BSD-3-Clause
  1. <?php
  2. // This file is part of Moodle - http://moodle.org/
  3. //
  4. // Moodle is free software: you can redistribute it and/or modify
  5. // it under the terms of the GNU General Public License as published by
  6. // the Free Software Foundation, either version 3 of the License, or
  7. // (at your option) any later version.
  8. //
  9. // Moodle is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU General Public License
  15. // along with Moodle. If not, see <http://www.gnu.org/licenses/>.
  16. /**
  17. * Group of date input element
  18. *
  19. * Contains class for a group of elements used to input a date.
  20. *
  21. * @package core_form
  22. * @copyright 2007 Jamie Pratt <me@jamiep.org>
  23. * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  24. */
  25. global $CFG;
  26. require_once($CFG->libdir . '/form/group.php');
  27. require_once($CFG->libdir . '/formslib.php');
  28. /**
  29. * Class for a group of elements used to input a date.
  30. *
  31. * Emulates moodle print_date_selector function
  32. *
  33. * @package core_form
  34. * @category form
  35. * @copyright 2007 Jamie Pratt <me@jamiep.org>
  36. * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  37. */
  38. class MoodleQuickForm_date_selector extends MoodleQuickForm_group {
  39. /**
  40. * Control the fieldnames for form elements.
  41. *
  42. * startyear => int start of range of years that can be selected
  43. * stopyear => int last year that can be selected
  44. * timezone => int|float|string (optional) timezone modifier used for edge case only.
  45. * If not specified, then date is caclulated based on current user timezone.
  46. * Note: dst will be calculated for string timezones only
  47. * {@link http://docs.moodle.org/dev/Time_API#Timezone}
  48. * optional => if true, show a checkbox beside the date to turn it on (or off)
  49. * @var array
  50. */
  51. protected $_options = array();
  52. /**
  53. * @var array These complement separators, they are appended to the resultant HTML.
  54. */
  55. protected $_wrap = array('', '');
  56. /**
  57. * @var null|bool Keeps track of whether the date selector was initialised using createElement
  58. * or addElement. If true, createElement was used signifying the element has been
  59. * added to a group - see MDL-39187.
  60. */
  61. protected $_usedcreateelement = true;
  62. /**
  63. * constructor
  64. *
  65. * @param string $elementName Element's name
  66. * @param mixed $elementLabel Label(s) for an element
  67. * @param array $options Options to control the element's display
  68. * @param mixed $attributes Either a typical HTML attribute string or an associative array
  69. */
  70. public function __construct($elementName = null, $elementLabel = null, $options = array(), $attributes = null) {
  71. // Get the calendar type used - see MDL-18375.
  72. $calendartype = \core_calendar\type_factory::get_calendar_instance();
  73. $this->_options = array('startyear' => $calendartype->get_min_year(), 'stopyear' => $calendartype->get_max_year(),
  74. 'defaulttime' => 0, 'timezone' => 99, 'step' => 1, 'optional' => false);
  75. // TODO MDL-52313 Replace with the call to parent::__construct().
  76. HTML_QuickForm_element::__construct($elementName, $elementLabel, $attributes);
  77. $this->_persistantFreeze = true;
  78. $this->_appendName = true;
  79. $this->_type = 'date_selector';
  80. // set the options, do not bother setting bogus ones
  81. if (is_array($options)) {
  82. foreach ($options as $name => $value) {
  83. if (isset($this->_options[$name])) {
  84. if (is_array($value) && is_array($this->_options[$name])) {
  85. $this->_options[$name] = @array_merge($this->_options[$name], $value);
  86. } else {
  87. $this->_options[$name] = $value;
  88. }
  89. }
  90. }
  91. }
  92. }
  93. /**
  94. * Old syntax of class constructor. Deprecated in PHP7.
  95. *
  96. * @deprecated since Moodle 3.1
  97. */
  98. public function MoodleQuickForm_date_selector($elementName = null, $elementLabel = null, $options = array(), $attributes = null) {
  99. debugging('Use of class name as constructor is deprecated', DEBUG_DEVELOPER);
  100. self::__construct($elementName, $elementLabel, $options, $attributes);
  101. }
  102. /**
  103. * This will create date group element constisting of day, month and year.
  104. *
  105. * @access private
  106. */
  107. function _createElements() {
  108. global $OUTPUT;
  109. // Get the calendar type used - see MDL-18375.
  110. $calendartype = \core_calendar\type_factory::get_calendar_instance();
  111. $this->_elements = array();
  112. $dateformat = $calendartype->get_date_order($this->_options['startyear'], $this->_options['stopyear']);
  113. // Reverse date element (Day, Month, Year), in RTL mode.
  114. if (right_to_left()) {
  115. $dateformat = array_reverse($dateformat);
  116. }
  117. foreach ($dateformat as $key => $value) {
  118. // E_STRICT creating elements without forms is nasty because it internally uses $this
  119. $this->_elements[] = $this->createFormElement('select', $key, get_string($key, 'form'), $value, $this->getAttributes(), true);
  120. }
  121. // The YUI2 calendar only supports the gregorian calendar type so only display the calendar image if this is being used.
  122. if ($calendartype->get_name() === 'gregorian') {
  123. $image = $OUTPUT->pix_icon('i/calendar', get_string('calendar', 'calendar'), 'moodle');
  124. $this->_elements[] = $this->createFormElement('link', 'calendar',
  125. null, '#', $image,
  126. array('class' => 'visibleifjs'));
  127. }
  128. // If optional we add a checkbox which the user can use to turn if on
  129. if ($this->_options['optional']) {
  130. $this->_elements[] = $this->createFormElement('checkbox', 'enabled', null, get_string('enable'), $this->getAttributes(), true);
  131. }
  132. foreach ($this->_elements as $element){
  133. if (method_exists($element, 'setHiddenLabel')){
  134. $element->setHiddenLabel(true);
  135. }
  136. }
  137. }
  138. /**
  139. * Called by HTML_QuickForm whenever form event is made on this element
  140. *
  141. * @param string $event Name of event
  142. * @param mixed $arg event arguments
  143. * @param object $caller calling object
  144. * @return bool
  145. */
  146. function onQuickFormEvent($event, $arg, &$caller) {
  147. $this->setMoodleForm($caller);
  148. switch ($event) {
  149. case 'updateValue':
  150. // Constant values override both default and submitted ones
  151. // default values are overriden by submitted.
  152. $value = $this->_findValue($caller->_constantValues);
  153. if (null === $value) {
  154. // If no boxes were checked, then there is no value in the array
  155. // yet we don't want to display default value in this case.
  156. if ($caller->isSubmitted() && !$caller->is_new_repeat($this->getName())) {
  157. $value = $this->_findValue($caller->_submitValues);
  158. } else {
  159. $value = $this->_findValue($caller->_defaultValues);
  160. }
  161. }
  162. $requestvalue=$value;
  163. if ($value == 0) {
  164. $value = time();
  165. }
  166. if (!is_array($value)) {
  167. $calendartype = \core_calendar\type_factory::get_calendar_instance();
  168. $currentdate = $calendartype->timestamp_to_date_array($value, $this->_options['timezone']);
  169. $value = array(
  170. 'day' => $currentdate['mday'],
  171. 'month' => $currentdate['mon'],
  172. 'year' => $currentdate['year']);
  173. // If optional, default to off, unless a date was provided.
  174. if ($this->_options['optional']) {
  175. $value['enabled'] = $requestvalue != 0;
  176. }
  177. } else {
  178. $value['enabled'] = isset($value['enabled']);
  179. }
  180. if (null !== $value) {
  181. $this->setValue($value);
  182. }
  183. break;
  184. case 'createElement':
  185. // Optional is an optional param, if its set we need to add a disabledIf rule.
  186. // If its empty or not specified then its not an optional dateselector.
  187. if (!empty($arg[2]['optional']) && !empty($arg[0])) {
  188. // When using the function addElement, rather than createElement, we still
  189. // enter this case, making this check necessary.
  190. if ($this->_usedcreateelement) {
  191. $caller->disabledIf($arg[0] . '[day]', $arg[0] . '[enabled]');
  192. $caller->disabledIf($arg[0] . '[month]', $arg[0] . '[enabled]');
  193. $caller->disabledIf($arg[0] . '[year]', $arg[0] . '[enabled]');
  194. } else {
  195. $caller->disabledIf($arg[0], $arg[0] . '[enabled]');
  196. }
  197. }
  198. return parent::onQuickFormEvent($event, $arg, $caller);
  199. break;
  200. case 'addElement':
  201. $this->_usedcreateelement = false;
  202. return parent::onQuickFormEvent($event, $arg, $caller);
  203. break;
  204. default:
  205. return parent::onQuickFormEvent($event, $arg, $caller);
  206. }
  207. }
  208. /**
  209. * Returns HTML for advchecbox form element.
  210. *
  211. * @return string
  212. */
  213. function toHtml() {
  214. include_once('HTML/QuickForm/Renderer/Default.php');
  215. $renderer = new HTML_QuickForm_Renderer_Default();
  216. $renderer->setElementTemplate('{element}');
  217. parent::accept($renderer);
  218. $html = $this->_wrap[0];
  219. if ($this->_usedcreateelement) {
  220. $html .= html_writer::tag('span', $renderer->toHtml(), array('class' => 'fdate_selector'));
  221. } else {
  222. $html .= $renderer->toHtml();
  223. }
  224. $html .= $this->_wrap[1];
  225. return $html;
  226. }
  227. /**
  228. * Accepts a renderer
  229. *
  230. * @param HTML_QuickForm_Renderer $renderer An HTML_QuickForm_Renderer object
  231. * @param bool $required Whether a group is required
  232. * @param string $error An error message associated with a group
  233. */
  234. function accept(&$renderer, $required = false, $error = null) {
  235. form_init_date_js();
  236. $renderer->renderElement($this, $required, $error);
  237. }
  238. /**
  239. * Export for template
  240. *
  241. * @param renderer_base $output
  242. * @return array|stdClass
  243. */
  244. public function export_for_template(renderer_base $output) {
  245. form_init_date_js();
  246. return parent::export_for_template($output);
  247. }
  248. /**
  249. * Output a timestamp. Give it the name of the group.
  250. *
  251. * @param array $submitValues values submitted.
  252. * @param bool $assoc specifies if returned array is associative
  253. * @return array
  254. */
  255. function exportValue(&$submitValues, $assoc = false) {
  256. $valuearray = array();
  257. foreach ($this->_elements as $element){
  258. $thisexport = $element->exportValue($submitValues[$this->getName()], true);
  259. if ($thisexport!=null){
  260. $valuearray += $thisexport;
  261. }
  262. }
  263. if (count($valuearray) && isset($valuearray['year'])) {
  264. if($this->_options['optional']) {
  265. // If checkbox is on, the value is zero, so go no further
  266. if(empty($valuearray['enabled'])) {
  267. return $this->_prepareValue(0, $assoc);
  268. }
  269. }
  270. // Get the calendar type used - see MDL-18375.
  271. $calendartype = \core_calendar\type_factory::get_calendar_instance();
  272. $gregoriandate = $calendartype->convert_to_gregorian($valuearray['year'], $valuearray['month'], $valuearray['day']);
  273. $value = make_timestamp($gregoriandate['year'],
  274. $gregoriandate['month'],
  275. $gregoriandate['day'],
  276. 0, 0, 0,
  277. $this->_options['timezone'],
  278. true);
  279. return $this->_prepareValue($value, $assoc);
  280. } else {
  281. return null;
  282. }
  283. }
  284. }