Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
<?php
2
// This file is part of Moodle - https://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 <https://www.gnu.org/licenses/>.
16
 
17
namespace core\context;
18
 
19
use core\context;
20
use stdClass;
21
use coding_exception, moodle_url;
22
 
23
/**
24
 * Course context class
25
 *
26
 * @package   core_access
27
 * @category  access
28
 * @copyright Petr Skoda
29
 * @license   https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
30
 * @since     Moodle 4.2
31
 */
32
class course extends context {
33
    /** @var int numeric context level value matching legacy CONTEXT_COURSE */
34
    public const LEVEL = 50;
35
 
36
    /**
37
     * Please use \core\context\course::instance($courseid) if you need the instance of context.
38
     * Alternatively if you know only the context id use \core\context::instance_by_id($contextid)
39
     *
40
     * @param stdClass $record
41
     */
42
    protected function __construct(stdClass $record) {
43
        parent::__construct($record);
44
        if ($record->contextlevel != self::LEVEL) {
45
            throw new coding_exception('Invalid $record->contextlevel in core\context\course constructor.');
46
        }
47
    }
48
 
49
    /**
50
     * Returns short context name.
51
     *
52
     * @since Moodle 4.2
53
     *
54
     * @return string
55
     */
56
    public static function get_short_name(): string {
57
        return 'course';
58
    }
59
 
60
    /**
61
     * Returns human readable context level name.
62
     *
63
     * @return string the human readable context level name.
64
     */
65
    public static function get_level_name() {
66
        return get_string('course');
67
    }
68
 
69
    /**
70
     * Returns human readable context identifier.
71
     *
72
     * @param boolean $withprefix whether to prefix the name of the context with Course
73
     * @param boolean $short whether to use the short name of the thing.
74
     * @param bool $escape Whether the returned category name is to be HTML escaped or not.
75
     * @return string the human readable context name.
76
     */
77
    public function get_context_name($withprefix = true, $short = false, $escape = true) {
78
        global $DB;
79
 
80
        $name = '';
81
        if ($this->_instanceid == SITEID) {
82
            $name = get_string('frontpage', 'admin');
83
        } else {
84
            if ($course = $DB->get_record('course', array('id' => $this->_instanceid))) {
85
                if ($withprefix) {
86
                    $name = get_string('course').': ';
87
                }
88
                if ($short) {
89
                    if (!$escape) {
90
                        $name .= format_string($course->shortname, true, array('context' => $this, 'escape' => false));
91
                    } else {
92
                        $name .= format_string($course->shortname, true, array('context' => $this));
93
                    }
94
                } else {
95
                    if (!$escape) {
96
                        $name .= format_string(get_course_display_name_for_list($course), true, array('context' => $this,
97
                            'escape' => false));
98
                    } else {
99
                        $name .= format_string(get_course_display_name_for_list($course), true, array('context' => $this));
100
                    }
101
                }
102
            }
103
        }
104
        return $name;
105
    }
106
 
107
    /**
108
     * Returns the most relevant URL for this context.
109
     *
110
     * @return moodle_url
111
     */
112
    public function get_url() {
113
        if ($this->_instanceid != SITEID) {
114
            return new moodle_url('/course/view.php', array('id' => $this->_instanceid));
115
        }
116
 
117
        return new moodle_url('/');
118
    }
119
 
120
    /**
121
     * Returns context instance database name.
122
     *
123
     * @return string|null table name for all levels except system.
124
     */
125
    protected static function get_instance_table(): ?string {
126
        return 'course';
127
    }
128
 
129
    /**
130
     * Returns list of columns that can be used from behat
131
     * to look up context by reference.
132
     *
133
     * @return array list of column names from instance table
134
     */
135
    protected static function get_behat_reference_columns(): array {
136
        return ['shortname'];
137
    }
138
 
139
    /**
140
     * Returns list of all role archetypes that are compatible
141
     * with role assignments in context level.
142
     * @since Moodle 4.2
143
     *
144
     * @return int[]
145
     */
146
    protected static function get_compatible_role_archetypes(): array {
147
        return ['manager', 'editingteacher', 'teacher', 'student'];
148
    }
149
 
150
    /**
151
     * Returns list of all possible parent context levels.
152
     * @since Moodle 4.2
153
     *
154
     * @return int[]
155
     */
156
    public static function get_possible_parent_levels(): array {
157
        return [coursecat::LEVEL];
158
    }
159
 
160
    /**
161
     * Returns array of relevant context capability records.
162
     *
163
     * @param string $sort
164
     * @return array
165
     */
166
    public function get_capabilities(string $sort = self::DEFAULT_CAPABILITY_SORT) {
167
        global $DB;
168
 
169
        $levels = \core\context_helper::get_child_levels(self::LEVEL);
170
        $levels[] = self::LEVEL;
171
 
172
        return $DB->get_records_list('capabilities', 'contextlevel', $levels, $sort);
173
    }
174
 
175
    /**
176
     * Is this context part of any course? If yes return course context.
177
     *
178
     * @param bool $strict true means throw exception if not found, false means return false if not found
179
     * @return course context of the enclosing course, null if not found or exception
180
     */
181
    public function get_course_context($strict = true) {
182
        return $this;
183
    }
184
 
185
    /**
186
     * Returns course context instance.
187
     *
188
     * @param int $courseid id from {course} table
189
     * @param int $strictness
190
     * @return course|false context instance
191
     */
192
    public static function instance($courseid, $strictness = MUST_EXIST) {
193
        global $DB;
194
 
195
        if ($context = context::cache_get(self::LEVEL, $courseid)) {
196
            return $context;
197
        }
198
 
199
        if (!$record = $DB->get_record('context', array('contextlevel' => self::LEVEL, 'instanceid' => $courseid))) {
200
            if ($course = $DB->get_record('course', array('id' => $courseid), 'id,category', $strictness)) {
201
                if ($course->category) {
202
                    $parentcontext = coursecat::instance($course->category);
203
                    $record = context::insert_context_record(self::LEVEL, $course->id, $parentcontext->path);
204
                } else {
205
                    $record = context::insert_context_record(self::LEVEL, $course->id, '/'.SYSCONTEXTID, 0);
206
                }
207
            }
208
        }
209
 
210
        if ($record) {
211
            $context = new course($record);
212
            context::cache_add($context);
213
            return $context;
214
        }
215
 
216
        return false;
217
    }
218
 
219
    /**
220
     * Create missing context instances at course context level
221
     */
222
    protected static function create_level_instances() {
223
        global $DB;
224
 
225
        $sql = "SELECT ".self::LEVEL.", c.id
226
                  FROM {course} c
227
                 WHERE NOT EXISTS (SELECT 'x'
228
                                     FROM {context} cx
229
                                    WHERE c.id = cx.instanceid AND cx.contextlevel=".self::LEVEL.")";
230
        $contextdata = $DB->get_recordset_sql($sql);
231
        foreach ($contextdata as $context) {
232
            context::insert_context_record(self::LEVEL, $context->id, null);
233
        }
234
        $contextdata->close();
235
    }
236
 
237
    /**
238
     * Returns sql necessary for purging of stale context instances.
239
     *
240
     * @return string cleanup SQL
241
     */
242
    protected static function get_cleanup_sql() {
243
        $sql = "
244
                  SELECT c.*
245
                    FROM {context} c
246
         LEFT OUTER JOIN {course} co ON c.instanceid = co.id
247
                   WHERE co.id IS NULL AND c.contextlevel = ".self::LEVEL."
248
               ";
249
 
250
        return $sql;
251
    }
252
 
253
    /**
254
     * Rebuild context paths and depths at course context level.
255
     *
256
     * @param bool $force
257
     */
258
    protected static function build_paths($force) {
259
        global $DB;
260
 
261
        if ($force || $DB->record_exists_select('context', "contextlevel = ".self::LEVEL." AND (depth = 0 OR path IS NULL)")) {
262
            if ($force) {
263
                $ctxemptyclause = $emptyclause = '';
264
            } else {
265
                $ctxemptyclause = "AND (ctx.path IS NULL OR ctx.depth = 0)";
266
                $emptyclause = "AND ({context}.path IS NULL OR {context}.depth = 0)";
267
            }
268
 
269
            $base = '/'.SYSCONTEXTID;
270
 
271
            // Standard frontpage.
272
            $sql = "UPDATE {context}
273
                       SET depth = 2,
274
                           path = ".$DB->sql_concat("'$base/'", 'id')."
275
                     WHERE contextlevel = ".self::LEVEL."
276
                           AND EXISTS (SELECT 'x'
277
                                         FROM {course} c
278
                                        WHERE c.id = {context}.instanceid AND c.category = 0)
279
                           $emptyclause";
280
            $DB->execute($sql);
281
 
282
            // Standard courses.
283
            $sql = "INSERT INTO {context_temp} (id, path, depth, locked)
284
                    SELECT ctx.id, ".$DB->sql_concat('pctx.path', "'/'", 'ctx.id').", pctx.depth+1, ctx.locked
285
                      FROM {context} ctx
286
                      JOIN {course} c ON (c.id = ctx.instanceid AND ctx.contextlevel = ".self::LEVEL." AND c.category <> 0)
287
                      JOIN {context} pctx ON (pctx.instanceid = c.category AND pctx.contextlevel = ".coursecat::LEVEL.")
288
                     WHERE pctx.path IS NOT NULL AND pctx.depth > 0
289
                           $ctxemptyclause";
290
            $trans = $DB->start_delegated_transaction();
291
            $DB->delete_records('context_temp');
292
            $DB->execute($sql);
293
            context::merge_context_temp_table();
294
            $DB->delete_records('context_temp');
295
            $trans->allow_commit();
296
        }
297
    }
298
}