first commit

This commit is contained in:
CHIEFSOFT\ameye
2024-09-30 18:11:26 -04:00
commit e592ca6823
27270 changed files with 5002257 additions and 0 deletions
@@ -0,0 +1,104 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Form.
*
* @package tool_lpmigrate
* @copyright 2016 Frédéric Massart - FMCorz.net
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace tool_lpmigrate\form;
defined('MOODLE_INTERNAL') || die();
require_once($CFG->libdir . '/formslib.php');
\MoodleQuickForm::registerElementType('framework_autocomplete',
$CFG->dirroot . '/admin/tool/lp/classes/form/framework_autocomplete.php',
'\\tool_lp\\form\\framework_autocomplete');
/**
* Form class.
*
* @package tool_lpmigrate
* @copyright 2016 Frédéric Massart - FMCorz.net
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class migrate_framework extends \moodleform {
/** @var context The page context. */
protected $pagecontext;
/**
* Constructor.
* @param \context $context The page context.
*/
public function __construct(\context $context) {
$this->pagecontext = $context;
parent::__construct();
}
protected function definition() {
$mform = $this->_form;
$mform->addElement('header', 'hdrcourses', get_string('frameworks', 'tool_lpmigrate'));
$mform->addElement('framework_autocomplete', 'from', get_string('migratefrom', 'tool_lpmigrate'), array(
'contextid' => $this->pagecontext->id,
'onlyvisible' => '0',
), 1, 2, 3);
$mform->addRule('from', get_string('required'), 'required', null);
$mform->addHelpButton('from', 'migratefrom', 'tool_lpmigrate');
$mform->addElement('framework_autocomplete', 'to', get_string('migrateto', 'tool_lpmigrate'), array(
'contextid' => $this->pagecontext->id,
'onlyvisible' => '1', // We cannot add competencies from hidden frameworks, so it must be visible.
), 1, 2, 3);
$mform->addRule('to', get_string('required'), 'required', null);
$mform->addHelpButton('to', 'migrateto', 'tool_lpmigrate');
$mform->addElement('header', 'hdrcourses', get_string('courses'));
$mform->addElement('course', 'allowedcourses', get_string('limittothese', 'tool_lpmigrate'),
array('showhidden' => true, 'multiple' => true));
$mform->addHelpButton('allowedcourses', 'allowedcourses', 'tool_lpmigrate');
$mform->addElement('course', 'disallowedcourses', get_string('excludethese', 'tool_lpmigrate'),
array('showhidden' => true, 'multiple' => true));
$mform->addHelpButton('disallowedcourses', 'disallowedcourses', 'tool_lpmigrate');
$mform->addElement('date_time_selector', 'coursestartdate', get_string('startdatefrom', 'tool_lpmigrate'),
array('optional' => true));
$mform->addHelpButton('coursestartdate', 'coursestartdate', 'tool_lpmigrate');
$this->add_action_buttons(true, get_string('performmigration', 'tool_lpmigrate'));
}
public function validation($data, $files) {
$errors = array();
if ($data['from'] == $data['to']) {
$errors['to'] = get_string('errorcannotmigratetosameframework', 'tool_lpmigrate');
} else if (!empty($data['from']) && !empty($data['to'])) {
$mapper = new \tool_lpmigrate\framework_mapper($data['from'], $data['to']);
$mapper->automap();
if (!$mapper->has_mappings()) {
$errors['to'] = 'Could not map to any competency in this framework.';
}
}
return $errors;
}
}
@@ -0,0 +1,189 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Framework mapper.
*
* @package tool_lpmigrate
* @copyright 2016 Frédéric Massart - FMCorz.net
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace tool_lpmigrate;
defined('MOODLE_INTERNAL') || die();
use core_competency\api;
/**
* Framework mapper class.
*
* @package tool_lpmigrate
* @copyright 2016 Frédéric Massart - FMCorz.net
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class framework_mapper {
/** @var int The ID of the framework we're migrating from. */
protected $from;
/** @var int The ID of the framework we're migrating to. */
protected $to;
/** @var array The collection of objects at origin. */
protected $collectionfrom;
/** @var array The collection of objects at destination. */
protected $collectionto;
/** @var array Mappings. */
protected $mappings = array();
/**
* Constructor.
* @param int $from Framework ID from.
* @param int $to Framework ID to.
*/
public function __construct($from, $to) {
$this->from = $from;
$this->to = $to;
}
/**
* Add a mapping.
* @param int $idfrom From ID.
* @param int $idto To ID.
*/
public function add_mapping($idfrom, $idto) {
$this->mappings[$idfrom] = $idto;
}
/**
* Auto map the frameworks.
* @return void
*/
public function automap() {
$map = array();
// Shallow copy.
$collectionfrom = $this->get_collection_from();
$collectionto = $this->get_collection_to();
// Find mappings.
foreach ($collectionfrom as $keyfrom => $compfrom) {
foreach ($collectionto as $keyto => $compto) {
if ($compfrom->get('idnumber') == $compto->get('idnumber')) {
$map[$compfrom->get('id')] = $compto->get('id');
unset($collectionfrom[$keyfrom]);
unset($collectionto[$keyto]);
break;
}
}
}
$this->mappings = $map;
}
/**
* Get all IDs at origin.
* @return array
*/
public function get_all_from() {
return array_keys($this->get_collection_from());
}
/**
* Get all IDs at destination.
* @return array
*/
public function get_all_to() {
return array_keys($this->get_collection_to());
}
/**
* Get the collection at origin.
* @return array
*/
protected function get_collection_from() {
if ($this->collectionfrom === null) {
$this->collectionfrom = api::search_competencies('', $this->from);
}
return $this->collectionfrom;
}
/**
* Get the collection at destination.
* @return array
*/
protected function get_collection_to() {
if ($this->collectionto === null) {
$this->collectionto = api::search_competencies('', $this->to);
}
return $this->collectionto;
}
/**
* Get the defined mappings.
* @return array
*/
public function get_mappings() {
return $this->mappings;
}
/**
* Get the IDs of the objects at origin which do not have a mapping at destination.
* @return array
*/
public function get_unmapped_from() {
return array_keys(array_diff_key($this->get_collection_from(), $this->mappings));
}
/**
* Get the origin objects with missing mappings.
* @return array
*/
public function get_unmapped_objects_from() {
return array_diff_key($this->get_collection_from(), $this->mappings);
}
/**
* Get the IDs of the objects at destination which do not have a mapping at origin.
* @return array
*/
public function get_unmapped_to() {
return array_keys(array_diff_key($this->get_collection_to(), array_flip($this->mappings)));
}
/**
* Get the destination objects with missing mappings.
* @return array
*/
public function get_unmapped_objects_to() {
return array_diff_key($this->get_collection_to(), array_flip($this->mappings));
}
/**
* Whether some mappings were set.
* @return bool
*/
public function has_mappings() {
return !empty($this->mappings);
}
/**
* Reset the mappings.
* @return void
*/
public function reset_mappings() {
$this->mappings = array();
}
}
@@ -0,0 +1,638 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Processor.
*
* @package tool_lpmigrate
* @copyright 2016 Frédéric Massart - FMCorz.net
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace tool_lpmigrate;
defined('MOODLE_INTERNAL') || die();
use coding_exception;
use moodle_exception;
use core_competency\api;
use core_competency\competency;
use core_competency\course_competency;
use core_competency\course_module_competency;
/**
* Processor class.
*
* @package tool_lpmigrate
* @copyright 2016 Frédéric Massart - FMCorz.net
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class framework_processor {
/** @var array Indexed as courseid => competencyids */
protected $coursescompetencies = array();
/** @var array Indexed as courseid => competencyid => ruleoutcome*/
protected $coursescompetenciesoutcomes = array();
/** @var array Indexed as courseid => cmid => competencyids */
protected $modulecompetencies = array();
/** @var array Indexed as courseid => cmid => competencyid => ruleoutcome*/
protected $modulecompetenciesoutcomes = array();
/** @var array The IDs of the objects of origin. */
protected $fromids = array();
/** @var array The mapping originId => destinationId. */
protected $mappings = array();
/** @var array Courses found. */
protected $coursesfound = array();
/** @var array Course modules found. */
protected $cmsfound = array();
/** @var integer Number of migrations expected in courses. */
protected $coursecompetencyexpectedmigrations = 0;
/** @var integer Count of migrations in the course level. */
protected $coursecompetencymigrations = 0;
/** @var integer Count of removals in the course level. */
protected $coursecompetencyremovals = 0;
/** @var integer Number of migrations expected in CMs. */
protected $modulecompetencyexpectedmigrations = 0;
/** @var integer Count of migrations in CMs. */
protected $modulecompetencymigrations = 0;
/** @var integer Count of removals in CMs. */
protected $modulecompetencyremovals = 0;
/** @var array IDs of objects missing a mapping in origin, originId => true. */
protected $missingmappings = array();
/** @var array List of errors. */
protected $errors = array();
/** @var array List of warnings. */
protected $warnings = array();
/** @var array List of course IDs that can be migrated. */
protected $allowedcourses = array();
/** @var int Minimum start date of courses that can be migrated. */
protected $coursestartdatefrom = 0;
/** @var array List of course IDs that cannot be migrated. */
protected $disallowedcourses = array();
/** @var bool Whether to remove the original competency when its destination was already there. */
protected $removeoriginalwhenalreadypresent = false;
/** @var bool Whether to remove the competency from course, or cm, when a mapping is not found. */
protected $removewhenmappingismissing = false;
/** @var boolean Has this processor run? */
protected $proceeded = false;
/** @var framework_mapper The mapper. */
protected $mapper;
/** @var \core\progress\base The progress. */
protected $progress;
/**
* Constructor.
*
* @param framework_mapper $mapper The mapper.
* @param \core\progress\base $progress The progress object.
*/
public function __construct(framework_mapper $mapper, \core\progress\base $progress = null) {
$this->mapper = $mapper;
if ($progress == null) {
$progress = new \core\progress\none();
}
$this->progress = $progress;
}
/**
* Process the mapping.
* @return void
*/
protected function process_mapping() {
$this->mappings = $this->mapper->get_mappings();
$this->fromids = $this->mapper->get_all_from();
}
/**
* Identifies what courses and their competencies to work with.
* @return void
*/
protected function find_coursescompetencies() {
global $DB;
$this->progress->start_progress(get_string('findingcoursecompetencies', 'tool_lpmigrate'), 3);
$this->progress->increment_progress();
$joins = array();
$conditions = array();
$params = array();
// Limit to mapped objects.
list($insql, $inparams) = $DB->get_in_or_equal($this->fromids, SQL_PARAMS_NAMED);
$conditions[] = "c.id $insql";
$params += $inparams;
// Restriction on course IDs.
if (!empty($this->allowedcourses)) {
list($insql, $inparams) = $DB->get_in_or_equal($this->allowedcourses, SQL_PARAMS_NAMED);
$conditions[] = "cc.courseid $insql";
$params += $inparams;
}
if (!empty($this->disallowedcourses)) {
list($insql, $inparams) = $DB->get_in_or_equal($this->disallowedcourses, SQL_PARAMS_NAMED, 'param', false);
$conditions[] = "cc.courseid $insql";
$params += $inparams;
}
// Restriction on start date.
if (!empty($this->coursestartdatefrom)) {
$joins[] = "JOIN {course} co
ON co.id = cc.courseid";
$conditions[] = "co.startdate >= :startdate";
$params += array('startdate' => $this->coursestartdatefrom);
}
// Find the courses.
$ccs = array();
$ccsoutcomes = array();
$joins = implode(' ', $joins);
$conditions = implode(' AND ', $conditions);
$sql = "SELECT cc.id, cc.courseid, cc.competencyid, cc.ruleoutcome
FROM {" . course_competency::TABLE . "} cc
JOIN {" . competency::TABLE . "} c
ON c.id = cc.competencyid
$joins
WHERE $conditions
ORDER BY cc.sortorder, cc.id";
$records = $DB->get_recordset_sql($sql, $params);
$this->progress->increment_progress();
foreach ($records as $record) {
if (!isset($ccs[$record->courseid])) {
$ccs[$record->courseid] = array();
$ccsoutcomes[$record->courseid] = array();
}
$ccs[$record->courseid][] = $record->competencyid;
$ccsoutcomes[$record->courseid][$record->competencyid] = $record->ruleoutcome;
}
$records->close();
$this->coursescompetencies = $ccs;
$this->coursescompetenciesoutcomes = $ccsoutcomes;
$this->coursesfound = $ccs;
$this->progress->increment_progress();
$this->progress->end_progress();
}
/**
* Identifies what course modules and their competencies to work with.
* @return void
*/
protected function find_modulecompetencies() {
global $DB;
if (empty($this->coursescompetencies)) {
return;
}
$this->progress->start_progress(get_string('findingmodulecompetencies', 'tool_lpmigrate'), 3);
$this->progress->increment_progress();
// Limit to mapped objects.
list($inidsql, $inidparams) = $DB->get_in_or_equal($this->fromids, SQL_PARAMS_NAMED);
// Limit to known courses.
list($incoursesql, $incourseparams) = $DB->get_in_or_equal(array_keys($this->coursescompetencies), SQL_PARAMS_NAMED);
$sql = "SELECT mc.id, cm.course AS courseid, mc.cmid, mc.competencyid, mc.ruleoutcome
FROM {" . course_module_competency::TABLE . "} mc
JOIN {course_modules} cm
ON cm.id = mc.cmid
AND cm.course $incoursesql
JOIN {" . competency::TABLE . "} c
ON c.id = mc.competencyid
WHERE c.id $inidsql
ORDER BY mc.sortorder, mc.id";
$params = $inidparams + $incourseparams;
$records = $DB->get_recordset_sql($sql, $params);
$this->progress->increment_progress();
$cmsfound = array();
$cmcs = array();
$cmcsoutcomes = array();
foreach ($records as $record) {
if (!isset($cmcs[$record->courseid])) {
$cmcs[$record->courseid] = array();
$cmcsoutcomes[$record->courseid] = array();
}
if (!isset($cmcs[$record->courseid][$record->cmid])) {
$cmcs[$record->courseid][$record->cmid] = array();
$cmcsoutcomes[$record->courseid][$record->cmid] = array();
}
$cmcs[$record->courseid][$record->cmid][] = $record->competencyid;
$cmcsoutcomes[$record->courseid][$record->cmid][$record->competencyid] = $record->ruleoutcome;
$cmsfound[$record->cmid] = true;
}
$records->close();
$this->modulecompetencies = $cmcs;
$this->modulecompetenciesoutcomes = $cmcsoutcomes;
$this->cmsfound = $cmsfound;
$this->progress->increment_progress();
$this->progress->end_progress();
}
/**
* Return a list of CMs found.
* @return int
*/
public function get_cms_found() {
return $this->cmsfound;
}
/**
* Return the number of CMs found.
* @return int
*/
public function get_cms_found_count() {
return count($this->cmsfound);
}
/**
* Return a list of courses found.
* @return int
*/
public function get_courses_found() {
return $this->coursesfound;
}
/**
* Return the number of courses found.
* @return int
*/
public function get_courses_found_count() {
return count($this->coursesfound);
}
/**
* Get the number of course migrations.
* @return int
*/
public function get_course_competency_migrations() {
return $this->coursecompetencymigrations;
}
/**
* Get the number of removals.
* @return int
*/
public function get_course_competency_removals() {
return $this->coursecompetencyremovals;
}
/**
* Get the number of expected course migrations.
* @return int
*/
public function get_expected_course_competency_migrations() {
return $this->coursecompetencyexpectedmigrations;
}
/**
* Get the number of expected course module migrations.
* @return int
*/
public function get_expected_module_competency_migrations() {
return $this->modulecompetencyexpectedmigrations;
}
/**
* Get the number of course module migrations.
* @return int
*/
public function get_module_competency_migrations() {
return $this->modulecompetencymigrations;
}
/**
* Get the number of removals.
* @return int
*/
public function get_module_competency_removals() {
return $this->modulecompetencyremovals;
}
/**
* Return a list of errors.
* @return array
*/
public function get_errors() {
return $this->errors;
}
/**
* Get the missing mappings.
* @return array Where keys are origin IDs.
*/
public function get_missing_mappings() {
if (!$this->has_run()) {
throw new coding_exception('The processor has not run yet.');
}
return $this->missingmappings;
}
/**
* Return a list of warnings.
* @return array
*/
public function get_warnings() {
return $this->warnings;
}
/**
* Whether the processor has run.
* @return boolean
*/
public function has_run() {
return $this->proceeded;
}
/**
* Log an error.
* @param int $courseid The course ID.
* @param int $competencyid The competency ID.
* @param int $cmid The CM ID.
* @param string $message The error message.
* @return void
*/
protected function log_error($courseid, $competencyid, $cmid, $message) {
$this->errors[] = array(
'courseid' => $courseid,
'competencyid' => $competencyid,
'cmid' => $cmid,
'message' => $message
);
}
/**
* Log a warning.
* @param int $courseid The course ID.
* @param int $competencyid The competency ID.
* @param int $cmid The CM ID.
* @param string $message The warning message.
* @return void
*/
protected function log_warning($courseid, $competencyid, $cmid, $message) {
$this->warnings[] = array(
'courseid' => $courseid,
'competencyid' => $competencyid,
'cmid' => $cmid,
'message' => $message
);
}
/**
* Execute the whole task.
* @return void
*/
public function proceed() {
if ($this->has_run()) {
throw new coding_exception('The processor has already run.');
} else if (!$this->mapper->has_mappings()) {
throw new coding_exception('Mapping was not set.');
}
$this->proceeded = true;
$this->process_mapping();
$this->find_coursescompetencies();
$this->find_modulecompetencies();
$this->process_courses();
}
/**
* Process each course individually.
* @return void
*/
protected function process_courses() {
global $DB;
$this->progress->start_progress(get_string('migratingcourses', 'tool_lpmigrate'), count($this->coursescompetencies));
// Process each course.
foreach ($this->coursescompetencies as $courseid => $competencyids) {
$this->progress->increment_progress();
$competenciestoremovefromcourse = array();
$skipcompetencies = array();
// First, add all the new competencies to the course.
foreach ($competencyids as $key => $competencyid) {
$this->coursecompetencyexpectedmigrations++;
$mapto = isset($this->mappings[$competencyid]) ? $this->mappings[$competencyid] : false;
// Skip the competencies that are not mapped.
if ($mapto === false) {
$this->missingmappings[$competencyid] = true;
if ($this->removewhenmappingismissing) {
$competenciestoremovefromcourse[$competencyid] = true;
}
continue;
}
$transaction = $DB->start_delegated_transaction();
try {
// Add the new competency to the course.
if (api::add_competency_to_course($courseid, $mapto)) {
// Find the added course competency.
$cc = course_competency::get_record(array('courseid' => $courseid, 'competencyid' => $mapto));
// Set the rule.
api::set_course_competency_ruleoutcome($cc, $this->coursescompetenciesoutcomes[$courseid][$competencyid]);
// Adapt the sortorder.
api::reorder_course_competency($courseid, $mapto, $competencyid);
$competenciestoremovefromcourse[$competencyid] = true;
$this->coursecompetencymigrations++;
} else {
// The competency was already in the course...
if ($this->removeoriginalwhenalreadypresent) {
$competenciestoremovefromcourse[$competencyid] = true;
} else {
$this->log_warning($courseid, $competencyid, null,
get_string('warningdestinationcoursecompetencyalreadyexists', 'tool_lpmigrate'));
}
}
} catch (moodle_exception $e) {
// There was a major problem with this competency, we will ignore it entirely for the course.
$skipcompetencies[$competencyid] = true;
$this->log_error($courseid, $competencyid, null,
get_string('errorwhilemigratingcoursecompetencywithexception', 'tool_lpmigrate', $e->getMessage()));
try {
$transaction->rollback($e);
} catch (moodle_exception $e) {
// Catch the re-thrown exception.
}
continue;
}
$transaction->allow_commit();
}
// Then, convert the module competencies.
if (!empty($this->modulecompetencies[$courseid])) {
foreach ($this->modulecompetencies[$courseid] as $cmid => $competencyids) {
foreach ($competencyids as $competencyid) {
$this->modulecompetencyexpectedmigrations++;
// This mapped competency was not added to the course.
if (!empty($skipcompetencies[$competencyid])) {
continue;
}
$remove = true;
$mapto = isset($this->mappings[$competencyid]) ? $this->mappings[$competencyid] : false;
// We don't have mapping.
if ($mapto === false) {
if (!$this->removewhenmappingismissing) {
$remove = false;
}
} else {
// We have a mapping.
$transaction = $DB->start_delegated_transaction();
try {
// The competency was added successfully.
if (api::add_competency_to_course_module($cmid, $mapto)) {
// Find the added module competency.
$mc = course_module_competency::get_record(array('cmid' => $cmid, 'competencyid' => $mapto));
// Set the competency rule.
api::set_course_module_competency_ruleoutcome($mc,
$this->modulecompetenciesoutcomes[$courseid][$cmid][$competencyid]);
// Adapt the sortorder.
api::reorder_course_module_competency($cmid, $mapto, $competencyid);
$this->modulecompetencymigrations++;
} else {
// The competency was already in the module.
if (!$this->removeoriginalwhenalreadypresent) {
$remove = false;
$competencieswithissues[$competencyid] = true;
$this->log_warning($courseid, $competencyid, $cmid,
get_string('warningdestinationmodulecompetencyalreadyexists', 'tool_lpmigrate'));
}
}
} catch (moodle_exception $e) {
// There was a major problem with this competency in this module.
$competencieswithissues[$competencyid] = true;
$message = get_string('errorwhilemigratingmodulecompetencywithexception', 'tool_lpmigrate',
$e->getMessage());
$this->log_error($courseid, $competencyid, $cmid, $message);
try {
$transaction->rollback($e);
} catch (moodle_exception $e) {
// Catch the re-thrown exception.
}
continue;
}
$transaction->allow_commit();
}
try {
// Go away competency!
if ($remove && api::remove_competency_from_course_module($cmid, $competencyid)) {
$this->modulecompetencyremovals++;
}
} catch (moodle_exception $e) {
$competencieswithissues[$competencyid] = true;
$this->log_warning($courseid, $competencyid, $cmid,
get_string('warningcouldnotremovemodulecompetency', 'tool_lpmigrate'));
}
}
}
}
// Finally, we remove the course competencies, but only for the 100% successful ones.
foreach ($competenciestoremovefromcourse as $competencyid => $unused) {
// Skip competencies with issues.
if (isset($competencieswithissues[$competencyid])) {
continue;
}
try {
// Process the course competency.
api::remove_competency_from_course($courseid, $competencyid);
$this->coursecompetencyremovals++;
} catch (moodle_exception $e) {
$this->log_warning($courseid, $competencyid, null,
get_string('warningcouldnotremovecoursecompetency', 'tool_lpmigrate'));
}
}
}
$this->progress->end_progress();
}
/**
* Set the IDs of the courses that are allowed.
* @param array $courseids
*/
public function set_allowedcourses(array $courseids) {
$this->allowedcourses = $courseids;
}
/**
* Set the minimum start date for courses to be migrated.
* @param int $value Timestamp, or 0.
*/
public function set_course_start_date_from($value) {
$this->coursestartdatefrom = intval($value);
}
/**
* Set the IDs of the courses that are not allowed.
* @param array $courseids
*/
public function set_disallowedcourses(array $courseids) {
$this->disallowedcourses = $courseids;
}
/**
* Set whether we should remove original competencies when the destination competency was already there.
* @param bool $value
*/
public function set_remove_original_when_destination_already_present($value) {
$this->removeoriginalwhenalreadypresent = $value;
}
/**
* Set whether we should remove unmapped competencies.
* @param bool $value
*/
public function set_remove_when_mapping_is_missing($value) {
$this->removewhenmappingismissing = $value;
}
}
@@ -0,0 +1,163 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Migrate frameworks results.
*
* @package tool_lpmigrate
* @copyright 2016 Frédéric Massart - FMCorz.net
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace tool_lpmigrate\output;
defined('MOODLE_INTERNAL') || die();
use context;
use context_course;
use context_module;
use moodle_url;
use renderable;
use templatable;
use stdClass;
use core_competency\competency;
use core_competency\competency_framework;
use core_competency\external\competency_exporter;
use core_competency\external\competency_framework_exporter;
use core_competency\url;
use tool_lpmigrate\framework_processor;
/**
* Migrate frameworks results class.
*
* @package tool_lpmigrate
* @copyright 2016 Frédéric Massart - FMCorz.net
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class migrate_framework_results implements renderable, templatable {
/** @var context The current page context. */
protected $pagecontext;
/** @var framework_processor The processor. */
protected $processor;
/** @var array $unmappedfrom Competencies from unmapped. */
protected array $unmappedfrom = [];
/** @var array $unmappedto competencies to unmapped. */
protected array $unmappedto = [];
/* @var competency_framework|null $frameworkfrom Framework from. */
protected $frameworkfrom = null;
/* @var competency_framework|null $frameworkto Framework to. */
protected $frameworkto = null;
/**
* Construct.
*
* @param context $pagecontext The current page context.
* @param framework_processor $processor The processor.
* @param competency_framework $frameworkfrom Framework from.
* @param competency_framework $frameworkto Framework to.
* @param array $unmappedfrom Competencies from unmapped.
* @param array $unmappedto Competencies to unmapped.
*/
public function __construct(context $pagecontext, framework_processor $processor, competency_framework $frameworkfrom,
competency_framework $frameworkto, array $unmappedfrom = array(), array $unmappedto = array()) {
if (!$processor->has_run()) {
throw new \coding_exception('The processor has not run.');
}
$this->pagecontext = $pagecontext;
$this->processor = $processor;
$this->unmappedfrom = $unmappedfrom;
$this->unmappedto = $unmappedto;
$this->frameworkfrom = $frameworkfrom;
$this->frameworkto = $frameworkto;
}
/**
* Export the data.
*
* @param renderer_base $output
* @return stdClass
*/
public function export_for_template(\renderer_base $output) {
global $DB;
$data = new stdClass();
$missingmappings = $this->processor->get_missing_mappings();
$data->pagecontextid = $this->pagecontext->id;
$data->expectedccmigrations = $this->processor->get_expected_course_competency_migrations();
$data->expectedmcmigrations = $this->processor->get_expected_module_competency_migrations();
$data->ccmigrationscount = $this->processor->get_course_competency_migrations();
$data->mcmigrationscount = $this->processor->get_module_competency_migrations();
$data->ccremovalscount = $this->processor->get_course_competency_removals();
$data->mcremovalscount = $this->processor->get_module_competency_removals();
$data->unmappedfrom = array();
$data->unmappedto = array();
$exporter = new competency_framework_exporter($this->frameworkfrom);
$data->frameworkfrom = $exporter->export($output);
$exporter = new competency_framework_exporter($this->frameworkto);
$data->frameworkto = $exporter->export($output);
$fromcontext = $this->frameworkfrom->get_context();
$tocontext = $this->frameworkto->get_context();
$compcontext = null;
foreach ($this->unmappedfrom as $comp) {
$exporter = new competency_exporter($comp, array('context' => $fromcontext));
$data->unmappedfrom[] = $exporter->export($output);
}
foreach ($this->unmappedto as $comp) {
$exporter = new competency_exporter($comp, array('context' => $tocontext));
$data->unmappedto[] = $exporter->export($output);
}
$data->coursesfound = $this->processor->get_courses_found_count();
$data->cmsfound = $this->processor->get_cms_found_count();
$data->mappingsmissingcount = count($missingmappings);
$data->hasunmappedto = count($data->unmappedto) > 0;
$data->hasunmappedfrom = count($data->unmappedfrom) > 0;
$warnings = $this->processor->get_warnings();
$data->warnings = array();
$data->warningcount = count($warnings);
$errors = $this->processor->get_errors();
$data->errors = array();
$data->errorcount = count($errors);
foreach ($warnings as $warning) {
$cmcontext = !empty($warning['cmid']) ? context_module::instance($warning['cmid']) : null;
$coursecontext = context_course::instance($warning['courseid']);
$warning['cm'] = $cmcontext ? $cmcontext->get_context_name() : null;
$warning['course'] = $coursecontext->get_context_name();
$warning['competency'] = $DB->get_field(competency::TABLE, 'idnumber', array('id' => $warning['competencyid']));
$data->warnings[] = $warning;
}
foreach ($errors as $error) {
$cmcontext = !empty($error['cmid']) ? context_module::instance($error['cmid']) : null;
$coursecontext = context_course::instance($error['courseid']);
$error['cm'] = $cmcontext ? $cmcontext->get_context_name() : null;
$error['course'] = $coursecontext->get_context_name();
$error['competency'] = $DB->get_field(competency::TABLE, 'idnumber', array('id' => $error['competencyid']));
$data->errors[] = $error;
}
$data->pluginbaseurl = (new moodle_url('/admin/tool/lpmigrate'))->out(false);
$data->frameworksurl = url::frameworks($this->pagecontext->id)->out(false);
return $data;
}
}
@@ -0,0 +1,51 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Renderers.
*
* @package tool_lpmigrate
* @copyright 2016 Frédéric Massart - FMCorz.net
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace tool_lpmigrate\output;
defined('MOODLE_INTERNAL') || die();
use plugin_renderer_base;
use renderable;
/**
* Renderer class.
*
* @package tool_lpmigrate
* @copyright 2016 Frédéric Massart - FMCorz.net
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class renderer extends plugin_renderer_base {
/**
* Defer to template.
*
* @param migrate_framework_results $page
* @return string
*/
public function render_migrate_framework_results(migrate_framework_results $page) {
$data = $page->export_for_template($this);
return parent::render_from_template('tool_lpmigrate/migrate_frameworks_results', $data);
}
}
@@ -0,0 +1,46 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Privacy Subsystem implementation for tool_lpmigrate.
*
* @package tool_lpmigrate
* @copyright 2018 Zig Tan <zig@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace tool_lpmigrate\privacy;
defined('MOODLE_INTERNAL') || die();
/**
* Privacy Subsystem for tool_lpmigrate implementing null_provider.
*
* @copyright 2018 Zig Tan <zig@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class provider implements \core_privacy\local\metadata\null_provider {
/**
* Get the language string identifier with the component's language
* file to explain why this plugin stores no data.
*
* @return string
*/
public static function get_reason(): string {
return 'privacy:metadata';
}
}
+35
View File
@@ -0,0 +1,35 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Capabilities.
*
* @package tool_lpmigrate
* @copyright 2016 Frédéric Massart - FMCorz.net
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
$capabilities = array(
'tool/lpmigrate:frameworksmigrate' => array(
'captype' => 'write',
'contextlevel' => CONTEXT_SYSTEM,
'archetypes' => array(
'manager' => CAP_ALLOW
),
),
);
+79
View File
@@ -0,0 +1,79 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Page to migrate frameworks.
*
* @package tool_lpmigrate
* @copyright 2016 Frédéric Massart - FMCorz.net
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
require_once(__DIR__ . '/../../../config.php');
$context = context_system::instance();
require_login(null, false);
require_capability('tool/lpmigrate:frameworksmigrate', $context);
$url = new moodle_url('/admin/tool/lpmigrate/frameworks.php');
$title = get_string('migrateframeworks', 'tool_lpmigrate');
$PAGE->set_context($context);
$PAGE->set_pagelayout('standard');
$PAGE->set_url($url);
$PAGE->set_title($title);
$PAGE->set_heading(get_string('pluginname', 'tool_lpmigrate'));
$form = new \tool_lpmigrate\form\migrate_framework($context);
if ($form->is_cancelled()) {
redirect($url);
}
$output = $PAGE->get_renderer('tool_lpmigrate');
echo $output->header();
echo $output->heading($title);
if ($data = $form->get_data()) {
// Map competencies from both framework.
$mapper = new \tool_lpmigrate\framework_mapper($data->from, $data->to);
$mapper->automap();
$progress = new \core\progress\display();
$progress->set_display_names(true);
$processor = new \tool_lpmigrate\framework_processor($mapper, $progress);
if (!empty($data->allowedcourses)) {
$processor->set_allowedcourses($data->allowedcourses);
}
if (!empty($data->disallowedcourses)) {
$processor->set_disallowedcourses($data->disallowedcourses);
}
$processor->set_course_start_date_from($data->coursestartdate);
$processor->proceed();
$unmappedfrom = $mapper->get_unmapped_objects_from();
$unmappedto = $mapper->get_unmapped_objects_to();
$renderable = new \tool_lpmigrate\output\migrate_framework_results($context, $processor,
\core_competency\api::read_framework($data->from), \core_competency\api::read_framework($data->to),
$unmappedfrom, $unmappedto);
echo $output->render($renderable);
} else {
echo html_writer::tag('p', get_string('explanation', 'tool_lpmigrate'));
$form->display();
}
echo $output->footer();
@@ -0,0 +1,72 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Language strings.
*
* @package tool_lpmigrate
* @copyright 2016 Frédéric Massart - FMCorz.net
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
$string['allowedcourses'] = 'Courses allowed';
$string['allowedcourses_help'] = 'Select courses to be migrated to the new framework. If no course is specified, then all courses will be migrated.';
$string['continuetoframeworks'] = 'Continue to frameworks';
$string['coursecompetencymigrations'] = 'Course competency migrations';
$string['coursemodulecompetencymigrations'] = 'Course activity and resource competency migrations';
$string['coursesfound'] = 'Courses found';
$string['coursemodulesfound'] = 'Course activities or resources found';
$string['coursestartdate'] = 'Courses start date';
$string['coursestartdate_help'] = 'If enabled, courses with a start date prior to the date specified will not be migrated.';
$string['disallowedcourses'] = 'Disallowed courses';
$string['disallowedcourses_help'] = 'Select any courses which should NOT be migrated to the new framework.';
$string['errorcannotmigratetosameframework'] = 'Cannot migrate from and to the same framework.';
$string['errorcouldnotmapcompetenciesinframework'] = 'Could not map to any competency in this framework.';
$string['errors'] = 'Errors';
$string['errorwhilemigratingcoursecompetencywithexception'] = 'Error while migrating the course competency: {$a}';
$string['errorwhilemigratingmodulecompetencywithexception'] = 'Error while migrating the activity or resource competency: {$a}';
$string['excludethese'] = 'Exclude these';
$string['explanation'] = 'This tool can be used to update a competency framework to a newer version. It searches for competencies in courses and activities using the older framework, and updates the links to point to the new framework.
It is not recommended to edit the old set of competencies directly, as this would change all of the competencies that have already been awarded in users\' learning plans.
Typically you would import the new version of a framework, hide the old framework, then use this tool to migrate new courses to the new framework.';
$string['findingcoursecompetencies'] = 'Finding course competencies';
$string['findingmodulecompetencies'] = 'Finding activity and resource competencies';
$string['frameworks'] = 'Frameworks';
$string['limittothese'] = 'Limit to these';
$string['lpmigrate:frameworksmigrate'] = 'Migrate frameworks';
$string['migrateframeworks'] = 'Migrate frameworks';
$string['migratefrom'] = 'Migrate from';
$string['migratefrom_help'] = 'Select the older framework currently in use.';
$string['migratemore'] = 'Migrate more';
$string['migrateto'] = 'Migrate to';
$string['migrateto_help'] = 'Select the newer version of the framework. It is only possible to select a framework which is not hidden.';
$string['migratingcourses'] = 'Migrating courses';
$string['missingmappings'] = 'Missing mappings';
$string['performmigration'] = 'Perform migration';
$string['pluginname'] = 'Competencies migration tool';
$string['results'] = 'Results';
$string['startdatefrom'] = 'Start date from';
$string['unmappedin'] = 'Unmapped in {$a}';
$string['warningcouldnotremovecoursecompetency'] = 'The course competency could not be removed.';
$string['warningcouldnotremovemodulecompetency'] = 'The activity or resource competency could not be removed.';
$string['warningdestinationcoursecompetencyalreadyexists'] = 'The destination course competency already exists.';
$string['warningdestinationmodulecompetencyalreadyexists'] = 'The destination activity or resource competency already exists.';
$string['warnings'] = 'Warnings';
$string['privacy:metadata'] = 'The Competencies migration tool plugin does not store any personal data.';
+39
View File
@@ -0,0 +1,39 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Links and settings.
*
* @package tool_lpmigrate
* @copyright 2016 Frédéric Massart - FMCorz.net
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
if (get_config('core_competency', 'enabled')) {
$parentname = 'competencies';
// Manage competency frameworks page.
$temp = new admin_externalpage(
'toollpmigrateframeworks',
get_string('migrateframeworks', 'tool_lpmigrate'),
new moodle_url('/admin/tool/lpmigrate/frameworks.php'),
array('tool/lpmigrate:frameworksmigrate')
);
$ADMIN->add($parentname, $temp);
}
@@ -0,0 +1,165 @@
{{!
This file is part of Moodle - http://moodle.org/
Moodle is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Moodle is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Moodle. If not, see <http://www.gnu.org/licenses/>.
}}
{{!
@template tool_lpmigrate/migrate_frameworks_results
Migrate frameworks results.
Classes required for JS:
* none
Data attributes required for JS:
* data-action="competency-dialogue"
* data-id
* data-region="migration-results"
Context variables required for this template:
* coursesfound
* cmsfound
* ccmigrationscount
* ccremovalscount
* mcmigrationscount
* mcremovalscount
* mappingsmissingcount
* warningcount
* errorcount
Example context (json):
{
"ccmigrationscount": 2,
"ccremovalscount": 3,
"cmsfound": 4,
"coursesfound": 3,
"errorcount": 1,
"errors": [{
"message": "This is a generic error",
"course": "The course A",
"cm": "The course module B",
"competency": "The competency C",
"competencyid": "1"
}],
"frameworkfrom": {
"id": 1,
"shortname": "Framework X"
},
"frameworkto": {
"id": 2,
"shortname": "Framework Y"
},
"hasunmappedfrom": 1,
"hasunmappedto": 1,
"mappingsmissingcount": 1,
"mcmigrationscount": 4,
"mcremovalscount": 5,
"unmappedfrom": [{
"id": 2,
"shortname": "Competency U1",
"idnumber": "CU1"
}],
"unmappedto": [{
"id": 3,
"shortname": "Competency Z2",
"idnumber": "CZ2"
}],
"warningcount": 1,
"warnings": [{
"message": "This is a generic warning",
"course": "The course D",
"cm": "The course module E",
"competency": "The competency F",
"competencyid": "1"
}]
}
}}
<div data-region="migration-results">
<h3>{{#str}}results, tool_lpmigrate{{/str}}</h3>
<dl>
<dt>{{#str}}coursesfound, tool_lpmigrate{{/str}}</dt>
<dd>{{coursesfound}}</dd>
<dt>{{#str}}coursemodulesfound, tool_lpmigrate{{/str}}</dt>
<dd>{{cmsfound}}</dd>
<dt>{{#str}}coursecompetencymigrations, tool_lpmigrate{{/str}}</dt>
<dd>+{{ccmigrationscount}} -{{ccremovalscount}}</dd>
<dt>{{#str}}coursemodulecompetencymigrations, tool_lpmigrate{{/str}}</dt>
<dd>+{{mcmigrationscount}} -{{mcremovalscount}}</dd>
<dt>{{#str}}missingmappings, tool_lpmigrate{{/str}}</dt>
<dd>{{mappingsmissingcount}}</dd>
<dt>{{#str}}warnings, tool_lpmigrate{{/str}}</dt>
<dd>{{warningcount}}</dd>
<dt>{{#str}}errors, tool_lpmigrate{{/str}}</dt>
<dd>{{errorcount}}</dd>
</dl>
{{#hasunmappedfrom}}
<h4>{{#str}}unmappedin, tool_lpmigrate, {{frameworkfrom.shortname}}{{/str}}</h4>
<ul>
{{#unmappedfrom}}
<li><a href="#" data-id="{{id}}" data-action="competency-dialogue" data-includecourses="true">{{{shortname}}}</a> <em>{{idnumber}}</em></li>
{{/unmappedfrom}}
</ul>
{{/hasunmappedfrom}}
{{#hasunmappedto}}
<h4>{{#str}}unmappedin, tool_lpmigrate, {{frameworkto.shortname}}{{/str}}</h4>
<ul>
{{#unmappedto}}
<li><a href="#" data-id="{{id}}" data-action="competency-dialogue" data-includecourses="true">{{{shortname}}}</a> <em>{{idnumber}}</em></li>
{{/unmappedto}}
</ul>
{{/hasunmappedto}}
{{#warningcount}}
<h4>{{#str}}warnings, tool_lpmigrate{{/str}}</h4>
<ul>
{{#warnings}}
<li>
<p>
{{message}}<br>
<small>{{course}} {{#cm}} - {{cm}} {{/cm}} - <a href="#" data-id="{{competencyid}}" data-action="competency-dialogue" data-includecourses="true">{{competency}}</a></small>
</p>
</li>
{{/warnings}}
</ul>
{{/warningcount}}
{{#errorcount}}
<h4>{{#str}}errors, tool_lpmigrate{{/str}}</h4>
<ul>
{{#errors}}
<li>
<p>
{{message}}<br>
<small>{{course}} {{#cm}} - {{cm}} {{/cm}} - <a href="#" data-id="{{competencyid}}" data-action="competency-dialogue" data-includecourses="true">{{competency}}</a></small>
</p>
</li>
{{/errors}}
</ul>
{{/errorcount}}
</div>
<div>
<p>
<a href="{{pluginbaseurl}}/frameworks.php" class="btn btn-primary">{{#str}}migratemore, tool_lpmigrate{{/str}}</a>
<a href="{{frameworksurl}}" class="btn">{{#str}}continuetoframeworks, tool_lpmigrate{{/str}}</a>
</p>
</div>
{{#js}}
require(['tool_lp/competencydialogue'], function(Compdialogue) {
Compdialogue.init();
});
{{/js}}
@@ -0,0 +1,637 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace tool_lpmigrate;
use core_competency\course_competency;
use core_competency\course_module_competency;
/**
* Framework processor testcase.
*
* @package tool_lpmigrate
* @copyright 2016 Frédéric Massart - FMCorz.net
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class processor_test extends \advanced_testcase {
/** @var \core_competency\competency_framework|null $f1 */
protected $f1 = null;
/** @var \core_competency\competency_framework|null $f2 */
protected $f2 = null;
/** @var object|null $c1 course instance. */
protected ?object $c1 = null;
/** @var object|null $c2 course instance. */
protected ?object $c2 = null;
/** @var array $f1comps */
protected array $f1comps = [];
/** @var array $f2comps */
protected array $f2comps = [];
/** @var array $cms */
protected array $cms = [];
/** @var array $ccs */
protected array $ccs = [];
/** @var array $cmcs */
protected array $cmcs = [];
/**
* This sets up a few things, and assign class variables.
*
* We create 2 frameworks, each with 2 matching competencies and 1 foreign.
* Then we create 2 courses, and in each 1 CM.
* Then we attach some competencies from the first framework to courses and CM.
*/
public function setUp(): void {
$this->resetAfterTest(true);
$dg = $this->getDataGenerator();
$lpg = $dg->get_plugin_generator('core_competency');
$f1 = $lpg->create_framework(array('idnumber' => 'BIO2015'));
$f2 = $lpg->create_framework(array('idnumber' => 'BIO2016'));
$f1comps = array();
$f1comps['A1'] = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id'), 'idnumber' => 'A1'));
$f1comps['A2'] = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id'), 'idnumber' => 'A2'));
$f1comps['A3'] = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id'), 'idnumber' => 'A3'));
$f1comps['X1'] = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id'), 'idnumber' => 'X1'));
$f2comps = array();
$f2comps['A1'] = $lpg->create_competency(array('competencyframeworkid' => $f2->get('id'), 'idnumber' => 'A1'));
$f2comps['A2'] = $lpg->create_competency(array('competencyframeworkid' => $f2->get('id'), 'idnumber' => 'A2'));
$f2comps['A3'] = $lpg->create_competency(array('competencyframeworkid' => $f2->get('id'), 'idnumber' => 'A3'));
$f2comps['Y1'] = $lpg->create_competency(array('competencyframeworkid' => $f2->get('id'), 'idnumber' => 'Y1'));
$c1 = $dg->create_course(array('startdate' => time() - 72000));
$c2 = $dg->create_course(array('startdate' => time() + 72000));
$cms = array(
$c1->id => array(
'F1' => $dg->create_module('forum', (object) array('course' => $c1->id)),
'P1' => $dg->create_module('page', (object) array('course' => $c1->id)),
'EmptyA' => $dg->create_module('page', (object) array('course' => $c1->id)),
),
$c2->id => array(
'F1' => $dg->create_module('forum', (object) array('course' => $c2->id)),
'EmptyB' => $dg->create_module('page', (object) array('course' => $c2->id)),
),
);
// Course CompetencieS.
$ccs = array(
$c1->id => array(
$f1comps['A1']->get('id') => $lpg->create_course_competency(array('courseid' => $c1->id,
'competencyid' => $f1comps['A1']->get('id'))),
$f1comps['A3']->get('id') => $lpg->create_course_competency(array('courseid' => $c1->id,
'competencyid' => $f1comps['A3']->get('id'))),
$f1comps['X1']->get('id') => $lpg->create_course_competency(array('courseid' => $c1->id,
'competencyid' => $f1comps['X1']->get('id'))),
),
$c2->id => array(
$f1comps['A2']->get('id') => $lpg->create_course_competency(array('courseid' => $c2->id,
'competencyid' => $f1comps['A2']->get('id'))),
$f1comps['A3']->get('id') => $lpg->create_course_competency(array('courseid' => $c2->id,
'competencyid' => $f1comps['A3']->get('id'))),
)
);
// Course Module CompetencieS.
$cmcs = array(
$cms[$c1->id]['F1']->cmid => array(
$f1comps['A1']->get('id') => $lpg->create_course_module_competency(array(
'cmid' => $cms[$c1->id]['F1']->cmid,
'competencyid' => $f1comps['A1']->get('id')
)),
$f1comps['X1']->get('id') => $lpg->create_course_module_competency(array(
'cmid' => $cms[$c1->id]['F1']->cmid,
'competencyid' => $f1comps['X1']->get('id')
)),
),
$cms[$c1->id]['P1']->cmid => array(
$f1comps['A3']->get('id') => $lpg->create_course_module_competency(array(
'cmid' => $cms[$c1->id]['P1']->cmid,
'competencyid' => $f1comps['A3']->get('id')
)),
),
$cms[$c2->id]['F1']->cmid => array(
$f1comps['A2']->get('id') => $lpg->create_course_module_competency(array(
'cmid' => $cms[$c2->id]['F1']->cmid,
'competencyid' => $f1comps['A2']->get('id')
)),
$f1comps['A3']->get('id') => $lpg->create_course_module_competency(array(
'cmid' => $cms[$c2->id]['F1']->cmid,
'competencyid' => $f1comps['A3']->get('id')
)),
),
);
$this->assertCourseCompetencyExists($c1, $f1comps['A1']);
$this->assertCourseCompetencyExists($c1, $f1comps['A3']);
$this->assertCourseCompetencyExists($c1, $f1comps['X1']);
$this->assertCourseCompetencyExists($c2, $f1comps['A2']);
$this->assertCourseCompetencyExists($c2, $f1comps['A3']);
$this->assertModuleCompetencyExists($cms[$c1->id]['F1'], $f1comps['A1']);
$this->assertModuleCompetencyExists($cms[$c1->id]['P1'], $f1comps['A3']);
$this->assertModuleCompetencyExists($cms[$c1->id]['F1'], $f1comps['X1']);
$this->assertModuleCompetencyExists($cms[$c2->id]['F1'], $f1comps['A2']);
$this->assertModuleCompetencyExists($cms[$c2->id]['F1'], $f1comps['A3']);
$this->f1 = $f1;
$this->f1comps = $f1comps;
$this->f2 = $f2;
$this->f2comps = $f2comps;
$this->c1 = $c1;
$this->c2 = $c2;
$this->cms = $cms;
$this->ccs = $ccs;
$this->cmcs = $cmcs;
}
public function test_simple_migration(): void {
$this->setAdminUser();
$mapper = new framework_mapper($this->f1->get('id'), $this->f2->get('id'));
$mapper->automap();
$processor = new framework_processor($mapper);
$processor->proceed();
$this->assertEquals(2, $processor->get_courses_found_count());
$this->assertEquals(5, $processor->get_expected_course_competency_migrations());
$this->assertEquals(4, $processor->get_course_competency_migrations());
$this->assertEquals(4, $processor->get_course_competency_removals());
$this->assertEquals(3, $processor->get_cms_found_count());
$this->assertEquals(5, $processor->get_expected_module_competency_migrations());
$this->assertEquals(4, $processor->get_module_competency_migrations());
$this->assertEquals(4, $processor->get_module_competency_removals());
$this->assertEquals(array(), $processor->get_warnings());
$this->assertEquals(array(), $processor->get_errors());
$this->assertEquals(array($this->f1comps['X1']->get('id') => true), $processor->get_missing_mappings());
$this->assertCourseCompetencyMigrated($this->c1, $this->f1comps['A1'], $this->f2comps['A1']);
$this->assertCourseCompetencyMigrated($this->c1, $this->f1comps['A3'], $this->f2comps['A3']);
$this->assertCourseCompetencyMigrated($this->c2, $this->f1comps['A2'], $this->f2comps['A2']);
$this->assertCourseCompetencyMigrated($this->c2, $this->f1comps['A3'], $this->f2comps['A3']);
$this->assertModuleCompetencyMigrated($this->cms[$this->c1->id]['F1'], $this->f1comps['A1'], $this->f2comps['A1']);
$this->assertModuleCompetencyMigrated($this->cms[$this->c1->id]['P1'], $this->f1comps['A3'], $this->f2comps['A3']);
$this->assertModuleCompetencyMigrated($this->cms[$this->c2->id]['F1'], $this->f1comps['A2'], $this->f2comps['A2']);
$this->assertModuleCompetencyMigrated($this->cms[$this->c2->id]['F1'], $this->f1comps['A3'], $this->f2comps['A3']);
$this->assertCourseCompetencyExists($this->c1, $this->f1comps['X1']);
$this->assertModuleCompetencyExists($this->cms[$this->c1->id]['F1'], $this->f1comps['X1']);
}
public function test_remove_when_missing(): void {
$this->setAdminUser();
$mapper = new framework_mapper($this->f1->get('id'), $this->f2->get('id'));
$mapper->automap();
$processor = new framework_processor($mapper);
$processor->set_remove_when_mapping_is_missing(true);
$processor->proceed();
$this->assertEquals(2, $processor->get_courses_found_count());
$this->assertEquals(5, $processor->get_expected_course_competency_migrations());
$this->assertEquals(4, $processor->get_course_competency_migrations());
$this->assertEquals(5, $processor->get_course_competency_removals());
$this->assertEquals(3, $processor->get_cms_found_count());
$this->assertEquals(5, $processor->get_expected_module_competency_migrations());
$this->assertEquals(4, $processor->get_module_competency_migrations());
$this->assertEquals(5, $processor->get_module_competency_removals());
$this->assertCount(0, $processor->get_errors());
$this->assertCount(0, $processor->get_warnings());
$this->assertCourseCompetencyNotExists($this->c1, $this->f1comps['X1']);
$this->assertModuleCompetencyNotExists($this->cms[$this->c1->id]['F1'], $this->f1comps['X1']);
}
public function test_allowed_courses(): void {
$this->setAdminUser();
$mapper = new framework_mapper($this->f1->get('id'), $this->f2->get('id'));
$mapper->automap();
$processor = new framework_processor($mapper);
$processor->set_allowedcourses(array($this->c1->id));
$processor->proceed();
$this->assertEquals(1, $processor->get_courses_found_count());
$this->assertEquals(3, $processor->get_expected_course_competency_migrations());
$this->assertEquals(2, $processor->get_course_competency_migrations());
$this->assertEquals(2, $processor->get_course_competency_removals());
$this->assertEquals(2, $processor->get_cms_found_count());
$this->assertEquals(3, $processor->get_expected_module_competency_migrations());
$this->assertEquals(2, $processor->get_module_competency_migrations());
$this->assertEquals(2, $processor->get_module_competency_removals());
$this->assertCount(0, $processor->get_errors());
$this->assertCount(0, $processor->get_warnings());
$this->assertCourseCompetencyMigrated($this->c1, $this->f1comps['A1'], $this->f2comps['A1']);
$this->assertCourseCompetencyMigrated($this->c1, $this->f1comps['A3'], $this->f2comps['A3']);
$this->assertModuleCompetencyMigrated($this->cms[$this->c1->id]['F1'], $this->f1comps['A1'], $this->f2comps['A1']);
$this->assertModuleCompetencyMigrated($this->cms[$this->c1->id]['P1'], $this->f1comps['A3'], $this->f2comps['A3']);
$this->assertCourseCompetencyNotMigrated($this->c2, $this->f1comps['A2'], $this->f2comps['A2']);
$this->assertCourseCompetencyNotMigrated($this->c2, $this->f1comps['A3'], $this->f2comps['A3']);
$this->assertModuleCompetencyNotMigrated($this->cms[$this->c2->id]['F1'], $this->f1comps['A2'], $this->f2comps['A2']);
$this->assertModuleCompetencyNotMigrated($this->cms[$this->c2->id]['F1'], $this->f1comps['A3'], $this->f2comps['A3']);
}
public function test_disallowed_courses(): void {
$this->setAdminUser();
$mapper = new framework_mapper($this->f1->get('id'), $this->f2->get('id'));
$mapper->automap();
$processor = new framework_processor($mapper);
$processor->set_disallowedcourses(array($this->c2->id));
$processor->proceed();
$this->assertEquals(1, $processor->get_courses_found_count());
$this->assertEquals(3, $processor->get_expected_course_competency_migrations());
$this->assertEquals(2, $processor->get_course_competency_migrations());
$this->assertEquals(2, $processor->get_course_competency_removals());
$this->assertEquals(2, $processor->get_cms_found_count());
$this->assertEquals(3, $processor->get_expected_module_competency_migrations());
$this->assertEquals(2, $processor->get_module_competency_migrations());
$this->assertEquals(2, $processor->get_module_competency_removals());
$this->assertCount(0, $processor->get_errors());
$this->assertCount(0, $processor->get_warnings());
$this->assertCourseCompetencyMigrated($this->c1, $this->f1comps['A1'], $this->f2comps['A1']);
$this->assertCourseCompetencyMigrated($this->c1, $this->f1comps['A3'], $this->f2comps['A3']);
$this->assertModuleCompetencyMigrated($this->cms[$this->c1->id]['F1'], $this->f1comps['A1'], $this->f2comps['A1']);
$this->assertModuleCompetencyMigrated($this->cms[$this->c1->id]['P1'], $this->f1comps['A3'], $this->f2comps['A3']);
$this->assertCourseCompetencyNotMigrated($this->c2, $this->f1comps['A2'], $this->f2comps['A2']);
$this->assertCourseCompetencyNotMigrated($this->c2, $this->f1comps['A3'], $this->f2comps['A3']);
$this->assertModuleCompetencyNotMigrated($this->cms[$this->c2->id]['F1'], $this->f1comps['A2'], $this->f2comps['A2']);
$this->assertModuleCompetencyNotMigrated($this->cms[$this->c2->id]['F1'], $this->f1comps['A3'], $this->f2comps['A3']);
}
public function test_course_start_date_from(): void {
$this->setAdminUser();
$mapper = new framework_mapper($this->f1->get('id'), $this->f2->get('id'));
$mapper->automap();
$processor = new framework_processor($mapper);
$processor->set_course_start_date_from(time());
$processor->proceed();
$this->assertEquals(1, $processor->get_courses_found_count());
$this->assertEquals(2, $processor->get_expected_course_competency_migrations());
$this->assertEquals(2, $processor->get_course_competency_migrations());
$this->assertEquals(2, $processor->get_course_competency_removals());
$this->assertEquals(1, $processor->get_cms_found_count());
$this->assertEquals(2, $processor->get_expected_module_competency_migrations());
$this->assertEquals(2, $processor->get_module_competency_migrations());
$this->assertEquals(2, $processor->get_module_competency_removals());
$this->assertCount(0, $processor->get_errors());
$this->assertCount(0, $processor->get_warnings());
$this->assertCourseCompetencyNotMigrated($this->c1, $this->f1comps['A1'], $this->f2comps['A1']);
$this->assertCourseCompetencyNotMigrated($this->c1, $this->f1comps['A3'], $this->f2comps['A3']);
$this->assertModuleCompetencyNotMigrated($this->cms[$this->c1->id]['F1'], $this->f1comps['A1'], $this->f2comps['A1']);
$this->assertModuleCompetencyNotMigrated($this->cms[$this->c1->id]['P1'], $this->f1comps['A3'], $this->f2comps['A3']);
$this->assertCourseCompetencyMigrated($this->c2, $this->f1comps['A2'], $this->f2comps['A2']);
$this->assertCourseCompetencyMigrated($this->c2, $this->f1comps['A3'], $this->f2comps['A3']);
$this->assertModuleCompetencyMigrated($this->cms[$this->c2->id]['F1'], $this->f1comps['A2'], $this->f2comps['A2']);
$this->assertModuleCompetencyMigrated($this->cms[$this->c2->id]['F1'], $this->f1comps['A3'], $this->f2comps['A3']);
}
public function test_destination_competency_exists(): void {
$this->setAdminUser();
$lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
// Pre-add the new competency to course 1.
$lpg->create_course_competency(array('courseid' => $this->c1->id, 'competencyid' => $this->f2comps['A1']->get('id')));
// Pre-add the new competency to module in course 2.
$lpg->create_course_module_competency(array(
'cmid' => $this->cms[$this->c2->id]['F1']->cmid,
'competencyid' => $this->f2comps['A2']->get('id')
));
$mapper = new framework_mapper($this->f1->get('id'), $this->f2->get('id'));
$mapper->automap();
$processor = new framework_processor($mapper);
$processor->proceed();
$this->assertEquals(2, $processor->get_courses_found_count());
$this->assertEquals(5, $processor->get_expected_course_competency_migrations());
$this->assertEquals(3, $processor->get_course_competency_migrations());
$this->assertEquals(2, $processor->get_course_competency_removals());
$this->assertEquals(3, $processor->get_cms_found_count());
$this->assertEquals(5, $processor->get_expected_module_competency_migrations());
$this->assertEquals(3, $processor->get_module_competency_migrations());
$this->assertEquals(3, $processor->get_module_competency_removals());
$this->assertEquals(array(), $processor->get_errors());
$warnings = $processor->get_warnings();
$this->assertCount(2, $warnings);
$warning = array_shift($warnings);
$this->assertEquals($this->c1->id, $warning['courseid']);
$this->assertEquals($this->f1comps['A1']->get('id'), $warning['competencyid']);
$this->assertEquals(null, $warning['cmid']);
$this->assertMatchesRegularExpression('/competency already exists/', $warning['message']);
$warning = array_shift($warnings);
$this->assertEquals($this->c2->id, $warning['courseid']);
$this->assertEquals($this->f1comps['A2']->get('id'), $warning['competencyid']);
$this->assertEquals($this->cms[$this->c2->id]['F1']->cmid, $warning['cmid']);
$this->assertMatchesRegularExpression('/competency already exists/', $warning['message']);
$this->assertCourseCompetencyExists($this->c1, $this->f1comps['A1']);
$this->assertModuleCompetencyExists($this->cms[$this->c2->id]['F1'], $this->f1comps['A2']);
}
public function test_destination_competency_exists_remove_original(): void {
$this->setAdminUser();
$lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
// Pre-add the new competency to course 1.
$lpg->create_course_competency(array('courseid' => $this->c1->id, 'competencyid' => $this->f2comps['A1']->get('id')));
// Pre-add the new competency to module in course 2.
$lpg->create_course_module_competency(array(
'cmid' => $this->cms[$this->c2->id]['F1']->cmid,
'competencyid' => $this->f2comps['A2']->get('id')
));
$mapper = new framework_mapper($this->f1->get('id'), $this->f2->get('id'));
$mapper->automap();
$processor = new framework_processor($mapper);
$processor->set_remove_original_when_destination_already_present(true);
$processor->proceed();
$this->assertEquals(2, $processor->get_courses_found_count());
$this->assertEquals(5, $processor->get_expected_course_competency_migrations());
$this->assertEquals(3, $processor->get_course_competency_migrations());
$this->assertEquals(4, $processor->get_course_competency_removals());
$this->assertEquals(3, $processor->get_cms_found_count());
$this->assertEquals(5, $processor->get_expected_module_competency_migrations());
$this->assertEquals(3, $processor->get_module_competency_migrations());
$this->assertEquals(4, $processor->get_module_competency_removals());
$this->assertEquals(array(), $processor->get_errors());
$this->assertEquals(array(), $processor->get_warnings());
$this->assertCourseCompetencyNotExists($this->c1, $this->f1comps['A1']);
$this->assertModuleCompetencyNotExists($this->cms[$this->c2->id]['F1'], $this->f1comps['A2']);
}
public function test_permission_exception(): void {
$this->preventResetByRollback(); // Test uses transactions, so we cannot use them for speedy reset.
$dg = $this->getDataGenerator();
$u = $dg->create_user();
$role = $dg->create_role();
$sysctx = \context_system::instance();
$dg->enrol_user($u->id, $this->c1->id, 'editingteacher');
$dg->enrol_user($u->id, $this->c2->id, 'editingteacher');
assign_capability('moodle/competency:coursecompetencymanage', CAP_PROHIBIT, $role, $sysctx->id);
role_assign($role, $u->id, \context_course::instance($this->c1->id)->id);
role_assign($role, $u->id, \context_module::instance($this->cms[$this->c2->id]['F1']->cmid)->id);
accesslib_clear_all_caches_for_unit_testing();
$this->setUser($u);
// Do C1 first.
$mapper = new framework_mapper($this->f1->get('id'), $this->f2->get('id'));
$mapper->automap();
$processor = new framework_processor($mapper);
$processor->set_allowedcourses(array($this->c1->id));
$processor->proceed();
$this->assertEquals(1, $processor->get_courses_found_count());
$this->assertEquals(3, $processor->get_expected_course_competency_migrations());
$this->assertEquals(0, $processor->get_course_competency_migrations());
$this->assertEquals(0, $processor->get_course_competency_removals());
$this->assertEquals(2, $processor->get_cms_found_count());
$this->assertEquals(3, $processor->get_expected_module_competency_migrations());
$this->assertEquals(0, $processor->get_module_competency_migrations());
$this->assertEquals(0, $processor->get_module_competency_removals());
$this->assertEquals(array(), $processor->get_warnings());
$errors = $processor->get_errors();
$this->assertCount(2, $errors);
$this->assertEquals($this->c1->id, $errors[0]['courseid']);
$this->assertEquals($this->f1comps['A1']->get('id'), $errors[0]['competencyid']);
$this->assertEquals(null, $errors[0]['cmid']);
$this->assertMatchesRegularExpression('/Sorry, but you do not currently have permissions to do that/',
$errors[0]['message']);
$this->assertEquals($this->f1comps['A3']->get('id'), $errors[1]['competencyid']);
$this->assertCourseCompetencyNotMigrated($this->c1, $this->f1comps['A1'], $this->f2comps['A1']);
$this->assertCourseCompetencyNotMigrated($this->c1, $this->f1comps['A3'], $this->f2comps['A3']);
$this->assertModuleCompetencyNotMigrated($this->cms[$this->c1->id]['F1'], $this->f1comps['A1'], $this->f2comps['A1']);
$this->assertModuleCompetencyNotMigrated($this->cms[$this->c1->id]['P1'], $this->f1comps['A3'], $this->f2comps['A3']);
// Do C2 now.
$processor = new framework_processor($mapper);
$processor->set_allowedcourses(array($this->c2->id));
$processor->proceed();
$this->assertEquals(1, $processor->get_courses_found_count());
$this->assertEquals(2, $processor->get_expected_course_competency_migrations());
$this->assertEquals(2, $processor->get_course_competency_migrations());
$this->assertEquals(0, $processor->get_course_competency_removals());
$this->assertEquals(1, $processor->get_cms_found_count());
$this->assertEquals(2, $processor->get_expected_module_competency_migrations());
$this->assertEquals(0, $processor->get_module_competency_migrations());
$this->assertEquals(0, $processor->get_module_competency_removals());
$this->assertEquals(array(), $processor->get_warnings());
$errors = $processor->get_errors();
$this->assertCount(2, $errors);
$this->assertEquals($this->c2->id, $errors[0]['courseid']);
$this->assertEquals($this->f1comps['A2']->get('id'), $errors[0]['competencyid']);
$this->assertEquals($this->cms[$this->c2->id]['F1']->cmid, $errors[0]['cmid']);
$this->assertMatchesRegularExpression('/Sorry, but you do not currently have permissions to do that/',
$errors[0]['message']);
$this->assertEquals($this->f1comps['A3']->get('id'), $errors[1]['competencyid']);
// The new competencies were added to the course, but the old ones were not removed because they are still in modules.
$this->assertCourseCompetencyExists($this->c2, $this->f1comps['A2']);
$this->assertCourseCompetencyExists($this->c2, $this->f1comps['A3']);
$this->assertCourseCompetencyExists($this->c2, $this->f2comps['A2']);
$this->assertCourseCompetencyExists($this->c2, $this->f2comps['A3']);
// Module competencies were not migrated because permissions are lacking.
$this->assertModuleCompetencyNotMigrated($this->cms[$this->c2->id]['F1'], $this->f1comps['A2'], $this->f2comps['A2']);
$this->assertModuleCompetencyNotMigrated($this->cms[$this->c2->id]['F1'], $this->f1comps['A3'], $this->f2comps['A2']);
}
/**
* Assert that the course competency exists.
*
* @param \stdClass $course The course.
* @param competency $competency The competency.
*/
protected function assertCourseCompetencyExists($course, $competency) {
$this->assertTrue(course_competency::record_exists_select("courseid = :courseid AND competencyid = :competencyid",
array('courseid' => $course->id, 'competencyid' => $competency->get('id'))));
}
/**
* Assert that the course competency does not exist.
*
* @param \stdClass $course The course.
* @param competency $competency The competency.
*/
protected function assertCourseCompetencyNotExists($course, $competency) {
$this->assertFalse(course_competency::record_exists_select("courseid = :courseid AND competencyid = :competencyid",
array('courseid' => $course->id, 'competencyid' => $competency->get('id'))));
}
/**
* Assert that the course competency was migrated.
*
* @param \stdClass $course The course.
* @param competency $compfrom The competency from.
* @param competency $compto The competency to.
*/
protected function assertCourseCompetencyMigrated($course, $compfrom, $compto) {
$ccs = $this->ccs[$course->id];
$this->assertCourseCompetencyNotExists($course, $compfrom);
$this->assertCourseCompetencyExists($course, $compto);
$before = $ccs[$compfrom->get('id')];
$after = course_competency::get_record(array(
'courseid' => $course->id,
'competencyid' => $compto->get('id')
));
$this->assertNotEquals($before->get('id'), $after->get('id'));
$this->assertEquals($before->get('courseid'), $after->get('courseid'));
$this->assertEquals($before->get('sortorder'), $after->get('sortorder'));
$this->assertEquals($before->get('ruleoutcome'), $after->get('ruleoutcome'));
}
/**
* Assert that the course competency was not migrated.
*
* @param \stdClass $course The course.
* @param competency $compfrom The competency from.
* @param competency $compto The competency to.
*/
protected function assertCourseCompetencyNotMigrated($course, $compfrom, $compto) {
$ccs = $this->ccs[$course->id];
$this->assertCourseCompetencyExists($course, $compfrom);
$this->assertCourseCompetencyNotExists($course, $compto);
$before = $ccs[$compfrom->get('id')];
$after = $ccs[$compfrom->get('id')];
$this->assertEquals($before->get('id'), $after->get('id'));
$this->assertEquals($before->get('courseid'), $after->get('courseid'));
$this->assertEquals($before->get('sortorder'), $after->get('sortorder'));
$this->assertEquals($before->get('ruleoutcome'), $after->get('ruleoutcome'));
}
/**
* Assert that the course module competency exists.
*
* @param \stdClass $cm The CM.
* @param competency $competency The competency.
*/
protected function assertModuleCompetencyExists($cm, $competency) {
$this->assertTrue(course_module_competency::record_exists_select("cmid = :cmid AND competencyid = :competencyid",
array('cmid' => $cm->cmid, 'competencyid' => $competency->get('id'))));
}
/**
* Assert that the course module competency does not exist.
*
* @param \stdClass $cm The CM.
* @param competency $competency The competency.
*/
protected function assertModuleCompetencyNotExists($cm, $competency) {
$this->assertFalse(course_module_competency::record_exists_select("cmid = :cmid AND competencyid = :competencyid",
array('cmid' => $cm->cmid, 'competencyid' => $competency->get('id'))));
}
/**
* Assert that the course module competency was migrated.
*
* @param \stdClass $cm The CM.
* @param competency $compfrom The competency from.
* @param competency $compto The competency to.
*/
protected function assertModuleCompetencyMigrated($cm, $compfrom, $compto) {
$cmcs = $this->cmcs[$cm->cmid];
$this->assertModuleCompetencyNotExists($cm, $compfrom);
$this->assertModuleCompetencyExists($cm, $compto);
$before = $cmcs[$compfrom->get('id')];
$after = course_module_competency::get_record(array(
'cmid' => $cm->cmid,
'competencyid' => $compto->get('id')
));
$this->assertNotEquals($before->get('id'), $after->get('id'));
$this->assertEquals($before->get('cmid'), $after->get('cmid'));
$this->assertEquals($before->get('sortorder'), $after->get('sortorder'));
$this->assertEquals($before->get('ruleoutcome'), $after->get('ruleoutcome'));
}
/**
* Assert that the course module competency was not migrated.
*
* @param \stdClass $cm The CM.
* @param competency $compfrom The competency from.
* @param competency $compto The competency to.
*/
protected function assertModuleCompetencyNotMigrated($cm, $compfrom, $compto) {
$cmcs = $this->cmcs[$cm->cmid];
$this->assertModuleCompetencyExists($cm, $compfrom);
$this->assertModuleCompetencyNotExists($cm, $compto);
$before = $cmcs[$compfrom->get('id')];
$after = $cmcs[$compfrom->get('id')];
$this->assertEquals($before->get('id'), $after->get('id'));
$this->assertEquals($before->get('cmid'), $after->get('cmid'));
$this->assertEquals($before->get('sortorder'), $after->get('sortorder'));
$this->assertEquals($before->get('ruleoutcome'), $after->get('ruleoutcome'));
}
}
+32
View File
@@ -0,0 +1,32 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Plugin version info.
*
* @package tool_lpmigrate
* @copyright 2016 Frédéric Massart - FMCorz.net
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
$plugin->version = 2024042200; // The current plugin version (Date: YYYYMMDDXX).
$plugin->requires = 2024041600; // Requires this Moodle version.
$plugin->component = 'tool_lpmigrate'; // Full name of the plugin (used for diagnostics).
$plugin->dependencies = [
'tool_lp' => ANY_VERSION,
];