Passed
Pull Request — master (#6894)
by
unknown
09:02
created

ForumExport::createForumXml()   B

Complexity

Conditions 5
Paths 9

Size

Total Lines 98
Code Lines 81

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 5
eloc 81
c 1
b 0
f 0
nc 9
nop 2
dl 0
loc 98
rs 8.1034

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
declare(strict_types=1);
4
5
/* For licensing terms, see /license.txt */
6
7
namespace Chamilo\CourseBundle\Component\CourseCopy\Moodle\Activities;
8
9
use Chamilo\CourseBundle\Component\CourseCopy\Moodle\Builder\MoodleExport;
10
11
use const PHP_EOL;
12
13
/**
14
 * Handles the export of forums within a course.
15
 */
16
class ForumExport extends ActivityExport
17
{
18
    /**
19
     * Export all forum data into a single Moodle forum activity.
20
     *
21
     * @param int    $activityId the ID of the forum
22
     * @param string $exportDir  destination base directory of the export
23
     * @param int    $moduleId   module id used to name the activity folder
24
     * @param int    $sectionId  moodle section id where the activity will live
25
     */
26
    public function export($activityId, $exportDir, $moduleId, $sectionId): void
27
    {
28
        $forumDir = $this->prepareActivityDirectory($exportDir, 'forum', (int) $moduleId);
29
        $forumData = $this->getData((int) $activityId, (int) $sectionId);
30
31
        $this->createForumXml($forumData, $forumDir);
32
        $this->createModuleXml($forumData, $forumDir);
33
        $this->createGradesXml($forumData, $forumDir);
34
        $this->createGradeHistoryXml($forumData, $forumDir);
35
        $this->createInforefXml($forumData, $forumDir);
36
        $this->createRolesXml($forumData, $forumDir);
37
        $this->createCalendarXml($forumData, $forumDir);
38
        $this->createCommentsXml($forumData, $forumDir);
39
        $this->createCompetenciesXml($forumData, $forumDir);
40
        $this->createFiltersXml($forumData, $forumDir);
41
    }
42
43
    /**
44
     * Build all forum data from the course resources.
45
     */
46
    public function getData(int $forumId, int $sectionId): array
47
    {
48
        $forumRes = $this->course->resources['forum'][$forumId] ?? null;
49
        $forumObj = $forumRes ? ($forumRes->obj ?? null) : null;
50
51
        $adminData = MoodleExport::getAdminUserData();
52
        $adminId = (int) ($adminData['id'] ?? 0);
53
54
        $catId = 0;
55
        $catTitle = '';
56
        if ($forumObj) {
57
            $catId = (int) ($forumObj->forum_category ?? $forumObj->forum_category_id ?? $forumObj->category_id ?? 0);
58
        }
59
        if ($catId > 0) {
60
            $catRes = $this->course->resources['Forum_Category'][$catId]
61
                ?? $this->course->resources['forum_category'][$catId]
62
                ?? null;
63
            if ($catRes) {
64
                $src = $catRes->obj ?? $catRes;
65
                $catTitle = (string) ($src->cat_title ?? $src->title ?? '');
66
            }
67
        }
68
69
        $threads = [];
70
        if (!empty($this->course->resources['thread'])) {
71
            foreach ($this->course->resources['thread'] as $threadId => $thread) {
72
                if (($thread->obj->forum_id ?? null) != $forumId) {
73
                    continue;
74
                }
75
76
                // Collect posts for this thread
77
                $posts = [];
78
                if (!empty($this->course->resources['post'])) {
79
                    foreach ($this->course->resources['post'] as $postId => $post) {
80
                        if (($post->obj->thread_id ?? null) == $threadId) {
81
                            $created = strtotime((string) ($post->obj->post_date ?? 'now'));
82
                            $msg = (string) ($post->obj->post_text ?? '');
83
                            $posts[] = [
84
                                'id' => (int) ($post->obj->post_id ?? $postId),
85
                                'parent' => (int) ($post->obj->parent_id ?? 0),
86
                                'userid' => $adminId,
87
                                'created' => $created,
88
                                'modified' => $created,
89
                                'mailed' => 0,
90
                                'subject' => $this->buildPostSubject($post->obj->post_title ?? '', $msg),
91
                                'message' => $msg,
92
                            ];
93
                        }
94
                    }
95
                }
96
97
                // Determine first post id (Moodle expects it)
98
                $firstpostId = 0;
99
                if (!empty($posts)) {
100
                    usort($posts, static fn ($a, $b) => $a['created'] <=> $b['created']);
101
                    $firstpostId = (int) $posts[0]['id'];
102
                }
103
104
                $threads[] = [
105
                    'id' => (int) ($thread->obj->thread_id ?? $threadId),
106
                    'title' => (string) ($thread->obj->thread_title ?? 'Discussion'),
107
                    'userid' => $adminId,
108
                    'timemodified' => strtotime((string) ($thread->obj->thread_date ?? 'now')),
109
                    'usermodified' => $adminId,
110
                    'firstpost' => $firstpostId,
111
                    'posts' => $posts,
112
                ];
113
            }
114
        }
115
116
        return [
117
            'id' => $forumId,
118
            'moduleid' => $forumId,
119
            'modulename' => 'forum',
120
            'contextid' => (int) ($this->course->info['real_id'] ?? 0),
121
            'name' => (string) ($forumObj->forum_title ?? 'Forum'),
122
            'description' => (string) ($forumObj->forum_comment ?? ''),
123
            'category_id' => $catId,
124
            'category_title' => $catTitle,
125
            'timecreated' => time(),
126
            'timemodified' => time(),
127
            'sectionid' => $sectionId,
128
            'sectionnumber' => 1,
129
            'userid' => $adminId,
130
            'threads' => $threads,
131
            'users' => [$adminId],
132
            'files' => [],
133
        ];
134
    }
135
136
    /**
137
     * Helper to build a short subject when none is provided.
138
     * Uses the post title, else a trimmed version of the message.
139
     */
140
    private function buildPostSubject(string $title, string $message): string
141
    {
142
        // Prefer explicit title
143
        $subject = trim($title);
144
        if ('' !== $subject) {
145
            return $subject;
146
        }
147
148
        // Fallback: derive from message
149
        $plain = trim(strip_tags($message));
150
        if ('' === $plain) {
151
            return 'Post';
152
        }
153
        $short = mb_substr($plain, 0, 80);
154
155
        return $short.(mb_strlen($plain) > 80 ? '…' : '');
156
    }
157
158
    /**
159
     * Write forum.xml including discussions and posts.
160
     */
161
    private function createForumXml(array $forumData, string $forumDir): void
162
    {
163
        // ----- intro with category hints (mirrors UrlExport) -----
164
        $intro = (string) $forumData['description'];
165
        if (!empty($forumData['category_id'])) {
166
            $intro .= "\n<!-- CHAMILO2:forum_category_id:{$forumData['category_id']} -->";
167
            if (!empty($forumData['category_title'])) {
168
                $intro .= "\n<!-- CHAMILO2:forum_category_title:".
169
                    htmlspecialchars((string) $forumData['category_title']).' -->';
170
            }
171
        }
172
        $introCdata = '<![CDATA['.$intro.']]>';
173
174
        $xml = '<?xml version="1.0" encoding="UTF-8"?>'.PHP_EOL;
175
        $xml .= '<activity id="'.$forumData['id'].'" moduleid="'.$forumData['moduleid'].'" modulename="forum" contextid="'.$forumData['contextid'].'">'.PHP_EOL;
176
        $xml .= '  <forum id="'.$forumData['id'].'">'.PHP_EOL;
177
        $xml .= '    <type>general</type>'.PHP_EOL;
178
        $xml .= '    <name>'.htmlspecialchars((string) $forumData['name']).'</name>'.PHP_EOL;
179
        $xml .= '    <intro>'.$introCdata.'</intro>'.PHP_EOL;
180
        $xml .= '    <introformat>1</introformat>'.PHP_EOL;
181
        $xml .= '    <duedate>0</duedate>'.PHP_EOL;
182
        $xml .= '    <cutoffdate>0</cutoffdate>'.PHP_EOL;
183
        $xml .= '    <assessed>0</assessed>'.PHP_EOL;
184
        $xml .= '    <assesstimestart>0</assesstimestart>'.PHP_EOL;
185
        $xml .= '    <assesstimefinish>0</assesstimefinish>'.PHP_EOL;
186
        $xml .= '    <scale>100</scale>'.PHP_EOL;
187
        $xml .= '    <maxbytes>512000</maxbytes>'.PHP_EOL;
188
        $xml .= '    <maxattachments>9</maxattachments>'.PHP_EOL;
189
        $xml .= '    <forcesubscribe>0</forcesubscribe>'.PHP_EOL;
190
        $xml .= '    <trackingtype>1</trackingtype>'.PHP_EOL;
191
        $xml .= '    <rsstype>0</rsstype>'.PHP_EOL;
192
        $xml .= '    <rssarticles>0</rssarticles>'.PHP_EOL;
193
        $xml .= '    <timemodified>'.$forumData['timemodified'].'</timemodified>'.PHP_EOL;
194
        $xml .= '    <warnafter>0</warnafter>'.PHP_EOL;
195
        $xml .= '    <blockafter>0</blockafter>'.PHP_EOL;
196
        $xml .= '    <blockperiod>0</blockperiod>'.PHP_EOL;
197
        $xml .= '    <completiondiscussions>0</completiondiscussions>'.PHP_EOL;
198
        $xml .= '    <completionreplies>0</completionreplies>'.PHP_EOL;
199
        $xml .= '    <completionposts>0</completionposts>'.PHP_EOL;
200
        $xml .= '    <displaywordcount>0</displaywordcount>'.PHP_EOL;
201
        $xml .= '    <lockdiscussionafter>0</lockdiscussionafter>'.PHP_EOL;
202
        $xml .= '    <grade_forum>0</grade_forum>'.PHP_EOL;
203
204
        // Discussions
205
        $xml .= '    <discussions>'.PHP_EOL;
206
        foreach ($forumData['threads'] as $thread) {
207
            $xml .= '      <discussion id="'.$thread['id'].'">'.PHP_EOL;
208
            $xml .= '        <name>'.htmlspecialchars((string) $thread['title']).'</name>'.PHP_EOL;
209
            $xml .= '        <firstpost>'.(int) $thread['firstpost'].'</firstpost>'.PHP_EOL;
210
            $xml .= '        <userid>'.$thread['userid'].'</userid>'.PHP_EOL;
211
            $xml .= '        <groupid>-1</groupid>'.PHP_EOL;
212
            $xml .= '        <assessed>0</assessed>'.PHP_EOL;
213
            $xml .= '        <timemodified>'.$thread['timemodified'].'</timemodified>'.PHP_EOL;
214
            $xml .= '        <usermodified>'.$thread['usermodified'].'</usermodified>'.PHP_EOL;
215
            $xml .= '        <timestart>0</timestart>'.PHP_EOL;
216
            $xml .= '        <timeend>0</timeend>'.PHP_EOL;
217
            $xml .= '        <pinned>0</pinned>'.PHP_EOL;
218
            $xml .= '        <timelocked>0</timelocked>'.PHP_EOL;
219
220
            // Posts
221
            $xml .= '        <posts>'.PHP_EOL;
222
            foreach ($thread['posts'] as $post) {
223
                $xml .= '          <post id="'.$post['id'].'">'.PHP_EOL;
224
                $xml .= '            <parent>'.(int) $post['parent'].'</parent>'.PHP_EOL;
225
                $xml .= '            <userid>'.$post['userid'].'</userid>'.PHP_EOL;
226
                $xml .= '            <created>'.$post['created'].'</created>'.PHP_EOL;
227
                $xml .= '            <modified>'.$post['modified'].'</modified>'.PHP_EOL;
228
                $xml .= '            <mailed>'.(int) $post['mailed'].'</mailed>'.PHP_EOL;
229
                $xml .= '            <subject>'.htmlspecialchars((string) $post['subject']).'</subject>'.PHP_EOL;
230
                $xml .= '            <message>'.htmlspecialchars((string) $post['message']).'</message>'.PHP_EOL;
231
                $xml .= '            <messageformat>1</messageformat>'.PHP_EOL;
232
                $xml .= '            <messagetrust>0</messagetrust>'.PHP_EOL;
233
                $xml .= '            <attachment></attachment>'.PHP_EOL;
234
                $xml .= '            <totalscore>0</totalscore>'.PHP_EOL;
235
                $xml .= '            <mailnow>0</mailnow>'.PHP_EOL;
236
                $xml .= '            <privatereplyto>0</privatereplyto>'.PHP_EOL;
237
                $xml .= '            <ratings>'.PHP_EOL;
238
                $xml .= '            </ratings>'.PHP_EOL;
239
                $xml .= '          </post>'.PHP_EOL;
240
            }
241
            $xml .= '        </posts>'.PHP_EOL;
242
243
            // Subscriptions (basic placeholder)
244
            $xml .= '        <discussion_subs>'.PHP_EOL;
245
            $xml .= '          <discussion_sub id="'.$thread['id'].'">'.PHP_EOL;
246
            $xml .= '            <userid>'.$thread['userid'].'</userid>'.PHP_EOL;
247
            $xml .= '            <preference>'.$thread['timemodified'].'</preference>'.PHP_EOL;
248
            $xml .= '          </discussion_sub>'.PHP_EOL;
249
            $xml .= '        </discussion_subs>'.PHP_EOL;
250
251
            $xml .= '      </discussion>'.PHP_EOL;
252
        }
253
        $xml .= '    </discussions>'.PHP_EOL;
254
255
        $xml .= '  </forum>'.PHP_EOL;
256
        $xml .= '</activity>';
257
258
        $this->createXmlFile('forum', $xml, $forumDir);
259
    }
260
}
261