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 - 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
 * Content API File Area definition.
19
 *
20
 * @package     core_files
21
 * @copyright   2020 Andrew Nicols <andrew@nicols.co.uk>
22
 * @license     http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23
 */
24
namespace core;
25
 
26
use coding_exception;
27
use context;
28
use core\content\export\exporters\course_exporter;
29
use core\content\export\exporters\component_exporter;
30
use core\content\export\exporters\abstract_mod_exporter;
31
use core\content\export\zipwriter;
32
use core_component;
33
use moodle_url;
34
use stdClass;
35
use stored_file;
36
 
37
/**
38
 * The Content API allows all parts of Moodle to determine details about content within a component, or plugintype.
39
 *
40
 * This includes the description of files.
41
 *
42
 * @copyright   2020 Andrew Nicols <andrew@nicols.co.uk>
43
 * @license     http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
44
 */
45
class content {
46
 
47
    /**
48
     * Check whether the specified user can export content for the specified context.
49
     *
50
     * @param   context $currentcontext
51
     * @param   stdClass $user
52
     * @return  bool
53
     */
54
    public static function can_export_context(context $currentcontext, stdClass $user): bool {
55
        global $CFG;
56
 
57
        $canexport = false;
58
 
59
        if ($currentcontext->contextlevel == CONTEXT_COURSE) {
60
            if ($CFG->downloadcoursecontentallowed &&
61
                    has_capability('moodle/course:downloadcoursecontent', $currentcontext, $user)) {
62
 
63
                $courseinfo = get_fast_modinfo($currentcontext->instanceid)->get_course();
64
 
65
                // If enabled/disabled explicitly set on course, use that as the course setting, otherwise use site default.
66
                if (isset($courseinfo->downloadcontent) && $courseinfo->downloadcontent != DOWNLOAD_COURSE_CONTENT_SITE_DEFAULT) {
67
                    $canexport = $courseinfo->downloadcontent;
68
                } else {
69
                    $canexport = get_config('moodlecourse')->downloadcontentsitedefault;
70
                }
71
 
72
            }
73
        } else if ($currentcontext->contextlevel == CONTEXT_MODULE) {
74
            $cm = get_fast_modinfo($currentcontext->get_course_context()->instanceid)->cms[$currentcontext->instanceid];
75
 
76
            // Do not export course content if disabled at activity level.
77
            if (isset($cm->downloadcontent) && $cm->downloadcontent == DOWNLOAD_COURSE_CONTENT_DISABLED) {
78
                return false;
79
            }
80
 
81
            // Modules can only be exported if exporting is allowed in their course context.
82
            $canexport = self::can_export_context($currentcontext->get_course_context(), $user);
83
        }
84
 
85
        return $canexport;
86
    }
87
 
88
    /**
89
     * Export content for the specified context.
90
     *
91
     * @param   context $requestedcontext The context to be exported
92
     * @param   stdClass $user The user being exported
93
     * @param   zipwriter $archive The Zip Archive to export to
94
     */
95
    public static function export_context(context $requestedcontext, stdClass $user, zipwriter $archive): void {
96
        global $USER;
97
 
98
        if ($requestedcontext->contextlevel != CONTEXT_COURSE) {
99
            throw new coding_exception('The Content Export API currently only supports the export of courses');
100
        }
101
 
102
        if ($USER->id != $user->id) {
103
            throw new coding_exception('The Content Export API currently only supports export of the current user');
104
        }
105
 
106
        // Ensure that the zipwriter is aware of the requested context.
107
        $archive->set_root_context($requestedcontext);
108
 
109
        // Fetch all child contexts, indexed by path.
110
        $contextlist = [
111
            $requestedcontext->path => $requestedcontext,
112
        ];
113
        foreach ($requestedcontext->get_child_contexts() as $context) {
114
            $contextlist[$context->path] = $context;
115
        }
116
 
117
        // Reverse the order by key - this ensures that child contexts are processed before their parent.
118
        krsort($contextlist);
119
 
120
        // Get the course modinfo.
121
        $modinfo = get_fast_modinfo($requestedcontext->instanceid);
122
 
123
        // Filter out any context which cannot be exported.
124
        $contextlist = array_filter($contextlist, function($context) use ($user, $modinfo): bool {
125
            if ($context->contextlevel == CONTEXT_COURSE) {
126
                return self::can_export_context($context, $user);
127
            }
128
 
129
            if ($context->contextlevel == CONTEXT_MODULE) {
130
                if (empty($modinfo->cms[$context->instanceid])) {
131
                    // Unknown coursemodule in the course.
132
                    return false;
133
                }
134
 
135
                $cm = $modinfo->cms[$context->instanceid];
136
 
137
                if (!$cm->uservisible) {
138
                    // This user cannot view the activity.
139
                    return false;
140
                }
141
 
142
                // Defer to setting checks.
143
                return self::can_export_context($context, $user);
144
            }
145
 
146
            // Only course and activities are supported at this time.
147
            return false;
148
        });
149
 
150
        // Export each context.
151
        $exportedcontexts = [];
152
        $coursecontroller = new course_exporter($requestedcontext->get_course_context(), $user, $archive);
153
        foreach ($contextlist as $context) {
154
            if ($context->contextlevel === CONTEXT_MODULE) {
155
                $cm = $modinfo->cms[$context->instanceid];
156
                $component = "mod_{$cm->modname}";
157
 
158
                // Check for a specific implementation for this module.
159
                // This will export any content specific to this activity.
160
                // For example, in mod_folder it will export the list of folders.
161
                $classname = component_exporter::get_classname_for_component($component);
162
                $exportables = [];
163
                if (class_exists($classname) && is_a($classname, abstract_mod_exporter::class, true)) {
164
                    $controller = new $classname($context, $component, $user, $archive);
165
                    $exportables = $controller->get_exportables();
166
                }
167
 
168
                // Pass the exportable content to the  course controller for export.
169
                $coursecontroller->export_mod_content($context, $exportables);
170
 
171
                $exportedcontexts[$context->id] = $context;
172
            } else if ($context->contextlevel === CONTEXT_COURSE) {
173
                // Export the course content.
174
                $coursecontroller->export_course($exportedcontexts);
175
            }
176
        }
177
 
178
        $archive->finish();
179
    }
180
}