1 |
efrain |
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 |
/**
|
|
|
18 |
* Node (base class) used to construct a tree of availability conditions.
|
|
|
19 |
*
|
|
|
20 |
* @package core_availability
|
|
|
21 |
* @copyright 2014 The Open University
|
|
|
22 |
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
|
|
23 |
*/
|
|
|
24 |
|
|
|
25 |
namespace core_availability;
|
|
|
26 |
|
|
|
27 |
defined('MOODLE_INTERNAL') || die();
|
|
|
28 |
|
|
|
29 |
/**
|
|
|
30 |
* Node (base class) used to construct a tree of availability conditions.
|
|
|
31 |
*
|
|
|
32 |
* @package core_availability
|
|
|
33 |
* @copyright 2014 The Open University
|
|
|
34 |
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
|
|
35 |
*/
|
|
|
36 |
abstract class tree_node {
|
|
|
37 |
|
|
|
38 |
/** @var int Counter to be used in {@link tree_node::unique_sql_parameter()}. */
|
|
|
39 |
protected static $uniquesqlparametercounter = 1;
|
|
|
40 |
|
|
|
41 |
/**
|
|
|
42 |
* Determines whether this particular item is currently available
|
|
|
43 |
* according to the availability criteria.
|
|
|
44 |
*
|
|
|
45 |
* - This does not include the 'visible' setting (i.e. this might return
|
|
|
46 |
* true even if visible is false); visible is handled independently.
|
|
|
47 |
* - This does not take account of the viewhiddenactivities capability.
|
|
|
48 |
* That should apply later.
|
|
|
49 |
*
|
|
|
50 |
* The $not option is potentially confusing. This option always indicates
|
|
|
51 |
* the 'real' value of NOT. For example, a condition inside a 'NOT AND'
|
|
|
52 |
* group will get this called with $not = true, but if you put another
|
|
|
53 |
* 'NOT OR' group inside the first group, then a condition inside that will
|
|
|
54 |
* be called with $not = false. We need to use the real values, rather than
|
|
|
55 |
* the more natural use of the current value at this point inside the tree,
|
|
|
56 |
* so that the information displayed to users makes sense.
|
|
|
57 |
*
|
|
|
58 |
* @param bool $not Set true if we are inverting the condition
|
|
|
59 |
* @param \core_availability\info $info Item we're checking
|
|
|
60 |
* @param bool $grabthelot Performance hint: if true, caches information
|
|
|
61 |
* required for all course-modules, to make the front page and similar
|
|
|
62 |
* pages work more quickly (works only for current user)
|
|
|
63 |
* @param int $userid User ID to check availability for
|
|
|
64 |
* @return result Availability check result
|
|
|
65 |
*/
|
|
|
66 |
abstract public function check_available($not,
|
|
|
67 |
\core_availability\info $info, $grabthelot, $userid);
|
|
|
68 |
|
|
|
69 |
/**
|
|
|
70 |
* Checks whether this condition is actually going to be available for
|
|
|
71 |
* all users under normal circumstances.
|
|
|
72 |
*
|
|
|
73 |
* Normally, if there are any conditions, then it may be hidden. However
|
|
|
74 |
* in the case of date conditions there are some conditions which will
|
|
|
75 |
* definitely not result in it being hidden for anyone.
|
|
|
76 |
*
|
|
|
77 |
* @param bool $not Set true if we are inverting the condition
|
|
|
78 |
* @return bool True if condition will return available for everyone
|
|
|
79 |
*/
|
|
|
80 |
abstract public function is_available_for_all($not = false);
|
|
|
81 |
|
|
|
82 |
/**
|
|
|
83 |
* Saves tree data back to a structure object.
|
|
|
84 |
*
|
|
|
85 |
* @return \stdClass Structure object (ready to be made into JSON format)
|
|
|
86 |
*/
|
|
|
87 |
abstract public function save();
|
|
|
88 |
|
|
|
89 |
/**
|
|
|
90 |
* Checks whether this node should be included after restore or not. The
|
|
|
91 |
* node may be removed depending on restore settings, which you can get from
|
|
|
92 |
* the $task object.
|
|
|
93 |
*
|
|
|
94 |
* By default nodes are still included after restore.
|
|
|
95 |
*
|
|
|
96 |
* @param string $restoreid Restore ID
|
|
|
97 |
* @param int $courseid ID of target course
|
|
|
98 |
* @param \base_logger $logger Logger for any warnings
|
|
|
99 |
* @param string $name Name of this item (for use in warning messages)
|
|
|
100 |
* @param \base_task $task Current restore task
|
|
|
101 |
* @return bool True if there was any change
|
|
|
102 |
*/
|
|
|
103 |
public function include_after_restore($restoreid, $courseid, \base_logger $logger, $name,
|
|
|
104 |
\base_task $task) {
|
|
|
105 |
return true;
|
|
|
106 |
}
|
|
|
107 |
|
|
|
108 |
/**
|
|
|
109 |
* Updates this node after restore, returning true if anything changed.
|
|
|
110 |
* The default behaviour is simply to return false. If there is a problem
|
|
|
111 |
* with the update, $logger can be used to output a warning.
|
|
|
112 |
*
|
|
|
113 |
* Note: If you need information about the date offset, call
|
|
|
114 |
* \core_availability\info::get_restore_date_offset($restoreid). For
|
|
|
115 |
* information on the restoring task and its settings, call
|
|
|
116 |
* \core_availability\info::get_restore_task($restoreid).
|
|
|
117 |
*
|
|
|
118 |
* @param string $restoreid Restore ID
|
|
|
119 |
* @param int $courseid ID of target course
|
|
|
120 |
* @param \base_logger $logger Logger for any warnings
|
|
|
121 |
* @param string $name Name of this item (for use in warning messages)
|
|
|
122 |
* @return bool True if there was any change
|
|
|
123 |
*/
|
|
|
124 |
public function update_after_restore($restoreid, $courseid, \base_logger $logger, $name) {
|
|
|
125 |
return false;
|
|
|
126 |
}
|
|
|
127 |
|
|
|
128 |
/**
|
|
|
129 |
* Updates this node if it contains any references (dependencies) to the
|
|
|
130 |
* given table and id.
|
|
|
131 |
*
|
|
|
132 |
* @param string $table Table name e.g. 'course_modules'
|
|
|
133 |
* @param int $oldid Previous ID
|
|
|
134 |
* @param int $newid New ID
|
|
|
135 |
* @return bool True if it changed, otherwise false
|
|
|
136 |
*/
|
|
|
137 |
abstract public function update_dependency_id($table, $oldid, $newid);
|
|
|
138 |
|
|
|
139 |
/**
|
|
|
140 |
* Checks whether this condition applies to user lists. The default is
|
|
|
141 |
* false (the condition is used to control access, but does not prevent
|
|
|
142 |
* the student from appearing in lists).
|
|
|
143 |
*
|
|
|
144 |
* For example, group conditions apply to user lists: we do not want to
|
|
|
145 |
* include a student in a list of users if they are prohibited from
|
|
|
146 |
* accessing the activity because they don't belong to a relevant group.
|
|
|
147 |
* However, date conditions do not apply - we still want to show users
|
|
|
148 |
* in a list of people who might have submitted an assignment, even if they
|
|
|
149 |
* are no longer able to access the assignment in question because there is
|
|
|
150 |
* a date restriction.
|
|
|
151 |
*
|
|
|
152 |
* The general idea is that conditions which are likely to be permanent
|
|
|
153 |
* (group membership, user profile) apply to user lists. Conditions which
|
|
|
154 |
* are likely to be temporary (date, grade requirement) do not.
|
|
|
155 |
*
|
|
|
156 |
* Conditions which do apply to user lists must implement the
|
|
|
157 |
* filter_user_list function.
|
|
|
158 |
*
|
|
|
159 |
* @return bool True if this condition applies to user lists
|
|
|
160 |
*/
|
|
|
161 |
public function is_applied_to_user_lists() {
|
|
|
162 |
return false;
|
|
|
163 |
}
|
|
|
164 |
|
|
|
165 |
/**
|
|
|
166 |
* Tests this condition against a user list. Users who do not meet the
|
|
|
167 |
* condition will be removed from the list, unless they have the ability
|
|
|
168 |
* to view hidden activities/sections.
|
|
|
169 |
*
|
|
|
170 |
* This function must be implemented if is_applied_to_user_lists returns
|
|
|
171 |
* true. Otherwise it will not be called.
|
|
|
172 |
*
|
|
|
173 |
* The function must operate efficiently, e.g. by using a fixed number of
|
|
|
174 |
* database queries regardless of how many users are in the list.
|
|
|
175 |
*
|
|
|
176 |
* Within this function, if you need to check capabilities, please use
|
|
|
177 |
* the provided checker which caches results where possible.
|
|
|
178 |
*
|
|
|
179 |
* Conditions do not need to check the viewhiddenactivities or
|
|
|
180 |
* viewhiddensections capabilities. These are handled by
|
|
|
181 |
* core_availability\info::filter_user_list.
|
|
|
182 |
*
|
|
|
183 |
* @param array $users Array of userid => object
|
|
|
184 |
* @param bool $not True if this condition is applying in negative mode
|
|
|
185 |
* @param \core_availability\info $info Item we're checking
|
|
|
186 |
* @param capability_checker $checker
|
|
|
187 |
* @return array Filtered version of input array
|
|
|
188 |
* @throws \coding_exception If called on a condition that doesn't apply to user lists
|
|
|
189 |
*/
|
|
|
190 |
public function filter_user_list(array $users, $not,
|
|
|
191 |
\core_availability\info $info, capability_checker $checker) {
|
|
|
192 |
throw new \coding_exception('Not implemented (do not call unless '.
|
|
|
193 |
'is_applied_to_user_lists is true)');
|
|
|
194 |
}
|
|
|
195 |
|
|
|
196 |
/**
|
|
|
197 |
* Obtains SQL that returns a list of enrolled users that has been filtered
|
|
|
198 |
* by the conditions applied in the availability API, similar to calling
|
|
|
199 |
* get_enrolled_users and then filter_user_list. As for filter_user_list,
|
|
|
200 |
* this ONLY filters out users with conditions that are marked as applying
|
|
|
201 |
* to user lists. For example, group conditions are included but date
|
|
|
202 |
* conditions are not included.
|
|
|
203 |
*
|
|
|
204 |
* The returned SQL is a query that returns a list of user IDs. It does not
|
|
|
205 |
* include brackets, so you neeed to add these to make it into a subquery.
|
|
|
206 |
* You would normally use it in an SQL phrase like "WHERE u.id IN ($sql)".
|
|
|
207 |
*
|
|
|
208 |
* The SQL will be complex and may be slow. It uses named parameters (sorry,
|
|
|
209 |
* I know they are annoying, but it was unavoidable here).
|
|
|
210 |
*
|
|
|
211 |
* If there are no conditions, the returned result is array('', array()).
|
|
|
212 |
*
|
|
|
213 |
* Conditions do not need to check the viewhiddenactivities or
|
|
|
214 |
* viewhiddensections capabilities. These are handled by
|
|
|
215 |
* core_availability\info::get_user_list_sql.
|
|
|
216 |
*
|
|
|
217 |
* @param bool $not True if this condition is applying in negative mode
|
|
|
218 |
* @param \core_availability\info $info Item we're checking
|
|
|
219 |
* @param bool $onlyactive If true, only returns active enrolments
|
|
|
220 |
* @return array Array with two elements: SQL subquery and parameters array
|
|
|
221 |
* @throws \coding_exception If called on a condition that doesn't apply to user lists
|
|
|
222 |
*/
|
|
|
223 |
public function get_user_list_sql($not, \core_availability\info $info, $onlyactive) {
|
|
|
224 |
if (!$this->is_applied_to_user_lists()) {
|
|
|
225 |
throw new \coding_exception('Not implemented (do not call unless '.
|
|
|
226 |
'is_applied_to_user_lists is true)');
|
|
|
227 |
}
|
|
|
228 |
|
|
|
229 |
// Handle situation where plugin does not implement this, by returning a
|
|
|
230 |
// default (all enrolled users). This ensures compatibility with 2.7
|
|
|
231 |
// plugins and behaviour. Plugins should be updated to support this
|
|
|
232 |
// new function (if they return true to is_applied_to_user_lists).
|
|
|
233 |
debugging('Availability plugins that return true to is_applied_to_user_lists ' .
|
|
|
234 |
'should also now implement get_user_list_sql: ' . get_class($this),
|
|
|
235 |
DEBUG_DEVELOPER);
|
|
|
236 |
return get_enrolled_sql($info->get_context(), '', 0, $onlyactive);
|
|
|
237 |
}
|
|
|
238 |
|
|
|
239 |
/**
|
|
|
240 |
* Utility function for generating SQL parameters (because we can't use ?
|
|
|
241 |
* parameters because get_enrolled_sql has infected us with horrible named
|
|
|
242 |
* parameters).
|
|
|
243 |
*
|
|
|
244 |
* @param array $params Params array (value will be added to this array)
|
|
|
245 |
* @param string|int $value Value
|
|
|
246 |
* @return SQL code for the parameter, e.g. ':pr1234'
|
|
|
247 |
*/
|
|
|
248 |
protected static function unique_sql_parameter(array &$params, $value) {
|
|
|
249 |
|
|
|
250 |
// Note we intentionally do not use self:: here.
|
|
|
251 |
$count = tree_node::$uniquesqlparametercounter++;
|
|
|
252 |
$unique = 'usp' . $count;
|
|
|
253 |
$params[$unique] = $value;
|
|
|
254 |
return ':' . $unique;
|
|
|
255 |
}
|
|
|
256 |
}
|