Passed
Pull Request — 1.11.x (#6923)
by
unknown
10:03
created

ActivityExport::createCommentsXml()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 11
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 8
dl 0
loc 11
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 2
1
<?php
2
3
/* For licensing terms, see /license.txt */
4
5
namespace moodleexport;
6
7
use Exception;
8
9
/**
10
 * Class ActivityExport.
11
 *
12
 * Base class for exporting common activities.
13
 */
14
abstract class ActivityExport
15
{
16
    protected $course;
17
    public const DOCS_MODULE_ID = 1000000;
18
19
    public function __construct($course)
20
    {
21
        $this->course = $course;
22
    }
23
24
    /**
25
     * Abstract method for exporting the activity.
26
     * Must be implemented by child classes.
27
     */
28
    abstract public function export($activityId, $exportDir, $moduleId, $sectionId);
29
30
    /**
31
     * Get the section ID (learnpath source_id) for a given activity.
32
     */
33
    public function getSectionIdForActivity(int $activityId, string $itemType): int
34
    {
35
        if (empty($this->course->resources[RESOURCE_LEARNPATH])) {
36
            return 0;
37
        }
38
39
        foreach ($this->course->resources[RESOURCE_LEARNPATH] as $learnpath) {
40
            if (empty($learnpath->items)) {
41
                continue;
42
            }
43
44
            foreach ($learnpath->items as $item) {
45
                $normalizedType = $item['item_type'] === 'student_publication'
46
                    ? 'work'
47
                    : $item['item_type'];
48
49
                if ($normalizedType !== $itemType) {
50
                    continue;
51
                }
52
53
                // Classic case: LP stores the numeric id in "path"
54
                if (ctype_digit((string) $item['path']) && (int) $item['path'] === $activityId) {
55
                    return (int) $learnpath->source_id;
56
                }
57
58
                // Fallback for documents when LP stores the path instead of the id
59
                if ($itemType === RESOURCE_DOCUMENT) {
60
                    $doc = \DocumentManager::get_document_data_by_id($activityId, $this->course->code);
61
                    if (!empty($doc['path'])) {
62
                        $p = (string) $doc['path'];
63
                        foreach ([$p, 'document/'.$p, '/'.$p] as $candidate) {
64
                            if ((string) $item['path'] === $candidate) {
65
                                return (int) $learnpath->source_id;
66
                            }
67
                        }
68
                    }
69
                }
70
            }
71
        }
72
73
        return 0;
74
    }
75
76
    /**
77
     * Prepares the directory for the activity.
78
     */
79
    protected function prepareActivityDirectory(string $exportDir, string $activityType, int $moduleId): string
80
    {
81
        $activityDir = "{$exportDir}/activities/{$activityType}_{$moduleId}";
82
        if (!is_dir($activityDir)) {
83
            mkdir($activityDir, 0777, true);
84
        }
85
86
        return $activityDir;
87
    }
88
89
    /**
90
     * Creates a generic XML file.
91
     */
92
    protected function createXmlFile(string $fileName, string $xmlContent, string $directory): void
93
    {
94
        $filePath = $directory.'/'.$fileName.'.xml';
95
        if (file_put_contents($filePath, $xmlContent) === false) {
96
            throw new Exception("Error creating {$fileName}.xml");
97
        }
98
    }
99
100
    /**
101
     * Creates the module.xml file.
102
     */
103
    protected function createModuleXml(array $data, string $directory): void
104
    {
105
        $xmlContent = '<?xml version="1.0" encoding="UTF-8"?>'.PHP_EOL;
106
        $xmlContent .= '<module id="'.$data['moduleid'].'" version="2021051700">'.PHP_EOL;
107
        $xmlContent .= '  <modulename>'.$data['modulename'].'</modulename>'.PHP_EOL;
108
        $xmlContent .= '  <sectionid>'.$data['sectionid'].'</sectionid>'.PHP_EOL;
109
        $xmlContent .= '  <sectionnumber>'.$data['sectionnumber'].'</sectionnumber>'.PHP_EOL;
110
        $xmlContent .= '  <idnumber></idnumber>'.PHP_EOL;
111
        $xmlContent .= '  <added>'.time().'</added>'.PHP_EOL;
112
        $xmlContent .= '  <score>0</score>'.PHP_EOL;
113
        $xmlContent .= '  <indent>0</indent>'.PHP_EOL;
114
        $xmlContent .= '  <visible>1</visible>'.PHP_EOL;
115
        $xmlContent .= '  <visibleoncoursepage>1</visibleoncoursepage>'.PHP_EOL;
116
        $xmlContent .= '  <visibleold>1</visibleold>'.PHP_EOL;
117
        $xmlContent .= '  <groupmode>0</groupmode>'.PHP_EOL;
118
        $xmlContent .= '  <groupingid>0</groupingid>'.PHP_EOL;
119
        $xmlContent .= '  <completion>1</completion>'.PHP_EOL;
120
        $xmlContent .= '  <completiongradeitemnumber>$@NULL@$</completiongradeitemnumber>'.PHP_EOL;
121
        $xmlContent .= '  <completionview>0</completionview>'.PHP_EOL;
122
        $xmlContent .= '  <completionexpected>0</completionexpected>'.PHP_EOL;
123
        $xmlContent .= '  <availability>$@NULL@$</availability>'.PHP_EOL;
124
        $xmlContent .= '  <showdescription>0</showdescription>'.PHP_EOL;
125
        $xmlContent .= '  <tags></tags>'.PHP_EOL;
126
        $xmlContent .= '</module>'.PHP_EOL;
127
128
        $this->createXmlFile('module', $xmlContent, $directory);
129
    }
130
131
    /**
132
     * Creates the grades.xml file.
133
     */
134
    protected function createGradesXml(array $data, string $directory): void
135
    {
136
        $xmlContent = '<?xml version="1.0" encoding="UTF-8"?>'.PHP_EOL;
137
        $xmlContent .= '<activity_gradebook>'.PHP_EOL;
138
        $xmlContent .= '  <grade_items></grade_items>'.PHP_EOL;
139
        $xmlContent .= '</activity_gradebook>'.PHP_EOL;
140
141
        $this->createXmlFile('grades', $xmlContent, $directory);
142
    }
143
144
    /**
145
     * Creates the inforef.xml file, referencing users and files associated with the activity.
146
     */
147
    protected function createInforefXml(array $references, string $directory): void
148
    {
149
        // Start the XML content
150
        $xmlContent = '<?xml version="1.0" encoding="UTF-8"?>'.PHP_EOL;
151
        $xmlContent .= '<inforef>'.PHP_EOL;
152
153
        // Add user references if provided
154
        if (isset($references['users']) && is_array($references['users'])) {
155
            $xmlContent .= '  <userref>'.PHP_EOL;
156
            foreach ($references['users'] as $userId) {
157
                $xmlContent .= '    <user>'.PHP_EOL;
158
                $xmlContent .= '      <id>'.htmlspecialchars($userId).'</id>'.PHP_EOL;
159
                $xmlContent .= '    </user>'.PHP_EOL;
160
            }
161
            $xmlContent .= '  </userref>'.PHP_EOL;
162
        }
163
164
        // Add file references if provided
165
        if (isset($references['files']) && is_array($references['files'])) {
166
            $xmlContent .= '  <fileref>'.PHP_EOL;
167
            foreach ($references['files'] as $file) {
168
                $xmlContent .= '    <file>'.PHP_EOL;
169
                $xmlContent .= '      <id>'.htmlspecialchars($file['id']).'</id>'.PHP_EOL;
170
                $xmlContent .= '    </file>'.PHP_EOL;
171
            }
172
            $xmlContent .= '  </fileref>'.PHP_EOL;
173
        }
174
175
        $xmlContent .= '</inforef>'.PHP_EOL;
176
177
        $this->createXmlFile('inforef', $xmlContent, $directory);
178
    }
179
180
    /**
181
     * Creates the roles.xml file.
182
     */
183
    protected function createRolesXml(array $activityData, string $directory): void
184
    {
185
        $xmlContent = '<?xml version="1.0" encoding="UTF-8"?>'.PHP_EOL;
186
        $xmlContent .= '<roles></roles>'.PHP_EOL;
187
188
        $this->createXmlFile('roles', $xmlContent, $directory);
189
    }
190
191
    /**
192
     * Creates the filters.xml file for the activity.
193
     */
194
    protected function createFiltersXml(array $activityData, string $destinationDir): void
195
    {
196
        $xmlContent = '<?xml version="1.0" encoding="UTF-8"?>'.PHP_EOL;
197
        $xmlContent .= '<filters>'.PHP_EOL;
198
        $xmlContent .= '  <filter_actives>'.PHP_EOL;
199
        $xmlContent .= '  </filter_actives>'.PHP_EOL;
200
        $xmlContent .= '  <filter_configs>'.PHP_EOL;
201
        $xmlContent .= '  </filter_configs>'.PHP_EOL;
202
        $xmlContent .= '</filters>'.PHP_EOL;
203
204
        $this->createXmlFile('filters', $xmlContent, $destinationDir);
205
    }
206
207
    /**
208
     * Creates the grade_history.xml file for the activity.
209
     */
210
    protected function createGradeHistoryXml(array $activityData, string $destinationDir): void
211
    {
212
        $xmlContent = '<?xml version="1.0" encoding="UTF-8"?>'.PHP_EOL;
213
        $xmlContent .= '<grade_history>'.PHP_EOL;
214
        $xmlContent .= '  <grade_grades>'.PHP_EOL;
215
        $xmlContent .= '  </grade_grades>'.PHP_EOL;
216
        $xmlContent .= '</grade_history>'.PHP_EOL;
217
218
        $this->createXmlFile('grade_history', $xmlContent, $destinationDir);
219
    }
220
221
    /**
222
     * Creates the completion.xml file.
223
     */
224
    protected function createCompletionXml(array $activityData, string $destinationDir): void
225
    {
226
        $xmlContent = '<?xml version="1.0" encoding="UTF-8"?>'.PHP_EOL;
227
        $xmlContent .= '<completion>'.PHP_EOL;
228
        $xmlContent .= '  <completiondata>'.PHP_EOL;
229
        $xmlContent .= '    <completion>'.PHP_EOL;
230
        $xmlContent .= '      <timecompleted>0</timecompleted>'.PHP_EOL;
231
        $xmlContent .= '      <completionstate>1</completionstate>'.PHP_EOL;
232
        $xmlContent .= '    </completion>'.PHP_EOL;
233
        $xmlContent .= '  </completiondata>'.PHP_EOL;
234
        $xmlContent .= '</completion>'.PHP_EOL;
235
236
        $this->createXmlFile('completion', $xmlContent, $destinationDir);
237
    }
238
239
    /**
240
     * Creates the comments.xml file.
241
     */
242
    protected function createCommentsXml(array $activityData, string $destinationDir): void
243
    {
244
        $xmlContent = '<?xml version="1.0" encoding="UTF-8"?>'.PHP_EOL;
245
        $xmlContent .= '<comments>'.PHP_EOL;
246
        $xmlContent .= '  <comment>'.PHP_EOL;
247
        $xmlContent .= '    <content>This is a sample comment</content>'.PHP_EOL;
248
        $xmlContent .= '    <author>Professor</author>'.PHP_EOL;
249
        $xmlContent .= '  </comment>'.PHP_EOL;
250
        $xmlContent .= '</comments>'.PHP_EOL;
251
252
        $this->createXmlFile('comments', $xmlContent, $destinationDir);
253
    }
254
255
    /**
256
     * Creates the competencies.xml file.
257
     */
258
    protected function createCompetenciesXml(array $activityData, string $destinationDir): void
259
    {
260
        $xmlContent = '<?xml version="1.0" encoding="UTF-8"?>'.PHP_EOL;
261
        $xmlContent .= '<competencies>'.PHP_EOL;
262
        $xmlContent .= '  <competency>'.PHP_EOL;
263
        $xmlContent .= '    <name>Sample Competency</name>'.PHP_EOL;
264
        $xmlContent .= '  </competency>'.PHP_EOL;
265
        $xmlContent .= '</competencies>'.PHP_EOL;
266
267
        $this->createXmlFile('competencies', $xmlContent, $destinationDir);
268
    }
269
270
    /**
271
     * Creates the calendar.xml file.
272
     */
273
    protected function createCalendarXml(array $activityData, string $destinationDir): void
274
    {
275
        $xmlContent = '<?xml version="1.0" encoding="UTF-8"?>'.PHP_EOL;
276
        $xmlContent .= '<calendar>'.PHP_EOL;
277
        $xmlContent .= '  <event>'.PHP_EOL;
278
        $xmlContent .= '    <name>Due Date</name>'.PHP_EOL;
279
        $xmlContent .= '    <timestart>'.time().'</timestart>'.PHP_EOL;
280
        $xmlContent .= '  </event>'.PHP_EOL;
281
        $xmlContent .= '</calendar>'.PHP_EOL;
282
283
        $this->createXmlFile('calendar', $xmlContent, $destinationDir);
284
    }
285
286
    /**
287
     * Returns the title of the item in the LP (if it exists); otherwise, $fallback.
288
     */
289
    protected function lpItemTitle(int $sectionId, string $itemType, int $resourceId, ?string $fallback): string
290
    {
291
        if (!isset($this->course->resources[RESOURCE_LEARNPATH])) {
292
            return $fallback ?? '';
293
        }
294
        foreach ($this->course->resources[RESOURCE_LEARNPATH] as $lp) {
295
            if ((int) $lp->source_id !== $sectionId || empty($lp->items)) {
296
                continue;
297
            }
298
            foreach ($lp->items as $it) {
299
                $type = $it['item_type'] === 'student_publication' ? 'work' : $it['item_type'];
300
                if ($type === $itemType && (int) $it['path'] === $resourceId) {
301
                    return $it['title'] ?? ($fallback ?? '');
302
                }
303
            }
304
        }
305
        return $fallback ?? '';
306
    }
307
}
308