Passed
Push — 1.11.x ( 056f3f...b39662 )
by
unknown
10:47 queued 14s
created

PageExport::normalizeContent()   A

Complexity

Conditions 2
Paths 1

Size

Total Lines 15
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 9
c 0
b 0
f 0
dl 0
loc 15
rs 9.9666
cc 2
nc 1
nop 1
1
<?php
2
3
/* For licensing terms, see /license.txt */
4
5
namespace moodleexport;
6
7
/**
8
 * Class PageExport.
9
 *
10
 * Handles the export of pages within a course.
11
 */
12
class PageExport extends ActivityExport
13
{
14
    /**
15
     * Export a page to the specified directory.
16
     *
17
     * @param int    $activityId The ID of the page.
18
     * @param string $exportDir  The directory where the page will be exported.
19
     * @param int    $moduleId   The ID of the module.
20
     * @param int    $sectionId  The ID of the section.
21
     */
22
    public function export($activityId, $exportDir, $moduleId, $sectionId): void
23
    {
24
        // Prepare the directory where the page export will be saved
25
        $pageDir = $this->prepareActivityDirectory($exportDir, 'page', $moduleId);
26
27
        // Retrieve page data
28
        $pageData = $this->getData($activityId, $sectionId);
29
30
        // Generate XML files
31
        $this->createPageXml($pageData, $pageDir);
32
        $this->createModuleXml($pageData, $pageDir);
33
        $this->createGradesXml($pageData, $pageDir);
34
        $this->createFiltersXml($pageData, $pageDir);
35
        $this->createGradeHistoryXml($pageData, $pageDir);
36
        $this->createInforefXml($pageData, $pageDir);
37
        $this->createRolesXml($pageData, $pageDir);
38
        $this->createCommentsXml($pageData, $pageDir);
39
        $this->createCalendarXml($pageData, $pageDir);
40
    }
41
42
    /**
43
     * Get page data dynamically from the course.
44
     */
45
    public function getData(int $pageId, int $sectionId): ?array
46
    {
47
        $contextid = $this->course->info['real_id'];
48
        if ($pageId === 0) {
49
            $introText = trim($this->course->resources[RESOURCE_TOOL_INTRO]['course_homepage']->intro_text ?? '');
50
51
            if (!empty($introText)) {
52
                $files = [];
53
                $resources = \DocumentManager::get_resources_from_source_html($introText);
54
                $courseInfo = api_get_course_info($this->course->code);
55
                $adminId = MoodleExport::getAdminUserData()['id'];
56
57
                foreach ($resources as [$src]) {
58
                    if (preg_match('#/document(/[^"\']+)#', $src, $matches)) {
59
                        $path = $matches[1];
60
                        $docId = \DocumentManager::get_document_id($courseInfo, $path);
61
                        if ($docId) {
62
                            $this->course->used_page_doc_ids[] = $docId;
63
                            $document = \DocumentManager::get_document_data_by_id($docId, $this->course->code);
64
                            if ($document) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $document of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
65
                                $contenthash = hash('sha1', basename($document['path']));
66
                                $mimetype = (new FileExport($this->course))->getMimeType($document['path']);
67
68
                                $files[] = [
69
                                    'id' => $document['id'],
70
                                    'contenthash' => $contenthash,
71
                                    'contextid' => $contextid,
72
                                    'component' => 'mod_page',
73
                                    'filearea' => 'content',
74
                                    'itemid' => 1,
75
                                    'filepath' => '/Documents/',
76
                                    'documentpath' => 'document' . $document['path'],
77
                                    'filename' => basename($document['path']),
78
                                    'userid' => $adminId,
79
                                    'filesize' => $document['size'],
80
                                    'mimetype' => $mimetype,
81
                                    'status' => 0,
82
                                    'timecreated' => time() - 3600,
83
                                    'timemodified' => time(),
84
                                    'source' => $document['title'],
85
                                    'author' => 'Unknown',
86
                                    'license' => 'allrightsreserved',
87
                                ];
88
                            }
89
                        }
90
                    }
91
                }
92
93
                return [
94
                    'id' => 0,
95
                    'moduleid' => 0,
96
                    'modulename' => 'page',
97
                    'contextid' => $contextid,
98
                    'name' => get_lang('Introduction'),
99
                    'intro' => '',
100
                    'content' => $this->normalizeContent($introText),
101
                    'sectionid' => $sectionId,
102
                    'sectionnumber' => 1,
103
                    'display' => 0,
104
                    'timemodified' => time(),
105
                    'users' => [],
106
                    'files' => $files,
107
                ];
108
            }
109
        }
110
111
        $pageResources = $this->course->resources[RESOURCE_DOCUMENT] ?? [];
112
        foreach ($pageResources as $page) {
113
            if ($page->source_id == $pageId) {
114
                return [
115
                    'id' => $page->source_id,
116
                    'moduleid' => $page->source_id,
117
                    'modulename' => 'page',
118
                    'contextid' => $contextid,
119
                    'name' => $page->title,
120
                    'intro' => $page->comment ?? '',
121
                    'content' => $this->normalizeContent($this->getPageContent($page)),
122
                    'sectionid' => $sectionId,
123
                    'sectionnumber' => 1,
124
                    'display' => 0,
125
                    'timemodified' => time(),
126
                    'users' => [],
127
                    'files' => [],
128
                ];
129
            }
130
        }
131
132
        return null;
133
    }
134
135
    /**
136
     * Create the XML file for the page.
137
     */
138
    private function createPageXml(array $pageData, string $pageDir): void
139
    {
140
        $xmlContent = '<?xml version="1.0" encoding="UTF-8"?>'.PHP_EOL;
141
        $xmlContent .= '<activity id="'.$pageData['id'].'" moduleid="'.$pageData['moduleid'].'" modulename="page" contextid="'.$pageData['contextid'].'">'.PHP_EOL;
142
        $xmlContent .= '  <page id="'.$pageData['id'].'">'.PHP_EOL;
143
        $xmlContent .= '    <name>'.htmlspecialchars($pageData['name']).'</name>'.PHP_EOL;
144
        $xmlContent .= '    <intro>'.htmlspecialchars($pageData['intro']).'</intro>'.PHP_EOL;
145
        $xmlContent .= '    <introformat>1</introformat>'.PHP_EOL;
146
        $xmlContent .= '    <content>'.htmlspecialchars($pageData['content']).'</content>'.PHP_EOL;
147
        $xmlContent .= '    <contentformat>1</contentformat>'.PHP_EOL;
148
        $xmlContent .= '    <legacyfiles>0</legacyfiles>'.PHP_EOL;
149
        $xmlContent .= '    <display>5</display>'.PHP_EOL;
150
        $xmlContent .= '    <displayoptions>a:3:{s:12:"printheading";s:1:"1";s:10:"printintro";s:1:"0";s:17:"printlastmodified";s:1:"1";}</displayoptions>'.PHP_EOL;
151
        $xmlContent .= '    <revision>1</revision>'.PHP_EOL;
152
        $xmlContent .= '    <timemodified>'.$pageData['timemodified'].'</timemodified>'.PHP_EOL;
153
        $xmlContent .= '  </page>'.PHP_EOL;
154
        $xmlContent .= '</activity>';
155
156
        $this->createXmlFile('page', $xmlContent, $pageDir);
157
    }
158
159
    private function normalizeContent(string $html): string
160
    {
161
        return preg_replace_callback(
162
            '#<img[^>]+src=["\'](?<url>[^"\']+)["\']#i',
163
            function ($match) {
164
                $src = $match['url'];
165
166
                if (preg_match('#/courses/[^/]+/document/(.+)$#', $src, $parts)) {
167
                    $filename = basename($parts[1]);
168
                    return str_replace($src, '@@PLUGINFILE@@/Documents/' . $filename, $match[0]);
169
                }
170
171
                return $match[0];
172
            },
173
            $html
174
        );
175
    }
176
177
    /**
178
     * Retrieves the content of the page.
179
     */
180
    private function getPageContent(object $page): string
181
    {
182
        if ($page->file_type === 'file') {
183
            return file_get_contents($this->course->path.$page->path);
184
        }
185
186
        return '';
187
    }
188
}
189