|
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 DocumentManager; |
|
10
|
|
|
|
|
11
|
|
|
use const ENT_XML1; |
|
12
|
|
|
use const PHP_EOL; |
|
13
|
|
|
|
|
14
|
|
|
/** |
|
15
|
|
|
* Exports a Chamilo assignment (work) to a Moodle 'assign' activity. |
|
16
|
|
|
* Assumes ActivityExport base provides: |
|
17
|
|
|
* - $this->course (with ->info and ->resources) |
|
18
|
|
|
* - prepareActivityDirectory(), createXmlFile(), createModuleXml(), |
|
19
|
|
|
* createGradesXml(), createInforefXml(), createGradeHistoryXml(), |
|
20
|
|
|
* createRolesXml(), createCommentsXml(), createCalendarXml(), |
|
21
|
|
|
* createFiltersXml(). |
|
22
|
|
|
*/ |
|
23
|
|
|
final class AssignExport extends ActivityExport |
|
24
|
|
|
{ |
|
25
|
|
|
/** |
|
26
|
|
|
* Export a single assign into the destination directory. |
|
27
|
|
|
*/ |
|
28
|
|
|
public function export(int $activityId, string $exportDir, int $moduleId, int $sectionId): void |
|
29
|
|
|
{ |
|
30
|
|
|
// 1) Ensure destination folder like activities/assign_<moduleId> |
|
31
|
|
|
$assignDir = $this->prepareActivityDirectory($exportDir, 'assign', $moduleId); |
|
32
|
|
|
|
|
33
|
|
|
// 2) Gather data |
|
34
|
|
|
$assignData = $this->getData($activityId, $sectionId); |
|
35
|
|
|
if (null === $assignData) { |
|
36
|
|
|
// Nothing to export (missing or invalid source) |
|
37
|
|
|
return; |
|
38
|
|
|
} |
|
39
|
|
|
|
|
40
|
|
|
// 3) Write activity files |
|
41
|
|
|
$this->createAssignXml($assignData, $assignDir); |
|
42
|
|
|
$this->createModuleXml($assignData, $assignDir); |
|
43
|
|
|
$this->createGradesXml($assignData, $assignDir); |
|
44
|
|
|
$this->createGradingXml($assignData, $assignDir); |
|
45
|
|
|
$this->createInforefXml($assignData, $assignDir); |
|
46
|
|
|
$this->createGradeHistoryXml($assignData, $assignDir); |
|
47
|
|
|
$this->createRolesXml($assignData, $assignDir); |
|
48
|
|
|
$this->createCommentsXml($assignData, $assignDir); |
|
49
|
|
|
$this->createCalendarXml($assignData, $assignDir); |
|
50
|
|
|
$this->createFiltersXml($assignData, $assignDir); |
|
51
|
|
|
} |
|
52
|
|
|
|
|
53
|
|
|
/** |
|
54
|
|
|
* Build the data array used by XML writers. |
|
55
|
|
|
*/ |
|
56
|
|
|
public function getData(int $assignId, int $sectionId): ?array |
|
57
|
|
|
{ |
|
58
|
|
|
$work = $this->course->resources[RESOURCE_WORK][$assignId] ?? null; |
|
59
|
|
|
if (!$work || empty($work->params['id']) || empty($work->params['title'])) { |
|
60
|
|
|
return null; |
|
61
|
|
|
} |
|
62
|
|
|
|
|
63
|
|
|
$sentDate = !empty($work->params['sent_date']) |
|
64
|
|
|
? (int) strtotime((string) $work->params['sent_date']) |
|
65
|
|
|
: time(); |
|
66
|
|
|
|
|
67
|
|
|
// Collect attached documents for this work |
|
68
|
|
|
$files = []; |
|
69
|
|
|
$workFiles = getAllDocumentToWork($assignId, (int) $this->course->info['real_id']) ?? []; |
|
70
|
|
|
foreach ($workFiles as $file) { |
|
71
|
|
|
$docId = (int) ($file['document_id'] ?? 0); |
|
72
|
|
|
if ($docId <= 0) { |
|
73
|
|
|
continue; |
|
74
|
|
|
} |
|
75
|
|
|
$docData = DocumentManager::get_document_data_by_id($docId, (string) $this->course->info['code']); |
|
|
|
|
|
|
76
|
|
|
if (!empty($docData) && isset($docData['path'])) { |
|
77
|
|
|
$files[] = [ |
|
78
|
|
|
'id' => $docId, |
|
79
|
|
|
// NOTE: Moodle uses filepool IDs. We keep a stable hash based on basename as a fallback. |
|
80
|
|
|
'contenthash' => sha1((string) basename((string) $docData['path'])), |
|
81
|
|
|
'filename' => (string) basename((string) $docData['path']), |
|
82
|
|
|
'filepath' => '/Documents/', |
|
83
|
|
|
]; |
|
84
|
|
|
} |
|
85
|
|
|
} |
|
86
|
|
|
|
|
87
|
|
|
// Prefer a base helper; if your base doesn't have it, replace with your static service |
|
88
|
|
|
$admin = method_exists($this, 'getAdminUserData') |
|
89
|
|
|
? $this->getAdminUserData() |
|
90
|
|
|
: ['id' => 2]; |
|
91
|
|
|
|
|
92
|
|
|
return [ |
|
93
|
|
|
'id' => (int) $work->params['id'], |
|
94
|
|
|
'moduleid' => (int) $work->params['id'], |
|
95
|
|
|
'modulename' => 'assign', |
|
96
|
|
|
'contextid' => (int) $this->course->info['real_id'], |
|
97
|
|
|
'sectionid' => $sectionId, |
|
98
|
|
|
'sectionnumber' => 0, |
|
99
|
|
|
'name' => (string) $work->params['title'], |
|
100
|
|
|
// Keep raw HTML; assign.xml will wrap it in CDATA |
|
101
|
|
|
'intro' => (string) ($work->params['description'] ?? ''), |
|
102
|
|
|
'duedate' => $sentDate, |
|
103
|
|
|
'gradingduedate' => $sentDate + 7 * 86400, |
|
104
|
|
|
'allowsubmissionsfromdate' => $sentDate, |
|
105
|
|
|
'timemodified' => time(), |
|
106
|
|
|
'grade_item_id' => 0, |
|
107
|
|
|
'files' => $files, |
|
108
|
|
|
'users' => [$admin['id']], |
|
109
|
|
|
'area_id' => 0, |
|
110
|
|
|
]; |
|
111
|
|
|
} |
|
112
|
|
|
|
|
113
|
|
|
/** |
|
114
|
|
|
* Write activity_gradebook/grades.xml for this activity. |
|
115
|
|
|
*/ |
|
116
|
|
|
protected function createGradesXml(array $data, string $directory): void |
|
117
|
|
|
{ |
|
118
|
|
|
$xml = '<?xml version="1.0" encoding="UTF-8"?>'.PHP_EOL; |
|
119
|
|
|
$xml .= '<activity_gradebook>'.PHP_EOL; |
|
120
|
|
|
$xml .= ' <grade_items>'.PHP_EOL; |
|
121
|
|
|
$xml .= ' <grade_item id="'.(int) $data['grade_item_id'].'">'.PHP_EOL; |
|
122
|
|
|
$xml .= ' <categoryid>1</categoryid>'.PHP_EOL; |
|
123
|
|
|
$xml .= ' <itemname>'.\htmlspecialchars((string) $data['name'], ENT_XML1).'</itemname>'.PHP_EOL; |
|
124
|
|
|
$xml .= ' <itemtype>mod</itemtype>'.PHP_EOL; |
|
125
|
|
|
$xml .= ' <itemmodule>'.$data['modulename'].'</itemmodule>'.PHP_EOL; |
|
126
|
|
|
$xml .= ' <iteminstance>'.$data['id'].'</iteminstance>'.PHP_EOL; |
|
127
|
|
|
$xml .= ' <itemnumber>0</itemnumber>'.PHP_EOL; |
|
128
|
|
|
$xml .= ' <iteminfo>$@NULL@$</iteminfo>'.PHP_EOL; |
|
129
|
|
|
$xml .= ' <idnumber></idnumber>'.PHP_EOL; |
|
130
|
|
|
$xml .= ' <calculation>$@NULL@$</calculation>'.PHP_EOL; |
|
131
|
|
|
$xml .= ' <gradetype>1</gradetype>'.PHP_EOL; |
|
132
|
|
|
$xml .= ' <grademax>100.00000</grademax>'.PHP_EOL; |
|
133
|
|
|
$xml .= ' <grademin>0.00000</grademin>'.PHP_EOL; |
|
134
|
|
|
$xml .= ' <scaleid>$@NULL@$</scaleid>'.PHP_EOL; |
|
135
|
|
|
$xml .= ' <outcomeid>$@NULL@$</outcomeid>'.PHP_EOL; |
|
136
|
|
|
$xml .= ' <gradepass>0.00000</gradepass>'.PHP_EOL; |
|
137
|
|
|
$xml .= ' <multfactor>1.00000</multfactor>'.PHP_EOL; |
|
138
|
|
|
$xml .= ' <plusfactor>0.00000</plusfactor>'.PHP_EOL; |
|
139
|
|
|
$xml .= ' <aggregationcoef>0.00000</aggregationcoef>'.PHP_EOL; |
|
140
|
|
|
$xml .= ' <aggregationcoef2>0.23810</aggregationcoef2>'.PHP_EOL; |
|
141
|
|
|
$xml .= ' <weightoverride>0</weightoverride>'.PHP_EOL; |
|
142
|
|
|
$xml .= ' <sortorder>5</sortorder>'.PHP_EOL; |
|
143
|
|
|
$xml .= ' <display>0</display>'.PHP_EOL; |
|
144
|
|
|
$xml .= ' <decimals>$@NULL@$</decimals>'.PHP_EOL; |
|
145
|
|
|
$xml .= ' <hidden>0</hidden>'.PHP_EOL; |
|
146
|
|
|
$xml .= ' <locked>0</locked>'.PHP_EOL; |
|
147
|
|
|
$xml .= ' <locktime>0</locktime>'.PHP_EOL; |
|
148
|
|
|
$xml .= ' <needsupdate>0</needsupdate>'.PHP_EOL; |
|
149
|
|
|
$xml .= ' <timecreated>'.$data['timemodified'].'</timecreated>'.PHP_EOL; |
|
150
|
|
|
$xml .= ' <timemodified>'.$data['timemodified'].'</timemodified>'.PHP_EOL; |
|
151
|
|
|
$xml .= ' <grade_grades></grade_grades>'.PHP_EOL; |
|
152
|
|
|
$xml .= ' </grade_item>'.PHP_EOL; |
|
153
|
|
|
$xml .= ' </grade_items>'.PHP_EOL; |
|
154
|
|
|
$xml .= ' <grade_letters></grade_letters>'.PHP_EOL; |
|
155
|
|
|
$xml .= '</activity_gradebook>'; |
|
156
|
|
|
|
|
157
|
|
|
$this->createXmlFile('grades', $xml, $directory); |
|
158
|
|
|
} |
|
159
|
|
|
|
|
160
|
|
|
/** |
|
161
|
|
|
* Write assign/assign.xml (main activity definition). |
|
162
|
|
|
* Uses CDATA for 'intro' to preserve HTML safely. |
|
163
|
|
|
*/ |
|
164
|
|
|
private function createAssignXml(array $d, string $dir): void |
|
165
|
|
|
{ |
|
166
|
|
|
$name = \htmlspecialchars((string) $d['name'], ENT_XML1); |
|
167
|
|
|
$intro = (string) $d['intro']; |
|
168
|
|
|
|
|
169
|
|
|
$xml = '<?xml version="1.0" encoding="UTF-8"?>'.PHP_EOL; |
|
170
|
|
|
$xml .= '<activity id="'.$d['id'].'" moduleid="'.$d['moduleid'].'" modulename="assign" contextid="'.$d['contextid'].'">'.PHP_EOL; |
|
171
|
|
|
$xml .= ' <assign id="'.$d['id'].'">'.PHP_EOL; |
|
172
|
|
|
$xml .= ' <name>'.$name.'</name>'.PHP_EOL; |
|
173
|
|
|
$xml .= ' <intro><![CDATA['.$intro.']]></intro>'.PHP_EOL; |
|
174
|
|
|
$xml .= ' <introformat>1</introformat>'.PHP_EOL; |
|
175
|
|
|
$xml .= ' <alwaysshowdescription>1</alwaysshowdescription>'.PHP_EOL; |
|
176
|
|
|
$xml .= ' <submissiondrafts>0</submissiondrafts>'.PHP_EOL; |
|
177
|
|
|
$xml .= ' <sendnotifications>0</sendnotifications>'.PHP_EOL; |
|
178
|
|
|
$xml .= ' <sendlatenotifications>0</sendlatenotifications>'.PHP_EOL; |
|
179
|
|
|
$xml .= ' <sendstudentnotifications>1</sendstudentnotifications>'.PHP_EOL; |
|
180
|
|
|
$xml .= ' <duedate>'.$d['duedate'].'</duedate>'.PHP_EOL; |
|
181
|
|
|
$xml .= ' <cutoffdate>0</cutoffdate>'.PHP_EOL; |
|
182
|
|
|
$xml .= ' <gradingduedate>'.$d['gradingduedate'].'</gradingduedate>'.PHP_EOL; |
|
183
|
|
|
$xml .= ' <allowsubmissionsfromdate>'.$d['allowsubmissionsfromdate'].'</allowsubmissionsfromdate>'.PHP_EOL; |
|
184
|
|
|
$xml .= ' <grade>100</grade>'.PHP_EOL; |
|
185
|
|
|
$xml .= ' <timemodified>'.$d['timemodified'].'</timemodified>'.PHP_EOL; |
|
186
|
|
|
$xml .= ' <completionsubmit>1</completionsubmit>'.PHP_EOL; |
|
187
|
|
|
$xml .= ' <requiresubmissionstatement>0</requiresubmissionstatement>'.PHP_EOL; |
|
188
|
|
|
$xml .= ' <teamsubmission>0</teamsubmission>'.PHP_EOL; |
|
189
|
|
|
$xml .= ' <requireallteammemberssubmit>0</requireallteammemberssubmit>'.PHP_EOL; |
|
190
|
|
|
$xml .= ' <teamsubmissiongroupingid>0</teamsubmissiongroupingid>'.PHP_EOL; |
|
191
|
|
|
$xml .= ' <blindmarking>0</blindmarking>'.PHP_EOL; |
|
192
|
|
|
$xml .= ' <hidegrader>0</hidegrader>'.PHP_EOL; |
|
193
|
|
|
$xml .= ' <revealidentities>0</revealidentities>'.PHP_EOL; |
|
194
|
|
|
$xml .= ' <attemptreopenmethod>none</attemptreopenmethod>'.PHP_EOL; |
|
195
|
|
|
$xml .= ' <maxattempts>1</maxattempts>'.PHP_EOL; |
|
196
|
|
|
$xml .= ' <markingworkflow>0</markingworkflow>'.PHP_EOL; |
|
197
|
|
|
$xml .= ' <markingallocation>0</markingallocation>'.PHP_EOL; |
|
198
|
|
|
$xml .= ' <preventsubmissionnotingroup>0</preventsubmissionnotingroup>'.PHP_EOL; |
|
199
|
|
|
$xml .= ' <userflags></userflags>'.PHP_EOL; |
|
200
|
|
|
$xml .= ' <submissions></submissions>'.PHP_EOL; |
|
201
|
|
|
$xml .= ' <grades></grades>'.PHP_EOL; |
|
202
|
|
|
$xml .= ' </assign>'.PHP_EOL; |
|
203
|
|
|
$xml .= '</activity>'; |
|
204
|
|
|
|
|
205
|
|
|
$this->createXmlFile('assign', $xml, $dir); |
|
206
|
|
|
} |
|
207
|
|
|
|
|
208
|
|
|
/** |
|
209
|
|
|
* Write assign/grading.xml (grading areas for this activity). |
|
210
|
|
|
*/ |
|
211
|
|
|
private function createGradingXml(array $d, string $dir): void |
|
212
|
|
|
{ |
|
213
|
|
|
$xml = '<?xml version="1.0" encoding="UTF-8"?>'.PHP_EOL; |
|
214
|
|
|
$xml .= '<areas>'.PHP_EOL; |
|
215
|
|
|
$xml .= ' <area id="'.(int) ($d['area_id'] ?? 0).'">'.PHP_EOL; |
|
216
|
|
|
$xml .= ' <areaname>submissions</areaname>'.PHP_EOL; |
|
217
|
|
|
$xml .= ' <activemethod>$@NULL@$</activemethod>'.PHP_EOL; |
|
218
|
|
|
$xml .= ' <definitions></definitions>'.PHP_EOL; |
|
219
|
|
|
$xml .= ' </area>'.PHP_EOL; |
|
220
|
|
|
$xml .= '</areas>'; |
|
221
|
|
|
|
|
222
|
|
|
$this->createXmlFile('grading', $xml, $dir); |
|
223
|
|
|
} |
|
224
|
|
|
} |
|
225
|
|
|
|
This function has been deprecated. The supplier of the function has supplied an explanatory message.
The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.