. namespace core_courseformat\external; use core_external\external_api; use core_external\external_function_parameters; use core_external\external_value; use moodle_exception; use coding_exception; use context_course; use core_courseformat\base as course_format; /** * External service to create a new module instance in the course. * * @package core_courseformat * @copyright 2024 Mikel Martín * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class create_module extends external_api { /** * Webservice parameters. * * @return external_function_parameters */ public static function execute_parameters(): external_function_parameters { return new external_function_parameters( [ 'courseid' => new external_value(PARAM_INT, 'course id', VALUE_REQUIRED), 'modname' => new external_value(PARAM_ALPHANUMEXT, 'module name', VALUE_REQUIRED), 'targetsectionnum' => new external_value(PARAM_INT, 'target section number', VALUE_REQUIRED, null), 'targetcmid' => new external_value(PARAM_INT, 'Optional target cm id', VALUE_DEFAULT, null), ] ); } /** * This webservice will execute the create_module action from the course editor. * * The action will register in a {@see \core_courseformat\stateupdates} all the affected * sections, cms and course attribute. This object (in JSON) will be sent back to the * frontend editor to refresh the updated state elements. * * By default, {@see \core_courseformat\stateupdates} will register only create, delete and update events * on cms, sections and the general course data. However, if some plugin needs adhoc messages for * its own mutation module, extend this class in format_XXX\course. * * @param int $courseid the course id * @param string $modname the module name * @param int $targetsectionnum the target section number * @param int|null $targetcmid optional target cm id * @return string Course state in JSON */ public static function execute( int $courseid, string $modname, int $targetsectionnum, ?int $targetcmid = null ): string { global $CFG; require_once($CFG->dirroot . '/course/lib.php'); [ 'courseid' => $courseid, 'modname' => $modname, 'targetsectionnum' => $targetsectionnum, 'targetcmid' => $targetcmid, ] = self::validate_parameters(self::execute_parameters(), [ 'courseid' => $courseid, 'modname' => $modname, 'targetsectionnum' => $targetsectionnum, 'targetcmid' => $targetcmid, ]); self::validate_context(context_course::instance($courseid)); // Plugin needs to support quick creation and the course format needs to support components. // Formats using YUI modules should not be able to quick-create because the front end cannot react to the change. if (!plugin_supports('mod', $modname, FEATURE_QUICKCREATE) || !course_get_format($courseid)->supports_components()) { throw new moodle_exception("Module $modname does not support quick creation"); } $courseformat = course_get_format($courseid); // Create a course changes tracker object. $defaultupdatesclass = 'core_courseformat\\stateupdates'; $updatesclass = 'format_' . $courseformat->get_format() . '\\courseformat\\stateupdates'; if (!class_exists($updatesclass)) { $updatesclass = $defaultupdatesclass; } $updates = new $updatesclass($courseformat); if (!is_a($updates, $defaultupdatesclass)) { throw new coding_exception("The \"$updatesclass\" class must extend \"$defaultupdatesclass\""); } // Get the actions class from the course format. $actionsclass = 'format_'. $courseformat->get_format().'\\courseformat\\stateactions'; if (!class_exists($actionsclass)) { $actionsclass = 'core_courseformat\\stateactions'; } $actions = new $actionsclass(); $action = 'create_module'; if (!is_callable([$actions, $action])) { throw new moodle_exception("Invalid course state action $action in ".get_class($actions)); } $course = $courseformat->get_course(); // Execute the action. $actions->$action($updates, $course, $modname, $targetsectionnum, $targetcmid); // Dispatch the hook for post course content update. $hook = new \core_courseformat\hook\after_course_content_updated( course: $course ); \core\di::get(\core\hook\manager::class)->dispatch($hook); return json_encode($updates); } /** * Webservice returns. * * @return external_value */ public static function execute_returns(): external_value { return new external_value(PARAM_RAW, 'Encoded course update JSON'); } }