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

/lib/form/dateselector.php

https://bitbucket.org/moodle/moodle
PHP | 305 lines | 160 code | 22 blank | 123 comment | 33 complexity | 25b3e564482d73005d2c3eae08fde6f8 MD5 | raw file
Possible License(s): Apache-2.0, LGPL-2.1, BSD-3-Clause, MIT, GPL-3.0
  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. }
  127. // If optional we add a checkbox which the user can use to turn if on
  128. if ($this->_options['optional']) {
  129. $this->_elements[] = $this->createFormElement('checkbox', 'enabled', null, get_string('enable'), $this->getAttributes(), true);
  130. }
  131. foreach ($this->_elements as $element){
  132. if (method_exists($element, 'setHiddenLabel')){
  133. $element->setHiddenLabel(true);
  134. }
  135. }
  136. }
  137. /**
  138. * Called by HTML_QuickForm whenever form event is made on this element
  139. *
  140. * @param string $event Name of event
  141. * @param mixed $arg event arguments
  142. * @param object $caller calling object
  143. * @return bool
  144. */
  145. function onQuickFormEvent($event, $arg, &$caller) {
  146. $this->setMoodleForm($caller);
  147. switch ($event) {
  148. case 'updateValue':
  149. // Constant values override both default and submitted ones
  150. // default values are overriden by submitted.
  151. $value = $this->_findValue($caller->_constantValues);
  152. if (null === $value) {
  153. // If no boxes were checked, then there is no value in the array
  154. // yet we don't want to display default value in this case.
  155. if ($caller->isSubmitted() && !$caller->is_new_repeat($this->getName())) {
  156. $value = $this->_findValue($caller->_submitValues);
  157. } else {
  158. $value = $this->_findValue($caller->_defaultValues);
  159. }
  160. }
  161. $requestvalue=$value;
  162. if ($value == 0) {
  163. $value = time();
  164. }
  165. if (!is_array($value)) {
  166. $calendartype = \core_calendar\type_factory::get_calendar_instance();
  167. $currentdate = $calendartype->timestamp_to_date_array($value, $this->_options['timezone']);
  168. $value = array(
  169. 'day' => $currentdate['mday'],
  170. 'month' => $currentdate['mon'],
  171. 'year' => $currentdate['year']);
  172. // If optional, default to off, unless a date was provided.
  173. if ($this->_options['optional']) {
  174. $value['enabled'] = $requestvalue != 0;
  175. }
  176. } else {
  177. $value['enabled'] = isset($value['enabled']);
  178. }
  179. if (null !== $value) {
  180. $this->setValue($value);
  181. }
  182. break;
  183. case 'createElement':
  184. // Optional is an optional param, if its set we need to add a disabledIf rule.
  185. // If its empty or not specified then its not an optional dateselector.
  186. if (!empty($arg[2]['optional']) && !empty($arg[0])) {
  187. // When using the function addElement, rather than createElement, we still
  188. // enter this case, making this check necessary.
  189. if ($this->_usedcreateelement) {
  190. $caller->disabledIf($arg[0] . '[day]', $arg[0] . '[enabled]');
  191. $caller->disabledIf($arg[0] . '[month]', $arg[0] . '[enabled]');
  192. $caller->disabledIf($arg[0] . '[year]', $arg[0] . '[enabled]');
  193. } else {
  194. $caller->disabledIf($arg[0], $arg[0] . '[enabled]');
  195. }
  196. }
  197. return parent::onQuickFormEvent($event, $arg, $caller);
  198. break;
  199. case 'addElement':
  200. $this->_usedcreateelement = false;
  201. return parent::onQuickFormEvent($event, $arg, $caller);
  202. break;
  203. default:
  204. return parent::onQuickFormEvent($event, $arg, $caller);
  205. }
  206. }
  207. /**
  208. * Returns HTML for advchecbox form element.
  209. *
  210. * @return string
  211. */
  212. function toHtml() {
  213. include_once('HTML/QuickForm/Renderer/Default.php');
  214. $renderer = new HTML_QuickForm_Renderer_Default();
  215. $renderer->setElementTemplate('{element}');
  216. parent::accept($renderer);
  217. $html = $this->_wrap[0];
  218. if ($this->_usedcreateelement) {
  219. $html .= html_writer::tag('span', $renderer->toHtml(), array('class' => 'fdate_selector'));
  220. } else {
  221. $html .= $renderer->toHtml();
  222. }
  223. $html .= $this->_wrap[1];
  224. return $html;
  225. }
  226. /**
  227. * Accepts a renderer
  228. *
  229. * @param HTML_QuickForm_Renderer $renderer An HTML_QuickForm_Renderer object
  230. * @param bool $required Whether a group is required
  231. * @param string $error An error message associated with a group
  232. */
  233. function accept(&$renderer, $required = false, $error = null) {
  234. form_init_date_js();
  235. $renderer->renderElement($this, $required, $error);
  236. }
  237. /**
  238. * Export for template
  239. *
  240. * @param renderer_base $output
  241. * @return array|stdClass
  242. */
  243. public function export_for_template(renderer_base $output) {
  244. form_init_date_js();
  245. return parent::export_for_template($output);
  246. }
  247. /**
  248. * Output a timestamp. Give it the name of the group.
  249. *
  250. * @param array $submitValues values submitted.
  251. * @param bool $assoc specifies if returned array is associative
  252. * @return array
  253. */
  254. function exportValue(&$submitValues, $assoc = false) {
  255. $valuearray = array();
  256. foreach ($this->_elements as $element){
  257. $thisexport = $element->exportValue($submitValues[$this->getName()], true);
  258. if ($thisexport!=null){
  259. $valuearray += $thisexport;
  260. }
  261. }
  262. if (count($valuearray) && isset($valuearray['year'])) {
  263. if($this->_options['optional']) {
  264. // If checkbox is on, the value is zero, so go no further
  265. if(empty($valuearray['enabled'])) {
  266. return $this->_prepareValue(0, $assoc);
  267. }
  268. }
  269. // Get the calendar type used - see MDL-18375.
  270. $calendartype = \core_calendar\type_factory::get_calendar_instance();
  271. $gregoriandate = $calendartype->convert_to_gregorian($valuearray['year'], $valuearray['month'], $valuearray['day']);
  272. $value = make_timestamp($gregoriandate['year'],
  273. $gregoriandate['month'],
  274. $gregoriandate['day'],
  275. 0, 0, 0,
  276. $this->_options['timezone'],
  277. true);
  278. return $this->_prepareValue($value, $assoc);
  279. } else {
  280. return null;
  281. }
  282. }
  283. }