MDL-51024 tool_lpmigrate: Tool to migrate between frameworks

This commit is contained in:
Frederic Massart
2016-02-25 10:30:37 +08:00
parent e43f6aa756
commit 057c14032b
12 changed files with 2101 additions and 0 deletions

View File

@@ -0,0 +1,96 @@
<?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 {
protected $pagecontext;
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;
}
}

View File

@@ -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 tool_lp\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();
}
}

View File

@@ -0,0 +1,631 @@
<?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 tool_lp\api;
use tool_lp\competency;
use tool_lp\course_competency;
use tool_lp\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|null $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++;
// The competency was already in the course...
} else {
if ($this->removeoriginalwhenalreadypresent) {
$competenciestoremovefromcourse[$competencyid] = true;
} else {
$this->log_warning($courseid, $competencyid, null,
get_string('warningdestinationcoursecompetencyalreadyexists', 'tool_lpmigrate'));
}
}
// There was a major problem with this competency, we will ignore it entirely for the course.
} catch (moodle_exception $e) {
$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;
}
// We have a mapping.
} else {
$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++;
// The competency was already in the module.
} else {
if (!$this->removeoriginalwhenalreadypresent) {
$remove = false;
$competencieswithissues[$competencyid] = true;
$this->log_warning($courseid, $competencyid, $cmid,
get_string('warningdestinationmodulecompetencyalreadyexists', 'tool_lpmigrate'));
}
}
// There was a major problem with this competency in this module.
} catch (moodle_exception $e) {
$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) {
$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) {
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;
}
}

View File

@@ -0,0 +1,151 @@
<?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 tool_lp\competency;
use tool_lp\competency_framework;
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;
protected $processor;
/**
* 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 \tool_lp\external\competency_framework_exporter($this->frameworkfrom);
$data->frameworkfrom = $exporter->export($output);
$exporter = new \tool_lp\external\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 \tool_lp\external\competency_exporter($comp, array('context' => $fromcontext));
$data->unmappedfrom[] = $exporter->export($output);
}
foreach ($this->unmappedto as $comp) {
$exporter = new \tool_lp\external\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->cbebaseurl = (new moodle_url('/admin/tool/lp'))->out(false);
return $data;
}
}

View File

@@ -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 renderable $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);
}
}

View File

@@ -0,0 +1,36 @@
<?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
),
'clonepermissionsfrom' => 'moodle/site:config'
),
);

View File

@@ -0,0 +1,78 @@
<?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'));
$output = $PAGE->get_renderer('tool_lpmigrate');
echo $output->header();
echo $output->heading($title);
$form = new \tool_lpmigrate\form\migrate_framework($context);
if ($form->is_cancelled()) {
redirect($url);
} else 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,
\tool_lp\api::read_framework($data->from), \tool_lp\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();

View File

@@ -0,0 +1,67 @@
<?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'] = 'When at least one course is specified, the migration will only occur on the courses listed here.';
$string['continuetoframeworks'] = 'Continue to frameworks';
$string['coursecompetencymigrations'] = 'Course competency migrations';
$string['coursemodulecompetencymigrations'] = 'Course module competency migrations';
$string['coursesfound'] = 'Courses found';
$string['coursemodulesfound'] = 'Course modules found';
$string['coursestartdate'] = 'Courses start date';
$string['coursestartdate_help'] = 'When enabled, courses with a start date prior to the one specified here will not be migrated.';
$string['disallowedcourses'] = 'Disallowed courses';
$string['disallowedcourses_help'] = 'Any course specified here will not be migrated.';
$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 course module competency: {$a}';
$string['excludethese'] = 'Exclude these';
$string['explanation'] = 'When updating a competency framework to a newer version, this tool can be used to search for competencies in courses and course modules using the older framework, and update the links to point to the new framework. This works by finding competencies with matching ID numbers in the two frameworks, and then mapping all of the competency links in the specified list of courses to point to the new version of the competency in 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, and use this tool to migrate new courses to the new framework.';
$string['findingcoursecompetencies'] = 'Finding course competencies';
$string['findingmodulecompetencies'] = 'Finding module 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 framework to migrate from.';
$string['migratemore'] = 'Migrate more';
$string['migrateto'] = 'Migrate to';
$string['migrateto_help'] = 'Select the framework to migrate to. Note that it must be not be 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 course module competency could not be removed.';
$string['warningdestinationcoursecompetencyalreadyexists'] = 'The destination course competency already exists.';
$string['warningdestinationmodulecompetencyalreadyexists'] = 'The destination course module competency already exists.';
$string['warnings'] = 'Warnings';

View File

@@ -0,0 +1,37 @@
<?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 (\tool_lp\api::is_enabled()) {
// 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('toollprootpage', $temp);
}

View File

@@ -0,0 +1,166 @@
{{!
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">{{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">{{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">{{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">{{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="{{cbebaseurl}}/competencyframeworks.php?pagecontextid={{frameworkto.contextid}}" class="btn">{{#str}}continuetoframeworks, tool_lpmigrate{{/str}}</a>
</p>
</div>
{{#js}}
require(['tool_lp/competencydialogue'], function(CompDialogue) {
var cd = new CompDialogue({includecourses: true, includerelated: true});
cd.watch('[data-region="migration-results"]');
})
{{/js}}

View File

@@ -0,0 +1,567 @@
<?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 processor tests.
*
* @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();
global $CFG;
use \tool_lp\course_competency;
use \tool_lp\course_module_competency;
use \tool_lpmigrate\framework_mapper;
use \tool_lpmigrate\framework_processor;
/**
* 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 tool_lpmigrate_framework_processor_testcase extends advanced_testcase {
/**
* 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() {
$this->resetAfterTest(true);
$dg = $this->getDataGenerator();
$lpg = $dg->get_plugin_generator('tool_lp');
$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() {
$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() {
$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() {
$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() {
$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 abc_test_course_start_date_from() {
$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() {
$this->setAdminUser();
$lpg = $this->getDataGenerator()->get_plugin_generator('tool_lp');
// 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(3, $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->assertRegexp('/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->assertRegexp('/competency already exists/', $warning['message']);
$this->assertCourseCompetencyExists($this->c1, $this->f1comps['A1']);
$this->assertModuleCompetencyExists($this->c2, $this->f1comps['A2']);
}
public function test_destination_competency_exists_remove_original() {
$this->setAdminUser();
$lpg = $this->getDataGenerator()->get_plugin_generator('tool_lp');
// 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->c2, $this->f1comps['A2']);
}
public function test_permission_exception() {
global $DB;
if ($DB->get_dbfamily() === 'postgres' or $DB->get_dbfamily() === 'mssql') {
$this->markTestSkipped('The processor is having issues with the transaction initialised in '
. 'advanced_testcase::runBare().');
return;
}
$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('tool/lp: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->assertRegexp('/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(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(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->assertRegexp('/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->assertCourseCompetencyMigrated($this->c2, $this->f1comps['A2'], $this->f2comps['A2']);
$this->assertCourseCompetencyMigrated($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['A2']);
}
protected function assertCourseCompetencyExists($course, $competency) {
return course_competency::record_exists_select("courseid = :courseid AND competencyid = :competencyid",
array('courseid' => $course->id, 'competencyid' => $competency->get_id()));
}
protected function assertCourseCompetencyNotExists($course, $competency) {
return !course_competency::record_exists_select("courseid = :courseid AND competencyid = :competencyid",
array('courseid' => $course->id, 'competencyid' => $competency->get_id()));
}
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());
}
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());
}
protected function assertModuleCompetencyExists($cm, $competency) {
return course_module_competency::record_exists_select("cmid = :cmid AND competencyid = :competencyid",
array('cmid' => $cm->id, 'competencyid' => $competency->get_id()));
}
protected function assertModuleCompetencyNotExists($cm, $competency) {
return !course_module_competency::record_exists_select("cmid = :cmid AND competencyid = :competencyid",
array('cmid' => $cm->id, 'competencyid' => $competency->get_id()));
}
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());
}
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());
}
}

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 = 2016022401; // The current plugin version (Date: YYYYMMDDXX).
$plugin->requires = 2014110400; // Requires this Moodle version.
$plugin->component = 'tool_lpmigrate'; // Full name of the plugin (used for diagnostics).
$plugin->dependencies = array(
'tool_lp' => 2016020904
);