Passed
Pull Request — master (#6921)
by
unknown
09:03
created

Course::serialize()   A

Complexity

Conditions 4
Paths 6

Size

Total Lines 15
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 8
c 0
b 0
f 0
nc 6
nop 1
dl 0
loc 15
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
/* For licensing terms, see /license.txt */
6
7
namespace Chamilo\CourseBundle\Component\CourseCopy;
8
9
use Chamilo\CourseBundle\Component\CourseCopy\Resources\Resource;
10
use UnserializeApi;
11
12
/**
13
 * A course-object to use in Export/Import/Backup/Copy.
14
 *
15
 * @author Bart Mollet <[email protected]>
16
 */
17
class Course
18
{
19
    public array $resources;
20
    public string $code;
21
    public string $path;
22
    public ?string $destination_path = null;
23
    public ?string $destination_db = null;
24
    public string $encoding;
25
    public string $type;
26
    public string $backup_path = '';
27
28
    /** @var array<string,mixed> Legacy-friendly metadata bag (alias of $meta) */
29
    public array $info;
30
31
    /** @var array<string,mixed> Canonical metadata bag */
32
    public array $meta;
33
34
    /**
35
     * Create a new Course-object.
36
     */
37
    public function __construct()
38
    {
39
        $this->resources = [];
40
        $this->code = '';
41
        $this->path = '';
42
        $this->backup_path = '';
43
        $this->encoding = api_get_system_encoding();
44
        $this->type = '';
45
46
        // Keep $info and $meta in sync (alias)
47
        $this->info = [];
48
        $this->meta =& $this->info;
49
    }
50
51
    /**
52
     * Check if a resource links to the given resource.
53
     *
54
     * @param mixed $resource_to_check
55
     */
56
    public function is_linked_resource(&$resource_to_check): bool
57
    {
58
        foreach ($this->resources as $type => $resources) {
59
            if (\is_array($resources)) {
60
                foreach ($resources as $resource) {
61
                    Resource::setClassType($resource);
62
                    if ($resource->links_to($resource_to_check)) {
63
                        return true;
64
                    }
65
                    if (RESOURCE_LEARNPATH === $type && 'CourseCopyLearnpath' === $resource::class) {
66
                        if ($resource->has_item($resource_to_check)) {
67
                            return true;
68
                        }
69
                    }
70
                }
71
            }
72
        }
73
74
        return false;
75
    }
76
77
    /**
78
     * Add a resource from a given type to this course.
79
     */
80
    public function add_resource(&$resource): void
81
    {
82
        $this->resources[$resource->get_type()][$resource->get_id()] = $resource;
83
    }
84
85
    /**
86
     * Does this course have resources?
87
     *
88
     * @param int|null $type If provided, only check that type.
89
     */
90
    public function has_resources($type = null): bool
91
    {
92
        if (null !== $type) {
93
            return isset($this->resources[$type])
94
                && \is_array($this->resources[$type])
95
                && \count($this->resources[$type]) > 0;
96
        }
97
98
        return \count($this->resources) > 0;
99
    }
100
101
    public function show(): void
102
    {
103
        // no-op
104
    }
105
106
    /**
107
     * Returns sample text based on the imported course content.
108
     * This is used for language/encoding detection when metadata is missing.
109
     */
110
    public function get_sample_text(): string
111
    {
112
        $sample_text = '';
113
114
        foreach ($this->resources as $type => &$resources) {
115
            if (\count($resources) <= 0) {
116
                continue;
117
            }
118
119
            foreach ($resources as $id => &$resource) {
120
                $title = '';
121
                $description = '';
122
123
                switch ($type) {
124
                    case RESOURCE_ANNOUNCEMENT:
125
                    case RESOURCE_EVENT:
126
                    case RESOURCE_THEMATIC:
127
                    case RESOURCE_WIKI:
128
                        $title = $resource->title;
129
                        $description = $resource->content;
130
                        break;
131
132
                    case RESOURCE_DOCUMENT:
133
                        $title = $resource->title;
134
                        $description = $resource->comment;
135
                        break;
136
137
                    case RESOURCE_FORUM:
138
                    case RESOURCE_FORUMCATEGORY:
139
                    case RESOURCE_LINK:
140
                    case RESOURCE_LINKCATEGORY:
141
                    case RESOURCE_QUIZ:
142
                    case RESOURCE_TEST_CATEGORY:
143
                    case RESOURCE_WORK:
144
                        $title = $resource->title;
145
                        $description = $resource->description;
146
                        break;
147
148
                    case RESOURCE_FORUMPOST:
149
                        $title = $resource->title;
150
                        $description = $resource->text;
151
                        break;
152
153
                    case RESOURCE_SCORM:
154
                    case RESOURCE_FORUMTOPIC:
155
                        $title = $resource->title;
156
                        break;
157
158
                    case RESOURCE_GLOSSARY:
159
                    case RESOURCE_LEARNPATH:
160
                        $title = $resource->name;
161
                        $description = $resource->description;
162
                        break;
163
164
                    case RESOURCE_LEARNPATH_CATEGORY:
165
                        $title = $resource->name;
166
                        break;
167
168
                    case RESOURCE_QUIZQUESTION:
169
                        $title = $resource->question;
170
                        $description = $resource->description;
171
                        break;
172
173
                    case RESOURCE_SURVEY:
174
                        $title = $resource->title;
175
                        $description = $resource->subtitle;
176
                        break;
177
178
                    case RESOURCE_SURVEYQUESTION:
179
                        $title = $resource->survey_question;
180
                        $description = $resource->survey_question_comment;
181
                        break;
182
183
                    case RESOURCE_TOOL_INTRO:
184
                        $description = $resource->intro_text;
185
                        break;
186
187
                    case RESOURCE_ATTENDANCE:
188
                        $title = $resource->params['name'];
189
                        $description = $resource->params['description'];
190
                        break;
191
192
                    default:
193
                        break;
194
                }
195
196
                $title = api_html_to_text($title);
197
                $description = api_html_to_text($description);
198
199
                if ($title !== '') {
200
                    $sample_text .= $title . "\n";
201
                }
202
                if ($description !== '') {
203
                    $sample_text .= $description . "\n";
204
                }
205
                if ($title !== '' || $description !== '') {
206
                    $sample_text .= "\n";
207
                }
208
            }
209
        }
210
211
        return $sample_text;
212
    }
213
214
    /**
215
     * Converts to the system encoding all the language-sensitive fields in the imported course.
216
     */
217
    public function to_system_encoding(): void
218
    {
219
        foreach ($this->resources as $type => &$resources) {
220
            if (\count($resources) <= 0) {
221
                continue;
222
            }
223
224
            foreach ($resources as &$resource) {
225
                switch ($type) {
226
                    case RESOURCE_ANNOUNCEMENT:
227
                    case RESOURCE_EVENT:
228
                        $resource->title = api_to_system_encoding($resource->title, $this->encoding);
229
                        $resource->content = api_to_system_encoding($resource->content, $this->encoding);
230
                        break;
231
232
                    case RESOURCE_DOCUMENT:
233
                        $resource->title = api_to_system_encoding($resource->title, $this->encoding);
234
                        $resource->comment = api_to_system_encoding($resource->comment, $this->encoding);
235
                        break;
236
237
                    case RESOURCE_FORUM:
238
                    case RESOURCE_QUIZ:
239
                    case RESOURCE_FORUMCATEGORY:
240
                        if (isset($resource->title)) {
241
                            $resource->title = api_to_system_encoding($resource->title, $this->encoding);
242
                        }
243
                        if (isset($resource->description)) {
244
                            $resource->description = api_to_system_encoding($resource->description, $this->encoding);
245
                        }
246
                        if (isset($resource->obj)) {
247
                            foreach (['cat_title', 'cat_comment', 'title', 'description'] as $f) {
248
                                if (isset($resource->obj->{$f}) && \is_string($resource->obj->{$f})) {
249
                                    $resource->obj->{$f} = api_to_system_encoding($resource->obj->{$f}, $this->encoding);
250
                                }
251
                            }
252
                        }
253
                        break;
254
255
                    case RESOURCE_LINK:
256
                    case RESOURCE_LINKCATEGORY:
257
                    case RESOURCE_TEST_CATEGORY:
258
                        $resource->title = api_to_system_encoding($resource->title, $this->encoding);
259
                        $resource->description = api_to_system_encoding($resource->description, $this->encoding);
260
                        break;
261
262
                    case RESOURCE_FORUMPOST:
263
                        if (isset($resource->title)) {
264
                            $resource->title = api_to_system_encoding($resource->title, $this->encoding);
265
                        }
266
                        if (isset($resource->text)) {
267
                            $resource->text = api_to_system_encoding($resource->text, $this->encoding);
268
                        }
269
                        if (isset($resource->poster_name)) {
270
                            $resource->poster_name = api_to_system_encoding($resource->poster_name, $this->encoding);
271
                        }
272
                        break;
273
274
                    case RESOURCE_FORUMTOPIC:
275
                        if (isset($resource->title)) {
276
                            $resource->title = api_to_system_encoding($resource->title, $this->encoding);
277
                        }
278
                        if (isset($resource->topic_poster_name)) {
279
                            $resource->topic_poster_name = api_to_system_encoding($resource->topic_poster_name, $this->encoding);
280
                        }
281
                        if (isset($resource->title_qualify)) {
282
                            $resource->title_qualify = api_to_system_encoding($resource->title_qualify, $this->encoding);
283
                        }
284
                        break;
285
286
                    case RESOURCE_GLOSSARY:
287
                        $resource->name = api_to_system_encoding($resource->name, $this->encoding);
288
                        $resource->description = api_to_system_encoding($resource->description, $this->encoding);
289
                        break;
290
291
                    case RESOURCE_LEARNPATH:
292
                        $resource->name = api_to_system_encoding($resource->name, $this->encoding);
293
                        $resource->description = api_to_system_encoding($resource->description, $this->encoding);
294
                        $resource->content_maker = api_to_system_encoding($resource->content_maker, $this->encoding);
295
                        $resource->content_license = api_to_system_encoding($resource->content_license, $this->encoding);
296
                        break;
297
298
                    case RESOURCE_QUIZQUESTION:
299
                        $resource->question = api_to_system_encoding($resource->question, $this->encoding);
300
                        $resource->description = api_to_system_encoding($resource->description, $this->encoding);
301
                        if (\is_array($resource->answers) && \count($resource->answers) > 0) {
302
                            foreach ($resource->answers as &$answer) {
303
                                $answer['answer'] = api_to_system_encoding($answer['answer'], $this->encoding);
304
                                $answer['comment'] = api_to_system_encoding($answer['comment'], $this->encoding);
305
                            }
306
                        }
307
                        break;
308
309
                    case RESOURCE_SCORM:
310
                        $resource->title = api_to_system_encoding($resource->title, $this->encoding);
311
                        break;
312
313
                    case RESOURCE_SURVEY:
314
                        $resource->title = api_to_system_encoding($resource->title, $this->encoding);
315
                        $resource->subtitle = api_to_system_encoding($resource->subtitle, $this->encoding);
316
                        $resource->author = api_to_system_encoding($resource->author, $this->encoding);
317
                        $resource->intro = api_to_system_encoding($resource->intro, $this->encoding);
318
                        $resource->surveythanks = api_to_system_encoding($resource->surveythanks, $this->encoding);
319
                        break;
320
321
                    case RESOURCE_SURVEYQUESTION:
322
                        $resource->survey_question = api_to_system_encoding($resource->survey_question, $this->encoding);
323
                        $resource->survey_question_comment = api_to_system_encoding($resource->survey_question_comment, $this->encoding);
324
                        break;
325
326
                    case RESOURCE_TOOL_INTRO:
327
                        $resource->intro_text = api_to_system_encoding($resource->intro_text, $this->encoding);
328
                        break;
329
330
                    case RESOURCE_WIKI:
331
                        $resource->title = api_to_system_encoding($resource->title, $this->encoding);
332
                        $resource->content = api_to_system_encoding($resource->content, $this->encoding);
333
                        $resource->reflink = api_to_system_encoding($resource->reflink, $this->encoding);
334
                        break;
335
336
                    case RESOURCE_WORK:
337
                        $resource->url = api_to_system_encoding($resource->url, $this->encoding);
338
                        $resource->title = api_to_system_encoding($resource->title, $this->encoding);
339
                        $resource->description = api_to_system_encoding($resource->description, $this->encoding);
340
                        break;
341
342
                    default:
343
                        break;
344
                }
345
            }
346
        }
347
348
        $this->encoding = api_get_system_encoding();
349
    }
350
351
    /**
352
     * Serialize the course with the best serializer available (optionally compressed).
353
     */
354
    public static function serialize($course): string
355
    {
356
        $serialized = \extension_loaded('igbinary')
357
            ? igbinary_serialize($course)
358
            : serialize($course);
359
360
        // Compress if possible
361
        if (\function_exists('gzdeflate')) {
362
            $deflated = gzdeflate($serialized, 9);
363
            if ($deflated !== false) {
364
                $serialized = $deflated;
365
            }
366
        }
367
368
        return $serialized;
369
    }
370
371
    /**
372
     * Unserialize the course with the best serializer available.
373
     *
374
     * @return Course
375
     */
376
    public static function unserialize($course): Course
377
    {
378
        // Try to uncompress
379
        if (\function_exists('gzinflate')) {
380
            $inflated = @gzinflate($course);
381
            if ($inflated !== false) {
382
                $course = $inflated;
383
            }
384
        }
385
386
        $unserialized = \extension_loaded('igbinary')
387
            ? igbinary_unserialize($course)
388
            : UnserializeApi::unserialize('course', $course);
389
390
        /** @var Course $unserialized */
391
        return $unserialized;
392
    }
393
}
394