MDL-50015 mod_imscp: New WS mod_imscp_view_imscp
[moodle.git] / mod / page / lib.php
1 <?php
3 // This file is part of Moodle - http://moodle.org/
4 //
5 // Moodle is free software: you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation, either version 3 of the License, or
8 // (at your option) any later version.
9 //
10 // Moodle is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
18 /**
19  * @package mod_page
20  * @copyright  2009 Petr Skoda (http://skodak.org)
21  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
22  */
24 defined('MOODLE_INTERNAL') || die;
26 /**
27  * List of features supported in Page module
28  * @param string $feature FEATURE_xx constant for requested feature
29  * @return mixed True if module supports feature, false if not, null if doesn't know
30  */
31 function page_supports($feature) {
32     switch($feature) {
33         case FEATURE_MOD_ARCHETYPE:           return MOD_ARCHETYPE_RESOURCE;
34         case FEATURE_GROUPS:                  return false;
35         case FEATURE_GROUPINGS:               return false;
36         case FEATURE_MOD_INTRO:               return true;
37         case FEATURE_COMPLETION_TRACKS_VIEWS: return true;
38         case FEATURE_GRADE_HAS_GRADE:         return false;
39         case FEATURE_GRADE_OUTCOMES:          return false;
40         case FEATURE_BACKUP_MOODLE2:          return true;
41         case FEATURE_SHOW_DESCRIPTION:        return true;
43         default: return null;
44     }
45 }
47 /**
48  * Returns all other caps used in module
49  * @return array
50  */
51 function page_get_extra_capabilities() {
52     return array('moodle/site:accessallgroups');
53 }
55 /**
56  * This function is used by the reset_course_userdata function in moodlelib.
57  * @param $data the data submitted from the reset course.
58  * @return array status array
59  */
60 function page_reset_userdata($data) {
61     return array();
62 }
64 /**
65  * List the actions that correspond to a view of this module.
66  * This is used by the participation report.
67  *
68  * Note: This is not used by new logging system. Event with
69  *       crud = 'r' and edulevel = LEVEL_PARTICIPATING will
70  *       be considered as view action.
71  *
72  * @return array
73  */
74 function page_get_view_actions() {
75     return array('view','view all');
76 }
78 /**
79  * List the actions that correspond to a post of this module.
80  * This is used by the participation report.
81  *
82  * Note: This is not used by new logging system. Event with
83  *       crud = ('c' || 'u' || 'd') and edulevel = LEVEL_PARTICIPATING
84  *       will be considered as post action.
85  *
86  * @return array
87  */
88 function page_get_post_actions() {
89     return array('update', 'add');
90 }
92 /**
93  * Add page instance.
94  * @param stdClass $data
95  * @param mod_page_mod_form $mform
96  * @return int new page instance id
97  */
98 function page_add_instance($data, $mform = null) {
99     global $CFG, $DB;
100     require_once("$CFG->libdir/resourcelib.php");
102     $cmid = $data->coursemodule;
104     $data->timemodified = time();
105     $displayoptions = array();
106     if ($data->display == RESOURCELIB_DISPLAY_POPUP) {
107         $displayoptions['popupwidth']  = $data->popupwidth;
108         $displayoptions['popupheight'] = $data->popupheight;
109     }
110     $displayoptions['printheading'] = $data->printheading;
111     $displayoptions['printintro']   = $data->printintro;
112     $data->displayoptions = serialize($displayoptions);
114     if ($mform) {
115         $data->content       = $data->page['text'];
116         $data->contentformat = $data->page['format'];
117     }
119     $data->id = $DB->insert_record('page', $data);
121     // we need to use context now, so we need to make sure all needed info is already in db
122     $DB->set_field('course_modules', 'instance', $data->id, array('id'=>$cmid));
123     $context = context_module::instance($cmid);
125     if ($mform and !empty($data->page['itemid'])) {
126         $draftitemid = $data->page['itemid'];
127         $data->content = file_save_draft_area_files($draftitemid, $context->id, 'mod_page', 'content', 0, page_get_editor_options($context), $data->content);
128         $DB->update_record('page', $data);
129     }
131     return $data->id;
134 /**
135  * Update page instance.
136  * @param object $data
137  * @param object $mform
138  * @return bool true
139  */
140 function page_update_instance($data, $mform) {
141     global $CFG, $DB;
142     require_once("$CFG->libdir/resourcelib.php");
144     $cmid        = $data->coursemodule;
145     $draftitemid = $data->page['itemid'];
147     $data->timemodified = time();
148     $data->id           = $data->instance;
149     $data->revision++;
151     $displayoptions = array();
152     if ($data->display == RESOURCELIB_DISPLAY_POPUP) {
153         $displayoptions['popupwidth']  = $data->popupwidth;
154         $displayoptions['popupheight'] = $data->popupheight;
155     }
156     $displayoptions['printheading'] = $data->printheading;
157     $displayoptions['printintro']   = $data->printintro;
158     $data->displayoptions = serialize($displayoptions);
160     $data->content       = $data->page['text'];
161     $data->contentformat = $data->page['format'];
163     $DB->update_record('page', $data);
165     $context = context_module::instance($cmid);
166     if ($draftitemid) {
167         $data->content = file_save_draft_area_files($draftitemid, $context->id, 'mod_page', 'content', 0, page_get_editor_options($context), $data->content);
168         $DB->update_record('page', $data);
169     }
171     return true;
174 /**
175  * Delete page instance.
176  * @param int $id
177  * @return bool true
178  */
179 function page_delete_instance($id) {
180     global $DB;
182     if (!$page = $DB->get_record('page', array('id'=>$id))) {
183         return false;
184     }
186     // note: all context files are deleted automatically
188     $DB->delete_records('page', array('id'=>$page->id));
190     return true;
193 /**
194  * Given a course_module object, this function returns any
195  * "extra" information that may be needed when printing
196  * this activity in a course listing.
197  *
198  * See {@link get_array_of_activities()} in course/lib.php
199  *
200  * @param stdClass $coursemodule
201  * @return cached_cm_info Info to customise main page display
202  */
203 function page_get_coursemodule_info($coursemodule) {
204     global $CFG, $DB;
205     require_once("$CFG->libdir/resourcelib.php");
207     if (!$page = $DB->get_record('page', array('id'=>$coursemodule->instance),
208             'id, name, display, displayoptions, intro, introformat')) {
209         return NULL;
210     }
212     $info = new cached_cm_info();
213     $info->name = $page->name;
215     if ($coursemodule->showdescription) {
216         // Convert intro to html. Do not filter cached version, filters run at display time.
217         $info->content = format_module_intro('page', $page, $coursemodule->id, false);
218     }
220     if ($page->display != RESOURCELIB_DISPLAY_POPUP) {
221         return $info;
222     }
224     $fullurl = "$CFG->wwwroot/mod/page/view.php?id=$coursemodule->id&amp;inpopup=1";
225     $options = empty($page->displayoptions) ? array() : unserialize($page->displayoptions);
226     $width  = empty($options['popupwidth'])  ? 620 : $options['popupwidth'];
227     $height = empty($options['popupheight']) ? 450 : $options['popupheight'];
228     $wh = "width=$width,height=$height,toolbar=no,location=no,menubar=no,copyhistory=no,status=no,directories=no,scrollbars=yes,resizable=yes";
229     $info->onclick = "window.open('$fullurl', '', '$wh'); return false;";
231     return $info;
235 /**
236  * Lists all browsable file areas
237  *
238  * @package  mod_page
239  * @category files
240  * @param stdClass $course course object
241  * @param stdClass $cm course module object
242  * @param stdClass $context context object
243  * @return array
244  */
245 function page_get_file_areas($course, $cm, $context) {
246     $areas = array();
247     $areas['content'] = get_string('content', 'page');
248     return $areas;
251 /**
252  * File browsing support for page module content area.
253  *
254  * @package  mod_page
255  * @category files
256  * @param stdClass $browser file browser instance
257  * @param stdClass $areas file areas
258  * @param stdClass $course course object
259  * @param stdClass $cm course module object
260  * @param stdClass $context context object
261  * @param string $filearea file area
262  * @param int $itemid item ID
263  * @param string $filepath file path
264  * @param string $filename file name
265  * @return file_info instance or null if not found
266  */
267 function page_get_file_info($browser, $areas, $course, $cm, $context, $filearea, $itemid, $filepath, $filename) {
268     global $CFG;
270     if (!has_capability('moodle/course:managefiles', $context)) {
271         // students can not peak here!
272         return null;
273     }
275     $fs = get_file_storage();
277     if ($filearea === 'content') {
278         $filepath = is_null($filepath) ? '/' : $filepath;
279         $filename = is_null($filename) ? '.' : $filename;
281         $urlbase = $CFG->wwwroot.'/pluginfile.php';
282         if (!$storedfile = $fs->get_file($context->id, 'mod_page', 'content', 0, $filepath, $filename)) {
283             if ($filepath === '/' and $filename === '.') {
284                 $storedfile = new virtual_root_file($context->id, 'mod_page', 'content', 0);
285             } else {
286                 // not found
287                 return null;
288             }
289         }
290         require_once("$CFG->dirroot/mod/page/locallib.php");
291         return new page_content_file_info($browser, $context, $storedfile, $urlbase, $areas[$filearea], true, true, true, false);
292     }
294     // note: page_intro handled in file_browser automatically
296     return null;
299 /**
300  * Serves the page files.
301  *
302  * @package  mod_page
303  * @category files
304  * @param stdClass $course course object
305  * @param stdClass $cm course module object
306  * @param stdClass $context context object
307  * @param string $filearea file area
308  * @param array $args extra arguments
309  * @param bool $forcedownload whether or not force download
310  * @param array $options additional options affecting the file serving
311  * @return bool false if file not found, does not return if found - just send the file
312  */
313 function page_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload, array $options=array()) {
314     global $CFG, $DB;
315     require_once("$CFG->libdir/resourcelib.php");
317     if ($context->contextlevel != CONTEXT_MODULE) {
318         return false;
319     }
321     require_course_login($course, true, $cm);
322     if (!has_capability('mod/page:view', $context)) {
323         return false;
324     }
326     if ($filearea !== 'content') {
327         // intro is handled automatically in pluginfile.php
328         return false;
329     }
331     // $arg could be revision number or index.html
332     $arg = array_shift($args);
333     if ($arg == 'index.html' || $arg == 'index.htm') {
334         // serve page content
335         $filename = $arg;
337         if (!$page = $DB->get_record('page', array('id'=>$cm->instance), '*', MUST_EXIST)) {
338             return false;
339         }
341         // remove @@PLUGINFILE@@/
342         $content = str_replace('@@PLUGINFILE@@/', '', $page->content);
344         $formatoptions = new stdClass;
345         $formatoptions->noclean = true;
346         $formatoptions->overflowdiv = true;
347         $formatoptions->context = $context;
348         $content = format_text($content, $page->contentformat, $formatoptions);
350         send_file($content, $filename, 0, 0, true, true);
351     } else {
352         $fs = get_file_storage();
353         $relativepath = implode('/', $args);
354         $fullpath = "/$context->id/mod_page/$filearea/0/$relativepath";
355         if (!$file = $fs->get_file_by_hash(sha1($fullpath)) or $file->is_directory()) {
356             $page = $DB->get_record('page', array('id'=>$cm->instance), 'id, legacyfiles', MUST_EXIST);
357             if ($page->legacyfiles != RESOURCELIB_LEGACYFILES_ACTIVE) {
358                 return false;
359             }
360             if (!$file = resourcelib_try_file_migration('/'.$relativepath, $cm->id, $cm->course, 'mod_page', 'content', 0)) {
361                 return false;
362             }
363             //file migrate - update flag
364             $page->legacyfileslast = time();
365             $DB->update_record('page', $page);
366         }
368         // finally send the file
369         send_stored_file($file, null, 0, $forcedownload, $options);
370     }
373 /**
374  * Return a list of page types
375  * @param string $pagetype current page type
376  * @param stdClass $parentcontext Block's parent context
377  * @param stdClass $currentcontext Current context of block
378  */
379 function page_page_type_list($pagetype, $parentcontext, $currentcontext) {
380     $module_pagetype = array('mod-page-*'=>get_string('page-mod-page-x', 'page'));
381     return $module_pagetype;
384 /**
385  * Export page resource contents
386  *
387  * @return array of file content
388  */
389 function page_export_contents($cm, $baseurl) {
390     global $CFG, $DB;
391     $contents = array();
392     $context = context_module::instance($cm->id);
394     $page = $DB->get_record('page', array('id'=>$cm->instance), '*', MUST_EXIST);
396     // page contents
397     $fs = get_file_storage();
398     $files = $fs->get_area_files($context->id, 'mod_page', 'content', 0, 'sortorder DESC, id ASC', false);
399     foreach ($files as $fileinfo) {
400         $file = array();
401         $file['type']         = 'file';
402         $file['filename']     = $fileinfo->get_filename();
403         $file['filepath']     = $fileinfo->get_filepath();
404         $file['filesize']     = $fileinfo->get_filesize();
405         $file['fileurl']      = file_encode_url("$CFG->wwwroot/" . $baseurl, '/'.$context->id.'/mod_page/content/'.$page->revision.$fileinfo->get_filepath().$fileinfo->get_filename(), true);
406         $file['timecreated']  = $fileinfo->get_timecreated();
407         $file['timemodified'] = $fileinfo->get_timemodified();
408         $file['sortorder']    = $fileinfo->get_sortorder();
409         $file['userid']       = $fileinfo->get_userid();
410         $file['author']       = $fileinfo->get_author();
411         $file['license']      = $fileinfo->get_license();
412         $contents[] = $file;
413     }
415     // page html conent
416     $filename = 'index.html';
417     $pagefile = array();
418     $pagefile['type']         = 'file';
419     $pagefile['filename']     = $filename;
420     $pagefile['filepath']     = '/';
421     $pagefile['filesize']     = 0;
422     $pagefile['fileurl']      = file_encode_url("$CFG->wwwroot/" . $baseurl, '/'.$context->id.'/mod_page/content/' . $filename, true);
423     $pagefile['timecreated']  = null;
424     $pagefile['timemodified'] = $page->timemodified;
425     // make this file as main file
426     $pagefile['sortorder']    = 1;
427     $pagefile['userid']       = null;
428     $pagefile['author']       = null;
429     $pagefile['license']      = null;
430     $contents[] = $pagefile;
432     return $contents;
435 /**
436  * Register the ability to handle drag and drop file uploads
437  * @return array containing details of the files / types the mod can handle
438  */
439 function page_dndupload_register() {
440     return array('types' => array(
441                      array('identifier' => 'text/html', 'message' => get_string('createpage', 'page')),
442                      array('identifier' => 'text', 'message' => get_string('createpage', 'page'))
443                  ));
446 /**
447  * Handle a file that has been uploaded
448  * @param object $uploadinfo details of the file / content that has been uploaded
449  * @return int instance id of the newly created mod
450  */
451 function page_dndupload_handle($uploadinfo) {
452     // Gather the required info.
453     $data = new stdClass();
454     $data->course = $uploadinfo->course->id;
455     $data->name = $uploadinfo->displayname;
456     $data->intro = '<p>'.$uploadinfo->displayname.'</p>';
457     $data->introformat = FORMAT_HTML;
458     if ($uploadinfo->type == 'text/html') {
459         $data->contentformat = FORMAT_HTML;
460         $data->content = clean_param($uploadinfo->content, PARAM_CLEANHTML);
461     } else {
462         $data->contentformat = FORMAT_PLAIN;
463         $data->content = clean_param($uploadinfo->content, PARAM_TEXT);
464     }
465     $data->coursemodule = $uploadinfo->coursemodule;
467     // Set the display options to the site defaults.
468     $config = get_config('page');
469     $data->display = $config->display;
470     $data->popupheight = $config->popupheight;
471     $data->popupwidth = $config->popupwidth;
472     $data->printheading = $config->printheading;
473     $data->printintro = $config->printintro;
475     return page_add_instance($data, null);
478 /**
479  * Mark the activity completed (if required) and trigger the course_module_viewed event.
480  *
481  * @param  stdClass $page       page object
482  * @param  stdClass $course     course object
483  * @param  stdClass $cm         course module object
484  * @param  stdClass $context    context object
485  * @since Moodle 3.0
486  */
487 function page_view($page, $course, $cm, $context) {
489     // Trigger course_module_viewed event.
490     $params = array(
491         'context' => $context,
492         'objectid' => $page->id
493     );
495     $event = \mod_page\event\course_module_viewed::create($params);
496     $event->add_record_snapshot('course_modules', $cm);
497     $event->add_record_snapshot('course', $course);
498     $event->add_record_snapshot('page', $page);
499     $event->trigger();
501     // Completion.
502     $completion = new completion_info($course);
503     $completion->set_module_viewed($cm);