MDL-51117 JavaScript: Convert alert to M.core.alert in dndupload
[moodle.git] / course / dnduploadlib.php
CommitLineData
32528f94
DS
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 * Library to handle drag and drop course uploads
19 *
20 * @package core
21 * @subpackage lib
22 * @copyright 2012 Davo smith
23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24 */
25
26defined('MOODLE_INTERNAL') || die();
27
28require_once($CFG->dirroot.'/repository/lib.php');
29require_once($CFG->dirroot.'/repository/upload/lib.php');
30require_once($CFG->dirroot.'/course/lib.php');
31
32/**
33 * Add the Javascript to enable drag and drop upload to a course page
34 *
35 * @param object $course The currently displayed course
5103b5e6
DS
36 * @param array $modnames The list of enabled (visible) modules on this site
37 * @return void
32528f94 38 */
5103b5e6 39function dndupload_add_to_course($course, $modnames) {
32528f94
DS
40 global $CFG, $PAGE;
41
3970a471 42 $showstatus = optional_param('notifyeditingon', false, PARAM_BOOL);
6c0ae99b 43
32528f94 44 // Get all handlers.
5103b5e6
DS
45 $handler = new dndupload_handler($course, $modnames);
46 $jsdata = $handler->get_js_data();
47 if (empty($jsdata->types) && empty($jsdata->filehandlers)) {
48 return; // No valid handlers - don't enable drag and drop.
49 }
32528f94
DS
50
51 // Add the javascript to the page.
52 $jsmodule = array(
33b24bdd 53 'name' => 'coursedndupload',
3f534371 54 'fullpath' => '/course/dndupload.js',
32528f94 55 'strings' => array(
33b24bdd 56 array('addfilehere', 'moodle'),
b64300fc
DS
57 array('dndworkingfiletextlink', 'moodle'),
58 array('dndworkingfilelink', 'moodle'),
59 array('dndworkingfiletext', 'moodle'),
60 array('dndworkingfile', 'moodle'),
61 array('dndworkingtextlink', 'moodle'),
62 array('dndworkingtext', 'moodle'),
63 array('dndworkinglink', 'moodle'),
296af14b 64 array('namedfiletoolarge', 'moodle'),
33b24bdd
DS
65 array('actionchoice', 'moodle'),
66 array('servererror', 'moodle'),
67 array('upload', 'moodle'),
68 array('cancel', 'moodle')
32528f94 69 ),
66079e28 70 'requires' => array('node', 'event', 'json', 'anim')
32528f94
DS
71 );
72 $vars = array(
73 array('courseid' => $course->id,
74 'maxbytes' => get_max_upload_file_size($CFG->maxbytes, $course->maxbytes),
6c0ae99b
DS
75 'handlers' => $handler->get_js_data(),
76 'showstatus' => $showstatus)
32528f94
DS
77 );
78
79 $PAGE->requires->js_init_call('M.course_dndupload.init', $vars, true, $jsmodule);
80}
81
82
83/**
84 * Stores all the information about the available dndupload handlers
85 *
86 * @package core
87 * @copyright 2012 Davo Smith
88 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
89 */
90class dndupload_handler {
91
92 /**
93 * @var array A list of all registered mime types that can be dropped onto a course
94 * along with the modules that will handle them.
95 */
96 protected $types = array();
97
98 /**
99 * @var array A list of the different file types (extensions) that different modules
100 * will handle.
101 */
102 protected $filehandlers = array();
103
e6a0f101
MG
104 /**
105 * @var context_course|null
106 */
107 protected $context = null;
108
32528f94
DS
109 /**
110 * Gather a list of dndupload handlers from the different mods
111 *
112 * @param object $course The course this is being added to (to check course_allowed_module() )
113 */
5103b5e6 114 public function __construct($course, $modnames = null) {
04348400 115 global $CFG, $PAGE;
32528f94
DS
116
117 // Add some default types to handle.
118 // Note: 'Files' type is hard-coded into the Javascript as this needs to be ...
119 // ... treated a little differently.
1c14b1c1 120 $this->register_type('url', array('url', 'text/uri-list', 'text/x-moz-url'), get_string('addlinkhere', 'moodle'),
66079e28 121 get_string('nameforlink', 'moodle'), get_string('whatforlink', 'moodle'), 10);
1c14b1c1 122 $this->register_type('text/html', array('text/html'), get_string('addpagehere', 'moodle'),
66079e28 123 get_string('nameforpage', 'moodle'), get_string('whatforpage', 'moodle'), 20);
1c14b1c1 124 $this->register_type('text', array('text', 'text/plain'), get_string('addpagehere', 'moodle'),
66079e28 125 get_string('nameforpage', 'moodle'), get_string('whatforpage', 'moodle'), 30);
32528f94 126
e6a0f101
MG
127 $this->context = context_course::instance($course->id);
128
32528f94 129 // Loop through all modules to find handlers.
abed5d65
DS
130 $mods = get_plugin_list_with_function('mod', 'dndupload_register');
131 foreach ($mods as $component => $funcname) {
56da374e 132 list($modtype, $modname) = core_component::normalize_component($component);
5103b5e6
DS
133 if ($modnames && !array_key_exists($modname, $modnames)) {
134 continue; // Module is deactivated (hidden) at the site level.
135 }
32528f94 136 if (!course_allowed_module($course, $modname)) {
5103b5e6 137 continue; // User does not have permission to add this module to the course.
32528f94 138 }
abed5d65 139 $resp = $funcname();
32528f94
DS
140 if (!$resp) {
141 continue;
142 }
143 if (isset($resp['files'])) {
144 foreach ($resp['files'] as $file) {
1c14b1c1 145 $this->register_file_handler($file['extension'], $modname, $file['message']);
32528f94
DS
146 }
147 }
148 if (isset($resp['addtypes'])) {
149 foreach ($resp['addtypes'] as $type) {
150 if (isset($type['priority'])) {
151 $priority = $type['priority'];
152 } else {
153 $priority = 100;
154 }
66079e28
DS
155 if (!isset($type['handlermessage'])) {
156 $type['handlermessage'] = '';
157 }
1c14b1c1 158 $this->register_type($type['identifier'], $type['datatransfertypes'],
66079e28 159 $type['addmessage'], $type['namemessage'], $type['handlermessage'], $priority);
32528f94
DS
160 }
161 }
162 if (isset($resp['types'])) {
163 foreach ($resp['types'] as $type) {
2748d8ef 164 $noname = !empty($type['noname']);
1c14b1c1 165 $this->register_type_handler($type['identifier'], $modname, $type['message'], $noname);
32528f94
DS
166 }
167 }
04348400 168 $PAGE->requires->string_for_js('pluginname', $modname);
32528f94
DS
169 }
170 }
171
172 /**
173 * Used to add a new mime type that can be drag and dropped onto a
174 * course displayed in a browser window
175 *
176 * @param string $identifier The name that this type will be known as
177 * @param array $datatransfertypes An array of the different types in the browser
178 * 'dataTransfer.types' object that will map to this type
179 * @param string $addmessage The message to display in the browser when this type is being
180 * dragged onto the page
181 * @param string $namemessage The message to pop up when asking for the name to give the
182 * course module instance when it is created
66079e28 183 * @param string $handlermessage The message to pop up when asking which module should handle this type
32528f94
DS
184 * @param int $priority Controls the order in which types are checked by the browser (mainly
185 * needed to check for 'text' last as that is usually given as fallback)
186 */
1c14b1c1 187 protected function register_type($identifier, $datatransfertypes, $addmessage, $namemessage, $handlermessage, $priority=100) {
32528f94
DS
188 if ($this->is_known_type($identifier)) {
189 throw new coding_exception("Type $identifier is already registered");
190 }
191
192 $add = new stdClass;
193 $add->identifier = $identifier;
194 $add->datatransfertypes = $datatransfertypes;
195 $add->addmessage = $addmessage;
196 $add->namemessage = $namemessage;
66079e28 197 $add->handlermessage = $handlermessage;
32528f94
DS
198 $add->priority = $priority;
199 $add->handlers = array();
200
abed5d65 201 $this->types[$identifier] = $add;
32528f94
DS
202 }
203
1c14b1c1
DW
204 /**
205 * Used to declare that a particular module will handle a particular type
206 * of dropped data
207 *
208 * @param string $type The name of the type (as declared in register_type)
209 * @param string $module The name of the module to handle this type
210 * @param string $message The message to show the user if more than one handler is registered
211 * for a type and the user needs to make a choice between them
212 * @param bool $noname If true, the 'name' dialog should be disabled in the pop-up.
213 * @throws coding_exception
214 */
215 protected function register_type_handler($type, $module, $message, $noname) {
abed5d65
DS
216 if (!$this->is_known_type($type)) {
217 throw new coding_exception("Trying to add handler for unknown type $type");
32528f94
DS
218 }
219
abed5d65
DS
220 $add = new stdClass;
221 $add->type = $type;
222 $add->module = $module;
223 $add->message = $message;
2748d8ef 224 $add->noname = $noname ? 1 : 0;
abed5d65
DS
225
226 $this->types[$type]->handlers[] = $add;
32528f94
DS
227 }
228
229 /**
230 * Used to declare that a particular module will handle a particular type
231 * of dropped file
232 *
233 * @param string $extension The file extension to handle ('*' for all types)
234 * @param string $module The name of the module to handle this type
235 * @param string $message The message to show the user if more than one handler is registered
236 * for a type and the user needs to make a choice between them
237 */
1c14b1c1 238 protected function register_file_handler($extension, $module, $message) {
abed5d65
DS
239 $extension = strtolower($extension);
240
32528f94
DS
241 $add = new stdClass;
242 $add->extension = $extension;
243 $add->module = $module;
244 $add->message = $message;
245
246 $this->filehandlers[] = $add;
247 }
248
249 /**
250 * Check to see if the type has been registered
251 *
252 * @param string $type The identifier of the type you are interested in
253 * @return bool True if the type is registered
254 */
255 public function is_known_type($type) {
abed5d65 256 return array_key_exists($type, $this->types);
32528f94
DS
257 }
258
259 /**
260 * Check to see if the module in question has registered to handle the
261 * type given
262 *
263 * @param string $module The name of the module
264 * @param string $type The identifier of the type
265 * @return bool True if the module has registered to handle that type
266 */
267 public function has_type_handler($module, $type) {
abed5d65
DS
268 if (!$this->is_known_type($type)) {
269 throw new coding_exception("Checking for handler for unknown type $type");
270 }
271 foreach ($this->types[$type]->handlers as $handler) {
272 if ($handler->module == $module) {
273 return true;
32528f94
DS
274 }
275 }
276 return false;
277 }
278
279 /**
280 * Check to see if the module in question has registered to handle files
281 * with the given extension (or to handle all file types)
282 *
283 * @param string $module The name of the module
284 * @param string $extension The extension of the uploaded file
285 * @return bool True if the module has registered to handle files with
286 * that extension (or to handle all file types)
287 */
288 public function has_file_handler($module, $extension) {
289 foreach ($this->filehandlers as $handler) {
290 if ($handler->module == $module) {
291 if ($handler->extension == '*' || $handler->extension == $extension) {
292 return true;
293 }
294 }
295 }
296 return false;
297 }
298
299 /**
300 * Gets a list of the file types that are handled by a particular module
301 *
302 * @param string $module The name of the module to check
303 * @return array of file extensions or string '*'
304 */
305 public function get_handled_file_types($module) {
306 $types = array();
307 foreach ($this->filehandlers as $handler) {
308 if ($handler->module == $module) {
309 if ($handler->extension == '*') {
310 return '*';
311 } else {
312 // Prepending '.' as otherwise mimeinfo fails.
313 $types[] = '.'.$handler->extension;
314 }
315 }
316 }
317 return $types;
318 }
319
320 /**
321 * Returns an object to pass onto the javascript code with data about all the
322 * registered file / type handlers
323 *
324 * @return object Data to pass on to Javascript code
325 */
326 public function get_js_data() {
f684250b
DS
327 global $CFG;
328
32528f94
DS
329 $ret = new stdClass;
330
331 // Sort the types by priority.
332 uasort($this->types, array($this, 'type_compare'));
333
334 $ret->types = array();
1ddc3d1f 335 if (!empty($CFG->dndallowtextandlinks)) {
f684250b
DS
336 foreach ($this->types as $type) {
337 if (empty($type->handlers)) {
338 continue; // Skip any types without registered handlers.
339 }
340 $ret->types[] = $type;
32528f94 341 }
32528f94
DS
342 }
343
344 $ret->filehandlers = $this->filehandlers;
e6a0f101 345 $uploadrepo = repository::get_instances(array('type' => 'upload', 'currentcontext' => $this->context));
32528f94
DS
346 if (empty($uploadrepo)) {
347 $ret->filehandlers = array(); // No upload repo => no file handlers.
348 }
349
350 return $ret;
351 }
352
353 /**
354 * Comparison function used when sorting types by priority
355 * @param object $type1 first type to compare
356 * @param object $type2 second type to compare
357 * @return integer -1 for $type1 < $type2; 1 for $type1 > $type2; 0 for equal
358 */
359 protected function type_compare($type1, $type2) {
360 if ($type1->priority < $type2->priority) {
361 return -1;
362 }
363 if ($type1->priority > $type2->priority) {
364 return 1;
365 }
366 return 0;
367 }
368
369}
370
371/**
372 * Processes the upload, creating the course module and returning the result
373 *
374 * @package core
375 * @copyright 2012 Davo Smith
376 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
377 */
abed5d65 378class dndupload_ajax_processor {
32528f94
DS
379
380 /** Returned when no error has occurred */
381 const ERROR_OK = 0;
382
383 /** @var object The course that we are uploading to */
384 protected $course = null;
385
386 /** @var context_course The course context for capability checking */
387 protected $context = null;
388
389 /** @var int The section number we are uploading to */
390 protected $section = null;
391
392 /** @var string The type of upload (e.g. 'Files', 'text/plain') */
393 protected $type = null;
394
395 /** @var object The details of the module type that will be created */
396 protected $module= null;
397
398 /** @var object The course module that has been created */
399 protected $cm = null;
400
401 /** @var dndupload_handler used to check the allowed file types */
402 protected $dnduploadhandler = null;
403
404 /** @var string The name to give the new activity instance */
405 protected $displayname = null;
406
407 /**
408 * Set up some basic information needed to handle the upload
409 *
410 * @param int $courseid The ID of the course we are uploading to
411 * @param int $section The section number we are uploading to
412 * @param string $type The type of upload (as reported by the browser)
413 * @param string $modulename The name of the module requested to handle this upload
414 */
415 public function __construct($courseid, $section, $type, $modulename) {
416 global $DB;
417
abed5d65
DS
418 if (!defined('AJAX_SCRIPT')) {
419 throw new coding_exception('dndupload_ajax_processor should only be used within AJAX requests');
420 }
421
74df2951 422 $this->course = $DB->get_record('course', array('id' => $courseid), '*', MUST_EXIST);
32528f94
DS
423
424 require_login($this->course, false);
425 $this->context = context_course::instance($this->course->id);
426
5103b5e6 427 if (!is_number($section) || $section < 0) {
32528f94
DS
428 throw new coding_exception("Invalid section number $section");
429 }
430 $this->section = $section;
431 $this->type = $type;
432
433 if (!$this->module = $DB->get_record('modules', array('name' => $modulename))) {
434 throw new coding_exception("Module $modulename does not exist");
435 }
436
437 $this->dnduploadhandler = new dndupload_handler($this->course);
438 }
439
440 /**
441 * Check if this upload is a 'file' upload
442 *
443 * @return bool true if it is a 'file' upload, false otherwise
444 */
445 protected function is_file_upload() {
446 return ($this->type == 'Files');
447 }
448
449 /**
450 * Process the upload - creating the module in the course and returning the result to the browser
451 *
452 * @param string $displayname optional the name (from the browser) to give the course module instance
453 * @param string $content optional the content of the upload (for non-file uploads)
454 */
455 public function process($displayname = null, $content = null) {
456 require_capability('moodle/course:manageactivities', $this->context);
457
458 if ($this->is_file_upload()) {
459 require_capability('moodle/course:managefiles', $this->context);
abed5d65 460 if ($content != null) {
33b24bdd 461 throw new moodle_exception('fileuploadwithcontent', 'moodle');
abed5d65 462 }
f684250b
DS
463 } else {
464 if (empty($content)) {
465 throw new moodle_exception('dnduploadwithoutcontent', 'moodle');
466 }
32528f94
DS
467 }
468
469 require_sesskey();
470
471 $this->displayname = $displayname;
472
473 if ($this->is_file_upload()) {
474 $this->handle_file_upload();
475 } else {
476 $this->handle_other_upload($content);
477 }
478 }
479
480 /**
481 * Handle uploads containing files - create the course module, ask the upload repository
482 * to process the file, ask the mod to set itself up, then return the result to the browser
483 */
484 protected function handle_file_upload() {
485 global $CFG;
486
487 // Add the file to a draft file area.
488 $draftitemid = file_get_unused_draft_itemid();
489 $maxbytes = get_max_upload_file_size($CFG->maxbytes, $this->course->maxbytes);
490 $types = $this->dnduploadhandler->get_handled_file_types($this->module->name);
a80f5922 491 $repo = repository::get_instances(array('type' => 'upload', 'currentcontext' => $this->context));
32528f94 492 if (empty($repo)) {
33b24bdd 493 throw new moodle_exception('errornouploadrepo', 'moodle');
32528f94
DS
494 }
495 $repo = reset($repo); // Get the first (and only) upload repo.
496 $details = $repo->process_upload(null, $maxbytes, $types, '/', $draftitemid);
497 if (empty($this->displayname)) {
498 $this->displayname = $this->display_name_from_file($details['file']);
499 }
500
501 // Create a course module to hold the new instance.
502 $this->create_course_module();
503
504 // Ask the module to set itself up.
505 $moduledata = $this->prepare_module_data($draftitemid);
506 $instanceid = plugin_callback('mod', $this->module->name, 'dndupload', 'handle', array($moduledata), 'invalidfunction');
507 if ($instanceid === 'invalidfunction') {
508 throw new coding_exception("{$this->module->name} does not support drag and drop upload (missing {$this->module->name}_dndupload_handle function");
509 }
510
511 // Finish setting up the course module.
512 $this->finish_setup_course_module($instanceid);
513 }
514
515 /**
516 * Handle uploads not containing file - create the course module, ask the mod to
517 * set itself up, then return the result to the browser
518 *
519 * @param string $content the content uploaded to the browser
520 */
521 protected function handle_other_upload($content) {
abed5d65
DS
522 // Check this plugin is registered to handle this type of upload
523 if (!$this->dnduploadhandler->has_type_handler($this->module->name, $this->type)) {
524 $info = (object)array('modname' => $this->module->name, 'type' => $this->type);
33b24bdd 525 throw new moodle_exception('moddoesnotsupporttype', 'moodle', $info);
abed5d65
DS
526 }
527
32528f94
DS
528 // Create a course module to hold the new instance.
529 $this->create_course_module();
530
531 // Ask the module to set itself up.
532 $moduledata = $this->prepare_module_data(null, $content);
533 $instanceid = plugin_callback('mod', $this->module->name, 'dndupload', 'handle', array($moduledata), 'invalidfunction');
534 if ($instanceid === 'invalidfunction') {
535 throw new coding_exception("{$this->module->name} does not support drag and drop upload (missing {$this->module->name}_dndupload_handle function");
536 }
537
538 // Finish setting up the course module.
539 $this->finish_setup_course_module($instanceid);
540 }
541
542 /**
543 * Generate the name of the mod instance from the name of the file
544 * (remove the extension and convert underscore => space
545 *
546 * @param string $filename the filename of the uploaded file
547 * @return string the display name to use
548 */
549 protected function display_name_from_file($filename) {
2f1e464a 550 $pos = core_text::strrpos($filename, '.');
32528f94 551 if ($pos) { // Want to skip if $pos === 0 OR $pos === false.
2f1e464a 552 $filename = core_text::substr($filename, 0, $pos);
32528f94
DS
553 }
554 return str_replace('_', ' ', $filename);
555 }
556
557 /**
558 * Create the coursemodule to hold the file/content that has been uploaded
559 */
560 protected function create_course_module() {
ac1a2975
EM
561 global $CFG;
562
32528f94
DS
563 if (!course_allowed_module($this->course, $this->module->name)) {
564 throw new coding_exception("The module {$this->module->name} is not allowed to be added to this course");
565 }
566
567 $this->cm = new stdClass();
568 $this->cm->course = $this->course->id;
569 $this->cm->section = $this->section;
570 $this->cm->module = $this->module->id;
571 $this->cm->modulename = $this->module->name;
572 $this->cm->instance = 0; // This will be filled in after we create the instance.
573 $this->cm->visible = 1;
574 $this->cm->groupmode = $this->course->groupmode;
575 $this->cm->groupingid = $this->course->defaultgroupingid;
576
c7e61fba
DS
577 // Set the correct default for completion tracking.
578 $this->cm->completion = COMPLETION_TRACKING_NONE;
579 $completion = new completion_info($this->course);
ac1a2975 580 if ($completion->is_enabled() && $CFG->completiondefault) {
c7e61fba
DS
581 if (plugin_supports('mod', $this->cm->modulename, FEATURE_MODEDIT_DEFAULT_COMPLETION, true)) {
582 $this->cm->completion = COMPLETION_TRACKING_MANUAL;
583 }
584 }
585
32528f94
DS
586 if (!$this->cm->id = add_course_module($this->cm)) {
587 throw new coding_exception("Unable to create the course module");
588 }
32528f94 589 $this->cm->coursemodule = $this->cm->id;
32528f94
DS
590 }
591
592 /**
593 * Gather together all the details to pass on to the mod, so that it can initialise it's
594 * own database tables
595 *
596 * @param int $draftitemid optional the id of the draft area containing the file (for file uploads)
597 * @param string $content optional the content dropped onto the course (for non-file uploads)
598 * @return object data to pass on to the mod, containing:
599 * string $type the 'type' as registered with dndupload_handler (or 'Files')
600 * object $course the course the upload was for
601 * int $draftitemid optional the id of the draft area containing the files
602 * int $coursemodule id of the course module that has already been created
603 * string $displayname the name to use for this activity (can be overriden by the mod)
604 */
605 protected function prepare_module_data($draftitemid = null, $content = null) {
606 $data = new stdClass();
607 $data->type = $this->type;
608 $data->course = $this->course;
609 if ($draftitemid) {
610 $data->draftitemid = $draftitemid;
611 } else if ($content) {
612 $data->content = $content;
613 }
614 $data->coursemodule = $this->cm->id;
615 $data->displayname = $this->displayname;
616 return $data;
617 }
618
619 /**
620 * Called after the mod has set itself up, to finish off any course module settings
621 * (set instance id, add to correct section, set visibility, etc.) and send the response
622 *
623 * @param int $instanceid id returned by the mod when it was created
624 */
625 protected function finish_setup_course_module($instanceid) {
626 global $DB, $USER;
627
628 if (!$instanceid) {
629 // Something has gone wrong - undo everything we can.
a347aee3 630 course_delete_module($this->cm->id);
33b24bdd 631 throw new moodle_exception('errorcreatingactivity', 'moodle', '', $this->module->name);
32528f94
DS
632 }
633
0470a094
DS
634 // Note the section visibility
635 $visible = get_fast_modinfo($this->course)->get_section_info($this->section)->visible;
636
32528f94 637 $DB->set_field('course_modules', 'instance', $instanceid, array('id' => $this->cm->id));
38b19bbc
MG
638 // Rebuild the course cache after update action
639 rebuild_course_cache($this->course->id, true);
32528f94 640
722e6ba9 641 $sectionid = course_add_cm_to_section($this->course, $this->cm->id, $this->section);
32528f94 642
0470a094
DS
643 set_coursemodule_visible($this->cm->id, $visible);
644 if (!$visible) {
645 $DB->set_field('course_modules', 'visibleold', 1, array('id' => $this->cm->id));
646 }
32528f94 647
38b19bbc 648 // retrieve the final info about this module.
32528f94 649 $info = get_fast_modinfo($this->course);
5103b5e6
DS
650 if (!isset($info->cms[$this->cm->id])) {
651 // The course module has not been properly created in the course - undo everything.
a347aee3 652 course_delete_module($this->cm->id);
33b24bdd 653 throw new moodle_exception('errorcreatingactivity', 'moodle', '', $this->module->name);
5103b5e6 654 }
0470a094 655 $mod = $info->get_cm($this->cm->id);
32528f94 656
63deb5c3 657 // Trigger course module created event.
e20d3069 658 $event = \core\event\course_module_created::create_from_cm($mod);
63deb5c3
AA
659 $event->trigger();
660
32528f94
DS
661 $this->send_response($mod);
662 }
663
664 /**
665 * Send the details of the newly created activity back to the client browser
666 *
667 * @param cm_info $mod details of the mod just created
668 */
669 protected function send_response($mod) {
9a36be73 670 global $OUTPUT, $PAGE;
abed5d65 671
32528f94
DS
672 $resp = new stdClass();
673 $resp->error = self::ERROR_OK;
9b2ad813
AN
674 $resp->elementid = 'module-' . $mod->id;
675
676 $courserenderer = $PAGE->get_renderer('core', 'course');
677 $completioninfo = new completion_info($this->course);
678 $info = get_fast_modinfo($this->course);
679 $sr = null;
680 $modulehtml = $courserenderer->course_section_cm($this->course, $completioninfo,
681 $mod, null, array());
682 $resp->fullcontent = $courserenderer->course_section_cm_list_item($this->course, $completioninfo, $mod, $sr);
d022f632 683
abed5d65 684 echo $OUTPUT->header();
32528f94
DS
685 echo json_encode($resp);
686 die();
687 }
3970a471 688}