Passed
Push — master ( 24a37f...f52bbb )
by
unknown
24:30 queued 12:07
created

GlossaryExport   A

Complexity

Total Complexity 32

Size/Duplication

Total Lines 219
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 151
c 1
b 0
f 0
dl 0
loc 219
rs 9.84
wmc 32

3 Methods

Rating   Name   Duplication   Size   Complexity  
B createGlossaryXml() 0 79 6
A export() 0 18 1
F getData() 0 101 25
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 glossaries within a course.
15
 */
16
class GlossaryExport extends ActivityExport
17
{
18
    /**
19
     * Export all glossary terms into a single Moodle glossary.
20
     *
21
     * @param int    $activityId the ID of the glossary (logical wrapper id)
22
     * @param string $exportDir  destination base directory for 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
        $glossaryDir = $this->prepareActivityDirectory($exportDir, 'glossary', (int) $moduleId);
29
30
        $glossaryData = $this->getData((int) $activityId, (int) $sectionId, (int) $moduleId);
31
32
        $this->createGlossaryXml($glossaryData, $glossaryDir);
33
        $this->createModuleXml($glossaryData, $glossaryDir);
34
        $this->createGradesXml($glossaryData, $glossaryDir);
35
        $this->createGradeHistoryXml($glossaryData, $glossaryDir);
36
        $this->createInforefXml($glossaryData, $glossaryDir);
37
        $this->createRolesXml($glossaryData, $glossaryDir);
38
        $this->createCalendarXml($glossaryData, $glossaryDir);
39
        $this->createCommentsXml($glossaryData, $glossaryDir);
40
        $this->createCompetenciesXml($glossaryData, $glossaryDir);
41
        $this->createFiltersXml($glossaryData, $glossaryDir);
42
43
        MoodleExport::flagActivityUserinfo('glossary', (int) $moduleId, true);
44
    }
45
46
    /**
47
     * Gather all terms and build a single glossary activity dataset.
48
     */
49
    public function getData(int $glossaryId, int $sectionId, ?int $moduleId = null): array
50
    {
51
        if ($moduleId === null) {
52
            $moduleId = $glossaryId;
53
        }
54
55
        $adminData = MoodleExport::getAdminUserData();
56
        $adminId   = (int) ($adminData['id'] ?? 0);
57
58
        $res  = \is_array($this->course->resources ?? null) ? $this->course->resources : [];
59
        $bags = [];
60
        if (\defined('RESOURCE_GLOSSARY') && !empty($res[RESOURCE_GLOSSARY]) && \is_array($res[RESOURCE_GLOSSARY])) {
61
            $bags[] = $res[RESOURCE_GLOSSARY];
62
        }
63
        foreach (['glossary', 'glossary_definition', 'glossary_terms'] as $k) {
64
            if (!empty($res[$k]) && \is_array($res[$k])) {
65
                $bags[] = $res[$k];
66
            }
67
        }
68
69
        $entries   = [];
70
        $seen      = [];
71
        $nextId    = 1;
72
        $userIds   = [];
73
74
        $norm = static function (string $s): string {
75
            $s = trim($s);
76
            $s = mb_strtolower($s, 'UTF-8');
77
            return $s;
78
        };
79
80
        foreach ($bags as $bag) {
81
            foreach ($bag as $g) {
82
                $o = (\is_object($g) && isset($g->obj) && \is_object($g->obj)) ? $g->obj : $g;
83
                if (!\is_object($o)) {
84
                    continue;
85
                }
86
87
                $concept = '';
88
                foreach (['name', 'term', 'title'] as $k) {
89
                    if (!empty($o->{$k}) && \is_string($o->{$k})) {
90
                        $concept = trim((string) $o->{$k});
91
                        break;
92
                    }
93
                }
94
                if ($concept === '') {
95
                    continue;
96
                }
97
98
                $key = $norm($concept);
99
                if (isset($seen[$key])) {
100
                    continue;
101
                }
102
                $seen[$key] = true;
103
104
                $definition = '';
105
                foreach (['description','definition','comment','text'] as $k) {
106
                    if (isset($o->{$k}) && \is_string($o->{$k})) {
107
                        $definition = (string) $o->{$k};
108
                        break;
109
                    }
110
                }
111
112
                $aliases = [];
113
                $lc = mb_strtolower($concept, 'UTF-8');
114
                if ($lc !== $concept) {
115
                    $aliases[] = $lc;
116
                }
117
118
                $entries[] = [
119
                    'id'           => $nextId++,
120
                    'userid'       => $adminId,
121
                    'concept'      => $concept,
122
                    'definition'   => $definition,
123
                    'timecreated'  => time(),
124
                    'timemodified' => time(),
125
                    'aliases'      => $aliases,
126
                ];
127
            }
128
        }
129
130
        if ($adminId > 0) {
131
            $userIds[$adminId] = true;
132
        }
133
134
        return [
135
            'id'               => $glossaryId,
136
            'moduleid'         => (int) $moduleId,
137
            'modulename'       => 'glossary',
138
            'contextid'        => (int) ($this->course->info['real_id'] ?? 0),
139
            'name'             => get_lang('Glossary'),
140
            'description'      => '',
141
            'timecreated'      => time(),
142
            'timemodified'     => time(),
143
            'sectionid'        => $sectionId,
144
            'sectionnumber'    => 0,
145
            'userid'           => $adminId,
146
            'entries'          => $entries,
147
            'users'            => array_map('intval', array_keys($userIds)),
148
            'files'            => [],
149
            'include_userinfo' => true,
150
        ];
151
    }
152
153
    /**
154
     * Create glossary.xml with all entries combined.
155
     */
156
    private function createGlossaryXml(array $glossaryData, string $glossaryDir): void
157
    {
158
        $esc = static function (?string $html): string {
159
            return htmlspecialchars((string) $html, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
160
        };
161
162
        $introHtml = $glossaryData['description'] !== ''
163
            ? $glossaryData['description']
164
            : '<p>'.get_lang('Glossary').'</p>';
165
166
        $xml  = '<?xml version="1.0" encoding="UTF-8"?>'.PHP_EOL;
167
        $xml .= '<activity id="'.$glossaryData['id'].'" moduleid="'.$glossaryData['moduleid'].'" modulename="'.$glossaryData['modulename'].'" contextid="'.$glossaryData['contextid'].'">'.PHP_EOL;
168
        $xml .= '  <glossary id="'.$glossaryData['id'].'">'.PHP_EOL;
169
        $xml .= '    <name>'.$esc((string) $glossaryData['name']).'</name>'.PHP_EOL;
170
        $xml .= '    <intro>'.$esc($introHtml).'</intro>'.PHP_EOL;
171
        $xml .= '    <introformat>1</introformat>'.PHP_EOL;
172
        $xml .= '    <allowduplicatedentries>0</allowduplicatedentries>'.PHP_EOL;
173
        $xml .= '    <displayformat>dictionary</displayformat>'.PHP_EOL;
174
        $xml .= '    <mainglossary>0</mainglossary>'.PHP_EOL;
175
        $xml .= '    <showspecial>1</showspecial>'.PHP_EOL;
176
        $xml .= '    <showalphabet>1</showalphabet>'.PHP_EOL;
177
        $xml .= '    <showall>1</showall>'.PHP_EOL;
178
        $xml .= '    <allowcomments>0</allowcomments>'.PHP_EOL;
179
        $xml .= '    <allowprintview>1</allowprintview>'.PHP_EOL;
180
        $xml .= '    <usedynalink>1</usedynalink>'.PHP_EOL;
181
        $xml .= '    <defaultapproval>1</defaultapproval>'.PHP_EOL;
182
        $xml .= '    <globalglossary>0</globalglossary>'.PHP_EOL;
183
        $xml .= '    <entbypage>10</entbypage>'.PHP_EOL;
184
        $xml .= '    <editalways>0</editalways>'.PHP_EOL;
185
        $xml .= '    <rsstype>0</rsstype>'.PHP_EOL;
186
        $xml .= '    <rssarticles>0</rssarticles>'.PHP_EOL;
187
        $xml .= '    <assessed>0</assessed>'.PHP_EOL;
188
        $xml .= '    <assesstimestart>0</assesstimestart>'.PHP_EOL;
189
        $xml .= '    <assesstimefinish>0</assesstimefinish>'.PHP_EOL;
190
        $xml .= '    <scale>100</scale>'.PHP_EOL;
191
        $xml .= '    <timecreated>'.$glossaryData['timecreated'].'</timecreated>'.PHP_EOL;
192
        $xml .= '    <timemodified>'.$glossaryData['timemodified'].'</timemodified>'.PHP_EOL;
193
        $xml .= '    <completionentries>0</completionentries>'.PHP_EOL;
194
195
        // Entries
196
        $xml .= '    <entries>'.PHP_EOL;
197
        foreach ($glossaryData['entries'] as $entry) {
198
            $xml .= '      <entry id="'.$entry['id'].'">'.PHP_EOL;
199
            $xml .= '        <userid>'.$entry['userid'].'</userid>'.PHP_EOL;
200
            $xml .= '        <concept>'.$esc((string) $entry['concept']).'</concept>'.PHP_EOL;
201
            $xml .= '        <definition>'.$esc((string) $entry['definition']).'</definition>'.PHP_EOL;
202
            $xml .= '        <definitionformat>1</definitionformat>'.PHP_EOL;
203
            $xml .= '        <definitiontrust>0</definitiontrust>'.PHP_EOL;
204
            $xml .= '        <attachment></attachment>'.PHP_EOL;
205
            $xml .= '        <timecreated>'.$entry['timecreated'].'</timecreated>'.PHP_EOL;
206
            $xml .= '        <timemodified>'.$entry['timemodified'].'</timemodified>'.PHP_EOL;
207
            $xml .= '        <teacherentry>1</teacherentry>'.PHP_EOL;
208
            $xml .= '        <sourceglossaryid>0</sourceglossaryid>'.PHP_EOL;
209
            $xml .= '        <usedynalink>1</usedynalink>'.PHP_EOL;
210
            $xml .= '        <casesensitive>0</casesensitive>'.PHP_EOL;
211
            $xml .= '        <fullmatch>0</fullmatch>'.PHP_EOL;
212
            $xml .= '        <approved>1</approved>'.PHP_EOL;
213
            $xml .= '        <aliases>'.PHP_EOL;
214
            $aliasId = 1;
215
            if (!empty($entry['aliases']) && \is_array($entry['aliases'])) {
216
                foreach ($entry['aliases'] as $a) {
217
                    $xml .= '          <alias id="'.$aliasId.'">'.PHP_EOL;
218
                    $xml .= '            <alias_text>'.$esc((string) $a).'</alias_text>'.PHP_EOL;
219
                    $xml .= '          </alias>'.PHP_EOL;
220
                    $aliasId++;
221
                }
222
            }
223
            $xml .= '        </aliases>'.PHP_EOL;
224
            $xml .= '        <ratings></ratings>'.PHP_EOL;
225
            $xml .= '      </entry>'.PHP_EOL;
226
        }
227
        $xml .= '    </entries>'.PHP_EOL;
228
229
        $xml .= '    <entriestags></entriestags>'.PHP_EOL;
230
        $xml .= '    <categories></categories>'.PHP_EOL;
231
        $xml .= '  </glossary>'.PHP_EOL;
232
        $xml .= '</activity>';
233
234
        $this->createXmlFile('glossary', $xml, $glossaryDir);
235
    }
236
}
237