ff2fe6850b72919d07c1902d828501d696f2575b
[moodle.git] / lib / form / tags.php
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/>.
18 /**
19  * Tag autocomplete field.
20  *
21  * Contains HTML class for editing tags, both official and personal.
22  *
23  * @package   core_form
24  * @copyright 2009 Tim Hunt
25  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
26  */
28 global $CFG;
29 require_once($CFG->libdir . '/form/autocomplete.php');
31 /**
32  * Form field type for editing tags.
33  *
34  * HTML class for editing tags, both official and personal.
35  *
36  * @package   core_form
37  * @copyright 2009 Tim Hunt
38  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
39  */
40 class MoodleQuickForm_tags extends MoodleQuickForm_autocomplete {
41     /**
42      * Inidcates that the user should be the usual interface, with the official
43      * tags listed seprately, and a text box where they can type anything.
44      * @var int
45      */
46     const DEFAULTUI = 'defaultui';
48     /**
49      * Indicates that the user should only be allowed to select official tags.
50      * @var int
51      */
52     const ONLYOFFICIAL = 'onlyofficial';
54     /**
55      * Indicates that the user should just be given a text box to type in (they
56      * can still type official tags though.
57      * @var int
58      */
59     const NOOFFICIAL = 'noofficial';
61     /**
62      * @var boolean $showingofficial Official tags shown? (if not, then don't show link to manage official tags).
63      */
64     protected $showingofficial = false;
66     /**
67      * Options passed when creating an element.
68      * @var array
69      */
70     protected $tagsoptions = array();
72     /**
73      * Constructor
74      *
75      * @param string $elementName Element name
76      * @param mixed $elementLabel Label(s) for an element
77      * @param array $options Options to control the element's display
78      * @param mixed $attributes Either a typical HTML attribute string or an associative array.
79      */
80     public function __construct($elementName = null, $elementLabel = null, $options = array(), $attributes = null) {
81         $validoptions = array();
83         if (!empty($options)) {
84             // Only execute it when the element was created and $options has values set by user.
85             // In onQuickFormEvent() we make sure that $options is not empty even if developer left it empty.
86             if (empty($options['display'])) {
87                 $options['display'] = self::DEFAULTUI;
88             }
89             $this->tagsoptions = $options;
91             $this->showingofficial = $options['display'] != self::NOOFFICIAL;
93             if ($this->showingofficial) {
94                 $validoptions = $this->load_official_tags();
95             }
96             // Option 'tags' allows us to type new tags.
97             if ($options['display'] == self::ONLYOFFICIAL) {
98                 $attributes['tags'] = false;
99             } else {
100                 $attributes['tags'] = true;
101             }
102             $attributes['multiple'] = 'multiple';
103             $attributes['placeholder'] = get_string('entertags', 'tag');
104             $attributes['showsuggestions'] = $this->showingofficial;
105         }
107         parent::__construct($elementName, $elementLabel, $validoptions, $attributes);
108     }
110     /**
111      * Called by HTML_QuickForm whenever form event is made on this element
112      *
113      * @param string $event Name of event
114      * @param mixed $arg event arguments
115      * @param object $caller calling object
116      * @return bool
117      */
118     public function onQuickFormEvent($event, $arg, &$caller) {
119         if ($event === 'createElement') {
120             $arg[2] += array('itemtype' => '', 'component' => '');
121         }
122         return parent::onQuickFormEvent($event, $arg, $caller);
123     }
125     /**
126      * Checks if tagging is enabled for this itemtype
127      *
128      * @return boolean
129      */
130     protected function is_tagging_enabled() {
131         if (!empty($this->tagsoptions['itemtype']) && !empty($this->tagsoptions['component'])) {
132             $enabled = core_tag_tag::is_enabled($this->tagsoptions['component'], $this->tagsoptions['itemtype']);
133             if ($enabled === false) {
134                 return false;
135             }
136         }
137         // Backward compatibility with code developed before Moodle 3.0 where itemtype/component were not specified.
138         return true;
139     }
141     /**
142      * Old syntax of class constructor. Deprecated in PHP7.
143      *
144      * @deprecated since Moodle 3.1
145      */
146     public function MoodleQuickForm_tags($elementName = null, $elementLabel = null, $options = array(), $attributes = null) {
147         debugging('Use of class name as constructor is deprecated', DEBUG_DEVELOPER);
148         self::__construct($elementName, $elementLabel, $options, $attributes);
149     }
151     /**
152      * Finds the tag collection to use for official tag selector
153      *
154      * @return int
155      */
156     protected function get_tag_collection() {
157         if (empty($this->tagsoptions['tagcollid']) && (empty($this->tagsoptions['itemtype']) ||
158                 empty($this->tagsoptions['component']))) {
159             debugging('You need to specify \'itemtype\' and \'component\' of the tagged '
160                     . 'area in the tags form element options',
161                     DEBUG_DEVELOPER);
162         }
163         if (!empty($this->tagsoptions['tagcollid'])) {
164             return $this->tagsoptions['tagcollid'];
165         }
166         if ($this->tagsoptions['itemtype']) {
167             $this->tagsoptions['tagcollid'] = core_tag_area::get_collection($this->tagsoptions['component'],
168                     $this->tagsoptions['itemtype']);
169         } else {
170             $this->tagsoptions['tagcollid'] = core_tag_collection::get_default();
171         }
172         return $this->tagsoptions['tagcollid'];
173     }
175     /**
176      * Returns HTML for select form element.
177      *
178      * @return string
179      */
180     function toHtml(){
181         global $OUTPUT;
183         $managelink = '';
184         if (has_capability('moodle/tag:manage', context_system::instance()) && $this->showingofficial) {
185             $url = new moodle_url('/tag/manage.php', array('tc' => $this->get_tag_collection()));
186             $managelink = ' ' . $OUTPUT->action_link($url, get_string('managestandardtags', 'tag'));
187         }
189         return parent::toHTML() . $managelink;
190     }
192     /**
193      * Accepts a renderer
194      *
195      * @param HTML_QuickForm_Renderer $renderer An HTML_QuickForm_Renderer object
196      * @param bool $required Whether a group is required
197      * @param string $error An error message associated with a group
198      */
199     public function accept(&$renderer, $required = false, $error = null) {
200         if ($this->is_tagging_enabled()) {
201             $renderer->renderElement($this, $required, $error);
202         } else {
203             $renderer->renderHidden($this);
204         }
205     }
207     /**
208      * Internal function to load official tags
209      */
210     protected function load_official_tags() {
211         global $CFG, $DB;
212         if (!$this->is_tagging_enabled()) {
213             return array();
214         }
215         $namefield = empty($CFG->keeptagnamecase) ? 'name' : 'rawname';
216         $tags = $DB->get_records_menu('tag',
217             array('tagtype' => core_tag_tag::TAGTYPE_OFFICIAL, 'tagcollid' => $this->get_tag_collection()),
218             $namefield, 'id,' . $namefield);
219         return array_combine($tags, $tags);
220     }
222     /**
223      * Returns a 'safe' element's value
224      *
225      * @param  array  $submitValues array of submitted values to search
226      * @param  bool   $assoc        whether to return the value as associative array
227      * @return mixed
228      */
229     public function exportValue(&$submitValues, $assoc = false) {
230         if (!$this->is_tagging_enabled()) {
231             return $assoc ? array($this->getName() => array()) : array();
232         }
234         return parent::exportValue($submitValues, $assoc);
235     }