3a66e69b402da5d6883d28ae54390a79eb5ccade
[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 standard and not.
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 standard and not.
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      * @deprecated since 3.1
45      * @var int
46      */
47     const DEFAULTUI = 'defaultui';
49     /**
50      * Indicates that the user should only be allowed to select official tags.
51      * @deprecated since 3.1
52      * @var int
53      */
54     const ONLYOFFICIAL = 'onlyofficial';
56     /**
57      * Indicates that the user should just be given a text box to type in (they
58      * can still type official tags though.
59      * @deprecated since 3.1
60      * @var int
61      */
62     const NOOFFICIAL = 'noofficial';
64     /**
65      * @var boolean $showstandard Standard tags suggested? (if not, then don't show link to manage standard tags).
66      */
67     protected $showstandard = false;
69     /**
70      * Options passed when creating an element.
71      * @var array
72      */
73     protected $tagsoptions = array();
75     /**
76      * Constructor
77      *
78      * @param string $elementName Element name
79      * @param mixed $elementLabel Label(s) for an element
80      * @param array $options Options to control the element's display
81      * @param mixed $attributes Either a typical HTML attribute string or an associative array.
82      */
83     public function __construct($elementName = null, $elementLabel = null, $options = array(), $attributes = null) {
84         $validoptions = array();
86         if (!empty($options)) {
87             // Only execute it when the element was created and $options has values set by user.
88             // In onQuickFormEvent() we make sure that $options is not empty even if developer left it empty.
89             $showstandard = core_tag_tag::BOTH_STANDARD_AND_NOT;
90             if (isset($options['showstandard'])) {
91                 $showstandard = $options['showstandard'];
92             } else if (isset($options['display'])) {
93                 debugging('Option "display" is deprecated, each tag area can be configured to show standard tags or not ' .
94                     'by admin or manager. If it is necessary for the developer to override it, please use "showstandard" option',
95                     DEBUG_DEVELOPER);
96                 if ($options['display'] === self::NOOFFICIAL) {
97                     $showstandard = core_tag_tag::HIDE_STANDARD;
98                 } else if ($options['display'] === self::ONLYOFFICIAL) {
99                     $showstandard = core_tag_tag::STANDARD_ONLY;
100                 }
101             } else if (!empty($options['component']) && !empty($options['itemtype'])) {
102                 $showstandard = core_tag_area::get_showstandard($options['component'], $options['itemtype']);
103             }
105             $this->tagsoptions = $options;
107             $this->showstandard = ($showstandard != core_tag_tag::HIDE_STANDARD);
108             if ($this->showstandard) {
109                 $validoptions = $this->load_standard_tags();
110             }
111             // Option 'tags' allows us to type new tags.
112             $attributes['tags'] = ($showstandard != core_tag_tag::STANDARD_ONLY);
113             $attributes['multiple'] = 'multiple';
114             $attributes['placeholder'] = get_string('entertags', 'tag');
115             $attributes['showsuggestions'] = $this->showstandard;
116         }
118         parent::__construct($elementName, $elementLabel, $validoptions, $attributes);
119     }
121     /**
122      * Called by HTML_QuickForm whenever form event is made on this element
123      *
124      * @param string $event Name of event
125      * @param mixed $arg event arguments
126      * @param object $caller calling object
127      * @return bool
128      */
129     public function onQuickFormEvent($event, $arg, &$caller) {
130         if ($event === 'createElement') {
131             $arg[2] += array('itemtype' => '', 'component' => '');
132         }
133         return parent::onQuickFormEvent($event, $arg, $caller);
134     }
136     /**
137      * Checks if tagging is enabled for this itemtype
138      *
139      * @return boolean
140      */
141     protected function is_tagging_enabled() {
142         if (!empty($this->tagsoptions['itemtype']) && !empty($this->tagsoptions['component'])) {
143             $enabled = core_tag_tag::is_enabled($this->tagsoptions['component'], $this->tagsoptions['itemtype']);
144             if ($enabled === false) {
145                 return false;
146             }
147         }
148         // Backward compatibility with code developed before Moodle 3.0 where itemtype/component were not specified.
149         return true;
150     }
152     /**
153      * Old syntax of class constructor. Deprecated in PHP7.
154      *
155      * @deprecated since Moodle 3.1
156      */
157     public function MoodleQuickForm_tags($elementName = null, $elementLabel = null, $options = array(), $attributes = null) {
158         debugging('Use of class name as constructor is deprecated', DEBUG_DEVELOPER);
159         self::__construct($elementName, $elementLabel, $options, $attributes);
160     }
162     /**
163      * Finds the tag collection to use for standard tag selector
164      *
165      * @return int
166      */
167     protected function get_tag_collection() {
168         if (empty($this->tagsoptions['tagcollid']) && (empty($this->tagsoptions['itemtype']) ||
169                 empty($this->tagsoptions['component']))) {
170             debugging('You need to specify \'itemtype\' and \'component\' of the tagged '
171                     . 'area in the tags form element options',
172                     DEBUG_DEVELOPER);
173         }
174         if (!empty($this->tagsoptions['tagcollid'])) {
175             return $this->tagsoptions['tagcollid'];
176         }
177         if ($this->tagsoptions['itemtype']) {
178             $this->tagsoptions['tagcollid'] = core_tag_area::get_collection($this->tagsoptions['component'],
179                     $this->tagsoptions['itemtype']);
180         } else {
181             $this->tagsoptions['tagcollid'] = core_tag_collection::get_default();
182         }
183         return $this->tagsoptions['tagcollid'];
184     }
186     /**
187      * Returns HTML for select form element.
188      *
189      * @return string
190      */
191     function toHtml(){
192         global $OUTPUT;
194         $managelink = '';
195         if (has_capability('moodle/tag:manage', context_system::instance()) && $this->showstandard) {
196             $url = new moodle_url('/tag/manage.php', array('tc' => $this->get_tag_collection()));
197             $managelink = ' ' . $OUTPUT->action_link($url, get_string('managestandardtags', 'tag'));
198         }
200         return parent::toHTML() . $managelink;
201     }
203     /**
204      * Accepts a renderer
205      *
206      * @param HTML_QuickForm_Renderer $renderer An HTML_QuickForm_Renderer object
207      * @param bool $required Whether a group is required
208      * @param string $error An error message associated with a group
209      */
210     public function accept(&$renderer, $required = false, $error = null) {
211         if ($this->is_tagging_enabled()) {
212             $renderer->renderElement($this, $required, $error);
213         } else {
214             $renderer->renderHidden($this);
215         }
216     }
218     /**
219      * Internal function to load standard tags
220      */
221     protected function load_standard_tags() {
222         global $CFG, $DB;
223         if (!$this->is_tagging_enabled()) {
224             return array();
225         }
226         $namefield = empty($CFG->keeptagnamecase) ? 'name' : 'rawname';
227         $tags = $DB->get_records_menu('tag',
228             array('isstandard' => 1, 'tagcollid' => $this->get_tag_collection()),
229             $namefield, 'id,' . $namefield);
230         return array_combine($tags, $tags);
231     }
233     /**
234      * Returns a 'safe' element's value
235      *
236      * @param  array  $submitValues array of submitted values to search
237      * @param  bool   $assoc        whether to return the value as associative array
238      * @return mixed
239      */
240     public function exportValue(&$submitValues, $assoc = false) {
241         if (!$this->is_tagging_enabled()) {
242             return $assoc ? array($this->getName() => array()) : array();
243         }
245         return parent::exportValue($submitValues, $assoc);
246     }