prepareActivityDirectory($exportDir, 'forum', $effectiveModuleId); $forumData = $this->getData((int) $activityId, (int) $sectionId, $effectiveModuleId); if (empty($forumData)) { return; } $this->createForumXml($forumData, $forumDir); $this->createModuleXml($forumData, $forumDir); $this->createGradesXml($forumData, $forumDir); $this->createGradeHistoryXml($forumData, $forumDir); $this->createInforefXml($forumData, $forumDir); $this->createRolesXml($forumData, $forumDir); $this->createCalendarXml($forumData, $forumDir); $this->createCommentsXml($forumData, $forumDir); $this->createCompetenciesXml($forumData, $forumDir); $this->createFiltersXml($forumData, $forumDir); } /** * Get all forum data from the course. */ public function getData(int $forumId, int $sectionId, ?int $moduleId = null): ?array { if (empty($this->course->resources[RESOURCE_FORUM][$forumId])) { return null; } $forum = $this->course->resources[RESOURCE_FORUM][$forumId]->obj; $effectiveModuleId = (int) ($moduleId ?? $forumId); if ($effectiveModuleId <= 0) { $effectiveModuleId = $forumId; } $adminData = MoodleExport::getAdminUserData(); $adminId = (int) ($adminData['id'] ?? 1); $name = (string) ($forum->forum_title ?? ''); if ($sectionId > 0) { $name = $this->lpItemTitle($sectionId, RESOURCE_FORUM, $forumId, $name); } $name = $this->sanitizeMoodleActivityName($name, 255); $descriptionResult = $this->extractEmbeddedFilesAndNormalizeContent( (string) ($forum->forum_comment ?? ''), $effectiveModuleId, 'mod_forum', 'intro', 0, fn (int $sequence): int => $this->buildForumEmbeddedFileId() ); $forumFiles = $descriptionResult['files']; $threads = []; $threadResources = $this->course->resources['thread'] ?? []; $postResources = $this->course->resources['post'] ?? []; foreach ($threadResources as $threadId => $thread) { if ((int) ($thread->obj->forum_id ?? 0) !== $forumId) { continue; } $threadPosts = []; foreach ($postResources as $post) { if ((int) ($post->obj->thread_id ?? 0) !== (int) $threadId) { continue; } $postId = (int) ($post->obj->post_id ?? 0); $postDate = strtotime((string) ($post->obj->post_date ?? 'now')); if ($postDate === false) { $postDate = time(); } $messageResult = $this->extractEmbeddedFilesAndNormalizeContent( (string) ($post->obj->post_text ?? ''), $effectiveModuleId, 'mod_forum', 'post', $postId, fn (int $sequence): int => $this->buildForumEmbeddedFileId() ); if (!empty($messageResult['files'])) { $forumFiles = array_merge($forumFiles, $messageResult['files']); } $threadPosts[] = [ 'id' => $postId, 'userid' => $adminId, 'message' => $messageResult['content'], 'created' => $postDate, 'modified' => $postDate, ]; } usort($threadPosts, static function (array $a, array $b): int { return ((int) $a['created']) <=> ((int) $b['created']); }); $firstPostId = 0; foreach ($threadPosts as $index => &$postData) { if ($index === 0) { $firstPostId = (int) $postData['id']; $postData['parent'] = 0; } else { $postData['parent'] = $firstPostId; } $postData['mailed'] = 0; $postData['subject'] = (string) ($thread->obj->thread_title ?? get_lang('Forum')); } unset($postData); $threadDate = strtotime((string) ($thread->obj->thread_date ?? 'now')); if ($threadDate === false) { $threadDate = time(); } $threads[] = [ 'id' => (int) ($thread->obj->thread_id ?? 0), 'title' => (string) ($thread->obj->thread_title ?? ''), 'firstpost' => $firstPostId, 'userid' => $adminId, 'timemodified' => $threadDate, 'usermodified' => $adminId, 'posts' => $threadPosts, ]; } return [ 'id' => $forumId, 'moduleid' => $effectiveModuleId, 'modulename' => 'forum', 'contextid' => $effectiveModuleId, 'name' => $name, 'description' => $descriptionResult['content'], 'timecreated' => time(), 'timemodified' => time(), 'sectionid' => $sectionId, 'sectionnumber' => 1, 'userid' => $adminId, 'threads' => $threads, 'users' => [$adminId], 'files' => $forumFiles, ]; } /** * Create the forum.xml file with all forum data. */ private function createForumXml(array $forumData, string $forumDir): void { $xmlContent = ''.PHP_EOL; $xmlContent .= ''.PHP_EOL; $xmlContent .= ' '.PHP_EOL; $xmlContent .= ' general'.PHP_EOL; $xmlContent .= ' '.htmlspecialchars((string) $forumData['name']).''.PHP_EOL; $xmlContent .= ' '.PHP_EOL; $xmlContent .= ' 1'.PHP_EOL; $xmlContent .= ' 0'.PHP_EOL; $xmlContent .= ' 0'.PHP_EOL; $xmlContent .= ' 0'.PHP_EOL; $xmlContent .= ' 0'.PHP_EOL; $xmlContent .= ' 0'.PHP_EOL; $xmlContent .= ' 100'.PHP_EOL; $xmlContent .= ' 512000'.PHP_EOL; $xmlContent .= ' 9'.PHP_EOL; $xmlContent .= ' 0'.PHP_EOL; $xmlContent .= ' 1'.PHP_EOL; $xmlContent .= ' 0'.PHP_EOL; $xmlContent .= ' 0'.PHP_EOL; $xmlContent .= ' '.$forumData['timemodified'].''.PHP_EOL; $xmlContent .= ' 0'.PHP_EOL; $xmlContent .= ' 0'.PHP_EOL; $xmlContent .= ' 0'.PHP_EOL; $xmlContent .= ' 0'.PHP_EOL; $xmlContent .= ' 0'.PHP_EOL; $xmlContent .= ' 0'.PHP_EOL; $xmlContent .= ' 0'.PHP_EOL; $xmlContent .= ' 0'.PHP_EOL; $xmlContent .= ' 0'.PHP_EOL; $xmlContent .= ' '.PHP_EOL; foreach ($forumData['threads'] as $thread) { $xmlContent .= ' '.PHP_EOL; $xmlContent .= ' '.htmlspecialchars((string) $thread['title']).''.PHP_EOL; $xmlContent .= ' '.(int) ($thread['firstpost'] ?? 0).''.PHP_EOL; $xmlContent .= ' '.$thread['userid'].''.PHP_EOL; $xmlContent .= ' -1'.PHP_EOL; $xmlContent .= ' 0'.PHP_EOL; $xmlContent .= ' '.$thread['timemodified'].''.PHP_EOL; $xmlContent .= ' '.$thread['usermodified'].''.PHP_EOL; $xmlContent .= ' 0'.PHP_EOL; $xmlContent .= ' 0'.PHP_EOL; $xmlContent .= ' 0'.PHP_EOL; $xmlContent .= ' 0'.PHP_EOL; $xmlContent .= ' '.PHP_EOL; foreach ($thread['posts'] as $post) { $xmlContent .= ' '.PHP_EOL; $xmlContent .= ' '.(int) ($post['parent'] ?? 0).''.PHP_EOL; $xmlContent .= ' '.$post['userid'].''.PHP_EOL; $xmlContent .= ' '.$post['created'].''.PHP_EOL; $xmlContent .= ' '.$post['modified'].''.PHP_EOL; $xmlContent .= ' '.(int) ($post['mailed'] ?? 0).''.PHP_EOL; $xmlContent .= ' '.htmlspecialchars((string) ($post['subject'] ?? '')).''.PHP_EOL; $xmlContent .= ' '.PHP_EOL; $xmlContent .= ' 1'.PHP_EOL; $xmlContent .= ' 0'.PHP_EOL; $xmlContent .= ' '.PHP_EOL; $xmlContent .= ' 0'.PHP_EOL; $xmlContent .= ' 0'.PHP_EOL; $xmlContent .= ' 0'.PHP_EOL; $xmlContent .= ' '.PHP_EOL; $xmlContent .= ' '.PHP_EOL; $xmlContent .= ' '.PHP_EOL; } $xmlContent .= ' '.PHP_EOL; $xmlContent .= ' '.PHP_EOL; $xmlContent .= ' '.PHP_EOL; $xmlContent .= ' '.$thread['userid'].''.PHP_EOL; $xmlContent .= ' '.$thread['timemodified'].''.PHP_EOL; $xmlContent .= ' '.PHP_EOL; $xmlContent .= ' '.PHP_EOL; $xmlContent .= ' '.PHP_EOL; } $xmlContent .= ' '.PHP_EOL; $xmlContent .= ' '.PHP_EOL; $xmlContent .= ''; $this->createXmlFile('forum', $xmlContent, $forumDir); } /** * Build a stable embedded file id for forum files. */ private function buildForumEmbeddedFileId(): int { self::$embeddedFileGlobalSeq++; return 1400000000 + self::$embeddedFileGlobalSeq; } }