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

ActivityExport   A

Complexity

Total Complexity 35

Size/Duplication

Total Lines 235
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 95
c 1
b 0
f 0
dl 0
loc 235
rs 9.6
wmc 35

15 Methods

Rating   Name   Duplication   Size   Complexity  
A getAdminUserData() 0 4 1
A createCalendarXml() 0 8 1
A prepareActivityDirectory() 0 8 4
B createInforefXml() 0 38 11
A createRolesXml() 0 4 1
B getSectionIdForActivity() 0 15 7
A createGradesXml() 0 8 1
A createCompletionXml() 0 8 1
A __construct() 0 3 1
A createCompetenciesXml() 0 6 1
A createFiltersXml() 0 5 1
A createGradeHistoryXml() 0 5 1
A createXmlFile() 0 5 2
A createModuleXml() 0 26 1
A createCommentsXml() 0 6 1
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\FileIndex;
10
use Exception;
11
12
use const PHP_EOL;
13
14
/**
15
 * Base class for Moodle activity exporters.
16
 * Child classes must implement export() and may reuse helpers here.
17
 *
18
 * Expected $this->course shape (legacy array/object used by coursecopy):
19
 *   - info: ['real_id'=>int, 'code'=>string]
20
 *   - resources: mixed structure per tool
21
 */
22
abstract class ActivityExport
23
{
24
    /**
25
     * @var mixed Legacy course snapshot used during export
26
     */
27
    protected $course;
28
29
    public function __construct($course)
30
    {
31
        $this->course = $course;
32
    }
33
34
    /**
35
     * Export this activity to the provided directory.
36
     */
37
    abstract public function export(int $activityId, string $exportDir, int $moduleId, int $sectionId): void;
38
39
    /**
40
     * Resolve the section id (learnpath/section) that contains a given activity.
41
     * Falls back to 0 if not found.
42
     */
43
    public function getSectionIdForActivity(int $activityId, string $itemType): int
44
    {
45
        // Normalize legacy "student_publication" -> "work"
46
        $needle = 'student_publication' === $itemType ? 'work' : $itemType;
47
48
        foreach ($this->course->resources[RESOURCE_LEARNPATH] ?? [] as $learnpath) {
49
            foreach ($learnpath->items ?? [] as $item) {
50
                $type = ($item['item_type'] ?? '') === 'student_publication' ? 'work' : ($item['item_type'] ?? '');
51
                if ($type === $needle && (int) ($item['path'] ?? -1) === $activityId) {
52
                    return (int) $learnpath->source_id;
53
                }
54
            }
55
        }
56
57
        return 0;
58
    }
59
60
    /**
61
     * Ensure the activity directory exists and return its absolute path.
62
     * Result: <exportDir>/activities/<activityType>_<moduleId>.
63
     */
64
    protected function prepareActivityDirectory(string $exportDir, string $activityType, int $moduleId): string
65
    {
66
        $activityDir = rtrim($exportDir, '/')."/activities/{$activityType}_{$moduleId}";
67
        if (!is_dir($activityDir) && !@mkdir($activityDir, 0777, true) && !is_dir($activityDir)) {
68
            throw new Exception("Can not create activity directory: {$activityDir}");
69
        }
70
71
        return $activityDir;
72
    }
73
74
    /**
75
     * Write a simple XML file into $directory with name $fileName.xml.
76
     */
77
    protected function createXmlFile(string $fileName, string $xmlContent, string $directory): void
78
    {
79
        $filePath = rtrim($directory, '/').'/'.$fileName.'.xml';
80
        if (false === @file_put_contents($filePath, $xmlContent)) {
81
            throw new Exception("Error creating {$fileName}.xml at {$filePath}");
82
        }
83
    }
84
85
    /**
86
     * module.xml — generic module metadata used by Moodle backup.
87
     */
88
    protected function createModuleXml(array $data, string $directory): void
89
    {
90
        $xml = '<?xml version="1.0" encoding="UTF-8"?>'.PHP_EOL;
91
        $xml .= '<module id="'.(int) $data['moduleid'].'" version="2021051700">'.PHP_EOL;
92
        $xml .= '  <modulename>'.($data['modulename'] ?? '').'</modulename>'.PHP_EOL;
93
        $xml .= '  <sectionid>'.(int) ($data['sectionid'] ?? 0).'</sectionid>'.PHP_EOL;
94
        $xml .= '  <sectionnumber>'.(int) ($data['sectionnumber'] ?? 0).'</sectionnumber>'.PHP_EOL;
95
        $xml .= '  <idnumber></idnumber>'.PHP_EOL;
96
        $xml .= '  <added>'.time().'</added>'.PHP_EOL;
97
        $xml .= '  <score>0</score>'.PHP_EOL;
98
        $xml .= '  <indent>0</indent>'.PHP_EOL;
99
        $xml .= '  <visible>1</visible>'.PHP_EOL;
100
        $xml .= '  <visibleoncoursepage>1</visibleoncoursepage>'.PHP_EOL;
101
        $xml .= '  <visibleold>1</visibleold>'.PHP_EOL;
102
        $xml .= '  <groupmode>0</groupmode>'.PHP_EOL;
103
        $xml .= '  <groupingid>0</groupingid>'.PHP_EOL;
104
        $xml .= '  <completion>1</completion>'.PHP_EOL;
105
        $xml .= '  <completiongradeitemnumber>$@NULL@$</completiongradeitemnumber>'.PHP_EOL;
106
        $xml .= '  <completionview>0</completionview>'.PHP_EOL;
107
        $xml .= '  <completionexpected>0</completionexpected>'.PHP_EOL;
108
        $xml .= '  <availability>$@NULL@$</availability>'.PHP_EOL;
109
        $xml .= '  <showdescription>0</showdescription>'.PHP_EOL;
110
        $xml .= '  <tags></tags>'.PHP_EOL;
111
        $xml .= '</module>'.PHP_EOL;
112
113
        $this->createXmlFile('module', $xml, $directory);
114
    }
115
116
    /**
117
     * grades.xml — override in child to include real grade_item definitions.
118
     */
119
    protected function createGradesXml(array $data, string $directory): void
120
    {
121
        $xml = '<?xml version="1.0" encoding="UTF-8"?>'.PHP_EOL;
122
        $xml .= '<activity_gradebook>'.PHP_EOL;
123
        $xml .= '  <grade_items></grade_items>'.PHP_EOL;
124
        $xml .= '</activity_gradebook>'.PHP_EOL;
125
126
        $this->createXmlFile('grades', $xml, $directory);
127
    }
128
129
    /**
130
     * inforef.xml — references to users/files used by this activity.
131
     */
132
    protected function createInforefXml(array $references, string $directory): void
133
    {
134
        $xml = '<?xml version="1.0" encoding="UTF-8"?>'.PHP_EOL;
135
        $xml .= '<inforef>'.PHP_EOL;
136
137
        if (!empty($references['users']) && \is_array($references['users'])) {
138
            $xml .= ' <userref>'.PHP_EOL;
139
            foreach ($references['users'] as $uid) {
140
                $xml .= ' <user><id>'.htmlspecialchars((string) $uid).'</id></user>'.PHP_EOL;
141
            }
142
            $xml .= ' </userref>'.PHP_EOL;
143
        }
144
145
        if (!empty($references['files']) && \is_array($references['files'])) {
146
            $xml .= ' <fileref>'.PHP_EOL;
147
            foreach ($references['files'] as $file) {
148
                $fid = null;
149
                if (\is_array($file)) {
150
                    $fid = $file['id'] ?? null;
151
                    $ch = $file['contenthash'] ?? null;
152
                    if ($ch) {
153
                        $resolved = FileIndex::resolveByContenthash((string) $ch);
154
                        if (null !== $resolved) {
155
                            $fid = $resolved;
156
                        }
157
                    }
158
                } else {
159
                    $fid = $file;
160
                }
161
                if (null !== $fid) {
162
                    $xml .= ' <file><id>'.htmlspecialchars((string) $fid).'</id></file>'.PHP_EOL;
163
                }
164
            }
165
            $xml .= ' </fileref>'.PHP_EOL;
166
        }
167
168
        $xml .= '</inforef>'.PHP_EOL;
169
        $this->createXmlFile('inforef', $xml, $directory);
170
    }
171
172
    /**
173
     * roles.xml — left empty by default. Override if needed.
174
     */
175
    protected function createRolesXml(array $activityData, string $directory): void
176
    {
177
        $xml = '<?xml version="1.0" encoding="UTF-8"?>'.PHP_EOL.'<roles></roles>'.PHP_EOL;
178
        $this->createXmlFile('roles', $xml, $directory);
179
    }
180
181
    /**
182
     * filters.xml — default empty.
183
     */
184
    protected function createFiltersXml(array $activityData, string $destinationDir): void
185
    {
186
        $xml = '<?xml version="1.0" encoding="UTF-8"?>'.PHP_EOL;
187
        $xml .= '<filters><filter_actives></filter_actives><filter_configs></filter_configs></filters>'.PHP_EOL;
188
        $this->createXmlFile('filters', $xml, $destinationDir);
189
    }
190
191
    /**
192
     * grade_history.xml — default empty.
193
     */
194
    protected function createGradeHistoryXml(array $activityData, string $destinationDir): void
195
    {
196
        $xml = '<?xml version="1.0" encoding="UTF-8"?>'.PHP_EOL;
197
        $xml .= '<grade_history><grade_grades></grade_grades></grade_history>'.PHP_EOL;
198
        $this->createXmlFile('grade_history', $xml, $destinationDir);
199
    }
200
201
    /**
202
     * completion.xml — default minimal placeholder.
203
     */
204
    protected function createCompletionXml(array $activityData, string $destinationDir): void
205
    {
206
        $xml = '<?xml version="1.0" encoding="UTF-8"?>'.PHP_EOL;
207
        $xml .= '<completion><completiondata><completion>'.PHP_EOL;
208
        $xml .= '  <timecompleted>0</timecompleted><completionstate>1</completionstate>'.PHP_EOL;
209
        $xml .= '</completion></completiondata></completion>'.PHP_EOL;
210
211
        $this->createXmlFile('completion', $xml, $destinationDir);
212
    }
213
214
    /**
215
     * comments.xml — default minimal placeholder.
216
     */
217
    protected function createCommentsXml(array $activityData, string $destinationDir): void
218
    {
219
        $xml = '<?xml version="1.0" encoding="UTF-8"?>'.PHP_EOL;
220
        $xml .= '<comments></comments>'.PHP_EOL;
221
222
        $this->createXmlFile('comments', $xml, $destinationDir);
223
    }
224
225
    /**
226
     * competencies.xml — default minimal placeholder.
227
     */
228
    protected function createCompetenciesXml(array $activityData, string $destinationDir): void
229
    {
230
        $xml = '<?xml version="1.0" encoding="UTF-8"?>'.PHP_EOL;
231
        $xml .= '<competencies></competencies>'.PHP_EOL;
232
233
        $this->createXmlFile('competencies', $xml, $destinationDir);
234
    }
235
236
    /**
237
     * calendar.xml — default with a single placeholder event.
238
     */
239
    protected function createCalendarXml(array $activityData, string $destinationDir): void
240
    {
241
        $xml = '<?xml version="1.0" encoding="UTF-8"?>'.PHP_EOL;
242
        $xml .= '<calendar><event>'.PHP_EOL;
243
        $xml .= '  <name>Due Date</name><timestart>'.time().'</timestart>'.PHP_EOL;
244
        $xml .= '</event></calendar>'.PHP_EOL;
245
246
        $this->createXmlFile('calendar', $xml, $destinationDir);
247
    }
248
249
    /**
250
     * Tiny helper to retrieve an admin user when needed by exporters.
251
     * Override if you have a service to resolve this properly.
252
     */
253
    protected function getAdminUserData(): array
254
    {
255
        // Default stub. Replace with real lookup if available.
256
        return ['id' => 2];
257
    }
258
}
259