Merge branch 'MDL-49545-master' of git://github.com/ryanwyllie/moodle
[moodle.git] / lib / form / tags.php
CommitLineData
9f1c9dfc 1<?php
6c1fd304
RT
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
9f1c9dfc 17
18/**
6c1fd304
RT
19 * Drop down for question categories.
20 *
21 * Contains HTML class for editing tags, both official and peronal.
9f1c9dfc 22 *
6c1fd304
RT
23 * @package core_form
24 * @copyright 2009 Tim Hunt
25 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
26 */
27
9f1c9dfc 28global $CFG;
29require_once($CFG->libdir . '/form/group.php');
30
31/**
6c1fd304
RT
32 * Form field type for editing tags.
33 *
34 * HTML class for editing tags, both official and peronal.
35 *
36 * @package core_form
37 * @category form
38 * @copyright 2009 Tim Hunt
39 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
9f1c9dfc 40 */
41class MoodleQuickForm_tags extends MoodleQuickForm_group {
6c1fd304
RT
42 /**
43 * Inidcates that the user should be the usual interface, with the official
9f1c9dfc 44 * tags listed seprately, and a text box where they can type anything.
6c1fd304
RT
45 * @var int
46 */
f48dccd4 47 const DEFAULTUI = 'defaultui';
6c1fd304
RT
48
49 /**
50 * Indicates that the user should only be allowed to select official tags.
51 * @var int
52 */
f48dccd4 53 const ONLYOFFICIAL = 'onlyofficial';
6c1fd304
RT
54
55 /**
56 * Indicates that the user should just be given a text box to type in (they
9f1c9dfc 57 * can still type official tags though.
6c1fd304
RT
58 * @var int
59 */
f48dccd4 60 const NOOFFICIAL = 'noofficial';
9f1c9dfc 61
62 /**
6c1fd304
RT
63 * Control the fieldnames for form elements display => int, one of the constants above.
64 * @var array
9f1c9dfc 65 */
f48dccd4 66 protected $_options = array('display' => MoodleQuickForm_tags::DEFAULTUI);
9f1c9dfc 67
f48dccd4 68 /**
69 * Caches the list of official tags, to save repeat DB queries.
70 * @var array
71 */
72 protected $_officialtags = null;
9f1c9dfc 73
74 /**
f48dccd4 75 * Constructor
76 *
77 * @param string $elementName Element name
78 * @param mixed $elementLabel Label(s) for an element
79 * @param array $options Options to control the element's display
80 * @param mixed $attributes Either a typical HTML attribute string or an associative array.
81 */
9f1c9dfc 82 function MoodleQuickForm_tags($elementName = null, $elementLabel = null, $options = array(), $attributes = null) {
83 $this->HTML_QuickForm_element($elementName, $elementLabel, $attributes);
84 $this->_persistantFreeze = true;
85 $this->_appendName = true;
86 $this->_type = 'tags';
87 // set the options, do not bother setting bogus ones
88 if (is_array($options)) {
89 foreach ($options as $name => $value) {
90 if (isset($this->_options[$name])) {
91 if (is_array($value) && is_array($this->_options[$name])) {
f48dccd4 92 $this->_options[$name] = array_merge($this->_options[$name], $value);
9f1c9dfc 93 } else {
94 $this->_options[$name] = $value;
95 }
96 }
97 }
98 }
8942fd77 99 global $CFG;
100 if (empty($CFG->usetags)) {
101 debugging('A tags formslib field has been created even thought $CFG->usetags is false.', DEBUG_DEVELOPER);
102 }
9f1c9dfc 103 }
104
6c1fd304
RT
105 /**
106 * Internal function to load official tags
107 *
108 * @access protected
109 */
f48dccd4 110 protected function _load_official_tags() {
9f1c9dfc 111 global $CFG, $DB;
f48dccd4 112 if (!is_null($this->_officialtags)) {
113 return;
114 }
115 $namefield = empty($CFG->keeptagnamecase) ? 'name' : 'rawname';
116 $this->_officialtags = $DB->get_records_menu('tag', array('tagtype' => 'official'), $namefield, 'id,' . $namefield);
117 }
118
6c1fd304
RT
119 /**
120 * Creates the group's elements.
121 */
f48dccd4 122 function _createElements() {
3bd6b994 123 global $CFG, $OUTPUT;
9f1c9dfc 124 $this->_elements = array();
125
126 // Official tags.
f48dccd4 127 $showingofficial = $this->_options['display'] != MoodleQuickForm_tags::NOOFFICIAL;
128 if ($showingofficial) {
129 $this->_load_official_tags();
130
9f1c9dfc 131 // If the user can manage official tags, give them a link to manage them.
132 $label = get_string('otags', 'tag');
b0c6dc1c 133 if (has_capability('moodle/tag:manage', context_system::instance())) {
75015e5f
PS
134 $url = $CFG->wwwroot .'/tag/manage.php';
135 $label .= ' (' . $OUTPUT->action_link(
136 $url,
137 get_string('manageofficialtags', 'tag'),
138 new popup_action('click', $url, 'managetags'),
139 array('title'=>get_string('newwindow'))) . ')';
9f1c9dfc 140 }
141
142 // Get the list of official tags.
143 $noofficial = false;
f48dccd4 144 if (empty($this->_officialtags)) {
9f1c9dfc 145 $officialtags = array('' => get_string('none'));
146 $noofficial = true;
147 } else {
f48dccd4 148 $officialtags = array_combine($this->_officialtags, $this->_officialtags);
9f1c9dfc 149 }
150
151 // Create the element.
152 $size = min(5, count($officialtags));
fabbf439
PS
153 // E_STRICT creating elements without forms is nasty because it internally uses $this
154 $officialtagsselect = @MoodleQuickForm::createElement('select', 'officialtags', $label, $officialtags, array('size' => $size));
9f1c9dfc 155 $officialtagsselect->setMultiple(true);
156 if ($noofficial) {
157 $officialtagsselect->updateAttributes(array('disabled' => 'disabled'));
158 }
9f1c9dfc 159 $this->_elements[] = $officialtagsselect;
160 }
161
162 // Other tags.
163 if ($this->_options['display'] != MoodleQuickForm_tags::ONLYOFFICIAL) {
f48dccd4 164 if ($showingofficial) {
165 $label = get_string('othertags', 'tag');
166 } else {
167 $label = get_string('entertags', 'tag');
168 }
fabbf439
PS
169 // E_STRICT creating elements without forms is nasty because it internally uses $this
170 $othertags = @MoodleQuickForm::createElement('textarea', 'othertags', $label, array('cols'=>'40', 'rows'=>'5'));
9f1c9dfc 171 $this->_elements[] = $othertags;
172 }
173
174 // Paradoxically, the only way to get labels output is to ask for 'hidden'
175 // labels, and then override the .accesshide class in the CSS!
176 foreach ($this->_elements as $element){
177 if (method_exists($element, 'setHiddenLabel')){
178 $element->setHiddenLabel(true);
179 }
180 }
181 }
182
6c1fd304
RT
183 /**
184 * Called by HTML_QuickForm whenever form event is made on this element
185 *
186 * @param string $event Name of event
187 * @param mixed $arg event arguments
188 * @param object $caller calling object
189 */
f48dccd4 190 function onQuickFormEvent($event, $arg, &$caller) {
191 switch ($event) {
192 case 'updateValue':
193 // Get the value we should be setting.
194 $value = $this->_findValue($caller->_constantValues);
195 if (null === $value) {
196 // if no boxes were checked, then there is no value in the array
197 // yet we don't want to display default value in this case
198 if ($caller->isSubmitted()) {
199 $value = $this->_findValue($caller->_submitValues);
200 } else {
201 $value = $this->_findValue($caller->_defaultValues);
202 }
203 }
204
205 if (!empty($value) && !(isset($value['officialtags']) || isset($value['othertags']))) {
206 // Separate the official and unoffical tags, if necessary.
207 $official = array();
208 $other = array();
209 if ($this->_options['display'] != MoodleQuickForm_tags::NOOFFICIAL) {
210 $this->_load_official_tags();
6f5f3cef 211 if (!empty($this->_officialtags)) {
212 $officaltags = array_combine($this->_officialtags, $this->_officialtags);
213 } else {
214 $officaltags = array();
215 }
f48dccd4 216 foreach ($value as $tag) {
217 if (isset($officaltags[$tag])) {
218 $official[] = $tag;
219 } else {
220 $other[] = $tag;
221 }
222 }
223 } else {
224 $other = $value;
225 }
226 $value = array('officialtags' => $official, 'othertags' => implode(', ', $other));
227 }
228 if (!empty($value)) {
229 $this->setValue($value);
230 }
231
232 break;
233 default:
234 return parent::onQuickFormEvent($event, $arg, $caller);
235 }
236 }
237
6c1fd304
RT
238 /**
239 * Returns HTML for submitlink form element.
240 *
241 * @return string
242 */
9f1c9dfc 243 function toHtml() {
244 require_once('HTML/QuickForm/Renderer/Default.php');
bd69b9db 245 $renderer = new HTML_QuickForm_Renderer_Default();
9f1c9dfc 246 $renderer->setElementTemplate('{element}');
247 parent::accept($renderer);
f48dccd4 248 return $renderer->toHtml();
249 }
250
6c1fd304
RT
251 /**
252 * Accepts a renderer
253 *
254 * @param HTML_QuickForm_Renderer $renderer An HTML_QuickForm_Renderer object
255 * @param bool $required Whether a group is required
256 * @param string $error An error message associated with a group
257 */
f48dccd4 258 function accept(&$renderer, $required = false, $error = null)
259 {
260 $renderer->renderElement($this, $required, $error);
9f1c9dfc 261 }
262
6c1fd304
RT
263 /**
264 * Output both official and peronal.
265 *
266 * @param array $submitValues values submitted.
267 * @param bool $assoc specifies if returned array is associative
268 * @return array
269 */
9f1c9dfc 270 function exportValue(&$submitValues, $assoc = false) {
271 $valuearray = array();
272
273 // Get the data out of our child elements.
274 foreach ($this->_elements as $element){
275 $thisexport = $element->exportValue($submitValues[$this->getName()], true);
276 if ($thisexport != null){
277 $valuearray += $thisexport;
278 }
279 }
280
281 // Get any manually typed tags.
282 $tags = array();
283 if ($this->_options['display'] != MoodleQuickForm_tags::ONLYOFFICIAL &&
284 !empty($valuearray['othertags'])) {
285 $rawtags = explode(',', clean_param($valuearray['othertags'], PARAM_NOTAGS));
286 foreach ($rawtags as $tag) {
287 $tags[] = trim($tag);
288 }
289 }
290
291 // Add any official tags that were selected.
292 if ($this->_options['display'] != MoodleQuickForm_tags::NOOFFICIAL &&
293 !empty($valuearray['officialtags'])) {
294 $tags = array_unique(array_merge($tags, $valuearray['officialtags']));
295 }
296
297 return array($this->getName() => $tags);
298 }
299}