Actualización

This commit is contained in:
Xes
2025-04-10 12:36:07 +02:00
parent 1da7c3f3b9
commit 4aff98e77b
3147 changed files with 320647 additions and 0 deletions

View File

@@ -0,0 +1,24 @@
# MigrationMoodlePlugin
Allow migrate course contents and user progress from a Moodle platform.
> In development.
## Instructions
- Install the plugin
- Set the configuration (params to moodle DB connection and moodledata directory)
- Optionally, set the admin region
You can run the migration tasks from browser using the admin panel.
You must ejecute the tasks in the order indicated in the task list.
Also you can run all the migrations running `php plugin/migrationmoodle/run_cli.php`.
But if you want to run the migration with multiple url, then you will need edi `MigrationMoodlePlugin::getAccessUrlId`,
`MigrationMoodlePlugin::getMoodledataPath` methods to set your plugin settings.
# Notes
- Check if exists an index on `c_lp_item_view.status` on Chamilo DB.
It for optimize the performance when executing the SQL query used in UserScormProgressLoader.
- It requires a Moodle DB with MySQL 8 or MariaDB 10.2.2 for some tasks (LessonPagesTask).

View File

@@ -0,0 +1,241 @@
<?php
/* For licensing terms, see /license.txt */
use Chamilo\PluginBundle\MigrationMoodle\Script\BaseScript;
use Chamilo\PluginBundle\MigrationMoodle\Task\BaseTask;
ini_set('memory_limit', -1);
ini_set('max_execution_time', 0);
$cidReset = true;
$outputBuffering = false;
require_once __DIR__.'/../../main/inc/global.inc.php';
api_protect_admin_script(true);
$action = isset($_GET['action']) ? $_GET['action'] : '';
$plugin = MigrationMoodlePlugin::create();
if ('true' != $plugin->get('active')) {
api_not_allowed(true);
}
$menuTasks = [
'_' => [
'course_categories',
'courses',
//'role_assignments',
'users',
],
'courses' => [
'course_introductions',
'course_sections',
'course_modules_scorm',
],
'course_sections' => [
'files_for_course_sections',
'course_modules_lesson',
'course_modules_quiz',
'course_modules_url',
//'c_quiz',
'sort_section_modules',
],
'course_modules_lesson' => [
'lesson_pages',
],
'lesson_pages' => [
'lesson_pages_document',
'lesson_pages_quiz',
],
'lesson_pages_document' => [
'files_for_lesson_pages',
],
'lesson_pages_quiz' => [
'lesson_pages_quiz_question',
'files_for_lesson_answers',
],
'lesson_pages_quiz_question' => [
'lesson_answers_true_false',
'lesson_answers_multiple_choice',
'lesson_answers_multiple_answer',
'lesson_answers_matching',
'lesson_answers_essay',
'lesson_answers_short_answer',
],
'course_modules_quiz' => [
'quizzes',
'quizzes_scores',
],
'quizzes' => [
'files_for_quizzes',
'question_categories',
'questions',
],
'questions' => [
'question_multi_choice_single',
'question_multi_choice_multiple',
'questions_true_false',
'question_short_answer',
'question_gapselect',
],
'course_modules_scorm' => [
'scorm_scoes',
],
'scorm_scoes' => [
'files_for_scorm_scoes',
],
'course_introductions' => [
'files_for_course_introductions',
],
'course_modules_url' => [
'urls',
],
'users' => [
'users_last_login',
'track_login',
'user_sessions',
],
'user_sessions' => [
'users_learn_paths',
'users_scorms_view',
'track_course_access',
],
'users_learn_paths' => [
'users_learn_paths_lesson_timer',
'users_learn_paths_lesson_branch',
'users_learn_paths_lesson_attempts',
'users_learn_paths_quizzes',
],
'users_learn_paths_quizzes' => [
'users_quizzes_attempts',
'user_question_attempts_shortanswer',
'user_question_attempts_gapselect',
'user_question_attempts_truefalse',
],
];
$menuScripts = [
'_' => [
'user_learn_paths_progress',
'user_scorms_progress',
],
];
$htmlHeadXtra[] = '<style>.fa-ul {list-style-type: decimal; list-style-position: outside;}</style>';
Display::display_header($plugin->get_title());
echo '<div class="row">';
echo '<div class="col-sm-6 col-sm-push-6">';
echo '<pre style="max-height: 1190px; overflow: auto; height: 1190px;">';
if (!empty($action) && isAllowedAction($action, $menuTasks) && !$plugin->isTaskDone($action)) {
$taskName = api_underscore_to_camel_case($action).'Task';
echo Display::page_subheader(
$plugin->get_lang($taskName)
);
$taskName = 'Chamilo\\PluginBundle\\MigrationMoodle\\Task\\'.$taskName;
/** @var BaseTask $task */
$task = new $taskName();
$task->execute();
}
if (!empty($action) && isAllowedAction($action, $menuScripts) && !$plugin->isTaskDone($action)) {
$scriptName = api_underscore_to_camel_case($action).'Script';
echo Display::page_subheader(
$plugin->get_lang($scriptName)
);
$scriptClass = 'Chamilo\\PluginBundle\\MigrationMoodle\\Script\\'.$scriptName;
/** @var BaseScript $script */
$script = new $scriptClass();
$script->run();
}
echo '</pre>';
echo '</div>';
echo '<div class="col-sm-6 col-sm-pull-6">';
echo Display::page_subheader('Tasks');
echo displayMenu($menuTasks);
echo Display::page_subheader('Scripts');
echo displayMenu($menuScripts, 'Script');
echo '</div>';
echo '</div>';
Display::display_footer();
/**
* @param string $parent
* @param string $type
*
* @return string
*/
function displayMenu(array $menu, $type = 'Task', $parent = '_')
{
$plugin = MigrationMoodlePlugin::create();
$items = $menu[$parent];
$isParentDone = $parent === '_' ? true : $plugin->isTaskDone($parent);
$baseUrl = api_get_self()."?action=";
$html = '<ol class="fa-ul">';
foreach ($items as $item) {
$title = api_underscore_to_camel_case($item);
$html .= '<li>';
$htmlItem = Display::returnFontAwesomeIcon('check-square-o', '', true);
$htmlItem .= $plugin->get_lang($title.$type);
if ($isParentDone) {
if (!$plugin->isTaskDone($item)) {
$htmlItem = Display::returnFontAwesomeIcon('square-o', '', true);
$htmlItem .= Display::url(
$plugin->get_lang($title.$type),
$baseUrl.$item
);
}
}
$html .= $htmlItem;
if (isset($menu[$item])) {
$html .= displayMenu($menu, $type, $item);
}
$html .= '</li>';
}
$html .= '</ol>';
return $html;
}
/**
* @param string $action
*
* @return bool
*/
function isAllowedAction($action, array $menu)
{
foreach ($menu as $items) {
if (in_array($action, $items)) {
return true;
}
}
return false;
}

View File

@@ -0,0 +1,59 @@
<?php
/* For licensing terms, see /license.txt */
$plugin = MigrationMoodlePlugin::create();
try {
UserManager::create_extra_field(
'moodle_password',
ExtraField::FIELD_TYPE_TEXT,
$plugin->get_lang('MoodlePassword'),
''
);
createPluginTables();
} catch (Exception $exception) {
$message = sprintf(
$plugin->get_lang('InstallError'),
$exception->getMessage()
);
echo Display::return_message($message, 'error');
}
/**
* Create database tables for this plugin.
*/
function createPluginTables()
{
$installed = AppPlugin::getInstance()->isInstalled('migrationmoodle');
if ($installed) {
return;
}
$queries = [];
$queries[] = "CREATE TABLE IF NOT EXISTS plugin_migrationmoodle_task (
id INT AUTO_INCREMENT NOT NULL,
name VARCHAR(255) NOT NULL,
PRIMARY KEY(id)
) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB";
$queries[] = "CREATE TABLE IF NOT EXISTS plugin_migrationmoodle_item (
id INT AUTO_INCREMENT NOT NULL,
task_id INT NOT NULL,
hash VARCHAR(255) NOT NULL,
extracted_id INT NOT NULL,
loaded_id INT NOT NULL,
INDEX IDX_HASH (hash),
INDEX IDX_EXTRACTED_LOADED (extracted_id, loaded_id),
INDEX IDX_LOADED (loaded_id),
INDEX IDX_TASK (task_id),
PRIMARY KEY(id)
) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB";
$queries[] = "ALTER TABLE plugin_migrationmoodle_item ADD CONSTRAINT FK_TASK FOREIGN KEY (task_id)
REFERENCES plugin_migrationmoodle_task (id) ON DELETE CASCADE";
foreach ($queries as $query) {
Database::query($query);
}
}

View File

@@ -0,0 +1,79 @@
<?php
/* For licensing terms, see /license.txt */
$strings['plugin_title'] = 'Import from Moodle';
$strings['plugin_comment'] = 'Execute an import process from a Moodle database and files to Chamilo.';
$strings['MoodlePassword'] = 'Moodle password';
$strings['UninstallError'] = 'An error ocurred uninstalling the plugin.';
$strings['active'] = 'Active';
$strings['db_host'] = 'Moodle DB host';
$strings['db_user'] = 'Moodle DB user';
$strings['db_password'] = 'Moodle DB password';
$strings['db_name'] = 'Moodle DB name';
$strings['user_filter'] = 'Filter for users';
$strings['user_filter_help'] = 'Only import users who have a username prefixed with this string.<br>'
.'The import of courses is also affected by this configuration, as it only imports courses in which users with this username prefix are enrolled.';
$strings['url_id'] = 'URL ID';
$strings['url_id_help'] = 'Access URL ID to save courses, users and sessions to (if using multi-url).';
$strings['moodle_path'] = 'Moodledata path';
$strings['moodle_path_help'] = 'The moodledata folder path. Usually something like <pre>/var/www/moodledata</pre>';
// Tasks
$strings['UsersTask'] = 'Users';
$strings['CourseCategoriesTask'] = 'Course categories';
$strings['CoursesTask'] = 'Courses';
$strings['CourseSectionsTask'] = 'Course sections';
$strings['CourseModulesLessonTask'] = 'Course modules: Lessons';
$strings['LessonPagesTask'] = 'Lesson pages';
$strings['LessonPagesDocumentTask'] = 'Lesson pages: Documents';
$strings['FilesForLessonPagesTask'] = 'Files for lesson pages';
$strings['LessonPagesQuizTask'] = 'Lesson pages: Questions';
$strings['LessonPagesQuizQuestionTask'] = 'Questions for question pages';
$strings['LessonAnswersTrueFalseTask'] = 'Answers for True/False questions';
$strings['LessonAnswersMultipleChoiceTask'] = 'Answers for Multiple Choice questions';
$strings['LessonAnswersMultipleAnswerTask'] = 'Answers for Multiple Answer questions';
$strings['LessonAnswersMatchingTask'] = 'Answers for Matching questions';
$strings['LessonAnswersEssayTask'] = 'Answers for Essay questions';
$strings['LessonAnswersShortAnswerTask'] = 'Answers for Short Answer questions';
$strings['FilesForLessonAnswersTask'] = 'Files for lesson answers';
$strings['CourseModulesQuizTask'] = 'Course modules: Quizzes';
$strings['CQuizTask'] = 'C Quiz';
$strings['RoleAssignmentsTask'] = 'Role assignments';
$strings['QuizzesTask'] = 'Quizzes';
$strings['FilesForQuizzesTask'] = 'Files for quizzes';
$strings['QuestionCategoriesTask'] = 'Question categories';
$strings['QuestionsTask'] = 'Questions';
$strings['QuestionMultiChoiceSingleTask'] = 'Answers for multichoice questions (single)';
$strings['QuestionMultiChoiceMultipleTask'] = 'Answers for multichoice questions (multiple)';
$strings['QuestionsTrueFalseTask'] = 'Answers for truefalse questions';
$strings['QuestionShortAnswerTask'] = 'Answers for shortanswers questions';
$strings['CourseModulesScormTask'] = 'SCORM courses';
$strings['ScormScoesTask'] = 'SCORM items';
$strings['FilesForScormScoesTask'] = 'Files for SCORM items';
$strings['UserSessionsTask'] = 'Course Sessions for users';
$strings['CourseIntroductionsTask'] = 'Course introductions';
$strings['FilesForCourseIntroductionsTask'] = 'Files for course introductions';
$strings['FilesForCourseSectionsTask'] = 'Files for course sections';
$strings['CourseModulesUrlTask'] = 'Course modules: URLs';
$strings['UrlsTask'] = 'URLs';
$strings['SortSectionModulesTask'] = 'Sort modules in section';
$strings['UsersScormsViewTask'] = 'SCORM views for users';
$strings['UsersScormsProgressTask'] = 'SCORM progress';
$strings['UsersLearnPathsTask'] = 'Learn paths views of users';
$strings['UsersLearnPathsLessonTimerTask'] = 'Lesson timer to start time of Learn paths section';
$strings['QuizzesScoresTask'] = 'Update quiz scores in learn path';
$strings['QuestionGapselectTask'] = 'Answers for gapselect questions';
$strings['UsersLearnPathsLessonBranchTask'] = 'Lesson branch to total time in learn paths documents';
$strings['UsersLearnPathsLessonAttemptsTask'] = 'Lesson attempts to total time in learn paths quizzes';
$strings['UsersLearnPathsQuizzesTask'] = 'Quizzes attempts to learn paths quizzes attempts';
$strings['UsersQuizzesAttemptsTask'] = 'Quiz attempts of users';
$strings['UserQuestionAttemptsShortanswerTask'] = 'Question attempts of users for shortanswer';
$strings['UserQuestionAttemptsGapselectTask'] = 'Question attempts of users for gapselect';
$strings['UserQuestionAttemptsTruefalseTask'] = 'Question attempts of users for truefalse';
$strings['UsersLastLoginTask'] = 'Last logins for users';
$strings['TrackLoginTask'] = 'First login and last logout';
$strings['TrackCourseAccessTask'] = 'User access to course';
$strings['UserLearnPathsProgressScript'] = 'Update progress in learning paths for users.';
$strings['UserScormsProgressScript'] = 'Update progress in SCORMs for users.';

View File

@@ -0,0 +1,24 @@
<?php
/* For licensing terms, see /license.txt */
$strings['plugin_title'] = 'Importation depuis Moodle';
$strings['plugin_comment'] = 'Exécuter un processus d\'import depuis une base de données et des fichiers Moodle dans Chamilo.';
$strings['MoodlePassword'] = 'Mot de passe Moodle';
$strings['UninstallError'] = 'Une erreur s\'est produite durant la désinstallation du plugin d\'import Moodle.';
$strings['active'] = 'Activé';
$strings['db_host'] = 'Hôte BdD Moodle';
$strings['db_user'] = 'Utilisateur BdD Moodle';
$strings['db_password'] = 'Mot de passe BdD Moodle';
$strings['db_name'] = 'Nom BdD Moodle';
$strings['user_filter'] = 'Filtre utilisateurs';
$strings['user_filter_help'] = 'Seuls les utilisateurs dont le nom d\'utilisateur est préfixé de cette chaîne de caractères seront importés.<br>'
.'L\'import des cours est aussi affecté par cette variable, car seuls les cours auxquels des utilisateurs commençant par ce préfixe sont inscrits seront migrés.';
$strings['url_id'] = 'ID d\'URL';
$strings['url_id_help'] = 'ID d\'URL (si multi-URL utilisés) dans lequel sauver les cours, utiilisateurs et sessions.';
$strings['moodle_path'] = 'Chemin vers moodledata';
$strings['moodle_path_help'] = 'Le chemin vers le répertoire moodledata. Habituellement quelque chose comme <pre>/var/www/moodledata</pre>';
// Tasks
$strings['UsersTask'] = 'Utilisateurs';

View File

@@ -0,0 +1,4 @@
<?php
/* For licensing terms, see /license.txt */
$plugin_info = MigrationMoodlePlugin::create()->get_info();

View File

@@ -0,0 +1,120 @@
<?php
/* For licensing terms, see /license.txt */
use Chamilo\PluginBundle\MigrationMoodle\Script\BaseScript;
use Chamilo\PluginBundle\MigrationMoodle\Task\BaseTask;
$cidReset = true;
ini_set('memory_limit', -1);
ini_set('max_execution_time', 0);
require_once __DIR__.'/../../main/inc/global.inc.php';
if (PHP_SAPI !== 'cli') {
echo 'Run on CLI.'.PHP_EOL;
exit;
}
$outputBuffering = false;
$plugin = MigrationMoodlePlugin::create();
$taskNames = [
'course_categories',
'courses',
'course_introductions',
'files_for_course_introductions',
'course_sections',
'files_for_course_sections',
'course_modules_lesson',
'lesson_pages',
'lesson_pages_document',
'files_for_lesson_pages',
'lesson_pages_quiz',
'lesson_pages_quiz_question',
'lesson_answers_true_false',
'lesson_answers_multiple_choice',
'lesson_answers_multiple_answer',
'lesson_answers_matching',
'lesson_answers_essay',
'lesson_answers_short_answer',
'files_for_lesson_answers',
'course_modules_quiz',
'quizzes',
'files_for_quizzes',
'question_categories',
'questions',
'question_multi_choice_single',
'question_multi_choice_multiple',
'questions_true_false',
'question_short_answer',
'question_gapselect',
'quizzes_scores',
'course_modules_url',
'urls',
'sort_section_modules',
'course_modules_scorm',
'scorm_scoes',
'files_for_scorm_scoes',
'users',
'users_last_login',
'track_login',
'user_sessions',
'users_learn_paths',
'users_learn_paths_lesson_timer',
'users_learn_paths_lesson_branch',
'users_learn_paths_lesson_attempts',
'users_learn_paths_quizzes',
'users_quizzes_attempts',
'user_question_attempts_shortanswer',
'user_question_attempts_gapselect',
'user_question_attempts_truefalse',
'users_scorms_view',
'track_course_access',
];
foreach ($taskNames as $i => $taskName) {
$taskClass = api_underscore_to_camel_case($taskName).'Task';
$taskClass = 'Chamilo\\PluginBundle\\MigrationMoodle\\Task\\'.$taskClass;
echo PHP_EOL.'['.date(DateTime::ATOM).'] '.($i + 1).': ';
if ($plugin->isTaskDone($taskName)) {
echo "Already done \"$taskClass\"".PHP_EOL;
continue;
}
echo "Executing \"$taskClass.\"".PHP_EOL;
/** @var BaseTask $task */
$task = new $taskClass();
$task->execute();
echo '['.date(DateTime::ATOM)."] End \"$taskClass\"".PHP_EOL;
}
$scriptNames = [
'user_learn_paths_progress',
'user_scorms_progress',
];
foreach ($scriptNames as $i => $scriptName) {
$scriptClass = api_underscore_to_camel_case($scriptName).'Script';
$scriptClass = 'Chamilo\\PluginBundle\\MigrationMoodle\\Script\\'.$scriptClass;
echo PHP_EOL.'['.date(DateTime::ATOM).'] '.($i + 1).': ';
if ($plugin->isTaskDone($scriptName)) {
echo "Already done \"$scriptClass\"".PHP_EOL;
continue;
}
echo "Executing \"$scriptClass.\"".PHP_EOL;
/** @var BaseScript $script */
$script = new $scriptClass();
$script->run();
echo '['.date(DateTime::ATOM)."] End \"$scriptClass\"".PHP_EOL;
}

View File

@@ -0,0 +1,63 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\MigrationMoodle\Extractor;
use Chamilo\PluginBundle\MigrationMoodle\Interfaces\ExtractorInterface;
use Doctrine\DBAL\DBALException;
use Doctrine\DBAL\FetchMode;
/**
* Class Extractor.
*/
class BaseExtractor implements ExtractorInterface
{
/**
* @var mixed
*/
private $query;
/**
* Extractor constructor.
*/
public function __construct(array $configuration)
{
$this->query = $configuration['query'];
}
/**
* @return bool
*/
public function filter(array $sourceData)
{
return false;
}
/**
* @throws \Exception
*
* @return \Generator|iterable
*/
public function extract()
{
$plugin = \MigrationMoodlePlugin::create();
try {
$connection = $plugin->getConnection();
} catch (DBALException $e) {
throw new \Exception('Unable to start connection.', 0, $e);
}
try {
$statement = $connection->executeQuery($this->query);
} catch (DBALException $e) {
throw new \Exception("Unable to execute query \"{$this->query}\".", 0, $e);
}
while ($sourceRow = $statement->fetch(FetchMode::ASSOCIATIVE)) {
yield $sourceRow;
}
$connection->close();
}
}

View File

@@ -0,0 +1,39 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\MigrationMoodle\Extractor;
use Chamilo\PluginBundle\MigrationMoodle\Traits\MapTrait\MapTrait;
/**
* Class FilterExtractor.
*
* @package Chamilo\PluginBundle\MigrationMoodle\Extractor
*/
abstract class FilterExtractor extends BaseExtractor
{
use MapTrait;
/**
* @param int $id
*
* @return bool
*/
protected function existsExtracted($id)
{
$taskName = $this->getTaskName();
$result = \Database::select(
'COUNT(1) AS c',
'plugin_migrationmoodle_item i INNER JOIN plugin_migrationmoodle_task t ON i.task_id = t.id',
[
'where' => [
't.name = ? AND i.extracted_id = ?' => [$taskName, $id],
],
],
'first'
);
return $result['c'] > 0;
}
}

View File

@@ -0,0 +1,40 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\MigrationMoodle\Extractor;
use Chamilo\PluginBundle\MigrationMoodle\Task\CoursesTask;
/**
* Class LoadedCoursesFilterExtractor.
*
* Extractor for course already extracted and loaded.
*
* @package Chamilo\PluginBundle\MigrationMoodle\Extractor
*/
class LoadedCoursesFilterExtractor extends FilterExtractor
{
/**
* LoadedCoursesFilterExtractor constructor.
*/
public function __construct(array $configuration)
{
parent::__construct($configuration);
$this->calledClass = CoursesTask::class;
}
/**
* @return bool
*/
public function filter(array $sourceData)
{
$courseId = $sourceData['id'];
if (isset($sourceData['course'])) {
$courseId = $sourceData['course'];
}
return !$this->existsExtracted($courseId);
}
}

View File

@@ -0,0 +1,38 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\MigrationMoodle\Extractor;
use Chamilo\PluginBundle\MigrationMoodle\Task\CourseModulesScormTask;
/**
* Class LoadedScormsFilterExtractor.
*
* Extractor for scorms already extracted and loaded.
*
* @package Chamilo\PluginBundle\MigrationMoodle\Extractor
*/
class LoadedScormsFilterExtractor extends FilterExtractor
{
/**
* LoadedScormsFilterExtractor constructor.
*/
public function __construct(array $configuration)
{
parent::__construct($configuration);
$this->calledClass = CourseModulesScormTask::class;
}
/**
* Filter to avoid scorms not yet migrated.
*
* @return bool
*/
public function filter(array $sourceData)
{
$scormId = $sourceData['scorm'];
return !$this->existsExtracted($scormId);
}
}

View File

@@ -0,0 +1,38 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\MigrationMoodle\Extractor;
use Chamilo\PluginBundle\MigrationMoodle\Task\UsersTask;
/**
* Class LoadedUsersFilterExtractor.
*
* @package Chamilo\PluginBundle\MigrationMoodle\Extractor
*/
class LoadedUsersFilterExtractor extends FilterExtractor
{
/**
* LoadedUsersFilterExtractor constructor.
*/
public function __construct(array $configuration)
{
parent::__construct($configuration);
$this->calledClass = UsersTask::class;
}
/**
* @return bool
*/
public function filter(array $sourceData)
{
$userId = $sourceData['id'];
if (isset($sourceData['userid'])) {
$userId = $sourceData['userid'];
}
return !$this->existsExtracted($userId);
}
}

View File

@@ -0,0 +1,22 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\MigrationMoodle\Interfaces;
/**
* Interface ExtractorInterface.
*/
interface ExtractorInterface
{
/**
* @return bool
*/
public function filter(array $sourceData);
/**
* @throws Exception
*
* @return iterable
*/
public function extract();
}

View File

@@ -0,0 +1,17 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\MigrationMoodle\Interfaces;
/**
* Interface LoaderInterface.
*/
interface LoaderInterface
{
/**
* Load the data and return the ID inserted.
*
* @return int
*/
public function load(array $incomingData);
}

View File

@@ -0,0 +1,15 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\MigrationMoodle\Interfaces;
/**
* Interface TransformPropertyInterface.
*/
interface TransformPropertyInterface
{
/**
* @return mixed
*/
public function transform(array $data);
}

View File

@@ -0,0 +1,17 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\MigrationMoodle\Interfaces;
/**
* Interface TransformerInterface.
*/
interface TransformerInterface
{
/**
* @throws \Exception
*
* @return array
*/
public function transform(array $sourceData);
}

View File

@@ -0,0 +1,67 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\MigrationMoodle\Loader;
use Chamilo\PluginBundle\MigrationMoodle\Interfaces\LoaderInterface;
/**
* Class CQuizLoader.
*
* @package Chamilo\PluginBundle\MigrationMoodle\Loader
*/
class CQuizLoader implements LoaderInterface
{
/**
* Load the data and return the ID inserted.
*
* @throws \Doctrine\DBAL\DBALException
*
* @return int
*/
public function load(array $incomingData)
{
$exercise = new \Exercise($incomingData['c_id']);
$exercise->updateTitle(\Exercise::format_title_variable($incomingData['exerciseTitle']));
$exercise->updateDescription($incomingData['exerciseDescription']);
$exercise->updateAttempts($incomingData['exerciseAttempts']);
$exercise->updateFeedbackType(0);
$exercise->updateType(2);
$exercise->setRandom(0);
$exercise->updateRandomAnswers($incomingData['randomAnswers']);
$exercise->updateResultsDisabled(0);
$exercise->updateExpiredTime($incomingData['enabletimercontroltotalminutes']);
//$exercise->updatePropagateNegative($incomingData['propagate_neg']);
//$exercise->updateSaveCorrectAnswers($incomingData['save_correct_answers']);
//$exercise->updateRandomByCat($incomingData['randomByCat']);
$exercise->updateTextWhenFinished('');
$exercise->updateDisplayCategoryName(1);
//$exercise->updateReviewAnswers($incomingData['review_answers']);
$exercise->updatePassPercentage($incomingData['pass_percentage']);
//$exercise->updateCategories($incomingData['category']);
//$exercise->updateEndButton($incomingData['end_button']);
//$exercise->setOnSuccessMessage($incomingData['on_success_message']);
//$exercise->setOnFailedMessage($incomingData['on_failed_message']);
//$exercise->updateEmailNotificationTemplate($incomingData['email_notification_template']);
//$exercise->setEmailNotificationTemplateToUser($incomingData['email_notification_template_to_user']);
//$exercise->setNotifyUserByEmail($incomingData['notify_user_by_email']);
//$exercise->setModelType($incomingData['model_type']);
$exercise->setQuestionSelectionType(1);
$exercise->setHideQuestionTitle(0);
$exercise->sessionId = 0;
//$exercise->setScoreTypeModel($incomingData['score_type_model']);
//$exercise->setGlobalCategoryId($incomingData['global_category_id']);
//$exercise->setShowPreviousButton($incomingData['show_previous_button']);
//$exercise->setNotifications($incomingData['notifications']);
//$exercise->setExerciseCategoryId($incomingData['exercise_category_id']);
$exercise->setPageResultConfiguration($incomingData);
$exercise->start_time = api_get_utc_datetime($incomingData['start_time'], true);
$exercise->end_time = api_get_utc_datetime($incomingData['end_time'], true);
$exercise->expired_time = $incomingData['enabletimercontroltotalminutes'];
$exercise->random_answers = $incomingData['randomAnswers'] == 1 ? 1 : 0;
$iId = $exercise->save();
return $iId;
}
}

View File

@@ -0,0 +1,42 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\MigrationMoodle\Loader;
use Chamilo\PluginBundle\MigrationMoodle\Interfaces\LoaderInterface;
/**
* Class CourseCategoriesLoader.
*
* @package Chamilo\PluginBundle\MigrationMoodle\Loader
*/
class CourseCategoriesLoader implements LoaderInterface
{
/**
* Load the data and return the ID inserted.
*
* @throws \Exception
*
* @return int
*/
public function load(array $incomingData)
{
$id = \CourseCategory::addNode(
$incomingData['code'],
$incomingData['name'],
'TRUE',
$incomingData['parent_id']
);
if (empty($id)) {
throw new \Exception("Course category ({$incomingData['code']}) not migrated. Maybe it already exists.");
}
$tblUrlCategory = \Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE_CATEGORY);
$accessUrlId = \MigrationMoodlePlugin::create()->getAccessUrlId();
\Database::query("UPDATE $tblUrlCategory SET access_url_id = $accessUrlId WHERE course_category_id = $id");
return $id;
}
}

View File

@@ -0,0 +1,65 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\MigrationMoodle\Loader;
use Chamilo\PluginBundle\MigrationMoodle\Interfaces\LoaderInterface;
use Chamilo\PluginBundle\MigrationMoodle\Traits\FileFinderTrait;
/**
* Class CourseFilesLoader.
*
* Loader to create the files needed for Chamilo course documents coming from the files in Moodle course.
*
* @package Chamilo\PluginBundle\MigrationMoodle\Loader
*/
class CourseFilesLoader implements LoaderInterface
{
use FileFinderTrait;
/**
* Load the data and return the ID inserted.
*
* @throws \Exception
*
* @return int
*/
public function load(array $incomingData)
{
$userId = 1;
$courseInfo = api_get_course_info_by_id($incomingData['course']);
$filePath = $this->findFilePath($incomingData['contenthash']);
$file = [
'file' => [
'name' => $incomingData['filename'],
'tmp_name' => $filePath,
'type' => $incomingData['mimetype'],
'size' => $incomingData['filesize'],
'error' => 0,
'from_file' => true,
'move_file' => true,
],
];
$_POST['language'] = $courseInfo['language'];
$fileData = \DocumentManager::upload_document(
$file,
'/',
$incomingData['filename'],
'',
null,
null,
true,
false,
'file',
false,
$userId,
$courseInfo
);
return $fileData['iid'];
}
}

View File

@@ -0,0 +1,30 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\MigrationMoodle\Loader;
use Chamilo\PluginBundle\MigrationMoodle\Interfaces\LoaderInterface;
/**
* Class CourseIntroductionLoader.
*
* @package Chamilo\PluginBundle\MigrationMoodle\Loader
*/
class CourseIntroductionLoader implements LoaderInterface
{
/**
* {@inheritdoc}
*/
public function load(array $incomingData)
{
return \Database::insert(
\Database::get_course_table(TABLE_TOOL_INTRO),
[
'session_id' => 0,
'c_id' => $incomingData['c_id'],
'id' => TOOL_COURSE_HOMEPAGE,
'intro_text' => $incomingData['description'],
]
);
}
}

View File

@@ -0,0 +1,40 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\MigrationMoodle\Loader;
use Chamilo\PluginBundle\MigrationMoodle\Interfaces\LoaderInterface;
/**
* Class CourseModulesLessonLoader.
*
* Loader for create and Chamilo learning path section coming from a Moodle course module.
*
* @package Chamilo\PluginBundle\MigrationMoodle\Loader
*/
class CourseModulesLessonLoader implements LoaderInterface
{
/**
* Load the data and return the ID inserted.
*
* @return int
*/
public function load(array $incomingData)
{
$lp = new \learnpath(
$incomingData['c_code'],
$incomingData['lp_id'],
1
);
$itemId = $lp->add_item(
0,
0,
'dir',
0,
$incomingData['title'],
''
);
return $itemId;
}
}

View File

@@ -0,0 +1,39 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\MigrationMoodle\Loader;
use Chamilo\PluginBundle\MigrationMoodle\Interfaces\LoaderInterface;
/**
* Class CourseModulesQuizLoader.
*
* Loader for create a Chamilo learning path item (quiz type) coming from transformed data of Moodle course quiz module.
*
* @package Chamilo\PluginBundle\MigrationMoodle\Loader
*/
class CourseModulesQuizLoader implements LoaderInterface
{
/**
* Load the data and return the ID inserted.
*
* @return int
*/
public function load(array $incomingData)
{
$lp = new \learnpath(
$incomingData['c_code'],
$incomingData['lp_id'],
1
);
return $lp->add_item(
0,
0,
'quiz',
0,
$incomingData['title'],
''
);
}
}

View File

@@ -0,0 +1,123 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\MigrationMoodle\Loader;
use Chamilo\PluginBundle\MigrationMoodle\Interfaces\LoaderInterface;
use Symfony\Component\Filesystem\Filesystem;
/**
* Class CourseModulesScormLoader.
*
* @package Chamilo\PluginBundle\MigrationMoodle\Loader
*/
class CourseModulesScormLoader implements LoaderInterface
{
/**
* {@inheritdoc}
*/
public function load(array $incomingData)
{
$tblLpMain = \Database::get_course_table(TABLE_LP_MAIN);
$resultDisplayOrder = \Database::query(
"SELECT
CASE WHEN MAX(display_order) > 0 THEN MAX(display_order) + 1 ELSE 1 END AS display_order
FROM $tblLpMain WHERE c_id = {$incomingData['c_id']}"
);
$row = \Database::fetch_assoc($resultDisplayOrder);
$displayOrder = $row['display_order'];
$courseInfo = api_get_course_info_by_id($incomingData['c_id']);
$userId = 1;
$incomingData['path'] = $this->createDirectory($incomingData['name'], $courseInfo['code']);
$incomingData['use_max_score'] = $incomingData['use_max_score'] == 100;
$incomingData['created_on'] = $incomingData['created_on']
? $incomingData['created_on']->format('Y-m-d h:i:s')
: null;
$incomingData['modified_on'] = $incomingData['modified_on']
? $incomingData['modified_on']->format('Y-m-d h:i:s')
: null;
$incomingData['publicated_on'] = $incomingData['publicated_on']
? $incomingData['publicated_on']->format('Y-m-d h:i:s')
: null;
$params = array_merge(
$incomingData,
[
'lp_type' => 2,
'description' => '',
'force_commit' => 0,
'default_view_mod' => 'embedded',
'default_encoding' => 'UTF-8',
'js_lib' => 'scorm_api.php',
'display_order' => $displayOrder,
'session_id' => 0,
'content_maker' => '',
'content_license' => '',
'debug' => 0,
'theme' => '',
'preview_image' => '',
'author' => '',
'prerequisite' => 0,
'seriousgame_mode' => 0,
'autolaunch' => 0,
'category_id' => 0,
'max_attempts' => 0,
'subscribe_users' => 0,
]
);
$lpId = \Database::insert($tblLpMain, $params);
if ($lpId) {
\Database::query("UPDATE $tblLpMain SET id = iid WHERE iid = $lpId");
api_item_property_update($courseInfo, TOOL_LEARNPATH, $lpId, 'LearnpathAdded', $userId);
api_item_property_update($courseInfo, TOOL_LEARNPATH, $lpId, 'visible', $userId);
}
return $lpId;
}
/**
* @param string $fileName
*
* @return string
*/
public static function generateDirectoryName($fileName)
{
$newDirectory = trim($fileName);
$newDirectory = trim($newDirectory, '/');
return api_replace_dangerous_char($newDirectory);
}
/**
* @param string $name
* @param string $courseCode
*
* @return string
*/
private function createDirectory($name, $courseCode)
{
$courseRelDir = api_get_path(SYS_COURSE_PATH).api_get_course_path($courseCode).'/scorm';
$newDirectory = self::generateDirectoryName($name);
$fullPath = "$courseRelDir/$newDirectory";
$fileSystem = new Filesystem();
if (!is_dir($fullPath)) {
$fileSystem->mkdir(
$fullPath,
api_get_permissions_for_new_directories()
);
}
return "$newDirectory/.";
}
}

View File

@@ -0,0 +1,35 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\MigrationMoodle\Loader;
use Chamilo\PluginBundle\MigrationMoodle\Interfaces\LoaderInterface;
/**
* Class CourseModulesUrlLoader.
*
* @package Chamilo\PluginBundle\MigrationMoodle\Loader
*/
class CourseModulesUrlLoader implements LoaderInterface
{
/**
* {@inheritdoc}
*/
public function load(array $incomingData)
{
$lp = new \learnpath(
$incomingData['c_code'],
$incomingData['lp_id'],
1
);
return $lp->add_item(
0,
0,
'link',
0,
$incomingData['title'],
''
);
}
}

View File

@@ -0,0 +1,52 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\MigrationMoodle\Loader;
use Chamilo\PluginBundle\MigrationMoodle\Interfaces\LoaderInterface;
/**
* Class CourseSectionsLoader.
*
* Loader for create a Chamilo learning path coming from a Moodle course section.
*
* @package Chamilo\PluginBundle\MigrationMoodle\Loader
*/
class CourseSectionsLoader implements LoaderInterface
{
/**
* Load the data and return the ID inserted.
*
* @return int
*/
public function load(array $incomingData)
{
$courseInfo = api_get_course_info($incomingData['course_code']);
$lpId = \learnpath::add_lp(
$incomingData['course_code'],
$incomingData['name'],
'',
'chamilo',
'manual'
);
$incomingData['description'] = trim($incomingData['description']);
if (!empty($incomingData['description'])) {
$lp = new \learnpath(
$incomingData['course_code'],
$lpId,
1
);
$lp->generate_lp_folder($courseInfo);
$itemTitle = get_lang('Description');
$documentId = $lp->create_document($courseInfo, $incomingData['description'], $itemTitle);
$lp->add_item(0, 0, 'document', $documentId, $itemTitle, '');
}
return $lpId;
}
}

View File

@@ -0,0 +1,50 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\MigrationMoodle\Loader;
use Chamilo\PluginBundle\MigrationMoodle\Interfaces\LoaderInterface;
/**
* Class CoursesLoader.
*
* @package Chamilo\PluginBundle\MigrationMoodle\Loader
*/
class CoursesLoader implements LoaderInterface
{
public const LOAD_MODE_REUSE = 'reuse';
public const LOAD_MODE_DUPLICATE = 'duplicate';
/**
* @var string Load mode: "reuse" or "duplicate". Default is "duplicate".
*/
private $loadMode = self::LOAD_MODE_DUPLICATE;
/**
* @return int
*/
public function load(array $incomingData)
{
$courseInfo = api_get_course_info($incomingData['wanted_code']);
if (!empty($courseInfo)) {
if ($this->loadMode === self::LOAD_MODE_REUSE) {
return $courseInfo['real_id'];
}
if ($this->loadMode === self::LOAD_MODE_DUPLICATE) {
$incomingData['wanted_code'] = $incomingData['wanted_code'].substr(md5(uniqid(rand())), 0, 10);
}
}
$incomingData['subscribe'] = false;
$incomingData['unsubscribe'] = false;
$incomingData['disk_quota'] = 500 * 1024 * 1024;
$accessUrlId = \MigrationMoodlePlugin::create()->getAccessUrlId();
$courseInfo = \CourseManager::create_course($incomingData, 1, $accessUrlId);
return $courseInfo['real_id'];
}
}

View File

@@ -0,0 +1,46 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\MigrationMoodle\Loader;
use Chamilo\PluginBundle\MigrationMoodle\Traits\FileFinderTrait;
use Symfony\Component\Filesystem\Filesystem;
/**
* Class FilesForScormScoLoader.
*
* @package Chamilo\PluginBundle\MigrationMoodle\Loader
*/
class FilesForScormScoLoader extends CourseFilesLoader
{
use FileFinderTrait;
/**
* {@inheritdoc}
*/
public function load(array $incomingData)
{
$course = api_get_course_entity($incomingData['c_id']);
$moodleFilePath = $this->findFilePath($incomingData['contenthash']);
$sysCourseScormPath = api_get_path(SYS_COURSE_PATH).$course->getDirectory().'/scorm';
$lpDirectory = CourseModulesScormLoader::generateDirectoryName($incomingData['lp_name']);
$lpDirectoryPath = "$sysCourseScormPath/$lpDirectory";
$fileDirectoryPath = $lpDirectoryPath.$incomingData['filepath'];
$filePath = $fileDirectoryPath.$incomingData['filename'];
$fileSystem = new Filesystem();
if ($incomingData['filepath'] != '/') {
$fileSystem->mkdir(
$fileDirectoryPath,
api_get_permissions_for_new_directories()
);
}
$fileSystem->copy($moodleFilePath, $filePath);
return 0;
}
}

View File

@@ -0,0 +1,36 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\MigrationMoodle\Loader;
use Chamilo\PluginBundle\MigrationMoodle\Interfaces\LoaderInterface;
/**
* Class LessonAnswersEssayLoader.
*
* Loader to create Free Answer question answers comming from Essay lesson page.
*
* @package Chamilo\PluginBundle\MigrationMoodle\Loader
*/
class LessonAnswersEssayLoader implements LoaderInterface
{
/**
* Load the data and return the ID inserted.
*
* @return int
*/
public function load(array $incomingData)
{
$courseInfo = api_get_course_info_by_id($incomingData['c_id']);
$exercise = new \Exercise($incomingData['c_id']);
$exercise->read($incomingData['quiz_id']);
$question = \Question::read($incomingData['question_id'], $courseInfo);
$question->weighting = $incomingData['score'];
$question->save($exercise);
return $question->id;
}
}

View File

@@ -0,0 +1,68 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\MigrationMoodle\Loader;
use Chamilo\PluginBundle\MigrationMoodle\Interfaces\LoaderInterface;
/**
* Class LessonAnswersMatchingLoader.
*
* Loader to create Matching question answers comming from Matching lesson page.
*
* @package Chamilo\PluginBundle\MigrationMoodle\Loader
*/
class LessonAnswersMatchingLoader implements LoaderInterface
{
/**
* Load the data and return the ID inserted.
*
* @return int
*/
public function load(array $incomingData)
{
$courseInfo = api_get_course_info_by_id($incomingData['c_id']);
$exercise = new \Exercise($incomingData['c_id']);
$exercise->read($incomingData['quiz_id']);
$question = \Question::read($incomingData['question_id'], $courseInfo);
$answer = new \Answer($incomingData['question_id'], $incomingData['c_id'], $exercise);
$questionsAnswers = $answer->getAnswers();
foreach ($questionsAnswers as $questionsAnswer) {
$answer->createAnswer(
$questionsAnswer['answer'],
$questionsAnswer['correct'],
$questionsAnswer['comment'],
$questionsAnswer['ponderation'],
$questionsAnswer['position'],
$questionsAnswer['hotspot_coordinates'],
$questionsAnswer['hotspot_type'],
$questionsAnswer['destination']
);
}
$optionPosition = $question->countAnswers() + 1;
$answer->createAnswer($incomingData['feedback'], 0, '', 0, $optionPosition);
$answerPosition = $optionPosition + 1;
$answer->createAnswer(
$incomingData['answer'],
$optionPosition,
'',
$incomingData['score'],
$answerPosition
);
$answer->save();
$question->weighting += $incomingData['score'];
$question->save($exercise);
return $question->id;
}
}

View File

@@ -0,0 +1,72 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\MigrationMoodle\Loader;
use Chamilo\CourseBundle\Entity\CQuizAnswer;
use Chamilo\PluginBundle\MigrationMoodle\Interfaces\LoaderInterface;
/**
* Class LessonAnswersMultipleAnswerLoader.
*
* Loader to create Unique Answer question comming from Multiple Choice lesson page.
*
* @package Chamilo\PluginBundle\MigrationMoodle\Loader
*/
class LessonAnswersMultipleAnswerLoader implements LoaderInterface
{
/**
* @return int
*/
public function load(array $incomingData)
{
$courseInfo = api_get_course_info_by_id($incomingData['c_id']);
$exercise = new \Exercise($incomingData['c_id']);
$exercise->read($incomingData['quiz_id']);
$question = \Question::read($incomingData['question_id'], $courseInfo);
$answer = new \Answer($incomingData['question_id'], $incomingData['c_id'], $exercise);
$questionsAnswers = $answer->getAnswers();
foreach ($questionsAnswers as $questionsAnswer) {
$answer->createAnswer(
$questionsAnswer['answer'],
$questionsAnswer['correct'],
$questionsAnswer['comment'],
$questionsAnswer['ponderation'],
$questionsAnswer['position'],
$questionsAnswer['hotspot_coordinates'],
$questionsAnswer['hotspot_type'],
$questionsAnswer['destination']
);
}
$incomingData['score'] = abs($incomingData['score']);
if (!$incomingData['is_correct']) {
$incomingData['score'] = -$incomingData['score'];
}
if ($incomingData['score'] > 0) {
$question->weighting += $incomingData['score'];
}
$answer->createAnswer(
$incomingData['answer'],
$incomingData['is_correct'],
$incomingData['feedback'],
$incomingData['score'],
$question->countAnswers() + 1,
null,
null,
CQuizAnswer::DEFAULT_DESTINATION
);
$answer->save();
$question->save($exercise);
return $question->id;
}
}

View File

@@ -0,0 +1,22 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\MigrationMoodle\Loader;
/**
* Class LessonAnswersMultipleChoiceLoader.
*
* Loader to create Unique Answer question comming from Multiple Choice lesson page.
*
* @package Chamilo\PluginBundle\MigrationMoodle\Loader
*/
class LessonAnswersMultipleChoiceLoader extends LessonAnswersTrueFalseLoader
{
/**
* @return int
*/
public function load(array $incomingData)
{
return parent::load($incomingData);
}
}

View File

@@ -0,0 +1,77 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\MigrationMoodle\Loader;
use Chamilo\PluginBundle\MigrationMoodle\Interfaces\LoaderInterface;
/**
* Class LessonAnswersShortAnswerLoader.
*
* Loader to create Fill Blanks question answers comming from Short Answer and Numerical lesson page.
*
* @package Chamilo\PluginBundle\MigrationMoodle\Loader
*/
class LessonAnswersShortAnswerLoader implements LoaderInterface
{
public const INPUT_WIDTH = 300;
/**
* Load the data and return the ID inserted.
*
* @return int
*/
public function load(array $incomingData)
{
$courseInfo = api_get_course_info_by_id($incomingData['c_id']);
$exercise = new \Exercise($incomingData['c_id']);
$exercise->read($incomingData['quiz_id']);
$question = \Question::read($incomingData['question_id'], $courseInfo);
$question->weighting = 0;
$answer = new \Answer($incomingData['question_id'], $incomingData['c_id'], $exercise);
$incomingData['answers'] = '['.$incomingData['answers'].']';
// Remove the "::" eventually written by the user
$incomingData['answers'] = str_replace('::', '', $incomingData['answers']);
// Remove starting and ending space and &nbsp;
$incomingData['answers'] = api_preg_replace("/\xc2\xa0/", " ", $incomingData['answers']);
$blankStartSeparator = '[';
$blankEndSeparator = ']';
$blankStartSeparatorRegexp = \FillBlanks::escapeForRegexp($blankStartSeparator);
$blankEndSeparatorRegexp = \FillBlanks::escapeForRegexp($blankEndSeparator);
// Remove spaces at the beginning and the end of text in square brackets
$return = preg_replace_callback(
"/".$blankStartSeparatorRegexp."[^]]+".$blankEndSeparatorRegexp."/",
function ($matches) use ($blankStartSeparator, $blankEndSeparator) {
$matchingResult = $matches[0];
$matchingResult = trim($matchingResult, $blankStartSeparator);
$matchingResult = trim($matchingResult, $blankEndSeparator);
$matchingResult = trim($matchingResult);
// Remove forbidden chars
$matchingResult = str_replace("/\\/", "", $matchingResult);
$matchingResult = str_replace('/"/', "", $matchingResult);
return $blankStartSeparator.$matchingResult.$blankEndSeparator;
},
$incomingData['answers']
);
$question->weighting += $incomingData['scores'];
$return .= '::'.$incomingData['scores'].':';
$return .= self::INPUT_WIDTH;
$return .= ':0@';
$answer->createAnswer($return, 0, $incomingData['comment'], 0, 1);
$answer->save();
$question->save($exercise);
return $question->id;
}
}

View File

@@ -0,0 +1,70 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\MigrationMoodle\Loader;
use Chamilo\CourseBundle\Entity\CQuizAnswer;
use Chamilo\PluginBundle\MigrationMoodle\Interfaces\LoaderInterface;
/**
* Class LessonAnswersTrueFalseLoader.
*
* Loader for True-False answers from lesson pages.
*
* @package Chamilo\PluginBundle\MigrationMoodle\Loader
*/
class LessonAnswersTrueFalseLoader implements LoaderInterface
{
/**
* Load the data and return the ID inserted.
*
* @return int
*/
public function load(array $incomingData)
{
$courseInfo = api_get_course_info_by_id($incomingData['c_id']);
$exercise = new \Exercise($incomingData['c_id']);
$exercise->read($incomingData['quiz_id']);
$question = \Question::read($incomingData['question_id'], $courseInfo);
$answer = new \Answer($incomingData['question_id'], $incomingData['c_id'], $exercise);
$questionsAnswers = $answer->getAnswers();
foreach ($questionsAnswers as $questionsAnswer) {
$answer->createAnswer(
$questionsAnswer['answer'],
$questionsAnswer['correct'],
$questionsAnswer['comment'],
$questionsAnswer['ponderation'],
$questionsAnswer['position'],
$questionsAnswer['hotspot_coordinates'],
$questionsAnswer['hotspot_type'],
$questionsAnswer['destination']
);
}
if ($incomingData['is_correct']) {
$incomingData['score'] = abs($incomingData['score']);
$question->weighting += $incomingData['score'];
}
$answer->createAnswer(
$incomingData['answer'],
$incomingData['is_correct'],
$incomingData['feedback'],
$incomingData['score'],
$question->countAnswers() + 1,
null,
null,
CQuizAnswer::DEFAULT_DESTINATION
);
$answer->save();
$question->save($exercise);
return $question->id;
}
}

View File

@@ -0,0 +1,47 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\MigrationMoodle\Loader;
use Chamilo\PluginBundle\MigrationMoodle\Interfaces\LoaderInterface;
/**
* Class LessonPagesLoader.
*
* Loader for create a HTML document with the transformed data coming from a Moodle lesson page.
*
* @package Chamilo\PluginBundle\MigrationMoodle\Loader
*/
class LessonPagesDocumentLoader implements LoaderInterface
{
/**
* Load the data and return the ID inserted.
*
* @return int
*/
public function load(array $incomingData)
{
$courseInfo = api_get_course_info_by_id($incomingData['c_id']);
$lp = new \learnpath(
$courseInfo['code'],
$incomingData['lp_id'],
1
);
$lp->generate_lp_folder($courseInfo);
$docId = $lp->create_document(
$courseInfo,
$incomingData['item_content'],
$incomingData['item_title'],
'html'
);
$tblLpItem = \Database::get_course_table(TABLE_LP_ITEM);
\Database::query("UPDATE $tblLpItem SET path = '$docId' WHERE iid = {$incomingData['item_id']}");
return $docId;
}
}

View File

@@ -0,0 +1,40 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\MigrationMoodle\Loader;
use Chamilo\PluginBundle\MigrationMoodle\Interfaces\LoaderInterface;
/**
* Class LpDocumentsLoader.
*
* Loader to create the items for Chamilo learning paths coming from the list of Moodle lesson pages in a course.
*
* @package Chamilo\PluginBundle\MigrationMoodle\Loader
*/
class LessonPagesLoader implements LoaderInterface
{
/**
* Load the data and return the ID inserted.
*
* @return int
*/
public function load(array $incomingData)
{
$lp = new \learnpath(
$incomingData['c_code'],
$incomingData['lp_id'],
1
);
$itemId = $lp->add_item(
$incomingData['parent'],
$incomingData['previous'],
$incomingData['item_type'],
0,
$incomingData['title'],
''
);
return $itemId;
}
}

View File

@@ -0,0 +1,40 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\MigrationMoodle\Loader;
use Chamilo\PluginBundle\MigrationMoodle\Interfaces\LoaderInterface;
/**
* Class LessonQuestionPagesQuestionLoader.
*
* Loader for create a question to be added in a quiz according the transformed data
* coming from a moodle's lesson question page.
*
* @package Chamilo\PluginBundle\MigrationMoodle\Loader
*/
class LessonQuestionPagesQuestionLoader implements LoaderInterface
{
/**
* Load the data and return the ID inserted.
*
* @return int
*/
public function load(array $incomingData)
{
$exercise = new \Exercise($incomingData['c_id']);
$exercise->read($incomingData['quiz_id']);
$question = \Question::getInstance($incomingData['question_type']);
$question->course = api_get_course_info_by_id($incomingData['c_id']);
$question->updateTitle($incomingData['question_title']);
$question->updateLevel(1);
$question->updateCategory(0);
$question->save($exercise);
$exercise->addToList($question->id);
$exercise->update_question_positions();
return $question->id;
}
}

View File

@@ -0,0 +1,55 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\MigrationMoodle\Loader;
use Chamilo\PluginBundle\MigrationMoodle\Interfaces\LoaderInterface;
/**
* Class LessonQuestionPagesQuizLoader.
*
* Loader for create a quiz according the transformed data coming from a moodle's lesson question page.
*
* @package Chamilo\PluginBundle\MigrationMoodle\Loader
*/
class LessonQuestionPagesQuizLoader implements LoaderInterface
{
/**
* Load the data and return the ID inserted.
*
* @throws \Doctrine\DBAL\DBALException
* @throws \Exception
*
* @return int
*/
public function load(array $incomingData)
{
$exercise = new \Exercise($incomingData['c_id']);
$exercise->updateTitle(\Exercise::format_title_variable($incomingData['item_title']));
$exercise->updateDescription('');
$exercise->updateAttempts(0);
$exercise->updateFeedbackType(0);
$exercise->updateType(ALL_ON_ONE_PAGE);
$exercise->setRandom(0);
$exercise->updateRandomAnswers(0);
$exercise->updateResultsDisabled(0);
$exercise->updateExpiredTime(0);
$exercise->updateTextWhenFinished('');
$exercise->updateDisplayCategoryName(1);
$exercise->updatePassPercentage(0);
$exercise->setQuestionSelectionType(1);
$exercise->setHideQuestionTitle(0);
$exercise->sessionId = 0;
$exercise->start_time = null;
$exercise->end_time = null;
$exercise->active = false;
$quizId = $exercise->save();
$tblLpItem = \Database::get_course_table(TABLE_LP_ITEM);
\Database::query("UPDATE $tblLpItem SET path = '$quizId' WHERE iid = {$incomingData['item_id']}");
return $quizId;
}
}

View File

@@ -0,0 +1,44 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\MigrationMoodle\Loader;
use Chamilo\PluginBundle\MigrationMoodle\Interfaces\LoaderInterface;
/**
* Class QuestionCategoriesLoader.
*
* Loader for create a category for Chamilo quiz questions coming from a Moodle question category.
*
* @package Chamilo\PluginBundle\MigrationMoodle\Loader
*/
class QuestionCategoriesLoader implements LoaderInterface
{
/**
* Load the data and return the ID inserted.
*
* @throws \Exception
*
* @return int
*/
public function load(array $incomingData)
{
$course = api_get_course_entity($incomingData['c_id']);
if (!$course) {
throw new \Exception("The question category ({$incomingData['name']}) found, but it will not be migrated.");
}
$category = new \TestCategory();
$category->name = $incomingData['name'];
$category->description = $incomingData['description'];
$id = $category->save($incomingData['c_id']);
if (false === $id) {
throw new \Exception("The quiz category \"{$incomingData['name']}\" already exists.");
}
return $id;
}
}

View File

@@ -0,0 +1,37 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\MigrationMoodle\Loader;
use Chamilo\PluginBundle\MigrationMoodle\Interfaces\LoaderInterface;
/**
* Class QuestionGapselectLoader.
*
* @package Chamilo\PluginBundle\MigrationMoodle\Loader
*/
class QuestionGapselectLoader implements LoaderInterface
{
/**
* {@inheritdoc}
*/
public function load(array $incomingData)
{
$courseInfo = api_get_course_info_by_id($incomingData['c_id']);
$exercise = new \Exercise($incomingData['c_id']);
$exercise->read($incomingData['quiz_id']);
$question = \Question::read($incomingData['question_id'], $courseInfo);
$question->setTitle(get_lang('FillBlanks'));
$question->weighting = $incomingData['score'];
$answer = new \Answer($incomingData['question_id'], $incomingData['c_id'], $exercise);
$answer->createAnswer($incomingData['answer'], 0, $incomingData['comment'], 0, 1);
$answer->save();
$question->save($exercise);
return $question->id;
}
}

View File

@@ -0,0 +1,50 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\MigrationMoodle\Loader;
use Chamilo\PluginBundle\MigrationMoodle\Interfaces\LoaderInterface;
/**
* Class QuizzesLoader.
*
* Loader for create a Chamilo quiz inside a learning path item coming from a Moodle quiz.
*
* @package Chamilo\PluginBundle\MigrationMoodle\Loader
*/
class QuizzesLoader implements LoaderInterface
{
/**
* Load the data and return the ID inserted.
*
* @return int
*/
public function load(array $incomingData)
{
$exercise = new \Exercise($incomingData['c_id']);
$exercise->updateTitle(\Exercise::format_title_variable($incomingData['exerciseTitle']));
$exercise->updateDescription($incomingData['exerciseDescription']);
$exercise->updateAttempts($incomingData['exerciseAttempts']);
$exercise->updateFeedbackType(0);
$exercise->updateType(ALL_ON_ONE_PAGE);
$exercise->setRandom(0);
$exercise->updateRandomAnswers($incomingData['randomAnswers']);
$exercise->updateResultsDisabled(0);
$exercise->updateExpiredTime($incomingData['enabletimercontroltotalminutes']);
$exercise->updateTextWhenFinished('');
$exercise->updateDisplayCategoryName(1);
$exercise->updatePassPercentage($incomingData['pass_percentage']);
$exercise->setQuestionSelectionType(1);
$exercise->setHideQuestionTitle(0);
$exercise->sessionId = 0;
$exercise->start_time = api_get_utc_datetime($incomingData['start_time'], true);
$exercise->end_time = api_get_utc_datetime($incomingData['end_time'], true);
$quizId = $exercise->save();
\Database::query("UPDATE c_quiz SET active = 0 WHERE iid = $quizId");
\Database::query("UPDATE c_lp_item SET path = '$quizId' WHERE iid = {$incomingData['item_id']}");
return $quizId;
}
}

View File

@@ -0,0 +1,39 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\MigrationMoodle\Loader;
use Chamilo\PluginBundle\MigrationMoodle\Interfaces\LoaderInterface;
/**
* Class QuizzesScoresLoader.
*
* @package Chamilo\PluginBundle\MigrationMoodle\Loader
*/
class QuizzesScoresLoader implements LoaderInterface
{
/**
* {@inheritdoc}
*/
public function load(array $incomingData)
{
$tblQuizQuestion = \Database::get_course_table(TABLE_QUIZ_QUESTION);
$tblQuizRelQuestion = \Database::get_course_table(TABLE_QUIZ_TEST_QUESTION);
$tblLpItem = \Database::get_course_table(TABLE_LP_ITEM);
$sql = "SELECT SUM(ponderation)
FROM $tblQuizQuestion as quiz_question
INNER JOIN $tblQuizRelQuestion as quiz_rel_question
ON quiz_question.iid = quiz_rel_question.question_id
WHERE
quiz_rel_question.exercice_id = {$incomingData['quiz_id']}
AND quiz_rel_question.c_id = {$incomingData['c_id']}";
$rsQuiz = \Database::query($sql);
$maxScore = \Database::result($rsQuiz, 0, 0) ?: 0;
\Database::query("UPDATE $tblLpItem SET max_score = $maxScore WHERE iid = {$incomingData['item_id']}");
return $incomingData['item_id'];
}
}

View File

@@ -0,0 +1,31 @@
<?php
namespace Chamilo\PluginBundle\MigrationMoodle\Loader;
use Chamilo\PluginBundle\MigrationMoodle\Interfaces\LoaderInterface;
/**
* Class RoleAssignmentsLoader.
*
* Loader to subscribe a Chamilo user in a course according their Moodle role assignment.
*
* @package Chamilo\PluginBundle\MigrationMoodle\Loader
*/
class RoleAssignmentsLoader implements LoaderInterface
{
/**
* Load the data and return the ID inserted.
*
* @return int
*/
public function load(array $incomingData)
{
$result = \CourseManager::subscribeUser(
$incomingData['user_id'],
$incomingData['course_code'],
$incomingData['status']
);
return (int) $result;
}
}

View File

@@ -0,0 +1,43 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\MigrationMoodle\Loader;
use Chamilo\PluginBundle\MigrationMoodle\Interfaces\LoaderInterface;
/**
* Class ScormScoLoader.
*
* @package Chamilo\PluginBundle\MigrationMoodle\Loader
*/
class ScormScoLoader implements LoaderInterface
{
/**
* {@inheritdoc}
*/
public function load(array $incomingData)
{
$scorm = new \scorm(
$incomingData['c_code'],
$incomingData['lp_id'],
1
);
$itemId = $scorm->add_item(
$incomingData['parent_item_id'],
0,
$incomingData['item_type'],
0,
$incomingData['title'],
''
);
$tblLpItem = \Database::get_course_table(TABLE_LP_ITEM);
\Database::query(
"UPDATE $tblLpItem SET path = '{$incomingData['path']}', ref = '{$incomingData['ref']}' WHERE iid = $itemId"
);
return $itemId;
}
}

View File

@@ -0,0 +1,51 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\MigrationMoodle\Loader;
use Chamilo\PluginBundle\MigrationMoodle\Interfaces\LoaderInterface;
/**
* Class SortSectionModuleLoader.
*
* @package Chamilo\PluginBundle\MigrationMoodle\Loader
*/
class SortSectionModuleLoader implements LoaderInterface
{
/**
* {@inheritdoc}
*/
public function load(array $incomingData)
{
// Search the Description document to put it as first item
$firstItem = \Database::select(
'iid',
\Database::get_course_table(TABLE_LP_ITEM),
[
'where' => [
'c_id = ? AND lp_id = ? AND parent_item_id = ? AND item_type = ?' => [
$incomingData['c_id'],
$incomingData['lp_id'],
0,
TOOL_DOCUMENT,
],
],
'order' => 'iid ASC',
],
'first'
);
$orderList = $incomingData['order_list'];
if ($firstItem) {
$orderList = [$firstItem['iid'] => 0] + $orderList;
}
\learnpath::sortItemByOrderList(
$orderList,
$incomingData['c_id']
);
return $incomingData['lp_id'];
}
}

View File

@@ -0,0 +1,66 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\MigrationMoodle\Loader;
use Chamilo\PluginBundle\MigrationMoodle\Interfaces\LoaderInterface;
/**
* Class TrackCourseAccessLoader.
*
* @package Chamilo\PluginBundle\MigrationMoodle\Loader
*/
class TrackCourseAccessLoader implements LoaderInterface
{
/**
* {@inheritdoc}
*/
public function load(array $incomingData)
{
list($userId, $cId, $loginCourseDate, $ip, $sessionId) = array_values($incomingData);
$sessionLifetime = api_get_configuration_value('session_lifetime');
/** @var \DateTime $time */
$time = clone $loginCourseDate;
$time->modify("-$sessionLifetime seconds");
$time = $time->format('Y-m-d H:i:s');
$loginCourseDate = $loginCourseDate->format('Y-m-d H:i:s');
$tableCourseAccess = \Database::get_main_table(TABLE_STATISTIC_TRACK_E_COURSE_ACCESS);
$result = \Database::query(
"SELECT course_access_id
FROM $tableCourseAccess
WHERE user_id = $userId AND c_id = $cId AND session_id = $sessionId AND login_course_date > '$time'
ORDER BY login_course_date DESC
LIMIT 1"
);
if (\Database::num_rows($result) > 0) {
$row = \Database::fetch_assoc($result);
\Database::query(
"UPDATE $tableCourseAccess
SET logout_course_date = '$loginCourseDate', counter = counter + 1
WHERE course_access_id = {$row['course_access_id']}"
);
return $row['course_access_id'];
}
return \Database::insert(
$tableCourseAccess,
[
'c_id' => $cId,
'user_ip' => $ip,
'user_id' => $userId,
'login_course_date' => $loginCourseDate,
'logout_course_date' => $loginCourseDate,
'counter' => 1,
'session_id' => $sessionId,
]
);
}
}

View File

@@ -0,0 +1,57 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\MigrationMoodle\Loader;
use Chamilo\PluginBundle\MigrationMoodle\Interfaces\LoaderInterface;
/**
* Class TrackLoginLoader.
*
* @package Chamilo\PluginBundle\MigrationMoodle\Loader
*/
class TrackLoginLoader implements LoaderInterface
{
/**
* {@inheritdoc}
*/
public function load(array $incomingData)
{
$incomingData['login_date'] = $incomingData['login_date']->format('Y-m-d H:i:s');
if ($incomingData['logout_date']) {
$incomingData['logout_date'] = $incomingData['logout_date']->format('Y-m-d H:i:s');
}
$tblTrackELogin = \Database::get_main_table(TABLE_STATISTIC_TRACK_E_LOGIN);
$firstId = \Database::insert(
$tblTrackELogin,
[
'login_user_id' => $incomingData['login_user_id'],
'login_date' => $incomingData['login_date'],
'user_ip' => '',
]
);
\Database::update(
$tblTrackELogin,
['logout_date' => $incomingData['logout_date']],
['login_id = ?' => [$firstId]]
);
$incomingData['user_ip'] = '';
\Database::insert(
$tblTrackELogin,
[
'login_user_id' => $incomingData['login_user_id'],
'login_date' => $incomingData['logout_date'],
'logout_date' => $incomingData['logout_date'],
'user_ip' => '',
]
);
return $incomingData['login_user_id'];
}
}

View File

@@ -0,0 +1,45 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\MigrationMoodle\Loader;
use Chamilo\PluginBundle\MigrationMoodle\Interfaces\LoaderInterface;
/**
* Class UrlLoader.
*
* The Link created is added in a learning path (from a Moodle course section).
*
* @package Chamilo\PluginBundle\MigrationMoodle\Loader
*/
class UrlLoader implements LoaderInterface
{
/**
* {@inheritdoc}
*/
public function load(array $incomingData)
{
$params = [
'c_id' => $incomingData['c_id'],
'url' => $incomingData['url'],
'title' => $incomingData['title'],
'description' => null,
'category_id' => null,
'on_homepage' => '0',
'target' => '_self',
'session_id' => 0,
];
$link = new \Link();
$link->setCourse(
api_get_course_info_by_id($incomingData['c_id'])
);
$linkId = $link->save($params);
$tblLpItem = \Database::get_course_table(TABLE_LP_ITEM);
\Database::query("UPDATE $tblLpItem SET path = '$linkId' WHERE iid = {$incomingData['item_id']}");
return $linkId;
}
}

View File

@@ -0,0 +1,28 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\MigrationMoodle\Loader;
use Chamilo\PluginBundle\MigrationMoodle\Interfaces\LoaderInterface;
/**
* Class UserLastLoginLoader.
*
* @package Chamilo\PluginBundle\MigrationMoodle\Loader
*/
class UserLastLoginLoader implements LoaderInterface
{
/**
* {@inheritdoc}
*/
public function load(array $incomingData)
{
\Database::update(
\Database::get_main_table(TABLE_MAIN_USER),
['last_login' => $incomingData['last_login']->format('Y-m-d H:i:s')],
['id = ?' => [$incomingData['user_id']]]
);
return $incomingData['user_id'];
}
}

View File

@@ -0,0 +1,32 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\MigrationMoodle\Loader;
/**
* Class UserLearnPathLessonAttemptLoader.
*
* @package Chamilo\PluginBundle\MigrationMoodle\Loader
*/
class UserLearnPathLessonAttemptLoader extends UserLearnPathLessonBranchLoader
{
/**
* @throws \Exception
*
* @return int
*/
public function load(array $incomingData)
{
$tblLpItemView = \Database::get_course_table(TABLE_LP_ITEM_VIEW);
$itemViewId = parent::load($incomingData);
if ((bool) $incomingData['is_correct']) {
\Database::query("UPDATE $tblLpItemView SET score = max_score WHERE iid = $itemViewId");
} else {
\Database::query("UPDATE $tblLpItemView SET score = 0 WHERE iid = $itemViewId");
}
return $itemViewId;
}
}

View File

@@ -0,0 +1,100 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\MigrationMoodle\Loader;
use Chamilo\PluginBundle\MigrationMoodle\Interfaces\LoaderInterface;
/**
* Class UserLearnPathLessonBranchLoader.
*
* @package Chamilo\PluginBundle\MigrationMoodle\Loader
*/
class UserLearnPathLessonBranchLoader implements LoaderInterface
{
/**
* {@inheritdoc}
*/
public function load(array $incomingData)
{
$tblLpItem = \Database::get_course_table(TABLE_LP_ITEM);
$tblLpItemView = \Database::get_course_table(TABLE_LP_ITEM_VIEW);
$item = \Database::fetch_assoc(
\Database::query("SELECT display_order FROM $tblLpItem WHERE iid = {$incomingData['item_id']}")
);
if (!$item) {
throw new \Exception("LP item ({$incomingData['item_id']}) not found.");
}
$itemView = $this->findViewOfItem($incomingData);
$itemViewParams = ['status' => 'completed'];
if ($item['display_order'] != 1) {
$previousItemView = $this->findViewOfPreviousItem($incomingData);
$itemViewParams['start_time'] = $previousItemView['start_time'] + $previousItemView['total_time'];
$itemView['start_time'] = $itemViewParams['start_time'];
}
$itemViewParams['total_time'] = $incomingData['end_time'] - $itemView['start_time'];
\Database::update(
$tblLpItemView,
$itemViewParams,
['iid = ?' => [$itemView['iid']]]
);
return $itemView['iid'];
}
/**
* @throws \Exception
*
* @return array
*/
private function findViewOfItem(array $incomingData)
{
$itemView = \Database::fetch_assoc(
\Database::query(
"SELECT lpiv.iid, lpiv.start_time
FROM c_lp_item_view lpiv
INNER JOIN c_lp_view lpv ON (lpv.iid = lpiv.lp_view_id AND lpv.c_id = lpiv.c_id)
WHERE lpiv.lp_item_id = {$incomingData['item_id']} AND lpv.user_id = {$incomingData['user_id']}
LIMIT 1"
)
);
if (!$itemView) {
throw new \Exception("Item view not found for "."item ({$incomingData['item_id']}) and user ({$incomingData['user_id']}).");
}
return $itemView;
}
/**
* @throws \Exception
*
* @return array
*/
private function findViewOfPreviousItem(array $incomingData)
{
$result = \Database::query(
"SELECT lpiv.start_time, lpiv.total_time
FROM c_lp_item_view lpiv
INNER JOIN c_lp_view lpv ON (lpv.iid = lpiv.lp_view_id AND lpv.c_id = lpiv.c_id)
INNER JOIN c_lp_item lpi ON (lpi.iid = lpiv.lp_item_id AND lpi.c_id = lpiv.c_id)
WHERE lpi.next_item_id = {$incomingData['item_id']} AND lpv.user_id = {$incomingData['user_id']}
LIMIT 1"
);
$previousItemView = \Database::fetch_assoc($result);
if (!$previousItemView) {
throw new \Exception("Item view not found for "."previous item ({$incomingData['item_id']}) and user ({$incomingData['user_id']}).");
}
return $previousItemView;
}
}

View File

@@ -0,0 +1,90 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\MigrationMoodle\Loader;
use Chamilo\PluginBundle\MigrationMoodle\Interfaces\LoaderInterface;
/**
* Class UserLearnPathLessonTimerLoader.
*
* @package Chamilo\PluginBundle\MigrationMoodle\Loader
*/
class UserLearnPathLessonTimerLoader implements LoaderInterface
{
/**
* {@inheritdoc}
*/
public function load(array $incomingData)
{
$tblItemView = \Database::get_course_table(TABLE_LP_ITEM_VIEW);
$parentItemView = $this->findViewOfParentItem($incomingData);
$itemView = $this->findViewOfFirstItem($incomingData);
\Database::query(
"UPDATE $tblItemView SET start_time = {$incomingData['start_time']} WHERE iid = {$parentItemView['iid']}"
);
\Database::query(
"UPDATE $tblItemView SET start_time = {$incomingData['start_time']} WHERE iid = {$itemView['iid']}"
);
return $itemView['iid'];
}
/**
* @throws \Exception
*
* @return array
*/
private function findViewOfParentItem(array $incomingData)
{
$parentItemView = \Database::fetch_assoc(
\Database::query(
"SELECT lpiv.iid
FROM c_lp_item_view lpiv
INNER JOIN c_lp_view lpv ON (lpv.iid = lpiv.lp_view_id AND lpv.c_id = lpiv.c_id)
WHERE lpiv.lp_item_id = {$incomingData['parent_item_id']}
AND lpv.user_id = {$incomingData['user_id']}
LIMIT 1"
)
);
if (!$parentItemView) {
throw new \Exception("Item dir ({$incomingData['parent_item_id']}) not found.");
}
return $parentItemView;
}
/**
* @throws \Exception
*
* @return array
*/
private function findViewOfFirstItem(array $incomingData)
{
$itemView = \Database::fetch_assoc(
\Database::query(
"SELECT lpiv.iid
FROM c_lp_item_view lpiv
INNER JOIN c_lp_view lpv
ON (lpv.iid = lpiv.lp_view_id AND lpv.c_id = lpiv.c_id)
INNER JOIN c_lp_item lpi
ON (lpi.lp_id = lpv.lp_id AND lpi.c_id = lpv.c_id AND lpi.iid = lpiv.lp_item_id)
WHERE lpi.item_type = 'document'
AND lpv.user_id = {$incomingData['user_id']}
AND lpi.parent_item_id = {$incomingData['parent_item_id']}
AND lpv.session_id = {$incomingData['session_id']}
ORDER BY lpi.display_order ASC
LIMIT 1"
)
);
if (!$itemView) {
throw new \Exception("Item view not found for item with"." parent item ({$incomingData['parent_item_id']}) and user ({$incomingData['user_id']})");
}
return $itemView;
}
}

View File

@@ -0,0 +1,66 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\MigrationMoodle\Loader;
use Chamilo\PluginBundle\MigrationMoodle\Interfaces\LoaderInterface;
/**
* Class UserLearnPathQuizLoader.
*
* @package Chamilo\PluginBundle\MigrationMoodle\Loader
*/
class UserLearnPathQuizLoader implements LoaderInterface
{
/**
* {@inheritdoc}
*/
public function load(array $incomingData)
{
$itemView = $this->findViewOfItem(
$incomingData['item_id'],
$incomingData['user_id'],
$incomingData['session_id']
);
\Database::update(
\Database::get_course_table(TABLE_LP_ITEM_VIEW),
[
'start_time' => $incomingData['start_time'],
'total_time' => $incomingData['total_time'],
'score' => $incomingData['score'],
'status' => $incomingData['status'],
],
['iid = ?' => $itemView['iid']]
);
return $itemView['iid'];
}
/**
* @param int $itemId
* @param int $userId
* @param int $sessionId
*
* @throws \Exception
*
* @return array
*/
private function findViewOfItem($itemId, $userId, $sessionId)
{
$result = \Database::query(
"SELECT lpiv.iid
FROM c_lp_item_view lpiv
INNER JOIN c_lp_view lpv ON (lpv.iid = lpiv.lp_view_id AND lpv.c_id = lpiv.c_id)
WHERE lpiv.lp_item_id = $itemId AND lpv.user_id = $userId AND lpv.session_id = $sessionId
LIMIT 1"
);
$itemView = \Database::fetch_assoc($result);
if (!$itemView) {
throw new \Exception("Item view not found for item ($itemId) and user ($userId) in session ($sessionId).");
}
return $itemView;
}
}

View File

@@ -0,0 +1,73 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\MigrationMoodle\Loader;
use Chamilo\PluginBundle\MigrationMoodle\Interfaces\LoaderInterface;
/**
* Class UserLearnPathsLoader.
*
* @package Chamilo\PluginBundle\MigrationMoodle\Loader
*/
class UserLearnPathsLoader implements LoaderInterface
{
/**
* {@inheritdoc}
*/
public function load(array $incomingData)
{
$tblLp = \Database::get_course_table(TABLE_LP_MAIN);
$tblLpItem = \Database::get_course_table(TABLE_LP_ITEM);
$tblLpView = \Database::get_course_table(TABLE_LP_VIEW);
$tblLpItemView = \Database::get_course_table(TABLE_LP_ITEM_VIEW);
$tblSrCrU = \Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
$resSubscriptions = \Database::query(
"SELECT c_id, session_id FROM $tblSrCrU WHERE user_id = {$incomingData['user_id']}"
);
while ($subscription = \Database::fetch_assoc($resSubscriptions)) {
$resLps = \Database::query("SELECT iid FROM $tblLp WHERE c_id = {$subscription['c_id']} AND lp_type = 1");
while ($lp = \Database::fetch_assoc($resLps)) {
$lpViewId = \Database::insert(
$tblLpView,
[
'c_id' => $subscription['c_id'],
'lp_id' => $lp['iid'],
'user_id' => $incomingData['user_id'],
'view_count' => 1,
'session_id' => $subscription['session_id'],
'last_item' => 0,
]
);
\Database::query("UPDATE $tblLpView SET id = iid WHERE iid = $lpViewId");
$resItems = \Database::query(
"SELECT iid, max_score FROM $tblLpItem
WHERE lp_id = {$lp['iid']} ORDER BY parent_item_id ASC, display_order ASC"
);
while ($lpItem = \Database::fetch_assoc($resItems)) {
$lpItemViewId = \Database::insert(
$tblLpItemView,
[
'c_id' => $subscription['c_id'],
'lp_item_id' => $lpItem['iid'],
'lp_view_id' => $lpViewId,
'view_count' => 1,
'status' => 'not attempted',
'start_time' => 0,
'total_time' => 0,
'score' => 0,
'max_score' => $lpItem['max_score'],
]
);
\Database::query("UPDATE $tblLpItemView SET id = iid WHERE iid = $lpItemViewId");
}
}
}
return $incomingData['user_id'];
}
}

View File

@@ -0,0 +1,30 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\MigrationMoodle\Loader;
use Chamilo\PluginBundle\MigrationMoodle\Interfaces\LoaderInterface;
/**
* Class UserQuestionAttemptLoader.
*
* @package Chamilo\PluginBundle\MigrationMoodle\Loader
*/
class UserQuestionAttemptLoader implements LoaderInterface
{
/**
* {@inheritdoc}
*/
public function load(array $incomingData)
{
$incomingData['marks'] = (float) $incomingData['marks'];
$incomingData['teacher_comment'] = '';
$incomingData['tms'] = $incomingData['tms']->format('Y-m-d H:i:s');
$incomingData['position'] = 0;
return \Database::insert(
\Database::get_main_table(TABLE_STATISTIC_TRACK_E_ATTEMPT),
$incomingData
);
}
}

View File

@@ -0,0 +1,80 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\MigrationMoodle\Loader;
use Chamilo\PluginBundle\MigrationMoodle\Interfaces\LoaderInterface;
/**
* Class UserQuizAttemptLoader.
*
* @package Chamilo\PluginBundle\MigrationMoodle\Loader
*/
class UserQuizAttemptLoader implements LoaderInterface
{
/**
* {@inheritdoc}
*/
public function load(array $incomingData)
{
$view = $this->findViewByQuiz(
$incomingData['exo_id'],
$incomingData['user_id'],
$incomingData['session_id']
);
/** @var \DateTime $exeDate */
$exeDate = clone $incomingData['date'];
$exeDate->modify("+{$incomingData['duration']} seconds");
return \Database::insert(
\Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES),
[
'exe_exo_id' => $incomingData['exo_id'],
'exe_user_id' => $incomingData['user_id'],
'c_id' => $view['c_id'],
'status' => $incomingData['status'] === 'finished' ? '' : 'incomplete',
'session_id' => $incomingData['session_id'],
'data_tracking' => $incomingData['data_tracking'],
'start_date' => $incomingData['date']->format('Y-m-d H:i:s'),
'orig_lp_id' => $view['lp_id'],
'orig_lp_item_id' => $view['lp_item_id'],
'orig_lp_item_view_id' => $view['iid'],
'exe_weighting' => $incomingData['weighting'],
'user_ip' => '',
'exe_date' => $exeDate->format('Y-m-d H:i:s'),
'exe_result' => (float) $incomingData['result'],
'steps_counter' => 0,
'exe_duration' => $incomingData['duration'],
'questions_to_check' => '',
]
);
}
/**
* @param int $quizId
* @param int $userId
* @param int $sessionId
*
* @throws \Exception
*
* @return array
*/
private function findViewByQuiz($quizId, $userId, $sessionId)
{
$query = \Database::query("SELECT lpiv.lp_item_id, lpv.c_id, lpiv.iid, lpv.lp_id
FROM c_lp_item_view lpiv
INNER JOIN c_lp_item lpi ON (lpiv.lp_item_id = lpi.iid AND lpiv.c_id = lpi.c_id)
INNER JOIN c_lp_view lpv ON (lpv.iid = lpiv.lp_view_id AND lpv.c_id = lpiv.c_id)
WHERE lpi.path = $quizId AND lpv.user_id = $userId AND lpv.session_id = $sessionId
LIMIT 1"
);
$result = \Database::fetch_assoc($query);
if (!$result) {
throw new \Exception("Item view not found for quiz ($quizId) and user ($userId) in session ($sessionId).");
}
return $result;
}
}

View File

@@ -0,0 +1,79 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\MigrationMoodle\Loader;
use Chamilo\PluginBundle\MigrationMoodle\Interfaces\LoaderInterface;
/**
* Class UserSessionLoader.
*
* @package Chamilo\PluginBundle\MigrationMoodle\Loader
*/
class UserSessionLoader implements LoaderInterface
{
public const LOAD_MODE_REUSE = 'reuse';
public const LOAD_MODE_DUPLICATE = 'duplicate';
/**
* @var string Load mode: "reuse" or "duplicate". Default is "duplicate".
*/
private $loadMode = self::LOAD_MODE_DUPLICATE;
/**
* {@inheritdoc}
*/
public function load(array $incomingData)
{
foreach ($incomingData['course_ids'] as $courseId) {
if (empty($courseId)) {
throw new \Exception("Course ($courseId) not found when creating course session for user ({$incomingData['user_id']}). ".'Session will not be created.');
}
}
$tblSession = \Database::get_main_table(TABLE_MAIN_SESSION);
$sessionInfo = \Database::fetch_assoc(
\Database::query("SELECT id FROM $tblSession WHERE name = '{$incomingData['name']}'")
);
if (!empty($sessionInfo)) {
if ($this->loadMode == self::LOAD_MODE_REUSE) {
return $sessionInfo['id'];
}
if ($this->loadMode === self::LOAD_MODE_DUPLICATE) {
$incomingData['name'] = '['.substr(md5(uniqid(rand())), 0, 5).'] '.$incomingData['name'];
}
}
$urlId = \MigrationMoodlePlugin::create()->getAccessUrlId();
$datetime = api_get_utc_datetime();
$coachId = 1;
$sessionId = \SessionManager::create_session(
$incomingData['name'],
$datetime,
'',
$datetime,
'',
$datetime,
'',
$coachId,
0,
1,
false,
null,
null,
0,
[],
0,
false,
$urlId
);
\SessionManager::add_courses_to_session($sessionId, $incomingData['course_ids']);
\SessionManager::subscribeUsersToSession($sessionId, [$incomingData['user_id']]);
return $sessionId;
}
}

View File

@@ -0,0 +1,97 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\MigrationMoodle\Loader;
use Chamilo\PluginBundle\MigrationMoodle\Interfaces\LoaderInterface;
use Chamilo\UserBundle\Entity\User;
/**
* Class UsersLoader.
*
* Loader to create a Chamilo user coming from a Moodle user.
*
* @package Chamilo\PluginBundle\MigrationMoodle\Loader
*/
class UsersLoader implements LoaderInterface
{
public const LOAD_MODE_REUSE = 'reuse';
public const LOAD_MODE_DUPLICATE = 'duplicate';
/**
* @var string Load mode: "reuse" or "duplicate". Default is "duplicate".
*/
private $loadMode = self::LOAD_MODE_DUPLICATE;
/**
* @throws \Exception
*
* @return int
*/
public function load(array $incomingData)
{
$tblUser = \Database::get_main_table(TABLE_MAIN_USER);
$userInfo = \Database::fetch_assoc(
\Database::query("SELECT id FROM $tblUser WHERE username = '{$incomingData['username']}'")
);
if (!empty($userInfo)) {
if ($this->loadMode == self::LOAD_MODE_REUSE) {
return $userInfo['id'];
}
if ($this->loadMode === self::LOAD_MODE_DUPLICATE) {
$incomingData['username'] .= substr(md5(uniqid(rand())), 0, 10);
}
}
$userId = \UserManager::create_user(
$incomingData['firstname'],
$incomingData['lastname'],
$incomingData['status'],
$incomingData['email'],
$incomingData['username'],
md5(time()),
'',
$incomingData['language'],
$incomingData['phone'],
null,
$incomingData['auth_source'],
null,
$incomingData['active'],
0,
[],
null,
false,
false,
$incomingData['address'],
false,
null,
0,
[]
);
if (empty($userId)) {
throw new \Exception('User was not created');
}
if ($incomingData['registration_date']) {
$incomingData['registration_date'] = $incomingData['registration_date']->format('Y-m-d H:i:s');
\Database::query(
"UPDATE $tblUser SET registration_date = '{$incomingData['registration_date']}' WHERE id = $userId"
);
}
\UserManager::update_extra_field_value($userId, 'moodle_password', $incomingData['plain_password']);
$urlId = \MigrationMoodlePlugin::create()->getAccessUrlId();
if ($urlId) {
\Database::query("UPDATE access_url_rel_user SET access_url_id = $urlId WHERE user_id = $userId");
}
return $userId;
}
}

View File

@@ -0,0 +1,163 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\MigrationMoodle\Loader;
use Chamilo\PluginBundle\MigrationMoodle\Interfaces\LoaderInterface;
/**
* Class UsersScormsViewLoader.
*
* @package Chamilo\PluginBundle\MigrationMoodle\Loader
*/
class UsersScormsViewLoader implements LoaderInterface
{
/**
* {@inheritdoc}
*/
public function load(array $incomingData)
{
$tblLpView = \Database::get_course_table(TABLE_LP_VIEW);
$tblLpItemView = \Database::get_course_table(TABLE_LP_ITEM_VIEW);
$sessionId = $this->getUserSubscriptionInSession($incomingData['user_id'], $incomingData['c_id']);
$lpViewId = $this->getLpView(
$incomingData['user_id'],
$incomingData['lp_id'],
$incomingData['c_id'],
$sessionId
);
$lpItemViewId = $this->getLpItemView($lpViewId, $incomingData['lp_item_id']);
$itemView = [
'c_id' => $incomingData['c_id'],
'lp_item_id' => $incomingData['lp_item_id'],
'lp_view_id' => $lpViewId,
'view_count' => $incomingData['lp_item_view_count'],
'status' => 'not attempted',
'start_time' => 0,
'total_time' => 0,
'score' => 0,
'max_score' => 100,
];
foreach (array_keys($itemView) as $key) {
if (isset($incomingData['item_data'][$key])) {
$itemView[$key] = $incomingData['item_data'][$key];
}
}
if (empty($lpItemViewId)) {
$lpItemViewId = \Database::insert($tblLpItemView, $itemView);
\Database::query("UPDATE $tblLpItemView SET id = iid WHERE iid = $lpItemViewId");
} else {
\Database::update($tblLpItemView, $itemView, ['iid = ?' => [$lpItemViewId]]);
}
\Database::query(
"UPDATE $tblLpView
SET last_item = {$incomingData['lp_item_id']},
view_count = {$incomingData['lp_item_view_count']}
WHERE iid = $lpViewId"
);
return $lpViewId;
}
/**
* @param int $userId
* @param int $courseId
*
* @throws \Exception
*
* @return int
*/
private function getUserSubscriptionInSession($userId, $courseId)
{
$srcru = \Database::select(
'session_id',
\Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER),
[
'where' => [
'user_id = ? AND c_id = ?' => [$userId, $courseId],
],
],
'first'
);
if (empty($srcru)) {
throw new \Exception("Session not found for user ($userId) with course ($courseId)");
}
return $srcru['session_id'];
}
/**
* @param int $userId
* @param int $lpId
* @param int $cId
* @param int $sessionId
*
* @return int
*/
private function getLpView($userId, $lpId, $cId, $sessionId)
{
$tblLpView = \Database::get_course_table(TABLE_LP_VIEW);
$lpView = \Database::select(
'iid',
$tblLpView,
[
'where' => [
'user_id = ? AND lp_id = ? AND c_id = ? AND session_id = ?' => [
$userId,
$lpId,
$cId,
$sessionId,
],
],
'order' => 'view_count DESC',
],
'first'
);
if (empty($lpView)) {
$lpView = [
'c_id' => $cId,
'lp_id' => $lpId,
'user_id' => $userId,
'view_count' => 1,
'session_id' => $sessionId,
'last_item' => 0,
];
$lpViewId = \Database::insert($tblLpView, $lpView);
\Database::query("UPDATE $tblLpView SET id = iid WHERE iid = $lpViewId");
return $lpViewId;
}
return $lpView['iid'];
}
/**
* @param int $lpViewId
* @param int $lpItemId
*
* @return int
*/
private function getLpItemView($lpViewId, $lpItemId)
{
$lpItemView = \Database::fetch_assoc(
\Database::query("SELECT iid FROM c_lp_item_view WHERE lp_view_id = $lpViewId AND lp_item_id = $lpItemId")
);
if (empty($lpItemView)) {
return 0;
}
return $lpItemView['iid'];
}
}

View File

@@ -0,0 +1,24 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\MigrationMoodle\Messages;
use Throwable;
/**
* Class ExtractException.
*
* @package Chamilo\PluginBundle\MigrationMoodle\Messages
*/
class ExtractMessage extends Message
{
/**
* ExtractMessage constructor.
*/
public function __construct(Throwable $previous = null)
{
$message = 'Error while extracting data.';
parent::__construct($message, $previous);
}
}

View File

@@ -0,0 +1,42 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\MigrationMoodle\Messages;
use Throwable;
/**
* Class LoadMessage.
*
* @package Chamilo\PluginBundle\MigrationMoodle\Messages
*/
class LoadMessage extends Message
{
/**
* @var array
*/
private $incomingData;
/**
* LoadMessage constructor.
*
* @param $incomingData
*/
public function __construct($incomingData, Throwable $previous = null)
{
$message = 'Error while loading transformed data.';
$this->incomingData = $incomingData;
parent::__construct($message, $previous);
}
public function displayAsString()
{
$pieces = [
parent::displayAsString(),
"\t".print_r($this->incomingData, true),
];
echo implode(PHP_EOL, $pieces);
}
}

View File

@@ -0,0 +1,63 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\MigrationMoodle\Messages;
use Throwable;
/**
* Class Message.
*
* @package Chamilo\PluginBundle\MigrationMoodle\Messages
*/
abstract class Message
{
/**
* @var string
*/
protected $message;
/**
* @var Throwable
*/
protected $previous;
/**
* Message constructor.
*
* @param string $message
*/
public function __construct($message = "", Throwable $previous = null)
{
$this->message = $message;
$this->previous = $previous;
$this->displayAsString();
}
/**
* @return string
*/
public function getMessage()
{
return $this->message;
}
/**
* @return Throwable
*/
public function getPrevious()
{
return $this->previous;
}
public function displayAsString()
{
$pieces = [$this->message];
if ($this->previous) {
$pieces[] = "\t".$this->previous->getMessage();
}
echo implode(PHP_EOL, $pieces);
}
}

View File

@@ -0,0 +1,40 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\MigrationMoodle\Messages;
use Throwable;
/**
* Class TransformMessage.
*
* @package Chamilo\PluginBundle\MigrationMoodle\Messages
*/
class TransformMessage extends Message
{
/**
* @var array
*/
private $extractedData;
/**
* TransformMessage constructor.
*/
public function __construct(array $extractedData, Throwable $previous = null)
{
$message = 'Error while transforming extracted data.';
$this->extractedData = $extractedData;
parent::__construct($message, $previous);
}
public function displayAsString()
{
$pieces = [
parent::displayAsString(),
"\t".print_r($this->extractedData, true),
];
echo implode(PHP_EOL, $pieces);
}
}

View File

@@ -0,0 +1,82 @@
<?php
/* For licensing terms, see /license.txt */
use Chamilo\CoreBundle\Entity\ExtraField;
use Chamilo\CoreBundle\Entity\ExtraFieldValues;
/**
* Class MigrationMoodleCheckLoginCredentialsHook.
*/
class MigrationMoodleCheckLoginCredentialsHook extends HookObserver implements CheckLoginCredentialsHookObserverInterface
{
/**
* MigrationMoodleCheckLoginCredentialsHook constructor.
*/
protected function __construct()
{
parent::__construct(
'plugin/migrationmoodle/src/MigrationMoodlePlugin.php',
'migrationmoodle'
);
}
/**
* @return bool
*/
public function checkLoginCredentials(CheckLoginCredentialsHookEventInterface $event)
{
$data = $event->getEventData();
/** @var array $userData */
$userData = $data['user'];
/** @var array $credentials */
$credentials = $data['credentials'];
$extraField = $this->getExtraField();
if (empty($extraField)) {
return false;
}
$fieldValue = $this->getExtraFieldValue($extraField, $userData);
if (empty($fieldValue)) {
return false;
}
$isPasswordVerified = password_verify(
$credentials['password'],
$fieldValue->getValue()
);
if (!$isPasswordVerified) {
return false;
}
return true;
}
/**
* @return ExtraField|null
*/
private function getExtraField()
{
return Database::getManager()
->getRepository('ChamiloCoreBundle:ExtraField')
->findOneBy(
[
'variable' => 'moodle_password',
'extraFieldType' => ExtraField::USER_FIELD_TYPE,
]
);
}
/**
* @return ExtraFieldValues|null
*/
private function getExtraFieldValue(ExtraField $extraField, array $userData)
{
return Database::getManager()
->getRepository('ChamiloCoreBundle:ExtraFieldValues')
->findOneBy(['field' => $extraField, 'itemId' => $userData['user_id']]);
}
}

View File

@@ -0,0 +1,169 @@
<?php
/* For licensing terms, see /license.txt */
use Doctrine\DBAL\Configuration;
use Doctrine\DBAL\Connection;
use Doctrine\DBAL\DriverManager;
/**
* Class MigrationMoodlePlugin.
*/
class MigrationMoodlePlugin extends Plugin implements HookPluginInterface
{
public const SETTING_USER_FILTER = 'user_filter';
public const SETTING_URL_ID = 'url_id';
public const SETTING_MOODLE_PATH = 'moodle_path';
public $isAdminPlugin = true;
/**
* MigrationMoodlePlugin constructor.
*/
protected function __construct()
{
$version = '0.0.1';
$author = 'Angel Fernando Quiroz Campos';
$settings = [
'active' => 'boolean',
'db_host' => 'text',
'db_user' => 'text',
'db_password' => 'text',
'db_name' => 'text',
self::SETTING_USER_FILTER => 'text',
self::SETTING_URL_ID => 'text',
self::SETTING_MOODLE_PATH => 'text',
];
parent::__construct($version, $author, $settings);
}
/**
* @return MigrationMoodlePlugin|null
*/
public static function create()
{
static $result = null;
return $result ? $result : $result = new self();
}
/**
* @throws \Doctrine\DBAL\DBALException
*
* @return Connection
*/
public function getConnection()
{
$params = [
'host' => $this->get('db_host'),
'user' => $this->get('db_user'),
'password' => $this->get('db_password'),
'dbname' => $this->get('db_name'),
'driver' => 'pdo_mysql',
];
$connection = DriverManager::getConnection($params, new Configuration());
return $connection;
}
/**
* Perform actions after configure the plugin.
*
* Add user extra field.
*
* @throws Exception
*
* @return MigrationMoodlePlugin
*/
public function performActionsAfterConfigure()
{
if ('true' === $this->get('active')) {
$this->installHook();
} else {
$this->uninstallHook();
}
return $this;
}
/**
* This method will call the Hook management insertHook to add Hook observer from this plugin.
*
* @throws Exception
*
* @return void
*/
public function installHook()
{
$hookObserver = MigrationMoodleCheckLoginCredentialsHook::create();
CheckLoginCredentialsHook::create()->attach($hookObserver);
}
/**
* This method will call the Hook management deleteHook to disable Hook observer from this plugin.
*
* @throws Exception
*
* @return void
*/
public function uninstallHook()
{
$hookObserver = MigrationMoodleCheckLoginCredentialsHook::create();
CheckLoginCredentialsHook::create()->detach($hookObserver);
}
/**
* @return string
*/
public function getUserFilterSetting()
{
$userFilter = $this->get(self::SETTING_USER_FILTER);
return trim($userFilter);
}
/**
* @return int
*/
public function getAccessUrlId()
{
$urlId = (int) $this->get(self::SETTING_URL_ID);
return $urlId ?: 1;
}
/**
* @return string
*/
public function getMoodledataPath()
{
$path = $this->get(self::SETTING_MOODLE_PATH);
return rtrim($path, ' /');
}
/**
* @param string $name
*
* @return bool
*/
public function isTaskDone($name)
{
$result = Database::select(
'COUNT(1) c',
'plugin_migrationmoodle_task',
[
'where' => [
'name = ?' => Database::escape_string($name.'_task'),
'or name = ?' => Database::escape_string($name.'_script'),
],
],
'first'
);
return $result['c'] > 0;
}
}

View File

@@ -0,0 +1,94 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\MigrationMoodle\Script;
use Chamilo\PluginBundle\MigrationMoodle\Traits\MapTrait\MapTrait;
/**
* Class BaseScript.
*
* @package Chamilo\PluginBundle\MigrationMoodle\Script
*/
abstract class BaseScript
{
use MapTrait;
/**
* BaseScript constructor.
*/
public function __construct()
{
$this->calledClass = get_called_class();
}
public function run()
{
\Database::insert(
'plugin_migrationmoodle_task',
['name' => $this->getTaskName()]
);
$this->process();
}
abstract public function process();
/**
* @param int $userId
*
* @return bool
*/
protected function isLoadedUser($userId)
{
return $this->isLoadedId($userId, 'users_task');
}
/**
* @param int $lpId
*
* @return bool
*/
protected function isMigratedLearningPath($lpId)
{
return $this->isLoadedId($lpId, 'course_sections_task');
}
/**
* @param int $scormId
*
* @return bool
*/
protected function isMigratedScorm($scormId)
{
return $this->isLoadedId($scormId, 'course_modules_scorm_task');
}
/**
* @param string $message
*/
protected function showMessage($message)
{
echo '['.date(\DateTime::ATOM)."]\t$message".PHP_EOL;
}
/**
* @param int $id
* @param string $taskName
*
* @return bool
*/
private function isLoadedId($id, $taskName)
{
$row = \Database::fetch_assoc(
\Database::query(
"SELECT COUNT(pmi.id) AS nbr
FROM plugin_migrationmoodle_item pmi
INNER JOIN plugin_migrationmoodle_task pmt ON pmi.task_id = pmt.id
WHERE pmt.name = '$taskName' AND pmi.loaded_id = $id"
)
);
return $row['nbr'] > 0;
}
}

View File

@@ -0,0 +1,132 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\MigrationMoodle\Script;
/**
* Class UserLearnPathsProgressScript.
*
* @package Chamilo\PluginBundle\MigrationMoodle\Script
*/
class UserLearnPathsProgressScript extends BaseScript
{
public function process()
{
$itemsInLp = $this->countItemsInLp();
foreach ($this->getUsersAndLps() as $lpView) {
$userId = $lpView['user_id'];
$lpId = $lpView['lp_id'];
$cId = $lpView['c_id'];
$lpViewId = $lpView['iid'];
$completedItems = $this->countCompletedItems($userId, $lpId, $cId);
if (empty($completedItems) || empty($itemsInLp[$lpId])) {
continue;
}
$progress = (int) ($completedItems / $itemsInLp[$lpId] * 100);
\Database::query(
"UPDATE c_lp_view
SET progress = $progress
WHERE user_id = $userId
AND lp_id = $lpId
AND c_id = $cId
AND iid = $lpViewId"
);
$this->showMessage("Updated: c_lp_view $lpViewId with progress $progress.");
}
}
/**
* @return array
*/
private function countItemsInLp()
{
$tblItem = \Database::get_course_table(TABLE_LP_ITEM);
$tblLp = \Database::get_course_table(TABLE_LP_MAIN);
$result = \Database::query(
"SELECT lpi.lp_id, COUNT(lpi.iid) AS c_lpi
FROM $tblItem lpi
INNER JOIN $tblLp lp ON lpi.lp_id = lp.iid
WHERE lpi.item_type != 'dir' AND lp.lp_type = 1
GROUP BY lpi.lp_id"
);
$data = [];
while ($row = \Database::fetch_assoc($result)) {
$data[$row['lp_id']] = $row['c_lpi'];
}
return $data;
}
/**
* @return \Generator
*/
private function getUsersAndLps()
{
$tblLpView = \Database::get_course_table(TABLE_LP_VIEW);
$tblLp = \Database::get_course_table(TABLE_LP_MAIN);
$result = \Database::query(
"SELECT lpv.iid, lpv.lp_id, lpv.user_id, lpv.c_id
FROM $tblLpView lpv
INNER JOIN $tblLp lp ON lpv.lp_id = lp.iid
INNER JOIN plugin_migrationmoodle_item pmi ON pmi.loaded_id = lpv.user_id
INNER JOIN plugin_migrationmoodle_task pmt ON pmi.task_id = pmt.id
WHERE lp.lp_type = 1 AND pmt.name = 'users_task'"
);
while ($row = \Database::fetch_assoc($result)) {
if (!$this->isLoadedUser($row['user_id']) ||
!$this->isMigratedLearningPath($row['lp_id'])
) {
continue;
}
yield $row;
}
}
/**
* @param int $userId
* @param int $lpId
* @param int $cId
*
* @return int
*/
private function countCompletedItems($userId, $lpId, $cId)
{
$tblItemView = \Database::get_course_table(TABLE_LP_ITEM_VIEW);
$tblLpView = \Database::get_course_table(TABLE_LP_VIEW);
$tblLp = \Database::get_course_table(TABLE_LP_MAIN);
$result = \Database::query("SELECT
lpiv.lp_view_id,
lpiv.c_id,
COUNT(lpiv.lp_item_id) c_lpiv
FROM $tblItemView lpiv
INNER JOIN $tblLpView lpv ON (lpiv.lp_view_id = lpv.iid AND lpiv.c_id = lpv.c_id)
INNER JOIN $tblLp lp ON (lpv.lp_id = lp.iid AND lpv.c_id = lp.c_id)
WHERE lpiv.status = 'completed'
AND lpv.user_id = $userId
AND lp.iid = $lpId
AND lp.c_id = $cId
AND lp.lp_type = 1
GROUP BY lpiv.lp_view_id");
$row = \Database::fetch_assoc($result);
if (empty($row) || empty($row['c_lpiv'])) {
return 0;
}
return $row['c_lpiv'];
}
}

View File

@@ -0,0 +1,138 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\MigrationMoodle\Script;
/**
* Class UserScormsProgressScript.
*
* @package Chamilo\PluginBundle\MigrationMoodle\Script
*/
class UserScormsProgressScript extends BaseScript
{
public function process()
{
$itemsInLp = $this->countItemsInLp();
foreach ($this->getUsersAndLps() as $lpView) {
$userId = $lpView['user_id'];
$lpId = $lpView['lp_id'];
$cId = $lpView['c_id'];
$lpViewId = $lpView['iid'];
$completedItems = $this->countCompletedItems($userId, $lpId, $cId);
if (empty($completedItems) || empty($itemsInLp[$lpId])) {
continue;
}
if ($completedItems > $itemsInLp[$lpId]) {
$progress = 100;
} else {
$progress = (int) ($completedItems / $itemsInLp[$lpId] * 100);
}
\Database::query(
"UPDATE c_lp_view
SET progress = $progress
WHERE user_id = $userId
AND lp_id = $lpId
AND c_id = $cId
AND iid = $lpViewId"
);
$this->showMessage("Updated: c_lp_view $lpViewId with progress $progress.");
}
}
/**
* @return array
*/
private function countItemsInLp()
{
$tblItem = \Database::get_course_table(TABLE_LP_ITEM);
$tblLp = \Database::get_course_table(TABLE_LP_MAIN);
$result = \Database::query(
"SELECT lpi.lp_id, COUNT(lpi.iid) AS c_lpi
FROM $tblItem lpi
INNER JOIN $tblLp lp ON lpi.lp_id = lp.iid
WHERE lpi.item_type = 'sco' AND lp.lp_type = 2
GROUP BY lpi.lp_id"
);
$data = [];
while ($row = \Database::fetch_assoc($result)) {
$data[$row['lp_id']] = $row['c_lpi'];
}
return $data;
}
/**
* @return \Generator
*/
private function getUsersAndLps()
{
$tblLpView = \Database::get_course_table(TABLE_LP_VIEW);
$tblLp = \Database::get_course_table(TABLE_LP_MAIN);
$result = \Database::query(
"SELECT lpv.iid, lpv.lp_id, lpv.user_id, lpv.c_id
FROM $tblLpView lpv
INNER JOIN $tblLp lp ON lpv.lp_id = lp.iid
WHERE lp.lp_type = 2"
);
while ($row = \Database::fetch_assoc($result)) {
if (!$this->isLoadedUser($row['user_id']) ||
!$this->isMigratedScorm($row['lp_id'])
) {
continue;
}
yield $row;
}
}
/**
* @param int $userId
* @param int $lpId
* @param int $cId
*
* @return int
*/
private function countCompletedItems($userId, $lpId, $cId)
{
$tblItemView = \Database::get_course_table(TABLE_LP_ITEM_VIEW);
$tblLpView = \Database::get_course_table(TABLE_LP_VIEW);
$tblLp = \Database::get_course_table(TABLE_LP_MAIN);
$result = \Database::query("SELECT
lpiv.lp_view_id,
lpiv.c_id,
COUNT(lpiv.lp_item_id) c_lpiv
FROM $tblItemView lpiv
INNER JOIN $tblLpView lpv ON (lpiv.lp_view_id = lpv.iid AND lpiv.c_id = lpv.c_id)
INNER JOIN $tblLp lp ON (lpv.lp_id = lp.iid AND lpv.c_id = lp.c_id)
WHERE lpiv.status = 'completed'
AND lpv.user_id = $userId
AND lp.iid = $lpId
AND lp.c_id = $cId
AND lp.lp_type = 2
GROUP BY lpiv.lp_view_id, lpiv.lp_item_id");
if (\Database::num_rows($result) == 0) {
return 0;
}
$count = 0;
while ($row = \Database::fetch_assoc($result)) {
$count += (int) $row['c_lpiv'];
}
return $count;
}
}

View File

@@ -0,0 +1,199 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\MigrationMoodle\Task;
use Chamilo\PluginBundle\MigrationMoodle\Interfaces\ExtractorInterface;
use Chamilo\PluginBundle\MigrationMoodle\Interfaces\LoaderInterface;
use Chamilo\PluginBundle\MigrationMoodle\Interfaces\TransformerInterface;
use Chamilo\PluginBundle\MigrationMoodle\Messages\ExtractMessage;
use Chamilo\PluginBundle\MigrationMoodle\Messages\LoadMessage;
use Chamilo\PluginBundle\MigrationMoodle\Messages\TransformMessage;
use Chamilo\PluginBundle\MigrationMoodle\Traits\MapTrait\MapTrait;
/**
* Class BaseTask.
*/
abstract class BaseTask
{
use MapTrait;
/**
* @var int
*/
protected $taskId;
/**
* @var ExtractorInterface
*/
protected $extractor;
/**
* @var TransformerInterface
*/
protected $transformer;
/**
* @var LoaderInterface
*/
protected $loader;
/**
* @var \MigrationMoodlePlugin
*/
protected $plugin;
/**
* BaseTask constructor.
*/
public function __construct()
{
$this->plugin = \MigrationMoodlePlugin::create();
$this->extractor = $this->getExtractor();
$this->transformer = $this->getTransformer();
$this->loader = $this->getLoader();
$this->calledClass = get_called_class();
}
/**
* @return array
*/
abstract public function getExtractConfiguration();
/**
* @return array
*/
abstract public function getTransformConfiguration();
/**
* @return array
*/
abstract public function getLoadConfiguration();
public function execute()
{
$outputBuffering = isset($GLOBALS['outputBuffering']) ? $GLOBALS['outputBuffering'] : true;
$taskId = \Database::insert(
'plugin_migrationmoodle_task',
['name' => $this->getTaskName()]
);
$i = 0;
foreach ($this->executeETL() as $hash => $ids) {
\Database::insert(
'plugin_migrationmoodle_item',
[
'hash' => $hash,
'extracted_id' => (int) $ids['extracted'],
'loaded_id' => (int) $ids['loaded'],
'task_id' => $taskId,
]
);
echo "[".date(\DateTime::ATOM)."]\tData migrated: $hash".PHP_EOL;
$i++;
if ($i % 10 === 0 && $outputBuffering) {
flush();
ob_flush();
}
}
if ($outputBuffering) {
ob_end_flush();
}
}
/**
* @return \Generator
*/
private function executeETL()
{
foreach ($this->extractFiltered() as $extractedData) {
try {
$incomingData = $this->transformer->transform($extractedData);
} catch (\Exception $exception) {
new TransformMessage($extractedData, $exception);
continue;
}
try {
$loadedId = $this->loader->load($incomingData);
} catch (\Exception $exception) {
new LoadMessage($incomingData, $exception);
continue;
}
yield md5("{$extractedData['id']}@@$loadedId") => [
'extracted' => $extractedData['id'],
'loaded' => $loadedId,
];
}
}
/**
* @return \Generator
*/
private function extractFiltered()
{
try {
foreach ($this->extractor->extract() as $extractedData) {
if ($this->extractor->filter($extractedData)) {
continue;
}
yield $extractedData;
}
} catch (\Exception $exception) {
new ExtractMessage($exception);
}
}
/**
* @return ExtractorInterface
*/
private function getExtractor()
{
$configuration = $this->getExtractConfiguration();
$extractorClass = $configuration['class'];
/** @var ExtractorInterface $extractor */
$extractor = new $extractorClass($configuration);
return $extractor;
}
/**
* @return TransformerInterface
*/
private function getTransformer()
{
$configuration = $this->getTransformConfiguration();
$transformerClass = $configuration['class'];
/** @var TransformerInterface $extractor */
$extractor = new $transformerClass($configuration);
return $extractor;
}
/**
* @return LoaderInterface
*/
private function getLoader()
{
$configuration = $this->getLoadConfiguration();
$loaderClass = $configuration['class'];
/** @var LoaderInterface $extractor */
$extractor = new $loaderClass($configuration);
return $extractor;
}
}

View File

@@ -0,0 +1,77 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\MigrationMoodle\Task;
use Chamilo\PluginBundle\MigrationMoodle\Extractor\BaseExtractor;
use Chamilo\PluginBundle\MigrationMoodle\Loader\CQuizLoader;
use Chamilo\PluginBundle\MigrationMoodle\Transformer\BaseTransformer;
use Chamilo\PluginBundle\MigrationMoodle\Transformer\Property\LoadedCourseLookup;
use Chamilo\PluginBundle\MigrationMoodle\Transformer\Property\Percentage;
/**
* Class CQuizTask.
*
* @package Chamilo\PluginBundle\MigrationMoodle\Task
*/
class CQuizTask extends BaseTask
{
/**
* @return array
*/
public function getExtractConfiguration()
{
return [
'class' => BaseExtractor::class,
'query' => 'SELECT * FROM mdl_quiz',
];
}
/**
* @return array
*/
public function getTransformConfiguration()
{
return [
'class' => BaseTransformer::class,
'map' => [
'c_id' => [
'class' => LoadedCourseLookup::class,
'properties' => ['course'],
],
'exerciseTitle' => 'name',
'exerciseDescription' => 'intro',
//'exerciseFeedbackType',
//'results_disabled',
//'exerciseType',
//'question_selection_type',
//'randomQuestions' => 'shufflequestions',
'randomAnswers' => 'shuffleanswers',
//'display_category_name',
//'hide_question_title',
'exerciseAttempts' => 'attempts',
//'activate_start_date_check',
'start_time' => 'timeopen',
//'activate_end_date_check',
'end_time' => 'timeclose',
//'enabletimercontrol',
'enabletimercontroltotalminutes' => 'timelimit',
'pass_percentage' => [
'class' => Percentage::class,
'properties' => ['sumgrades', 'grade'],
],
//'text_when_finished',
],
];
}
/**
* @return array
*/
public function getLoadConfiguration()
{
return [
'class' => CQuizLoader::class,
];
}
}

View File

@@ -0,0 +1,61 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\MigrationMoodle\Task;
use Chamilo\PluginBundle\MigrationMoodle\Extractor\BaseExtractor;
use Chamilo\PluginBundle\MigrationMoodle\Loader\CourseCategoriesLoader;
use Chamilo\PluginBundle\MigrationMoodle\Transformer\BaseTransformer;
use Chamilo\PluginBundle\MigrationMoodle\Transformer\Property\CourseCategoryLookup;
use Chamilo\PluginBundle\MigrationMoodle\Transformer\Property\CourseCode;
/**
* Class CourseCategoriesTask.
*
* @package Chamilo\PluginBundle\MigrationMoodle\Task
*/
class CourseCategoriesTask extends BaseTask
{
/**
* @return array
*/
public function getExtractConfiguration()
{
return [
'class' => BaseExtractor::class,
'query' => 'SELECT * FROM mdl_course_categories ORDER BY parent ASC, id ASC',
];
}
/**
* @return array
*/
public function getTransformConfiguration()
{
return [
'class' => BaseTransformer::class,
'map' => [
'name' => 'name',
'code' => [
'class' => CourseCode::class,
'properties' => ['name'],
],
'description' => 'description',
'parent_id' => [
'class' => CourseCategoryLookup::class,
'properties' => ['parent'],
],
],
];
}
/**
* @return array
*/
public function getLoadConfiguration()
{
return [
'class' => CourseCategoriesLoader::class,
];
}
}

View File

@@ -0,0 +1,47 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\MigrationMoodle\Task;
use Chamilo\PluginBundle\MigrationMoodle\Loader\CourseFilesLoader;
use Chamilo\PluginBundle\MigrationMoodle\Transformer\BaseTransformer;
use Chamilo\PluginBundle\MigrationMoodle\Transformer\Property\LoadedCourseLookup;
/**
* Class CourseFilesTask.
*
* @package Chamilo\PluginBundle\MigrationMoodle\Task
*/
abstract class CourseFilesTask extends BaseTask
{
/**
* @return array
*/
public function getTransformConfiguration()
{
return [
'class' => BaseTransformer::class,
'map' => [
'contenthash' => 'contenthash',
'filepath' => 'filepath',
'filename' => 'filename',
'filesize' => 'filesize',
'mimetype' => 'mimetype',
'course' => [
'class' => LoadedCourseLookup::class,
'properties' => ['course'],
],
],
];
}
/**
* @return array
*/
public function getLoadConfiguration()
{
return [
'class' => CourseFilesLoader::class,
];
}
}

View File

@@ -0,0 +1,64 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\MigrationMoodle\Task;
use Chamilo\PluginBundle\MigrationMoodle\Extractor\LoadedCoursesFilterExtractor;
use Chamilo\PluginBundle\MigrationMoodle\Loader\CourseIntroductionLoader;
use Chamilo\PluginBundle\MigrationMoodle\Transformer\BaseTransformer;
use Chamilo\PluginBundle\MigrationMoodle\Transformer\Property\LoadedCourseLookup;
use Chamilo\PluginBundle\MigrationMoodle\Transformer\Property\ReplaceFilePaths;
/**
* Class CourseIntroductionsTask.
*
* Migrate the first section (section 0) from a moodle course as introduction for a chamilo course.
*
* @package Chamilo\PluginBundle\MigrationMoodle\Task
*/
class CourseIntroductionsTask extends BaseTask
{
/**
* {@inheritdoc}
*/
public function getExtractConfiguration()
{
return [
'class' => LoadedCoursesFilterExtractor::class,
'query' => "SELECT id, course, name, summary
FROM mdl_course_sections
WHERE section = 0 AND (summary != '' AND summary IS NOT NULL)",
];
}
/**
* {@inheritdoc}
*/
public function getTransformConfiguration()
{
return [
'class' => BaseTransformer::class,
'map' => [
'c_id' => [
'class' => LoadedCourseLookup::class,
'properties' => ['course'],
],
'name' => 'name',
'description' => [
'class' => ReplaceFilePaths::class,
'properties' => ['summary', 'course'],
],
],
];
}
/**
* {@inheritdoc}
*/
public function getLoadConfiguration()
{
return [
'class' => CourseIntroductionLoader::class,
];
}
}

View File

@@ -0,0 +1,68 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\MigrationMoodle\Task;
use Chamilo\PluginBundle\MigrationMoodle\Extractor\LoadedCoursesFilterExtractor;
use Chamilo\PluginBundle\MigrationMoodle\Loader\CourseModulesLessonLoader;
use Chamilo\PluginBundle\MigrationMoodle\Transformer\BaseTransformer;
use Chamilo\PluginBundle\MigrationMoodle\Transformer\Property\LoadedCourseCodeLookup;
use Chamilo\PluginBundle\MigrationMoodle\Transformer\Property\LoadedCourseSectionLookup;
/**
* Class CourseModulesLessonTask.
*
* Task for convert a Moodle course module in a Chamilo learning path section.
*
* @package Chamilo\PluginBundle\MigrationMoodle\Task
*/
class CourseModulesLessonTask extends BaseTask
{
/**
* @return array
*/
public function getExtractConfiguration()
{
return [
'class' => LoadedCoursesFilterExtractor::class,
'query' => "SELECT cm.id, l.course, l.name, cm.section
FROM mdl_lesson l
INNER JOIN mdl_course_modules cm ON (l.course = cm.course AND cm.instance = l.id)
INNER JOIN mdl_modules m ON cm.module = m.id
INNER JOIN mdl_course_sections cs ON (cm.course = cs.course AND cm.section = cs.id )
WHERE m.name = 'lesson'
ORDER BY cs.id, FIND_IN_SET(cm.id, cs.sequence)",
];
}
/**
* @return array
*/
public function getTransformConfiguration()
{
return [
'class' => BaseTransformer::class,
'map' => [
'c_code' => [
'class' => LoadedCourseCodeLookup::class,
'properties' => ['course'],
],
'lp_id' => [
'class' => LoadedCourseSectionLookup::class,
'properties' => ['section'],
],
'title' => 'name',
],
];
}
/**
* @return array
*/
public function getLoadConfiguration()
{
return [
'class' => CourseModulesLessonLoader::class,
];
}
}

View File

@@ -0,0 +1,68 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\MigrationMoodle\Task;
use Chamilo\PluginBundle\MigrationMoodle\Extractor\LoadedCoursesFilterExtractor;
use Chamilo\PluginBundle\MigrationMoodle\Loader\CourseModulesQuizLoader;
use Chamilo\PluginBundle\MigrationMoodle\Transformer\BaseTransformer;
use Chamilo\PluginBundle\MigrationMoodle\Transformer\Property\LoadedCourseCodeLookup;
use Chamilo\PluginBundle\MigrationMoodle\Transformer\Property\LoadedCourseSectionLookup;
/**
* Class CourseModulesQuizTask.
*
* Task for convert a Moodle quiz inside a page section in a quiz item of Chamilo learning path.
*
* @package Chamilo\PluginBundle\MigrationMoodle\Task
*/
class CourseModulesQuizTask extends BaseTask
{
/**
* @return array
*/
public function getExtractConfiguration()
{
return [
'class' => LoadedCoursesFilterExtractor::class,
'query' => "SELECT cm.id, q.course, q.name, cm.section
FROM mdl_quiz q
INNER JOIN mdl_course_modules cm ON (q.course = cm.course AND cm.instance = q.id)
INNER JOIN mdl_modules m ON cm.module = m.id
INNER JOIN mdl_course_sections cs ON (cm.course = cs.course AND cm.section = cs.id )
WHERE m.name = 'quiz'
ORDER BY cs.id, FIND_IN_SET(cm.id, cs.sequence)",
];
}
/**
* @return array
*/
public function getTransformConfiguration()
{
return [
'class' => BaseTransformer::class,
'map' => [
'c_code' => [
'class' => LoadedCourseCodeLookup::class,
'properties' => ['course'],
],
'lp_id' => [
'class' => LoadedCourseSectionLookup::class,
'properties' => ['section'],
],
'title' => 'name',
],
];
}
/**
* @return array
*/
public function getLoadConfiguration()
{
return [
'class' => CourseModulesQuizLoader::class,
];
}
}

View File

@@ -0,0 +1,92 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\MigrationMoodle\Task;
use Chamilo\PluginBundle\MigrationMoodle\Extractor\LoadedCoursesFilterExtractor;
use Chamilo\PluginBundle\MigrationMoodle\Loader\CourseModulesScormLoader;
use Chamilo\PluginBundle\MigrationMoodle\Transformer\BaseTransformer;
use Chamilo\PluginBundle\MigrationMoodle\Transformer\Property\DateTimeObject;
use Chamilo\PluginBundle\MigrationMoodle\Transformer\Property\LoadedCourseLookup;
/**
* Class CourseModulesScormTask.
*
* Task to convert Moodle scorm in Chamilo scorm.
*
* @package Chamilo\PluginBundle\MigrationMoodle\Task
*/
class CourseModulesScormTask extends BaseTask
{
/**
* {@inheritdoc}
*/
public function getExtractConfiguration()
{
return [
'class' => LoadedCoursesFilterExtractor::class,
'query' => "SELECT
sco.id,
sco.course,
sco.name,
sco.reference,
sco.version,
sco.maxgrade,
sco.hidetoc,
i.identifier,
cm.added,
sco.timemodified
FROM mdl_scorm sco
INNER JOIN mdl_scorm_scoes i on sco.id = i.scorm
INNER JOIN mdl_course_modules cm ON (sco.course = cm.course AND cm.instance = sco.id)
INNER JOIN mdl_modules m ON cm.module = m.id
INNER JOIN mdl_course_sections cs ON (cm.course = cs.course AND cm.section = cs.id )
WHERE m.name = 'scorm'
AND i.parent = '/'
ORDER BY cs.id, FIND_IN_SET(cm.id, cs.sequence)",
];
}
/**
* {@inheritdoc}
*/
public function getTransformConfiguration()
{
return [
'class' => BaseTransformer::class,
'map' => [
'c_id' => [
'class' => LoadedCourseLookup::class,
'properties' => ['course'],
],
'name' => 'name',
'ref' => 'identifier',
'path' => 'reference',
'use_max_score' => 'maxgrade',
'hide_toc_frame' => 'hidetoc',
'created_on' => [
'class' => DateTimeObject::class,
'properties' => ['added'],
],
'modified_on' => [
'class' => DateTimeObject::class,
'properties' => ['timemodified'],
],
'publicated_on' => [
'class' => DateTimeObject::class,
'properties' => ['added'],
],
],
];
}
/**
* {@inheritdoc}
*/
public function getLoadConfiguration()
{
return [
'class' => CourseModulesScormLoader::class,
];
}
}

View File

@@ -0,0 +1,75 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\MigrationMoodle\Task;
use Chamilo\PluginBundle\MigrationMoodle\Extractor\LoadedCoursesFilterExtractor;
use Chamilo\PluginBundle\MigrationMoodle\Loader\CourseModulesUrlLoader;
use Chamilo\PluginBundle\MigrationMoodle\Transformer\BaseTransformer;
use Chamilo\PluginBundle\MigrationMoodle\Transformer\Property\LoadedCourseCodeLookup;
use Chamilo\PluginBundle\MigrationMoodle\Transformer\Property\LoadedCourseSectionLookup;
/**
* Class CourseModulesUrlTask.
*
* Task to create a Chamilo Link from a Moodle URL module.
*
* @package Chamilo\PluginBundle\MigrationMoodle\Task
*/
class CourseModulesUrlTask extends BaseTask
{
/**
* {@inheritdoc}
*/
public function getExtractConfiguration()
{
return [
'class' => LoadedCoursesFilterExtractor::class,
'query' => "SELECT cm.id, u.course, u.name, cm.section
FROM mdl_url u
INNER JOIN mdl_course_modules cm ON (u.course = cm.course AND cm.instance = u.id)
INNER JOIN mdl_modules m ON cm.module = m.id
INNER JOIN mdl_course_sections cs ON (cm.course = cs.course AND cm.section = cs.id )
WHERE m.name = 'url'
AND u.course NOT IN (
SELECT sco.course
FROM mdl_scorm sco
INNER JOIN mdl_course_modules cm ON (sco.course = cm.course AND cm.instance = sco.id)
INNER JOIN mdl_modules m ON cm.module = m.id
INNER JOIN mdl_course_sections cs ON (cm.course = cs.course AND cm.section = cs.id )
WHERE m.name = 'scorm'
)",
];
}
/**
* {@inheritdoc}
*/
public function getTransformConfiguration()
{
return [
'class' => BaseTransformer::class,
'map' => [
'c_code' => [
'class' => LoadedCourseCodeLookup::class,
'properties' => ['course'],
],
'lp_id' => [
'class' => LoadedCourseSectionLookup::class,
'properties' => ['section'],
],
'title' => 'name',
],
];
}
/**
* {@inheritdoc}
*/
public function getLoadConfiguration()
{
return [
'class' => CourseModulesUrlLoader::class,
];
}
}

View File

@@ -0,0 +1,74 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\MigrationMoodle\Task;
use Chamilo\PluginBundle\MigrationMoodle\Extractor\LoadedCoursesFilterExtractor;
use Chamilo\PluginBundle\MigrationMoodle\Loader\CourseSectionsLoader;
use Chamilo\PluginBundle\MigrationMoodle\Transformer\BaseTransformer;
use Chamilo\PluginBundle\MigrationMoodle\Transformer\Property\LoadedCourseCodeLookup;
use Chamilo\PluginBundle\MigrationMoodle\Transformer\Property\WrapHtmlReplacingFilePaths;
/**
* Class CourseSectionsTask.
*
* Task to convert Moodle course sections in a Chamilo learning paths.
* The section summary will be the first item in the learning path.
*
* @package Chamilo\PluginBundle\MigrationMoodle\Task
*/
class CourseSectionsTask extends BaseTask
{
/**
* @return array
*/
public function getExtractConfiguration()
{
return [
'class' => LoadedCoursesFilterExtractor::class,
'query' => "SELECT id, course, name, summary
FROM mdl_course_sections
WHERE section > 0 AND (name != '' OR name IS NOT NULL)
AND course NOT IN (
SELECT sco.course
FROM mdl_scorm sco
INNER JOIN mdl_course_modules cm ON (sco.course = cm.course AND cm.instance = sco.id)
INNER JOIN mdl_modules m ON cm.module = m.id
INNER JOIN mdl_course_sections cs ON (cm.course = cs.course AND cm.section = cs.id )
WHERE m.name = 'scorm'
)
ORDER BY course, section",
];
}
/**
* @return array
*/
public function getTransformConfiguration()
{
return [
'class' => BaseTransformer::class,
'map' => [
'course_code' => [
'class' => LoadedCourseCodeLookup::class,
'properties' => ['course'],
],
'name' => 'name',
'description' => [
'class' => WrapHtmlReplacingFilePaths::class,
'properties' => ['summary', 'course'],
],
],
];
}
/**
* @return array
*/
public function getLoadConfiguration()
{
return [
'class' => CourseSectionsLoader::class,
];
}
}

View File

@@ -0,0 +1,85 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\MigrationMoodle\Task;
use Chamilo\PluginBundle\MigrationMoodle\Extractor\BaseExtractor;
use Chamilo\PluginBundle\MigrationMoodle\Loader\CoursesLoader;
use Chamilo\PluginBundle\MigrationMoodle\Transformer\BaseTransformer;
use Chamilo\PluginBundle\MigrationMoodle\Transformer\Property\CourseCategoryLookup;
use Chamilo\PluginBundle\MigrationMoodle\Transformer\Property\CourseVisibility;
use Chamilo\PluginBundle\MigrationMoodle\Transformer\Property\DateTimeObject;
use Chamilo\PluginBundle\MigrationMoodle\Transformer\Property\Language;
/**
* Class CoursesTask.
*
* @package Chamilo\PluginBundle\MigrationMoodle\Task
*/
class CoursesTask extends BaseTask
{
/**
* @return array
*/
public function getExtractConfiguration()
{
$query = "SELECT * FROM mdl_course";
$userFilter = $this->plugin->getUserFilterSetting();
if (!empty($userFilter)) {
$query = "SELECT DISTINCT c.*
FROM mdl_course c
INNER JOIN mdl_context ctx ON c.id = ctx.instanceid
INNER JOIN mdl_role_assignments ra ON ctx.id = ra.contextid
INNER JOIN mdl_user u ON ra.userid = u.id
WHERE u.username LIKE '$userFilter%'";
}
return [
'class' => BaseExtractor::class,
'query' => $query,
];
}
/**
* @return array
*/
public function getTransformConfiguration()
{
return [
'class' => BaseTransformer::class,
'map' => [
'title' => 'fullname',
'wanted_code' => 'shortname',
'course_category' => [
'class' => CourseCategoryLookup::class,
'properties' => ['category'],
],
'course_language' => [
'class' => Language::class,
'properties' => ['lang'],
],
'visibility' => [
'class' => CourseVisibility::class,
'properties' => ['visible'],
],
'description' => 'summary',
'creation_date' => [
'class' => DateTimeObject::class,
'properties' => ['timecreated'],
],
],
];
}
/**
* @return array
*/
public function getLoadConfiguration()
{
return [
'class' => CoursesLoader::class,
];
}
}

View File

@@ -0,0 +1,41 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\MigrationMoodle\Task;
use Chamilo\PluginBundle\MigrationMoodle\Extractor\LoadedCoursesFilterExtractor;
/**
* Class FilesForCourseIntroductionsTask.
*
* @package Chamilo\PluginBundle\MigrationMoodle\Task
*/
class FilesForCourseIntroductionsTask extends CourseFilesTask
{
/**
* {@inheritdoc}
*/
public function getExtractConfiguration()
{
return [
'class' => LoadedCoursesFilterExtractor::class,
'query' => "SELECT
f.id,
f.contenthash,
f.filepath,
f.filename,
f.filesize,
f.mimetype,
c.id course
FROM mdl_files f
INNER JOIN mdl_context ctx ON f.contextid = ctx.id
INNER JOIN mdl_course c ON ctx.instanceid = c.id
INNER JOIN mdl_course_sections cs ON (cs.course = c.id AND cs.id = f.itemid)
WHERE f.component = 'course'
AND f.filearea = 'section'
AND ctx.contextlevel = 50
AND f.filename NOT IN ('.', '..')
AND cs.section = 0 AND (cs.summary != '' AND cs.summary IS NOT NULL)",
];
}
}

View File

@@ -0,0 +1,49 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\MigrationMoodle\Task;
use Chamilo\PluginBundle\MigrationMoodle\Extractor\LoadedCoursesFilterExtractor;
/**
* Class FilesForCourseSectionsTask.
*
* @package Chamilo\PluginBundle\MigrationMoodle\Task
*/
class FilesForCourseSectionsTask extends CourseFilesTask
{
/**
* {@inheritdoc}
*/
public function getExtractConfiguration()
{
return [
'class' => LoadedCoursesFilterExtractor::class,
'query' => "SELECT
f.id,
f.contenthash,
f.filepath,
f.filename,
f.filesize,
f.mimetype,
c.id course
FROM mdl_files f
INNER JOIN mdl_context ctx ON f.contextid = ctx.id
INNER JOIN mdl_course c ON ctx.instanceid = c.id
INNER JOIN mdl_course_sections cs ON (cs.course = c.id AND cs.id = f.itemid)
WHERE f.component = 'course'
AND f.filearea = 'section'
AND ctx.contextlevel = 50
AND f.filename NOT IN ('.', '..')
AND cs.section > 0
AND c.id NOT IN (
SELECT sco.course
FROM mdl_scorm sco
INNER JOIN mdl_course_modules cm ON (sco.course = cm.course AND cm.instance = sco.id)
INNER JOIN mdl_modules m ON cm.module = m.id
INNER JOIN mdl_course_sections cs ON (cm.course = cs.course AND cm.section = cs.id )
WHERE m.name = 'scorm'
)",
];
}
}

View File

@@ -0,0 +1,41 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\MigrationMoodle\Task;
use Chamilo\PluginBundle\MigrationMoodle\Extractor\LoadedCoursesFilterExtractor;
/**
* Class FilesForLessonAnswersTask.
*
* Task for migrate the files for Moodle lesson answers in the files for Chamilo course documents.
*
* @package Chamilo\PluginBundle\MigrationMoodle\Task
*/
class FilesForLessonAnswersTask extends CourseFilesTask
{
/**
* @return array
*/
public function getExtractConfiguration()
{
return [
'class' => LoadedCoursesFilterExtractor::class,
'query' => "SELECT
f.id,
f.contenthash,
f.filepath,
f.filename,
f.filesize,
f.mimetype,
cm.course
FROM mdl_files f
INNER JOIN mdl_context c ON f.contextid = c.id
INNER JOIN mdl_course_modules cm ON c.instanceid = cm.id
WHERE f.component = 'mod_lesson'
AND f.filearea = 'page_answers'
AND c.contextlevel = 70
AND f.filename NOT IN ('.', '..')",
];
}
}

View File

@@ -0,0 +1,41 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\MigrationMoodle\Task;
use Chamilo\PluginBundle\MigrationMoodle\Extractor\LoadedCoursesFilterExtractor;
/**
* Class FilesForLessonPagesTask.
*
* Task for migrate the files for Moodle lesson pages in the files for Chamilo course documents.
*
* @package Chamilo\PluginBundle\MigrationMoodle\Task
*/
class FilesForLessonPagesTask extends CourseFilesTask
{
/**
* @return array
*/
public function getExtractConfiguration()
{
return [
'class' => LoadedCoursesFilterExtractor::class,
'query' => "SELECT
f.id,
f.contenthash,
f.filepath,
f.filename,
f.filesize,
f.mimetype,
cm.course
FROM mdl_files f
INNER JOIN mdl_context c ON f.contextid = c.id
INNER JOIN mdl_course_modules cm ON c.instanceid = cm.id
WHERE f.component = 'mod_lesson'
AND f.filearea = 'page_contents'
AND c.contextlevel = 70
AND f.filename NOT IN ('.', '..')",
];
}
}

View File

@@ -0,0 +1,39 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\MigrationMoodle\Task;
use Chamilo\PluginBundle\MigrationMoodle\Extractor\LoadedCoursesFilterExtractor;
/**
* Class FilesForQuizzesTask.
*
* @package Chamilo\PluginBundle\MigrationMoodle\Task
*/
class FilesForQuizzesTask extends CourseFilesTask
{
/**
* @return array
*/
public function getExtractConfiguration()
{
return [
'class' => LoadedCoursesFilterExtractor::class,
'query' => "SELECT
f.id,
f.contenthash,
f.filepath,
f.filename,
f.filesize,
f.mimetype,
cm.course
FROM mdl_files f
INNER JOIN mdl_context c ON f.contextid = c.id
INNER JOIN mdl_course_modules cm ON c.instanceid = cm.id
WHERE f.component = 'mod_quiz'
AND f.filearea = 'intro'
AND c.contextlevel = 70
AND f.filename NOT IN ('.', '..')",
];
}
}

View File

@@ -0,0 +1,83 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\MigrationMoodle\Task;
use Chamilo\PluginBundle\MigrationMoodle\Extractor\LoadedCoursesFilterExtractor;
use Chamilo\PluginBundle\MigrationMoodle\Loader\FilesForScormScoLoader;
use Chamilo\PluginBundle\MigrationMoodle\Transformer\BaseTransformer;
use Chamilo\PluginBundle\MigrationMoodle\Transformer\Property\LoadedCourseLookup;
/**
* Class FilesForScormScoesTask.
*
* @package Chamilo\PluginBundle\MigrationMoodle\Task
*/
class FilesForScormScoesTask extends BaseTask
{
/**
* {@inheritdoc}
*/
public function getExtractConfiguration()
{
return [
'class' => LoadedCoursesFilterExtractor::class,
'query' => "SELECT
f.id,
f.contenthash,
f.filepath,
f.filename,
f.mimetype,
s.name scorm_name,
cm.course
FROM mdl_files f
INNER JOIN mdl_context ctx ON f.contextid = ctx.id
INNER JOIN mdl_course_modules cm ON ctx.instanceid = cm.id
INNER JOIN mdl_modules m ON cm.module = m.id
INNER JOIN mdl_scorm s ON (cm.course = s.course AND cm.instance = s.id)
WHERE
m.name = 'scorm'
AND ctx.contextlevel = 70
AND f.filename NOT IN ('.', '..')
AND s.reference != f.filename
AND f.filearea = 'content'
AND f.component = 'mod_scorm'
ORDER BY s.course, s.id",
];
}
/**
* {@inheritdoc}
*/
/**
* @return array
*/
public function getTransformConfiguration()
{
return [
'class' => BaseTransformer::class,
'map' => [
'contenthash' => 'contenthash',
'filepath' => 'filepath',
'filename' => 'filename',
'mimetype' => 'mimetype',
'c_id' => [
'class' => LoadedCourseLookup::class,
'properties' => ['course'],
],
'lp_name' => 'scorm_name',
],
];
}
/**
* {@inheritdoc}
*/
public function getLoadConfiguration()
{
return [
'class' => FilesForScormScoLoader::class,
];
}
}

View File

@@ -0,0 +1,70 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\MigrationMoodle\Task;
use Chamilo\PluginBundle\MigrationMoodle\Extractor\LoadedCoursesFilterExtractor;
use Chamilo\PluginBundle\MigrationMoodle\Loader\LessonAnswersEssayLoader;
use Chamilo\PluginBundle\MigrationMoodle\Transformer\BaseTransformer;
use Chamilo\PluginBundle\MigrationMoodle\Transformer\Property\LoadedCourseLookup;
use Chamilo\PluginBundle\MigrationMoodle\Transformer\Property\LoadedLessonPageQuizLookup;
use Chamilo\PluginBundle\MigrationMoodle\Transformer\Property\LoadedLessonPageQuizQuestionLookup;
/**
* Class LessonAnswersEssayTask.
*
* @package Chamilo\PluginBundle\MigrationMoodle\Task
*/
class LessonAnswersEssayTask extends BaseTask
{
/**
* @return array
*/
public function getExtractConfiguration()
{
return [
'class' => LoadedCoursesFilterExtractor::class,
'query' => 'SELECT la.id, la.pageid, la.score, l.course
FROM mdl_lesson_answers la
INNER JOIN mdl_lesson_pages lp ON (la.pageid = lp.id AND la.lessonid = lp.lessonid)
INNER JOIN mdl_lesson l ON (lp.lessonid = l.id AND la.lessonid = l.id)
WHERE lp.qtype = 10
ORDER BY lp.id',
];
}
/**
* @return array
*/
public function getTransformConfiguration()
{
return [
'class' => BaseTransformer::class,
'map' => [
'c_id' => [
'class' => LoadedCourseLookup::class,
'properties' => ['course'],
],
'quiz_id' => [
'class' => LoadedLessonPageQuizLookup::class,
'properties' => ['pageid'],
],
'question_id' => [
'class' => LoadedLessonPageQuizQuestionLookup::class,
'properties' => ['pageid'],
],
'score' => 'score',
],
];
}
/**
* @return array
*/
public function getLoadConfiguration()
{
return [
'class' => LessonAnswersEssayLoader::class,
];
}
}

View File

@@ -0,0 +1,83 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\MigrationMoodle\Task;
use Chamilo\PluginBundle\MigrationMoodle\Extractor\LoadedCoursesFilterExtractor;
use Chamilo\PluginBundle\MigrationMoodle\Loader\LessonAnswersMatchingLoader;
use Chamilo\PluginBundle\MigrationMoodle\Transformer\BaseTransformer;
use Chamilo\PluginBundle\MigrationMoodle\Transformer\Property\LessonAnswersMatchingScore;
use Chamilo\PluginBundle\MigrationMoodle\Transformer\Property\LoadedCourseLookup;
use Chamilo\PluginBundle\MigrationMoodle\Transformer\Property\LoadedLessonPageQuizLookup;
use Chamilo\PluginBundle\MigrationMoodle\Transformer\Property\LoadedLessonPageQuizQuestionLookup;
use Chamilo\PluginBundle\MigrationMoodle\Transformer\Property\ReplaceFilePaths;
/**
* Class LessonAnswersMatchingTask.
*
* Task to convert Matching answers from a lesson page in quiz answers for chamilo.
*
* @package Chamilo\PluginBundle\MigrationMoodle\Task
*/
class LessonAnswersMatchingTask extends BaseTask
{
/**
* @return array
*/
public function getExtractConfiguration()
{
return [
'class' => LoadedCoursesFilterExtractor::class,
'query' => "SELECT la.id, la.pageid, la.answer, la.response, la.lessonid, l.course
FROM mdl_lesson_answers la
INNER JOIN mdl_lesson_pages lp ON (la.pageid = lp.id AND la.lessonid = lp.lessonid)
INNER JOIN mdl_lesson l ON (lp.lessonid = l.id AND la.lessonid = l.id)
WHERE lp.qtype = 5
AND (la.response IS NOT NULL OR la.response != '')
ORDER BY lp.id",
];
}
/**
* @return array
*/
public function getTransformConfiguration()
{
return [
'class' => BaseTransformer::class,
'map' => [
'c_id' => [
'class' => LoadedCourseLookup::class,
'properties' => ['course'],
],
'quiz_id' => [
'class' => LoadedLessonPageQuizLookup::class,
'properties' => ['pageid'],
],
'question_id' => [
'class' => LoadedLessonPageQuizQuestionLookup::class,
'properties' => ['pageid'],
],
'score' => [
'class' => LessonAnswersMatchingScore::class,
'properties' => ['pageid', 'lessonid', 'course'],
],
'answer' => [
'class' => ReplaceFilePaths::class,
'properties' => ['answer', 'course'],
],
'feedback' => 'response',
],
];
}
/**
* @return array
*/
public function getLoadConfiguration()
{
return [
'class' => LessonAnswersMatchingLoader::class,
];
}
}

View File

@@ -0,0 +1,43 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\MigrationMoodle\Task;
use Chamilo\PluginBundle\MigrationMoodle\Extractor\LoadedCoursesFilterExtractor;
use Chamilo\PluginBundle\MigrationMoodle\Loader\LessonAnswersMultipleAnswerLoader;
/**
* Class LessonAnswersMultipleAnswerTask.
*
* Task to convert Multiple Choice answers from a Moodle lesson page in answers for Unique Answer question for Chamilo.
*
* @package Chamilo\PluginBundle\MigrationMoodle\Task
*/
class LessonAnswersMultipleAnswerTask extends LessonAnswersMultipleChoiceTask
{
/**
* @return array
*/
public function getExtractConfiguration()
{
return [
'class' => LoadedCoursesFilterExtractor::class,
'query' => 'SELECT la.id, la.pageid, la.score, la.answer, la.response, l.course
FROM mdl_lesson_answers la
INNER JOIN mdl_lesson_pages lp ON (la.pageid = lp.id AND la.lessonid = lp.lessonid)
INNER JOIN mdl_lesson l ON (lp.lessonid = l.id AND la.lessonid = l.id)
WHERE lp.qtype = 3 AND lp.qoption = 1
ORDER BY lp.id',
];
}
/**
* @return array
*/
public function getLoadConfiguration()
{
return [
'class' => LessonAnswersMultipleAnswerLoader::class,
];
}
}

View File

@@ -0,0 +1,43 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\MigrationMoodle\Task;
use Chamilo\PluginBundle\MigrationMoodle\Extractor\LoadedCoursesFilterExtractor;
use Chamilo\PluginBundle\MigrationMoodle\Loader\LessonAnswersMultipleChoiceLoader;
/**
* Class LessonAnswersMultipleChoiceTask.
*
* Task to convert Multiple Choice answers from a Moodle lesson page in answers for Unique Answer question for Chamilo.
*
* @package Chamilo\PluginBundle\MigrationMoodle\Task
*/
class LessonAnswersMultipleChoiceTask extends LessonAnswersTrueFalseTask
{
/**
* @return array
*/
public function getExtractConfiguration()
{
return [
'class' => LoadedCoursesFilterExtractor::class,
'query' => 'SELECT la.id, la.pageid, la.score, la.answer, la.response, l.course
FROM mdl_lesson_answers la
INNER JOIN mdl_lesson_pages lp ON (la.pageid = lp.id AND la.lessonid = lp.lessonid)
INNER JOIN mdl_lesson l ON (lp.lessonid = l.id AND la.lessonid = l.id)
WHERE lp.qtype = 3 AND lp.qoption = 0
ORDER BY lp.id',
];
}
/**
* @return array
*/
public function getLoadConfiguration()
{
return [
'class' => LessonAnswersMultipleChoiceLoader::class,
];
}
}

View File

@@ -0,0 +1,83 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\MigrationMoodle\Task;
use Chamilo\PluginBundle\MigrationMoodle\Extractor\LoadedCoursesFilterExtractor;
use Chamilo\PluginBundle\MigrationMoodle\Loader\LessonAnswersShortAnswerLoader;
use Chamilo\PluginBundle\MigrationMoodle\Transformer\BaseTransformer;
use Chamilo\PluginBundle\MigrationMoodle\Transformer\Property\LoadedCourseLookup;
use Chamilo\PluginBundle\MigrationMoodle\Transformer\Property\LoadedLessonPageQuizLookup;
use Chamilo\PluginBundle\MigrationMoodle\Transformer\Property\LoadedLessonPageQuizQuestionLookup;
/**
* Class LessonAnswersShortAnswerTask.
*
* Task to convert Short Answers and Numerical answers from a lesson page in quiz answers for chamilo.
*
* @package Chamilo\PluginBundle\MigrationMoodle\Task
*/
class LessonAnswersShortAnswerTask extends BaseTask
{
/**
* @return array
*/
public function getExtractConfiguration()
{
return [
'class' => LoadedCoursesFilterExtractor::class,
'query' => "SELECT
la.id,
la.pageid,
GROUP_CONCAT(la.answer SEPARATOR '||') answers,
GROUP_CONCAT(la.response SEPARATOR '') comment,
MAX(la.score) scores,
l.course,
COUNT(la.pageid) nb
FROM mdl_lesson_answers la
INNER JOIN mdl_lesson_pages lp ON (la.pageid = lp.id AND la.lessonid = lp.lessonid)
INNER JOIN mdl_lesson l ON (lp.lessonid = l.id AND la.lessonid = l.id)
WHERE lp.qtype IN (1, 8)
GROUP BY lp.id
ORDER BY lp.id",
];
}
/**
* @return array
*/
public function getTransformConfiguration()
{
return [
'class' => BaseTransformer::class,
'map' => [
'c_id' => [
'class' => LoadedCourseLookup::class,
'properties' => ['course'],
],
'quiz_id' => [
'class' => LoadedLessonPageQuizLookup::class,
'properties' => ['pageid'],
],
'question_id' => [
'class' => LoadedLessonPageQuizQuestionLookup::class,
'properties' => ['pageid'],
],
'scores' => 'scores',
'answers' => 'answers',
'comment' => 'comment',
'nb' => 'nb',
],
];
}
/**
* @return array
*/
public function getLoadConfiguration()
{
return [
'class' => LessonAnswersShortAnswerLoader::class,
];
}
}

View File

@@ -0,0 +1,85 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\MigrationMoodle\Task;
use Chamilo\PluginBundle\MigrationMoodle\Extractor\LoadedCoursesFilterExtractor;
use Chamilo\PluginBundle\MigrationMoodle\Loader\LessonAnswersTrueFalseLoader;
use Chamilo\PluginBundle\MigrationMoodle\Transformer\BaseTransformer;
use Chamilo\PluginBundle\MigrationMoodle\Transformer\Property\LoadedCourseLookup;
use Chamilo\PluginBundle\MigrationMoodle\Transformer\Property\LoadedLessonPageQuizLookup;
use Chamilo\PluginBundle\MigrationMoodle\Transformer\Property\LoadedLessonPageQuizQuestionLookup;
use Chamilo\PluginBundle\MigrationMoodle\Transformer\Property\ReplaceFilePaths;
/**
* Class LessonAnswersTrueFalseTask.
*
* Task to convert True/False answers from a lesson page in quiz answers for chamilo.
*
* @package Chamilo\PluginBundle\MigrationMoodle\Task
*/
class LessonAnswersTrueFalseTask extends BaseTask
{
/**
* @return array
*/
public function getExtractConfiguration()
{
return [
'class' => LoadedCoursesFilterExtractor::class,
'query' => 'SELECT la.id, la.pageid, la.score, la.answer, la.response, l.course,
(
SELECT MIN(id) = la.id
FROM mdl_lesson_answers
WHERE pageid = la.pageid
GROUP BY lessonid, pageid
) is_correct
FROM mdl_lesson_answers la
INNER JOIN mdl_lesson_pages lp ON (la.pageid = lp.id AND la.lessonid = lp.lessonid)
INNER JOIN mdl_lesson l ON (lp.lessonid = l.id AND la.lessonid = l.id)
WHERE lp.qtype = 2
ORDER BY lp.id',
];
}
/**
* @return array
*/
public function getTransformConfiguration()
{
return [
'class' => BaseTransformer::class,
'map' => [
'c_id' => [
'class' => LoadedCourseLookup::class,
'properties' => ['course'],
],
'quiz_id' => [
'class' => LoadedLessonPageQuizLookup::class,
'properties' => ['pageid'],
],
'question_id' => [
'class' => LoadedLessonPageQuizQuestionLookup::class,
'properties' => ['pageid'],
],
'score' => 'score',
'answer' => [
'class' => ReplaceFilePaths::class,
'properties' => ['answer', 'course'],
],
'feedback' => 'response',
'is_correct' => 'is_correct',
],
];
}
/**
* @return array
*/
public function getLoadConfiguration()
{
return [
'class' => LessonAnswersTrueFalseLoader::class,
];
}
}

View File

@@ -0,0 +1,75 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\MigrationMoodle\Task;
use Chamilo\PluginBundle\MigrationMoodle\Extractor\LoadedCoursesFilterExtractor;
use Chamilo\PluginBundle\MigrationMoodle\Loader\LessonPagesDocumentLoader;
use Chamilo\PluginBundle\MigrationMoodle\Transformer\BaseTransformer;
use Chamilo\PluginBundle\MigrationMoodle\Transformer\Property\LoadedCourseLookup;
use Chamilo\PluginBundle\MigrationMoodle\Transformer\Property\LoadedCourseSectionFromLessonLookup;
use Chamilo\PluginBundle\MigrationMoodle\Transformer\Property\LoadedLessonPageLookup;
use Chamilo\PluginBundle\MigrationMoodle\Transformer\Property\WrapHtmlReplacingFilePaths;
/**
* Class LessonPagesDocumentTask.
*
* Task for convert the Moodle lesson pages in Chamilo course documents.
*
* @package Chamilo\PluginBundle\MigrationMoodle\Task
*/
class LessonPagesDocumentTask extends BaseTask
{
/**
* @return array
*/
public function getExtractConfiguration()
{
return [
'class' => LoadedCoursesFilterExtractor::class,
'query' => 'SELECT lp.id, l.id lessonid, l.course, lp.title, lp.contents
FROM mdl_lesson_pages lp
INNER JOIN mdl_lesson l ON lp.lessonid = l.id
WHERE lp.qtype = 20',
];
}
/**
* @return array
*/
public function getTransformConfiguration()
{
return [
'class' => BaseTransformer::class,
'map' => [
'c_id' => [
'class' => LoadedCourseLookup::class,
'properties' => ['course'],
],
'lp_id' => [
'class' => LoadedCourseSectionFromLessonLookup::class,
'properties' => ['lessonid'],
],
'item_id' => [
'class' => LoadedLessonPageLookup::class,
'properties' => ['id'],
],
'item_title' => 'title',
'item_content' => [
'class' => WrapHtmlReplacingFilePaths::class,
'properties' => ['contents', 'course'],
],
],
];
}
/**
* @return array
*/
public function getLoadConfiguration()
{
return [
'class' => LessonPagesDocumentLoader::class,
];
}
}

View File

@@ -0,0 +1,77 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\MigrationMoodle\Task;
use Chamilo\PluginBundle\MigrationMoodle\Extractor\LoadedCoursesFilterExtractor;
use Chamilo\PluginBundle\MigrationMoodle\Loader\LessonQuestionPagesQuestionLoader;
use Chamilo\PluginBundle\MigrationMoodle\Transformer\BaseTransformer;
use Chamilo\PluginBundle\MigrationMoodle\Transformer\Property\LoadedCourseLookup;
use Chamilo\PluginBundle\MigrationMoodle\Transformer\Property\LoadedLessonPageQuizLookup;
use Chamilo\PluginBundle\MigrationMoodle\Transformer\Property\QuizQuestionTypeFromLessonPage;
use Chamilo\PluginBundle\MigrationMoodle\Transformer\Property\ReplaceFilePaths;
/**
* Class LessonPagesQuizQuestionTask.
*
* Task to convert the question pages from a moodle lesson in one chamilo question to be added in quiz already creadted.
*
* The types question pages are:
* 1, short answer; 2, true-false; 3, multiple choice or multiple answer; 5, matching; 8, numerical; 10, essay.
*
* @package Chamilo\PluginBundle\MigrationMoodle\Task
*/
class LessonPagesQuizQuestionTask extends BaseTask
{
/**
* @return array
*/
public function getExtractConfiguration()
{
return [
'class' => LoadedCoursesFilterExtractor::class,
'query' => 'SELECT lp.id, l.course, lp.contents, lp.qoption, lp.qtype
FROM mdl_lesson_pages lp
INNER JOIN mdl_lesson l ON lp.lessonid = l.id
WHERE lp.qtype IN (1, 2, 3, 5, 8, 10)',
];
}
/**
* @return array
*/
public function getTransformConfiguration()
{
return [
'class' => BaseTransformer::class,
'map' => [
'c_id' => [
'class' => LoadedCourseLookup::class,
'properties' => ['course'],
],
'quiz_id' => [
'class' => LoadedLessonPageQuizLookup::class,
'properties' => ['id'],
],
'question_title' => [
'class' => ReplaceFilePaths::class,
'properties' => ['contents', 'course'],
],
'question_type' => [
'class' => QuizQuestionTypeFromLessonPage::class,
'properties' => ['qtype', 'qoption'],
],
],
];
}
/**
* @return array
*/
public function getLoadConfiguration()
{
return [
'class' => LessonQuestionPagesQuestionLoader::class,
];
}
}

View File

@@ -0,0 +1,65 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\MigrationMoodle\Task;
use Chamilo\PluginBundle\MigrationMoodle\Extractor\LoadedCoursesFilterExtractor;
use Chamilo\PluginBundle\MigrationMoodle\Loader\LessonQuestionPagesQuizLoader;
use Chamilo\PluginBundle\MigrationMoodle\Transformer\BaseTransformer;
use Chamilo\PluginBundle\MigrationMoodle\Transformer\Property\LoadedCourseLookup;
use Chamilo\PluginBundle\MigrationMoodle\Transformer\Property\LoadedLessonPageLookup;
/**
* Class LessonPagesQuizTask.
*
* Task to convert the question pages from a moodle lesson in one chamilo quiz with one question.
*
* @package Chamilo\PluginBundle\MigrationMoodle\Task
*/
class LessonPagesQuizTask extends BaseTask
{
/**
* @return array
*/
public function getExtractConfiguration()
{
return [
'class' => LoadedCoursesFilterExtractor::class,
'query' => 'SELECT lp.id, l.course, lp.title
FROM mdl_lesson_pages lp
INNER JOIN mdl_lesson l ON lp.lessonid = l.id
WHERE lp.qtype IN (1, 2, 3, 5, 8, 10)',
];
}
/**
* @return array
*/
public function getTransformConfiguration()
{
return [
'class' => BaseTransformer::class,
'map' => [
'c_id' => [
'class' => LoadedCourseLookup::class,
'properties' => ['course'],
],
'item_id' => [
'class' => LoadedLessonPageLookup::class,
'properties' => ['id'],
],
'item_title' => 'title',
],
];
}
/**
* @return array
*/
public function getLoadConfiguration()
{
return [
'class' => LessonQuestionPagesQuizLoader::class,
];
}
}

View File

@@ -0,0 +1,104 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\MigrationMoodle\Task;
use Chamilo\PluginBundle\MigrationMoodle\Extractor\LoadedCoursesFilterExtractor;
use Chamilo\PluginBundle\MigrationMoodle\Loader\LessonPagesLoader;
use Chamilo\PluginBundle\MigrationMoodle\Transformer\BaseTransformer;
use Chamilo\PluginBundle\MigrationMoodle\Transformer\Property\LessonPageType;
use Chamilo\PluginBundle\MigrationMoodle\Transformer\Property\LoadedCourseCodeLookup;
use Chamilo\PluginBundle\MigrationMoodle\Transformer\Property\LoadedCourseModuleLessonLookup;
use Chamilo\PluginBundle\MigrationMoodle\Transformer\Property\LoadedCourseSectionFromLessonLookup;
use Chamilo\PluginBundle\MigrationMoodle\Transformer\Property\LoadedLessonPageLookup;
/**
* Class LessonPagesTask.
*
* Task to conver the Moodle lesson pages in items for Chamilo learning paths.
*
* @package Chamilo\PluginBundle\MigrationMoodle\Task
*/
class LessonPagesTask extends BaseTask
{
public const TYPE_END_BRANCH = 21;
public const TYPE_CLUSTER = 30;
public const TYPE_END_CLUSTER = 31;
/**
* @return array
*/
public function getExtractConfiguration()
{
return [
'class' => LoadedCoursesFilterExtractor::class,
'query' => "WITH RECURSIVE lesson_pages_ordered (id, title, qtype, prev, next, lesson, display_order) AS
(
SELECT id, title, qtype, prevpageid, nextpageid, lessonid, '01'
FROM mdl_lesson_pages
WHERE prevpageid = 0
UNION
SELECT lp.id, lp.title, lp.qtype, lp.prevpageid, lp.nextpageid, lp.lessonid, lpo.display_order + 1
FROM lesson_pages_ordered lpo
LEFT JOIN mdl_lesson_pages lp
ON (lpo.next = lp.id AND lpo.lesson = lp.lessonid)
)
SELECT
lpo.id,
lpo.title,
lpo.qtype,
lpo.prev,
lpo.lesson,
CAST(lpo.display_order AS SIGNED) lpo_display_order,
l.course
FROM lesson_pages_ordered lpo
INNER JOIN mdl_lesson l ON lpo.lesson = l.id
WHERE lpo.qtype NOT IN (".self::TYPE_END_BRANCH.", ".self::TYPE_CLUSTER.", ".self::TYPE_END_CLUSTER.")
ORDER BY l.course, lpo.lesson, lpo_display_order",
];
}
/**
* @return array
*/
public function getTransformConfiguration()
{
return [
'class' => BaseTransformer::class,
'map' => [
'c_code' => [
'class' => LoadedCourseCodeLookup::class,
'properties' => ['course'],
],
'lp_id' => [
'class' => LoadedCourseSectionFromLessonLookup::class,
'properties' => ['lesson'],
],
'parent' => [
'class' => LoadedCourseModuleLessonLookup::class,
'properties' => ['lesson'],
],
'previous' => [
'class' => LoadedLessonPageLookup::class,
'properties' => ['prev'],
],
'item_type' => [
'class' => LessonPageType::class,
'properties' => ['qtype'],
],
'title' => 'title',
'display_order' => 'lpo_display_order',
],
];
}
/**
* @return array
*/
public function getLoadConfiguration()
{
return [
'class' => LessonPagesLoader::class,
];
}
}

View File

@@ -0,0 +1,62 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\MigrationMoodle\Task;
use Chamilo\PluginBundle\MigrationMoodle\Extractor\BaseExtractor;
use Chamilo\PluginBundle\MigrationMoodle\Loader\QuestionCategoriesLoader;
use Chamilo\PluginBundle\MigrationMoodle\Transformer\BaseTransformer;
use Chamilo\PluginBundle\MigrationMoodle\Transformer\Property\LoadedCourseFromQuestionCategoryLookup;
/**
* Class QuestionCategoriesTask.
*
* Task for create categories for Chamilo quiz questions coming from a Moodle questions categories.
*
* @package Chamilo\PluginBundle\MigrationMoodle\Task
*/
class QuestionCategoriesTask extends BaseTask
{
/**
* @return array
*/
public function getExtractConfiguration()
{
return [
'class' => BaseExtractor::class,
'query' => "SELECT qc.id, qc.name, qc.info, c.contextlevel, c.instanceid
FROM mdl_question_categories qc
INNER JOIN mdl_context c ON qc.contextid = c.id
WHERE c.contextlevel IN (50, 70)
AND qc.parent != 0",
];
}
/**
* @return array
*/
public function getTransformConfiguration()
{
return [
'class' => BaseTransformer::class,
'map' => [
'c_id' => [
'class' => LoadedCourseFromQuestionCategoryLookup::class,
'properties' => ['contextlevel', 'instanceid'],
],
'name' => 'name',
'description' => 'info',
],
];
}
/**
* @return array
*/
public function getLoadConfiguration()
{
return [
'class' => QuestionCategoriesLoader::class,
];
}
}

View File

@@ -0,0 +1,90 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\MigrationMoodle\Task;
use Chamilo\PluginBundle\MigrationMoodle\Extractor\LoadedCoursesFilterExtractor;
use Chamilo\PluginBundle\MigrationMoodle\Loader\QuestionGapselectLoader;
use Chamilo\PluginBundle\MigrationMoodle\Transformer\BaseTransformer;
use Chamilo\PluginBundle\MigrationMoodle\Transformer\Property\LoadedCourseLookup;
use Chamilo\PluginBundle\MigrationMoodle\Transformer\Property\LoadedQuestionLookup;
use Chamilo\PluginBundle\MigrationMoodle\Transformer\Property\LoadedQuizLookup;
use Chamilo\PluginBundle\MigrationMoodle\Transformer\Property\QuestionGapselectAnswer;
/**
* Class QuestionGapselectTask.
*
* @package Chamilo\PluginBundle\MigrationMoodle\Task
*/
class QuestionGapselectTask extends BaseTask
{
/**
* {@inheritdoc}
*/
public function getExtractConfiguration()
{
return [
'class' => LoadedCoursesFilterExtractor::class,
'query' => "SELECT
qa.id,
qq.id,
qa.question,
GROUP_CONCAT(
CONCAT(qa.feedback, '==>>', qa.answer) ORDER BY qa.id ASC SEPARATOR '@||@'
) answers,
qq.questiontext,
qs.maxmark,
qg.correctfeedback,
q.id quiz_id,
q.course
FROM mdl_question_answers qa
INNER JOIN mdl_question qq ON qa.question = qq.id
INNER JOIN mdl_question_gapselect qg ON qq.id = qg.questionid
INNER JOIN mdl_quiz_slots qs ON qq.id = qs.questionid
INNER JOIN mdl_quiz q ON qs.quizid = q.id
WHERE qq.qtype = 'gapselect'
GROUP BY q.id, qq.id
ORDER BY q.id, qq.id",
];
}
/**
* {@inheritdoc}
*/
public function getTransformConfiguration()
{
return [
'class' => BaseTransformer::class,
'map' => [
'c_id' => [
'class' => LoadedCourseLookup::class,
'properties' => ['course'],
],
'quiz_id' => [
'class' => LoadedQuizLookup::class,
'properties' => ['quiz_id'],
],
'question_id' => [
'class' => LoadedQuestionLookup::class,
'properties' => ['question'],
],
'answer' => [
'class' => QuestionGapselectAnswer::class,
'properties' => ['answers', 'questiontext', 'maxmark'],
],
'score' => 'maxmark',
'comment' => 'correctfeedback',
],
];
}
/**
* {@inheritdoc}
*/
public function getLoadConfiguration()
{
return [
'class' => QuestionGapselectLoader::class,
];
}
}

View File

@@ -0,0 +1,51 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\MigrationMoodle\Task;
use Chamilo\PluginBundle\MigrationMoodle\Extractor\LoadedCoursesFilterExtractor;
use Chamilo\PluginBundle\MigrationMoodle\Loader\LessonAnswersMultipleAnswerLoader;
/**
* Class QuestionMultiChoiceMultipleTask.
*
* @package Chamilo\PluginBundle\MigrationMoodle\Task
*/
class QuestionMultiChoiceMultipleTask extends QuestionMultiChoiceSingleTask
{
/**
* {@inheritdoc}
*/
public function getExtractConfiguration()
{
return [
'class' => LoadedCoursesFilterExtractor::class,
'query' => "SELECT
qa.id,
qa.question,
qa.answer,
qa.feedback,
(qa.fraction * qq.defaultmark) score,
IF (qa.fraction > 0, TRUE, FALSE) is_correct,
q.id quizid,
q.course
FROM mdl_question_answers qa
INNER JOIN mdl_question qq ON qa.question = qq.id
INNER JOIN mdl_qtype_multichoice_options qo ON qq.id = qo.questionid
INNER JOIN mdl_quiz_slots qs ON qq.id = qs.questionid
INNER JOIN mdl_quiz q ON qs.quizid = q.id
WHERE qq.qtype = 'multichoice'
AND qo.single = 0",
];
}
/**
* {@inheritdoc}
*/
public function getLoadConfiguration()
{
return [
'class' => LessonAnswersMultipleAnswerLoader::class,
];
}
}

View File

@@ -0,0 +1,92 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\MigrationMoodle\Task;
use Chamilo\PluginBundle\MigrationMoodle\Extractor\LoadedCoursesFilterExtractor;
use Chamilo\PluginBundle\MigrationMoodle\Loader\LessonAnswersMultipleChoiceLoader;
use Chamilo\PluginBundle\MigrationMoodle\Transformer\BaseTransformer;
use Chamilo\PluginBundle\MigrationMoodle\Transformer\Property\LoadedCourseLookup;
use Chamilo\PluginBundle\MigrationMoodle\Transformer\Property\LoadedLessonPageQuizLookup;
use Chamilo\PluginBundle\MigrationMoodle\Transformer\Property\LoadedQuestionLookup;
use Chamilo\PluginBundle\MigrationMoodle\Transformer\Property\ReplaceFilePaths;
/**
* Class QuestionMultiChoiceSingleTask.
*
* Task to convert Moodle question answers of multichoice type in Chamilo unique/multiple answers.
*
* @package Chamilo\PluginBundle\MigrationMoodle\Task
*/
class QuestionMultiChoiceSingleTask extends BaseTask
{
/**
* {@inheritdoc}
*/
public function getExtractConfiguration()
{
return [
'class' => LoadedCoursesFilterExtractor::class,
'query' => "SELECT
qa.id,
qa.question,
qa.answer,
qa.feedback,
(qa.fraction * qq.defaultmark) score,
IF (qa.fraction = 1, TRUE, FALSE) is_correct,
q.id quizid,
q.course
FROM mdl_question_answers qa
INNER JOIN mdl_question qq ON qa.question = qq.id
INNER JOIN mdl_qtype_multichoice_options qo ON qq.id = qo.questionid
INNER JOIN mdl_quiz_slots qs ON qq.id = qs.questionid
INNER JOIN mdl_quiz q ON qs.quizid = q.id
WHERE qq.qtype = 'multichoice'
AND qo.single = 1",
];
}
/**
* {@inheritdoc}
*/
public function getTransformConfiguration()
{
return [
'class' => BaseTransformer::class,
'map' => [
'c_id' => [
'class' => LoadedCourseLookup::class,
'properties' => ['course'],
],
'quiz_id' => [
'class' => LoadedLessonPageQuizLookup::class,
'properties' => ['quizid'],
],
'question_id' => [
'class' => LoadedQuestionLookup::class,
'properties' => ['question'],
],
'score' => 'score',
'answer' => [
'class' => ReplaceFilePaths::class,
'properties' => ['answer', 'course'],
],
'feedback' => [
'class' => ReplaceFilePaths::class,
'properties' => ['feedback', 'course'],
],
'is_correct' => 'is_correct',
],
];
}
/**
* {@inheritdoc}
*/
public function getLoadConfiguration()
{
return [
'class' => LessonAnswersMultipleChoiceLoader::class,
];
}
}

View File

@@ -0,0 +1,73 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\MigrationMoodle\Task;
use Chamilo\PluginBundle\MigrationMoodle\Extractor\LoadedCoursesFilterExtractor;
use Chamilo\PluginBundle\MigrationMoodle\Transformer\BaseTransformer;
use Chamilo\PluginBundle\MigrationMoodle\Transformer\Property\LoadedCourseLookup;
use Chamilo\PluginBundle\MigrationMoodle\Transformer\Property\LoadedLessonPageQuizLookup;
use Chamilo\PluginBundle\MigrationMoodle\Transformer\Property\LoadedQuestionLookup;
/**
* Class QuestionShortAnswerTask.
*
* @package Chamilo\PluginBundle\MigrationMoodle\Task
*/
class QuestionShortAnswerTask extends LessonAnswersShortAnswerTask
{
/**
* {@inheritdoc}
*/
public function getExtractConfiguration()
{
return [
'class' => LoadedCoursesFilterExtractor::class,
'query' => "SELECT
qa.id,
qa.question,
GROUP_CONCAT(qa.answer SEPARATOR '||') answers,
qq.defaultmark,
GROUP_CONCAT(qa.feedback SEPARATOR '\n') feedback,
COUNT(qa.id) nb,
q.id quizid,
q.course
FROM mdl_question_answers qa
INNER JOIN mdl_question qq ON qa.question = qq.id
INNER JOIN mdl_qtype_shortanswer_options qo ON qq.id = qo.questionid
INNER JOIN mdl_quiz_slots qs ON qq.id = qs.questionid
INNER JOIN mdl_quiz q ON qs.quizid = q.id
WHERE qq.qtype = 'shortanswer'
GROUP BY qq.id
ORDER BY q.course, qq.id",
];
}
/**
* {@inheritdoc}
*/
public function getTransformConfiguration()
{
return [
'class' => BaseTransformer::class,
'map' => [
'c_id' => [
'class' => LoadedCourseLookup::class,
'properties' => ['course'],
],
'quiz_id' => [
'class' => LoadedLessonPageQuizLookup::class,
'properties' => ['quizid'],
],
'question_id' => [
'class' => LoadedQuestionLookup::class,
'properties' => ['question'],
],
'scores' => 'defaultmark',
'answers' => 'answers',
'comment' => 'feedback',
'nb' => 'nb',
],
];
}
}

View File

@@ -0,0 +1,76 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\MigrationMoodle\Task;
use Chamilo\PluginBundle\MigrationMoodle\Extractor\LoadedCoursesFilterExtractor;
use Chamilo\PluginBundle\MigrationMoodle\Loader\LessonQuestionPagesQuestionLoader;
use Chamilo\PluginBundle\MigrationMoodle\Transformer\BaseTransformer;
use Chamilo\PluginBundle\MigrationMoodle\Transformer\Property\LoadedCourseLookup;
use Chamilo\PluginBundle\MigrationMoodle\Transformer\Property\LoadedQuizLookup;
use Chamilo\PluginBundle\MigrationMoodle\Transformer\Property\QuestionType;
use Chamilo\PluginBundle\MigrationMoodle\Transformer\Property\ReplaceFilePaths;
/**
* Class QuestionsTask.
*
* @package Chamilo\PluginBundle\MigrationMoodle\Task
*/
class QuestionsTask extends BaseTask
{
/**
* @return array
*/
public function getExtractConfiguration()
{
return [
'class' => LoadedCoursesFilterExtractor::class,
'query' => "SELECT qq.id, qq.category, qq.questiontext, qq.qtype, q.course, q.id quiz_id
FROM mdl_question qq
INNER JOIN mdl_quiz_slots qs ON qq.id = qs.questionid
INNER JOIN mdl_quiz q ON qs.quizid = q.id
INNER JOIN mdl_course_modules cm ON (q.course = cm.course AND cm.instance = q.id)
INNER JOIN mdl_modules m ON cm.module = m.id
INNER JOIN mdl_course_sections cs ON (cm.course = cs.course AND cm.section = cs.id )
WHERE m.name = 'quiz'",
];
}
/**
* @return array
*/
public function getTransformConfiguration()
{
return [
'class' => BaseTransformer::class,
'map' => [
'c_id' => [
'class' => LoadedCourseLookup::class,
'properties' => ['course'],
],
'quiz_id' => [
'class' => LoadedQuizLookup::class,
'properties' => ['quiz_id'],
],
'question_title' => [
'class' => ReplaceFilePaths::class,
'properties' => ['questiontext', 'course'],
],
'question_type' => [
'class' => QuestionType::class,
'properties' => ['qtype', 'id'],
],
],
];
}
/**
* @return array
*/
public function getLoadConfiguration()
{
return [
'class' => LessonQuestionPagesQuestionLoader::class,
];
}
}

Some files were not shown because too many files have changed in this diff Show More