From 715eec9ce29dc637c480b796ad4ca1d473395145 Mon Sep 17 00:00:00 2001 From: Christian Beeznest Date: Thu, 11 Jun 2026 22:23:51 -0500 Subject: [PATCH 1/2] Add legacy migration support structures --- .../Entity/AutomaticUnregistration.php | 88 ++++++ src/CoreBundle/Entity/UserSessionTracking.php | 73 +++++ .../Schema/V210/Version20260611183000.php | 253 ++++++++++++++++++ .../Entity/CForumThreadComment.php | 105 ++++++++ src/CourseBundle/Entity/CLpSchedule.php | 88 ++++++ src/CourseBundle/Entity/CLpView.php | 16 ++ src/CourseBundle/Entity/CTrackProgress.php | 89 ++++++ 7 files changed, 712 insertions(+) create mode 100644 src/CoreBundle/Entity/AutomaticUnregistration.php create mode 100644 src/CoreBundle/Entity/UserSessionTracking.php create mode 100644 src/CoreBundle/Migrations/Schema/V210/Version20260611183000.php create mode 100644 src/CourseBundle/Entity/CForumThreadComment.php create mode 100644 src/CourseBundle/Entity/CLpSchedule.php create mode 100644 src/CourseBundle/Entity/CTrackProgress.php diff --git a/src/CoreBundle/Entity/AutomaticUnregistration.php b/src/CoreBundle/Entity/AutomaticUnregistration.php new file mode 100644 index 00000000000..f3be7578b43 --- /dev/null +++ b/src/CoreBundle/Entity/AutomaticUnregistration.php @@ -0,0 +1,88 @@ +id; + } + + public function getUserId(): int + { + return $this->userId; + } + + public function setUserId(int $userId): self + { + $this->userId = $userId; + + return $this; + } + + public function getCourseId(): int + { + return $this->courseId; + } + + public function setCourseId(int $courseId): self + { + $this->courseId = $courseId; + + return $this; + } + + public function getDateDeleted(): string + { + return $this->dateDeleted; + } + + public function setDateDeleted(string $dateDeleted): self + { + $this->dateDeleted = $dateDeleted; + + return $this; + } + + public function getLastAccess(): string + { + return $this->lastAccess; + } + + public function setLastAccess(string $lastAccess): self + { + $this->lastAccess = $lastAccess; + + return $this; + } +} diff --git a/src/CoreBundle/Entity/UserSessionTracking.php b/src/CoreBundle/Entity/UserSessionTracking.php new file mode 100644 index 00000000000..07ca01862c5 --- /dev/null +++ b/src/CoreBundle/Entity/UserSessionTracking.php @@ -0,0 +1,73 @@ + 1])] + protected int $isActive = 1; + + public function getTrackingId(): ?string + { + return $this->trackingId; + } + + public function getUserId(): string + { + return $this->userId; + } + + public function setUserId(string|int $userId): self + { + $this->userId = (string) $userId; + + return $this; + } + + public function getSessionTime(): string + { + return $this->sessionTime; + } + + public function setSessionTime(string $sessionTime): self + { + $this->sessionTime = $sessionTime; + + return $this; + } + + public function getIsActive(): int + { + return $this->isActive; + } + + public function setIsActive(int $isActive): self + { + $this->isActive = $isActive; + + return $this; + } +} diff --git a/src/CoreBundle/Migrations/Schema/V210/Version20260611183000.php b/src/CoreBundle/Migrations/Schema/V210/Version20260611183000.php new file mode 100644 index 00000000000..7a132312dd2 --- /dev/null +++ b/src/CoreBundle/Migrations/Schema/V210/Version20260611183000.php @@ -0,0 +1,253 @@ +addLpViewCompletionDate($schema); + $this->createTrackProgressTable($schema); + $this->createLpScheduleTable($schema); + $this->createForumThreadCommentTable($schema); + $this->createUserSessionTrackingTable($schema); + $this->createAutomaticUnregistrationTable($schema); + $this->createTrackEExercisesBackupTable($schema); + $this->createQuizQuestionNoDuplicatesTable($schema); + } + + public function down(Schema $schema): void + { + // Intentionally left empty. + // + // These structures can contain migrated legal/tracking/certificate evidence. + // Dropping them in a rollback could delete imported legacy data. + } + + private function addLpViewCompletionDate(Schema $schema): void + { + if (!$schema->hasTable('c_lp_view')) { + return; + } + + $table = $schema->getTable('c_lp_view'); + + if (!$table->hasColumn('compdate')) { + $this->addSql('ALTER TABLE c_lp_view ADD compdate DATE DEFAULT NULL'); + } + } + + private function createTrackProgressTable(Schema $schema): void + { + if ($schema->hasTable('track_progress')) { + $table = $schema->getTable('track_progress'); + + if (!$table->hasIndex('idx_track_progress_course_user_lp')) { + $this->addSql('CREATE INDEX idx_track_progress_course_user_lp ON track_progress (cId, userId, lpId)'); + } + + if (!$table->hasIndex('idx_track_progress_lp')) { + $this->addSql('CREATE INDEX idx_track_progress_lp ON track_progress (lpId)'); + } + + return; + } + + $this->addSql(<<<'SQL' +CREATE TABLE track_progress ( + progressId BIGINT AUTO_INCREMENT NOT NULL, + cId INT NOT NULL, + userId BIGINT NOT NULL, + lpId INT NOT NULL, + complete VARCHAR(250) NOT NULL, + INDEX idx_track_progress_course_user_lp (cId, userId, lpId), + INDEX idx_track_progress_lp (lpId), + PRIMARY KEY(progressId) +) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB ROW_FORMAT = DYNAMIC +SQL); + } + + private function createLpScheduleTable(Schema $schema): void + { + if ($schema->hasTable('paramedic')) { + $table = $schema->getTable('paramedic'); + + if (!$table->hasIndex('idx_lp_schedule_course_lp')) { + $this->addSql('CREATE INDEX idx_lp_schedule_course_lp ON paramedic (cId, lpId)'); + } + + return; + } + + $this->addSql(<<<'SQL' +CREATE TABLE paramedic ( + id INT AUTO_INCREMENT NOT NULL, + cId BIGINT NOT NULL, + lpId BIGINT NOT NULL, + title VARCHAR(100) DEFAULT NULL, + weekofday VARCHAR(100) DEFAULT NULL, + INDEX idx_lp_schedule_course_lp (cId, lpId), + PRIMARY KEY(id) +) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB ROW_FORMAT = DYNAMIC +SQL); + } + + private function createForumThreadCommentTable(Schema $schema): void + { + if ($schema->hasTable('message_comment')) { + $table = $schema->getTable('message_comment'); + + if (!$table->hasIndex('idx_message_comment_forum_thread')) { + $this->addSql('CREATE INDEX idx_message_comment_forum_thread ON message_comment (forum_id, thread_id)'); + } + + if (!$table->hasIndex('idx_message_comment_receiver')) { + $this->addSql('CREATE INDEX idx_message_comment_receiver ON message_comment (receiver_id)'); + } + + if (!$table->hasIndex('idx_message_comment_sender')) { + $this->addSql('CREATE INDEX idx_message_comment_sender ON message_comment (sender_id)'); + } + + return; + } + + $this->addSql(<<<'SQL' +CREATE TABLE message_comment ( + id BIGINT AUTO_INCREMENT NOT NULL, + sender_id BIGINT NOT NULL, + receiver_id BIGINT NOT NULL, + forum_id BIGINT NOT NULL, + thread_id BIGINT NOT NULL, + comment BLOB NOT NULL, + INDEX idx_message_comment_forum_thread (forum_id, thread_id), + INDEX idx_message_comment_receiver (receiver_id), + INDEX idx_message_comment_sender (sender_id), + PRIMARY KEY(id) +) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB ROW_FORMAT = DYNAMIC +SQL); + } + + private function createUserSessionTrackingTable(Schema $schema): void + { + if ($schema->hasTable('tracking_user')) { + $table = $schema->getTable('tracking_user'); + + if (!$table->hasIndex('idx_user_session_tracking_user_active')) { + $this->addSql('CREATE INDEX idx_user_session_tracking_user_active ON tracking_user (userId, isActive)'); + } + + return; + } + + $this->addSql(<<<'SQL' +CREATE TABLE tracking_user ( + trackingId BIGINT AUTO_INCREMENT NOT NULL, + userId BIGINT NOT NULL, + sessionTime VARCHAR(200) NOT NULL, + isActive INT NOT NULL DEFAULT 1, + INDEX idx_user_session_tracking_user_active (userId, isActive), + PRIMARY KEY(trackingId) +) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB ROW_FORMAT = DYNAMIC +SQL); + } + + private function createAutomaticUnregistrationTable(Schema $schema): void + { + if ($schema->hasTable('unregister_automatic')) { + $table = $schema->getTable('unregister_automatic'); + + if (!$table->hasIndex('idx_automatic_unregistration_user_course')) { + $this->addSql('CREATE INDEX idx_automatic_unregistration_user_course ON unregister_automatic (userId, cId)'); + } + + return; + } + + $this->addSql(<<<'SQL' +CREATE TABLE unregister_automatic ( + id BIGINT AUTO_INCREMENT NOT NULL, + userId INT NOT NULL, + cId INT NOT NULL, + dateDeleted VARCHAR(500) NOT NULL, + lastaccess VARCHAR(500) NOT NULL, + INDEX idx_automatic_unregistration_user_course (userId, cId), + PRIMARY KEY(id) +) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB ROW_FORMAT = DYNAMIC +SQL); + } + + private function createTrackEExercisesBackupTable(Schema $schema): void + { + if ($schema->hasTable('track_e_exercises_backup')) { + return; + } + + $this->addSql(<<<'SQL' +CREATE TABLE track_e_exercises_backup ( + exe_id INT AUTO_INCREMENT NOT NULL, + exe_user_id INT DEFAULT NULL, + exe_date DATETIME NOT NULL, + c_id INT NOT NULL, + exe_exo_id INT NOT NULL, + exe_result DOUBLE PRECISION NOT NULL, + exe_weighting DOUBLE PRECISION NOT NULL, + user_ip VARCHAR(39) NOT NULL, + status VARCHAR(20) NOT NULL, + data_tracking LONGTEXT NOT NULL, + start_date DATETIME NOT NULL, + steps_counter SMALLINT NOT NULL, + session_id SMALLINT NOT NULL, + orig_lp_id INT NOT NULL, + orig_lp_item_id INT NOT NULL, + exe_duration INT NOT NULL, + expired_time_control DATETIME DEFAULT NULL, + orig_lp_item_view_id INT NOT NULL, + questions_to_check LONGTEXT NOT NULL, + INDEX idx_exercises_backup_user (exe_user_id), + INDEX idx_exercises_backup_course (c_id), + INDEX idx_exercises_backup_session (session_id), + PRIMARY KEY(exe_id) +) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB ROW_FORMAT = DYNAMIC +SQL); + } + + private function createQuizQuestionNoDuplicatesTable(Schema $schema): void + { + if ($schema->hasTable('c_quiz_question_noduplicates')) { + return; + } + + $this->addSql(<<<'SQL' +CREATE TABLE c_quiz_question_noduplicates ( + iid INT AUTO_INCREMENT NOT NULL, + c_id INT NOT NULL, + id INT DEFAULT NULL, + question LONGTEXT NOT NULL, + description LONGTEXT DEFAULT NULL, + ponderation DOUBLE PRECISION NOT NULL DEFAULT 0, + position INT NOT NULL, + type TINYINT NOT NULL, + picture VARCHAR(50) DEFAULT NULL, + level INT NOT NULL, + extra VARCHAR(255) DEFAULT NULL, + question_code VARCHAR(10) DEFAULT NULL, + INDEX idx_question_nodup_course (c_id), + INDEX idx_question_nodup_position (position), + PRIMARY KEY(iid) +) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB ROW_FORMAT = DYNAMIC +SQL); + } +} diff --git a/src/CourseBundle/Entity/CForumThreadComment.php b/src/CourseBundle/Entity/CForumThreadComment.php new file mode 100644 index 00000000000..6f62ef7cd98 --- /dev/null +++ b/src/CourseBundle/Entity/CForumThreadComment.php @@ -0,0 +1,105 @@ +id; + } + + public function getSenderId(): string + { + return $this->senderId; + } + + public function setSenderId(string|int $senderId): self + { + $this->senderId = (string) $senderId; + + return $this; + } + + public function getReceiverId(): string + { + return $this->receiverId; + } + + public function setReceiverId(string|int $receiverId): self + { + $this->receiverId = (string) $receiverId; + + return $this; + } + + public function getForumId(): string + { + return $this->forumId; + } + + public function setForumId(string|int $forumId): self + { + $this->forumId = (string) $forumId; + + return $this; + } + + public function getThreadId(): string + { + return $this->threadId; + } + + public function setThreadId(string|int $threadId): self + { + $this->threadId = (string) $threadId; + + return $this; + } + + public function getComment(): mixed + { + return $this->comment; + } + + public function setComment(mixed $comment): self + { + $this->comment = $comment; + + return $this; + } +} diff --git a/src/CourseBundle/Entity/CLpSchedule.php b/src/CourseBundle/Entity/CLpSchedule.php new file mode 100644 index 00000000000..3ee75105383 --- /dev/null +++ b/src/CourseBundle/Entity/CLpSchedule.php @@ -0,0 +1,88 @@ +id; + } + + public function getCourseId(): string + { + return $this->courseId; + } + + public function setCourseId(string|int $courseId): self + { + $this->courseId = (string) $courseId; + + return $this; + } + + public function getLpId(): string + { + return $this->lpId; + } + + public function setLpId(string|int $lpId): self + { + $this->lpId = (string) $lpId; + + return $this; + } + + public function getTitle(): ?string + { + return $this->title; + } + + public function setTitle(?string $title): self + { + $this->title = $title; + + return $this; + } + + public function getWeekOfDay(): ?string + { + return $this->weekOfDay; + } + + public function setWeekOfDay(?string $weekOfDay): self + { + $this->weekOfDay = $weekOfDay; + + return $this; + } +} diff --git a/src/CourseBundle/Entity/CLpView.php b/src/CourseBundle/Entity/CLpView.php index 83b4b90d650..f8b8ee81437 100644 --- a/src/CourseBundle/Entity/CLpView.php +++ b/src/CourseBundle/Entity/CLpView.php @@ -9,6 +9,7 @@ use Chamilo\CoreBundle\Entity\Course; use Chamilo\CoreBundle\Entity\Session; use Chamilo\CoreBundle\Entity\User; +use DateTimeInterface; use Doctrine\ORM\Mapping as ORM; /** @@ -51,6 +52,9 @@ class CLpView #[ORM\Column(name: 'progress', type: 'integer', nullable: true)] protected ?int $progress = null; + #[ORM\Column(name: 'compdate', type: 'date', nullable: true)] + protected ?DateTimeInterface $completionDate = null; + public function getIid(): ?int { return $this->iid; @@ -107,6 +111,18 @@ public function getProgress() return $this->progress; } + public function getCompletionDate(): ?DateTimeInterface + { + return $this->completionDate; + } + + public function setCompletionDate(?DateTimeInterface $completionDate): self + { + $this->completionDate = $completionDate; + + return $this; + } + public function getLp(): CLp { return $this->lp; diff --git a/src/CourseBundle/Entity/CTrackProgress.php b/src/CourseBundle/Entity/CTrackProgress.php new file mode 100644 index 00000000000..db4fb42f784 --- /dev/null +++ b/src/CourseBundle/Entity/CTrackProgress.php @@ -0,0 +1,89 @@ +progressId; + } + + public function getCourseId(): int + { + return $this->courseId; + } + + public function setCourseId(int $courseId): self + { + $this->courseId = $courseId; + + return $this; + } + + public function getUserId(): string + { + return $this->userId; + } + + public function setUserId(string|int $userId): self + { + $this->userId = (string) $userId; + + return $this; + } + + public function getLpId(): int + { + return $this->lpId; + } + + public function setLpId(int $lpId): self + { + $this->lpId = $lpId; + + return $this; + } + + public function getComplete(): string + { + return $this->complete; + } + + public function setComplete(string $complete): self + { + $this->complete = $complete; + + return $this; + } +} From 22d0bba7693564d8cc4107e6318755e694ce282f Mon Sep 17 00:00:00 2001 From: Christian Beeznest Date: Fri, 12 Jun 2026 11:29:54 -0500 Subject: [PATCH 2/2] Move legacy support structures to GradingElectronic plugin --- .../src/GradingElectronicPlugin.php | 74 ++++++ .../Entity/AutomaticUnregistration.php | 88 ------- src/CoreBundle/Entity/UserSessionTracking.php | 73 ------ .../Schema/V210/Version20260611183000.php | 224 +----------------- .../Entity/CForumThreadComment.php | 105 -------- src/CourseBundle/Entity/CLpSchedule.php | 88 ------- src/CourseBundle/Entity/CTrackProgress.php | 89 ------- 7 files changed, 78 insertions(+), 663 deletions(-) delete mode 100644 src/CoreBundle/Entity/AutomaticUnregistration.php delete mode 100644 src/CoreBundle/Entity/UserSessionTracking.php delete mode 100644 src/CourseBundle/Entity/CForumThreadComment.php delete mode 100644 src/CourseBundle/Entity/CLpSchedule.php delete mode 100644 src/CourseBundle/Entity/CTrackProgress.php diff --git a/public/plugin/GradingElectronic/src/GradingElectronicPlugin.php b/public/plugin/GradingElectronic/src/GradingElectronicPlugin.php index 946334e9312..48e58380446 100644 --- a/public/plugin/GradingElectronic/src/GradingElectronicPlugin.php +++ b/public/plugin/GradingElectronic/src/GradingElectronicPlugin.php @@ -45,6 +45,7 @@ public static function create() public function install() { $this->setUpExtraFields(); + $this->setUpDatabaseTables(); } /** @@ -801,6 +802,79 @@ private function setDownExtraFields() } + /** + * Create plugin-specific migration support tables. + * + * These tables keep custom grading/tracking structures outside the core schema. + * They intentionally use generic plugin table names instead of the legacy table names. + */ + private function setUpDatabaseTables(): void + { + Database::query(<<<'SQL' +CREATE TABLE IF NOT EXISTS plugin_grading_electronic_lp_completion ( + id BIGINT AUTO_INCREMENT NOT NULL, + course_id INT NOT NULL, + user_id BIGINT NOT NULL, + lp_id INT NOT NULL, + completion_status VARCHAR(250) NOT NULL, + INDEX idx_pge_lp_completion_course_user_lp (course_id, user_id, lp_id), + INDEX idx_pge_lp_completion_lp (lp_id), + PRIMARY KEY(id) +) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB ROW_FORMAT = DYNAMIC +SQL); + + Database::query(<<<'SQL' +CREATE TABLE IF NOT EXISTS plugin_grading_electronic_lp_schedule ( + id INT AUTO_INCREMENT NOT NULL, + course_id BIGINT NOT NULL, + lp_id BIGINT NOT NULL, + title VARCHAR(100) DEFAULT NULL, + week_day VARCHAR(100) DEFAULT NULL, + INDEX idx_pge_lp_schedule_course_lp (course_id, lp_id), + PRIMARY KEY(id) +) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB ROW_FORMAT = DYNAMIC +SQL); + + Database::query(<<<'SQL' +CREATE TABLE IF NOT EXISTS plugin_grading_electronic_forum_thread_comment ( + id BIGINT AUTO_INCREMENT NOT NULL, + sender_user_id BIGINT NOT NULL, + receiver_user_id BIGINT NOT NULL, + forum_id BIGINT NOT NULL, + thread_id BIGINT NOT NULL, + comment BLOB NOT NULL, + INDEX idx_pge_forum_thread_comment_forum_thread (forum_id, thread_id), + INDEX idx_pge_forum_thread_comment_receiver (receiver_user_id), + INDEX idx_pge_forum_thread_comment_sender (sender_user_id), + PRIMARY KEY(id) +) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB ROW_FORMAT = DYNAMIC +SQL); + + Database::query(<<<'SQL' +CREATE TABLE IF NOT EXISTS plugin_grading_electronic_user_session_tracking ( + id BIGINT AUTO_INCREMENT NOT NULL, + user_id BIGINT NOT NULL, + session_time VARCHAR(200) NOT NULL, + is_active INT NOT NULL DEFAULT 1, + INDEX idx_pge_user_session_tracking_user_active (user_id, is_active), + PRIMARY KEY(id) +) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB ROW_FORMAT = DYNAMIC +SQL); + + Database::query(<<<'SQL' +CREATE TABLE IF NOT EXISTS plugin_grading_electronic_unregistration_log ( + id BIGINT AUTO_INCREMENT NOT NULL, + user_id INT NOT NULL, + course_id INT NOT NULL, + deleted_at_legacy VARCHAR(500) NOT NULL, + last_access_legacy VARCHAR(500) NOT NULL, + INDEX idx_pge_unregistration_user_course (user_id, course_id), + PRIMARY KEY(id) +) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB ROW_FORMAT = DYNAMIC +SQL); + } + + private function getCurrentPluginRegion(): string { $requestUri = $_SERVER['REQUEST_URI'] ?? ''; diff --git a/src/CoreBundle/Entity/AutomaticUnregistration.php b/src/CoreBundle/Entity/AutomaticUnregistration.php deleted file mode 100644 index f3be7578b43..00000000000 --- a/src/CoreBundle/Entity/AutomaticUnregistration.php +++ /dev/null @@ -1,88 +0,0 @@ -id; - } - - public function getUserId(): int - { - return $this->userId; - } - - public function setUserId(int $userId): self - { - $this->userId = $userId; - - return $this; - } - - public function getCourseId(): int - { - return $this->courseId; - } - - public function setCourseId(int $courseId): self - { - $this->courseId = $courseId; - - return $this; - } - - public function getDateDeleted(): string - { - return $this->dateDeleted; - } - - public function setDateDeleted(string $dateDeleted): self - { - $this->dateDeleted = $dateDeleted; - - return $this; - } - - public function getLastAccess(): string - { - return $this->lastAccess; - } - - public function setLastAccess(string $lastAccess): self - { - $this->lastAccess = $lastAccess; - - return $this; - } -} diff --git a/src/CoreBundle/Entity/UserSessionTracking.php b/src/CoreBundle/Entity/UserSessionTracking.php deleted file mode 100644 index 07ca01862c5..00000000000 --- a/src/CoreBundle/Entity/UserSessionTracking.php +++ /dev/null @@ -1,73 +0,0 @@ - 1])] - protected int $isActive = 1; - - public function getTrackingId(): ?string - { - return $this->trackingId; - } - - public function getUserId(): string - { - return $this->userId; - } - - public function setUserId(string|int $userId): self - { - $this->userId = (string) $userId; - - return $this; - } - - public function getSessionTime(): string - { - return $this->sessionTime; - } - - public function setSessionTime(string $sessionTime): self - { - $this->sessionTime = $sessionTime; - - return $this; - } - - public function getIsActive(): int - { - return $this->isActive; - } - - public function setIsActive(int $isActive): self - { - $this->isActive = $isActive; - - return $this; - } -} diff --git a/src/CoreBundle/Migrations/Schema/V210/Version20260611183000.php b/src/CoreBundle/Migrations/Schema/V210/Version20260611183000.php index 7a132312dd2..3215e1736ac 100644 --- a/src/CoreBundle/Migrations/Schema/V210/Version20260611183000.php +++ b/src/CoreBundle/Migrations/Schema/V210/Version20260611183000.php @@ -13,30 +13,10 @@ final class Version20260611183000 extends AbstractMigrationChamilo { public function getDescription(): string { - return 'Add legacy migration support structures for LP progress, forum comments and tracking.'; + return 'Add learning path completion date support.'; } public function up(Schema $schema): void - { - $this->addLpViewCompletionDate($schema); - $this->createTrackProgressTable($schema); - $this->createLpScheduleTable($schema); - $this->createForumThreadCommentTable($schema); - $this->createUserSessionTrackingTable($schema); - $this->createAutomaticUnregistrationTable($schema); - $this->createTrackEExercisesBackupTable($schema); - $this->createQuizQuestionNoDuplicatesTable($schema); - } - - public function down(Schema $schema): void - { - // Intentionally left empty. - // - // These structures can contain migrated legal/tracking/certificate evidence. - // Dropping them in a rollback could delete imported legacy data. - } - - private function addLpViewCompletionDate(Schema $schema): void { if (!$schema->hasTable('c_lp_view')) { return; @@ -49,205 +29,9 @@ private function addLpViewCompletionDate(Schema $schema): void } } - private function createTrackProgressTable(Schema $schema): void - { - if ($schema->hasTable('track_progress')) { - $table = $schema->getTable('track_progress'); - - if (!$table->hasIndex('idx_track_progress_course_user_lp')) { - $this->addSql('CREATE INDEX idx_track_progress_course_user_lp ON track_progress (cId, userId, lpId)'); - } - - if (!$table->hasIndex('idx_track_progress_lp')) { - $this->addSql('CREATE INDEX idx_track_progress_lp ON track_progress (lpId)'); - } - - return; - } - - $this->addSql(<<<'SQL' -CREATE TABLE track_progress ( - progressId BIGINT AUTO_INCREMENT NOT NULL, - cId INT NOT NULL, - userId BIGINT NOT NULL, - lpId INT NOT NULL, - complete VARCHAR(250) NOT NULL, - INDEX idx_track_progress_course_user_lp (cId, userId, lpId), - INDEX idx_track_progress_lp (lpId), - PRIMARY KEY(progressId) -) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB ROW_FORMAT = DYNAMIC -SQL); - } - - private function createLpScheduleTable(Schema $schema): void - { - if ($schema->hasTable('paramedic')) { - $table = $schema->getTable('paramedic'); - - if (!$table->hasIndex('idx_lp_schedule_course_lp')) { - $this->addSql('CREATE INDEX idx_lp_schedule_course_lp ON paramedic (cId, lpId)'); - } - - return; - } - - $this->addSql(<<<'SQL' -CREATE TABLE paramedic ( - id INT AUTO_INCREMENT NOT NULL, - cId BIGINT NOT NULL, - lpId BIGINT NOT NULL, - title VARCHAR(100) DEFAULT NULL, - weekofday VARCHAR(100) DEFAULT NULL, - INDEX idx_lp_schedule_course_lp (cId, lpId), - PRIMARY KEY(id) -) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB ROW_FORMAT = DYNAMIC -SQL); - } - - private function createForumThreadCommentTable(Schema $schema): void - { - if ($schema->hasTable('message_comment')) { - $table = $schema->getTable('message_comment'); - - if (!$table->hasIndex('idx_message_comment_forum_thread')) { - $this->addSql('CREATE INDEX idx_message_comment_forum_thread ON message_comment (forum_id, thread_id)'); - } - - if (!$table->hasIndex('idx_message_comment_receiver')) { - $this->addSql('CREATE INDEX idx_message_comment_receiver ON message_comment (receiver_id)'); - } - - if (!$table->hasIndex('idx_message_comment_sender')) { - $this->addSql('CREATE INDEX idx_message_comment_sender ON message_comment (sender_id)'); - } - - return; - } - - $this->addSql(<<<'SQL' -CREATE TABLE message_comment ( - id BIGINT AUTO_INCREMENT NOT NULL, - sender_id BIGINT NOT NULL, - receiver_id BIGINT NOT NULL, - forum_id BIGINT NOT NULL, - thread_id BIGINT NOT NULL, - comment BLOB NOT NULL, - INDEX idx_message_comment_forum_thread (forum_id, thread_id), - INDEX idx_message_comment_receiver (receiver_id), - INDEX idx_message_comment_sender (sender_id), - PRIMARY KEY(id) -) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB ROW_FORMAT = DYNAMIC -SQL); - } - - private function createUserSessionTrackingTable(Schema $schema): void - { - if ($schema->hasTable('tracking_user')) { - $table = $schema->getTable('tracking_user'); - - if (!$table->hasIndex('idx_user_session_tracking_user_active')) { - $this->addSql('CREATE INDEX idx_user_session_tracking_user_active ON tracking_user (userId, isActive)'); - } - - return; - } - - $this->addSql(<<<'SQL' -CREATE TABLE tracking_user ( - trackingId BIGINT AUTO_INCREMENT NOT NULL, - userId BIGINT NOT NULL, - sessionTime VARCHAR(200) NOT NULL, - isActive INT NOT NULL DEFAULT 1, - INDEX idx_user_session_tracking_user_active (userId, isActive), - PRIMARY KEY(trackingId) -) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB ROW_FORMAT = DYNAMIC -SQL); - } - - private function createAutomaticUnregistrationTable(Schema $schema): void - { - if ($schema->hasTable('unregister_automatic')) { - $table = $schema->getTable('unregister_automatic'); - - if (!$table->hasIndex('idx_automatic_unregistration_user_course')) { - $this->addSql('CREATE INDEX idx_automatic_unregistration_user_course ON unregister_automatic (userId, cId)'); - } - - return; - } - - $this->addSql(<<<'SQL' -CREATE TABLE unregister_automatic ( - id BIGINT AUTO_INCREMENT NOT NULL, - userId INT NOT NULL, - cId INT NOT NULL, - dateDeleted VARCHAR(500) NOT NULL, - lastaccess VARCHAR(500) NOT NULL, - INDEX idx_automatic_unregistration_user_course (userId, cId), - PRIMARY KEY(id) -) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB ROW_FORMAT = DYNAMIC -SQL); - } - - private function createTrackEExercisesBackupTable(Schema $schema): void - { - if ($schema->hasTable('track_e_exercises_backup')) { - return; - } - - $this->addSql(<<<'SQL' -CREATE TABLE track_e_exercises_backup ( - exe_id INT AUTO_INCREMENT NOT NULL, - exe_user_id INT DEFAULT NULL, - exe_date DATETIME NOT NULL, - c_id INT NOT NULL, - exe_exo_id INT NOT NULL, - exe_result DOUBLE PRECISION NOT NULL, - exe_weighting DOUBLE PRECISION NOT NULL, - user_ip VARCHAR(39) NOT NULL, - status VARCHAR(20) NOT NULL, - data_tracking LONGTEXT NOT NULL, - start_date DATETIME NOT NULL, - steps_counter SMALLINT NOT NULL, - session_id SMALLINT NOT NULL, - orig_lp_id INT NOT NULL, - orig_lp_item_id INT NOT NULL, - exe_duration INT NOT NULL, - expired_time_control DATETIME DEFAULT NULL, - orig_lp_item_view_id INT NOT NULL, - questions_to_check LONGTEXT NOT NULL, - INDEX idx_exercises_backup_user (exe_user_id), - INDEX idx_exercises_backup_course (c_id), - INDEX idx_exercises_backup_session (session_id), - PRIMARY KEY(exe_id) -) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB ROW_FORMAT = DYNAMIC -SQL); - } - - private function createQuizQuestionNoDuplicatesTable(Schema $schema): void + public function down(Schema $schema): void { - if ($schema->hasTable('c_quiz_question_noduplicates')) { - return; - } - - $this->addSql(<<<'SQL' -CREATE TABLE c_quiz_question_noduplicates ( - iid INT AUTO_INCREMENT NOT NULL, - c_id INT NOT NULL, - id INT DEFAULT NULL, - question LONGTEXT NOT NULL, - description LONGTEXT DEFAULT NULL, - ponderation DOUBLE PRECISION NOT NULL DEFAULT 0, - position INT NOT NULL, - type TINYINT NOT NULL, - picture VARCHAR(50) DEFAULT NULL, - level INT NOT NULL, - extra VARCHAR(255) DEFAULT NULL, - question_code VARCHAR(10) DEFAULT NULL, - INDEX idx_question_nodup_course (c_id), - INDEX idx_question_nodup_position (position), - PRIMARY KEY(iid) -) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB ROW_FORMAT = DYNAMIC -SQL); + // Intentionally left empty. + // The completion date can be part of migrated tracking/legal evidence. } } diff --git a/src/CourseBundle/Entity/CForumThreadComment.php b/src/CourseBundle/Entity/CForumThreadComment.php deleted file mode 100644 index 6f62ef7cd98..00000000000 --- a/src/CourseBundle/Entity/CForumThreadComment.php +++ /dev/null @@ -1,105 +0,0 @@ -id; - } - - public function getSenderId(): string - { - return $this->senderId; - } - - public function setSenderId(string|int $senderId): self - { - $this->senderId = (string) $senderId; - - return $this; - } - - public function getReceiverId(): string - { - return $this->receiverId; - } - - public function setReceiverId(string|int $receiverId): self - { - $this->receiverId = (string) $receiverId; - - return $this; - } - - public function getForumId(): string - { - return $this->forumId; - } - - public function setForumId(string|int $forumId): self - { - $this->forumId = (string) $forumId; - - return $this; - } - - public function getThreadId(): string - { - return $this->threadId; - } - - public function setThreadId(string|int $threadId): self - { - $this->threadId = (string) $threadId; - - return $this; - } - - public function getComment(): mixed - { - return $this->comment; - } - - public function setComment(mixed $comment): self - { - $this->comment = $comment; - - return $this; - } -} diff --git a/src/CourseBundle/Entity/CLpSchedule.php b/src/CourseBundle/Entity/CLpSchedule.php deleted file mode 100644 index 3ee75105383..00000000000 --- a/src/CourseBundle/Entity/CLpSchedule.php +++ /dev/null @@ -1,88 +0,0 @@ -id; - } - - public function getCourseId(): string - { - return $this->courseId; - } - - public function setCourseId(string|int $courseId): self - { - $this->courseId = (string) $courseId; - - return $this; - } - - public function getLpId(): string - { - return $this->lpId; - } - - public function setLpId(string|int $lpId): self - { - $this->lpId = (string) $lpId; - - return $this; - } - - public function getTitle(): ?string - { - return $this->title; - } - - public function setTitle(?string $title): self - { - $this->title = $title; - - return $this; - } - - public function getWeekOfDay(): ?string - { - return $this->weekOfDay; - } - - public function setWeekOfDay(?string $weekOfDay): self - { - $this->weekOfDay = $weekOfDay; - - return $this; - } -} diff --git a/src/CourseBundle/Entity/CTrackProgress.php b/src/CourseBundle/Entity/CTrackProgress.php deleted file mode 100644 index db4fb42f784..00000000000 --- a/src/CourseBundle/Entity/CTrackProgress.php +++ /dev/null @@ -1,89 +0,0 @@ -progressId; - } - - public function getCourseId(): int - { - return $this->courseId; - } - - public function setCourseId(int $courseId): self - { - $this->courseId = $courseId; - - return $this; - } - - public function getUserId(): string - { - return $this->userId; - } - - public function setUserId(string|int $userId): self - { - $this->userId = (string) $userId; - - return $this; - } - - public function getLpId(): int - { - return $this->lpId; - } - - public function setLpId(int $lpId): self - { - $this->lpId = $lpId; - - return $this; - } - - public function getComplete(): string - { - return $this->complete; - } - - public function setComplete(string $complete): self - { - $this->complete = $complete; - - return $this; - } -}