Passed
Push — master ( 6c23c3...c1688f )
by Julito
09:45
created

ScormExport::exportToPdf()   C

Complexity

Conditions 12
Paths 3

Size

Total Lines 79
Code Lines 51

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 12
eloc 51
c 1
b 0
f 0
nc 3
nop 2
dl 0
loc 79
rs 6.9666

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/* For licensing terms, see /license.txt */
4
5
use Chamilo\CoreBundle\Framework\Container;
6
use Chamilo\CourseBundle\Entity\CLp;
7
use Chamilo\CourseBundle\Entity\CLpItem;
8
use Symfony\Component\Filesystem\Filesystem;
9
10
class ScormExport
11
{
12
    public static function export(learnpath $lp)
13
    {
14
        // @todo fix export
15
        api_set_more_memory_and_time_limits();
16
17
        $_course = api_get_course_info();
18
        $course_id = $_course['real_id'];
19
        // Create the zip handler (this will remain available throughout the method).
20
        $archivePath = api_get_path(SYS_ARCHIVE_PATH);
21
        $sys_course_path = api_get_path(SYS_COURSE_PATH);
22
        $temp_dir_short = uniqid('scorm_export', true);
23
        $temp_zip_dir = $archivePath.'/'.$temp_dir_short;
24
        $temp_zip_file = $temp_zip_dir.'/'.md5(time()).'.zip';
25
        $zip_folder = new PclZip($temp_zip_file);
26
        $current_course_path = api_get_path(SYS_COURSE_PATH).api_get_course_path();
27
        $root_path = $main_path = api_get_path(SYS_PATH);
28
        $files_cleanup = [];
29
30
        // Place to temporarily stash the zip file.
31
        // create the temp dir if it doesn't exist
32
        // or do a cleanup before creating the zip file.
33
        if (!is_dir($temp_zip_dir)) {
34
            mkdir($temp_zip_dir, api_get_permissions_for_new_directories());
35
        } else {
36
            // Cleanup: Check the temp dir for old files and delete them.
37
            $handle = opendir($temp_zip_dir);
38
            while (false !== ($file = readdir($handle))) {
39
                if ('.' != $file && '..' != $file) {
40
                    unlink("$temp_zip_dir/$file");
41
                }
42
            }
43
            closedir($handle);
44
        }
45
        $zip_files = $zip_files_abs = $zip_files_dist = [];
46
        if (is_dir($current_course_path.'/scorm/'.$lp->path) &&
47
            is_file($current_course_path.'/scorm/'.$lp->path.'/imsmanifest.xml')
48
        ) {
49
            // Remove the possible . at the end of the path.
50
            $dest_path_to_lp = '.' == substr($lp->path, -1) ? substr($lp->path, 0, -1) : $lp->path;
51
            $dest_path_to_scorm_folder = str_replace('//', '/', $temp_zip_dir.'/scorm/'.$dest_path_to_lp);
52
            mkdir(
53
                $dest_path_to_scorm_folder,
54
                api_get_permissions_for_new_directories(),
55
                true
56
            );
57
            copyr(
58
                $current_course_path.'/scorm/'.$lp->path,
59
                $dest_path_to_scorm_folder,
60
                ['imsmanifest'],
61
                $zip_files
62
            );
63
        }
64
65
        // Build a dummy imsmanifest structure.
66
        // Do not add to the zip yet (we still need it).
67
        // This structure is developed following regulations for SCORM 1.2 packaging in the SCORM 1.2 Content
68
        // Aggregation Model official document, section "2.3 Content Packaging".
69
        // We are going to build a UTF-8 encoded manifest.
70
        // Later we will recode it to the desired (and supported) encoding.
71
        $xmldoc = new DOMDocument('1.0');
72
        $root = $xmldoc->createElement('manifest');
73
        $root->setAttribute('identifier', 'SingleCourseManifest');
74
        $root->setAttribute('version', '1.1');
75
        $root->setAttribute('xmlns', 'http://www.imsproject.org/xsd/imscp_rootv1p1p2');
76
        $root->setAttribute('xmlns:adlcp', 'http://www.adlnet.org/xsd/adlcp_rootv1p2');
77
        $root->setAttribute('xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance');
78
        $root->setAttribute(
79
            'xsi:schemaLocation',
80
            'http://www.imsproject.org/xsd/imscp_rootv1p1p2 imscp_rootv1p1p2.xsd http://www.imsglobal.org/xsd/imsmd_rootv1p2p1 imsmd_rootv1p2p1.xsd http://www.adlnet.org/xsd/adlcp_rootv1p2 adlcp_rootv1p2.xsd'
81
        );
82
        // Build mandatory sub-root container elements.
83
        $metadata = $xmldoc->createElement('metadata');
84
        $md_schema = $xmldoc->createElement('schema', 'ADL SCORM');
85
        $metadata->appendChild($md_schema);
86
        $md_schemaversion = $xmldoc->createElement('schemaversion', '1.2');
87
        $metadata->appendChild($md_schemaversion);
88
        $root->appendChild($metadata);
89
90
        $organizations = $xmldoc->createElement('organizations');
91
        $resources = $xmldoc->createElement('resources');
92
93
        // Build the only organization we will use in building our learnpaths.
94
        $organizations->setAttribute('default', 'chamilo_scorm_export');
95
        $organization = $xmldoc->createElement('organization');
96
        $organization->setAttribute('identifier', 'chamilo_scorm_export');
97
        // To set the title of the SCORM entity (=organization), we take the name given
98
        // in Chamilo and convert it to HTML entities using the Chamilo charset (not the
99
        // learning path charset) as it is the encoding that defines how it is stored
100
        // in the database. Then we convert it to HTML entities again as the "&" character
101
        // alone is not authorized in XML (must be &amp;).
102
        // The title is then decoded twice when extracting (see scorm::parse_manifest).
103
        $org_title = $xmldoc->createElement('title', api_utf8_encode($lp->get_name()));
104
        $organization->appendChild($org_title);
105
        $folder_name = 'document';
106
107
        // Removes the learning_path/scorm_folder path when exporting see #4841
108
        $path_to_remove = '';
109
        $path_to_replace = '';
110
        $result = $lp->generate_lp_folder($_course);
111
        if (isset($result['dir']) && strpos($result['dir'], 'learning_path')) {
112
            $path_to_remove = 'document'.$result['dir'];
113
            $path_to_replace = $folder_name.'/';
114
        }
115
116
        // Fixes chamilo scorm exports
117
        if ('chamilo_scorm_export' === $lp->ref) {
118
            $path_to_remove = 'scorm/'.$lp->path.'/document/';
119
        }
120
121
        // For each element, add it to the imsmanifest structure, then add it to the zip.
122
        $link_updates = [];
123
        $links_to_create = [];
124
        foreach ($lp->ordered_items as $index => $itemId) {
125
            /** @var learnpathItem $item */
126
            $item = $lp->items[$itemId];
127
            if (!in_array($item->type, [TOOL_QUIZ, TOOL_FORUM, TOOL_THREAD, TOOL_LINK, TOOL_STUDENTPUBLICATION])) {
128
                // Get included documents from this item.
129
                if ('sco' === $item->type) {
130
                    $inc_docs = $item->get_resources_from_source(
131
                        null,
132
                        $current_course_path.'/scorm/'.$lp->path.'/'.$item->get_path()
133
                    );
134
                } else {
135
                    $inc_docs = $item->get_resources_from_source();
136
                }
137
138
                // Give a child element <item> to the <organization> element.
139
                $my_item_id = $item->get_id();
140
                $my_item = $xmldoc->createElement('item');
141
                $my_item->setAttribute('identifier', 'ITEM_'.$my_item_id);
142
                $my_item->setAttribute('identifierref', 'RESOURCE_'.$my_item_id);
143
                $my_item->setAttribute('isvisible', 'true');
144
                // Give a child element <title> to the <item> element.
145
                $my_title = $xmldoc->createElement(
146
                    'title',
147
                    htmlspecialchars(
148
                        api_utf8_encode($item->get_title()),
149
                        ENT_QUOTES,
150
                        'UTF-8'
151
                    )
152
                );
153
                $my_item->appendChild($my_title);
154
                // Give a child element <adlcp:prerequisites> to the <item> element.
155
                $my_prereqs = $xmldoc->createElement(
156
                    'adlcp:prerequisites',
157
                    $lp->get_scorm_prereq_string($my_item_id)
158
                );
159
                $my_prereqs->setAttribute('type', 'aicc_script');
160
                $my_item->appendChild($my_prereqs);
161
                // Give a child element <adlcp:maxtimeallowed> to the <item> element - not yet supported.
162
                //$xmldoc->createElement('adlcp:maxtimeallowed','');
163
                // Give a child element <adlcp:timelimitaction> to the <item> element - not yet supported.
164
                //$xmldoc->createElement('adlcp:timelimitaction','');
165
                // Give a child element <adlcp:datafromlms> to the <item> element - not yet supported.
166
                //$xmldoc->createElement('adlcp:datafromlms','');
167
                // Give a child element <adlcp:masteryscore> to the <item> element.
168
                $my_masteryscore = $xmldoc->createElement('adlcp:masteryscore', $item->get_mastery_score());
169
                $my_item->appendChild($my_masteryscore);
170
171
                // Attach this item to the organization element or hits parent if there is one.
172
                if (!empty($item->parent) && 0 != $item->parent) {
173
                    $children = $organization->childNodes;
174
                    $possible_parent = $lp->get_scorm_xml_node($children, 'ITEM_'.$item->parent);
175
                    if (is_object($possible_parent)) {
176
                        $possible_parent->appendChild($my_item);
177
                    } else {
178
                        if ($lp->debug > 0) {
179
                            error_log('Parent ITEM_'.$item->parent.' of item ITEM_'.$my_item_id.' not found');
180
                        }
181
                    }
182
                } else {
183
                    if ($lp->debug > 0) {
184
                        error_log('No parent');
185
                    }
186
                    $organization->appendChild($my_item);
187
                }
188
189
                // Get the path of the file(s) from the course directory root.
190
                $my_file_path = $item->get_file_path('scorm/'.$lp->path.'/');
191
                $my_xml_file_path = $my_file_path;
192
                if (!empty($path_to_remove)) {
193
                    // From docs
194
                    $my_xml_file_path = str_replace($path_to_remove, $path_to_replace, $my_file_path);
195
196
                    // From quiz
197
                    if ('chamilo_scorm_export' === $lp->ref) {
198
                        $path_to_remove = 'scorm/'.$lp->path.'/';
199
                        $my_xml_file_path = str_replace($path_to_remove, '', $my_file_path);
200
                    }
201
                }
202
203
                $my_sub_dir = dirname($my_file_path);
204
                $my_sub_dir = str_replace('\\', '/', $my_sub_dir);
205
                $my_xml_sub_dir = $my_sub_dir;
206
                // Give a <resource> child to the <resources> element
207
                $my_resource = $xmldoc->createElement('resource');
208
                $my_resource->setAttribute('identifier', 'RESOURCE_'.$item->get_id());
209
                $my_resource->setAttribute('type', 'webcontent');
210
                $my_resource->setAttribute('href', $my_xml_file_path);
211
                // adlcp:scormtype can be either 'sco' or 'asset'.
212
                if ('sco' === $item->type) {
213
                    $my_resource->setAttribute('adlcp:scormtype', 'sco');
214
                } else {
215
                    $my_resource->setAttribute('adlcp:scormtype', 'asset');
216
                }
217
                // xml:base is the base directory to find the files declared in this resource.
218
                $my_resource->setAttribute('xml:base', '');
219
                // Give a <file> child to the <resource> element.
220
                $my_file = $xmldoc->createElement('file');
221
                $my_file->setAttribute('href', $my_xml_file_path);
222
                $my_resource->appendChild($my_file);
223
224
                // Dependency to other files - not yet supported.
225
                $i = 1;
226
                if ($inc_docs) {
227
                    foreach ($inc_docs as $doc_info) {
228
                        if (count($doc_info) < 1 || empty($doc_info[0])) {
229
                            continue;
230
                        }
231
                        $my_dep = $xmldoc->createElement('resource');
232
                        $res_id = 'RESOURCE_'.$item->get_id().'_'.$i;
233
                        $my_dep->setAttribute('identifier', $res_id);
234
                        $my_dep->setAttribute('type', 'webcontent');
235
                        $my_dep->setAttribute('adlcp:scormtype', 'asset');
236
                        $my_dep_file = $xmldoc->createElement('file');
237
                        // Check type of URL.
238
                        if ('remote' == $doc_info[1]) {
239
                            // Remote file. Save url as is.
240
                            $my_dep_file->setAttribute('href', $doc_info[0]);
241
                            $my_dep->setAttribute('xml:base', '');
242
                        } elseif ('local' === $doc_info[1]) {
243
                            switch ($doc_info[2]) {
244
                                case 'url':
245
                                    // Local URL - save path as url for now, don't zip file.
246
                                    $abs_path = api_get_path(SYS_PATH).
247
                                        str_replace(api_get_path(WEB_PATH), '', $doc_info[0]);
248
                                    $current_dir = dirname($abs_path);
249
                                    $current_dir = str_replace('\\', '/', $current_dir);
250
                                    $file_path = realpath($abs_path);
251
                                    $file_path = str_replace('\\', '/', $file_path);
252
                                    $my_dep_file->setAttribute('href', $file_path);
253
                                    $my_dep->setAttribute('xml:base', '');
254
                                    if (false !== strstr($file_path, $main_path)) {
255
                                        // The calculated real path is really inside Chamilo's root path.
256
                                        // Reduce file path to what's under the DocumentRoot.
257
                                        $replace = $file_path;
258
                                        $file_path = substr($file_path, strlen($root_path) - 1);
259
                                        $destinationFile = $file_path;
260
261
                                        if (false !== strstr($file_path, 'upload/users')) {
262
                                            $pos = strpos($file_path, 'my_files/');
263
                                            if (false !== $pos) {
264
                                                $onlyDirectory = str_replace(
265
                                                    'upload/users/',
266
                                                    '',
267
                                                    substr($file_path, $pos, strlen($file_path))
268
                                                );
269
                                            }
270
                                            $replace = $onlyDirectory;
271
                                            $destinationFile = $replace;
272
                                        }
273
                                        $zip_files_abs[] = $file_path;
274
                                        $link_updates[$my_file_path][] = [
275
                                            'orig' => $doc_info[0],
276
                                            'dest' => $destinationFile,
277
                                            'replace' => $replace,
278
                                        ];
279
                                        $my_dep_file->setAttribute('href', $file_path);
280
                                        $my_dep->setAttribute('xml:base', '');
281
                                    } elseif (empty($file_path)) {
282
                                        $file_path = $_SERVER['DOCUMENT_ROOT'].$abs_path;
283
                                        $file_path = str_replace('//', '/', $file_path);
284
                                        if (file_exists($file_path)) {
285
                                            // We get the relative path.
286
                                            $file_path = substr($file_path, strlen($current_dir));
287
                                            $zip_files[] = $my_sub_dir.'/'.$file_path;
288
                                            $link_updates[$my_file_path][] = [
289
                                                'orig' => $doc_info[0],
290
                                                'dest' => $file_path,
291
                                            ];
292
                                            $my_dep_file->setAttribute('href', $file_path);
293
                                            $my_dep->setAttribute('xml:base', '');
294
                                        }
295
                                    }
296
                                    break;
297
                                case 'abs':
298
                                    // Absolute path from DocumentRoot. Save file and leave path as is in the zip.
299
                                    $my_dep_file->setAttribute('href', $doc_info[0]);
300
                                    $my_dep->setAttribute('xml:base', '');
301
302
                                    // The next lines fix a bug when using the "subdir" mode of Chamilo, whereas
303
                                    // an image path would be constructed as /var/www/subdir/subdir/img/foo.bar
304
                                    $abs_img_path_without_subdir = $doc_info[0];
305
                                    $relp = api_get_path(REL_PATH); // The url-append config param.
306
                                    $pos = strpos($abs_img_path_without_subdir, $relp);
307
                                    if (0 === $pos) {
308
                                        $abs_img_path_without_subdir = trim('/'.substr($abs_img_path_without_subdir, strlen($relp)));
309
                                    }
310
311
                                    $file_path = realpath(api_get_path(SYS_APP_PATH).$abs_img_path_without_subdir);
312
                                    $file_path = str_replace(['\\', '//'], '/', $file_path);
313
314
                                    // Prepare the current directory path (until just under 'document') with a trailing slash.
315
                                    $cur_path = '/' == substr($current_course_path, -1) ? $current_course_path : $current_course_path.'/';
316
                                    // Check if the current document is in that path.
317
                                    if (false !== strstr($file_path, $cur_path)) {
318
                                        $destinationFile = substr($file_path, strlen($cur_path));
319
                                        $filePathNoCoursePart = substr($file_path, strlen($cur_path));
320
321
                                        $fileToTest = $cur_path.$my_file_path;
322
                                        if (!empty($path_to_remove)) {
323
                                            $fileToTest = str_replace(
324
                                                $path_to_remove.'/',
325
                                                $path_to_replace,
326
                                                $cur_path.$my_file_path
327
                                            );
328
                                        }
329
330
                                        $relative_path = api_get_relative_path($fileToTest, $file_path);
331
332
                                        // Put the current document in the zip (this array is the array
333
                                        // that will manage documents already in the course folder - relative).
334
                                        $zip_files[] = $filePathNoCoursePart;
335
                                        // Update the links to the current document in the
336
                                        // containing document (make them relative).
337
                                        $link_updates[$my_file_path][] = [
338
                                            'orig' => $doc_info[0],
339
                                            'dest' => $destinationFile,
340
                                            'replace' => $relative_path,
341
                                        ];
342
343
                                        $my_dep_file->setAttribute('href', $file_path);
344
                                        $my_dep->setAttribute('xml:base', '');
345
                                    } elseif (false !== strstr($file_path, $main_path)) {
346
                                        // The calculated real path is really inside Chamilo's root path.
347
                                        // Reduce file path to what's under the DocumentRoot.
348
                                        $file_path = substr($file_path, strlen($root_path));
349
                                        $zip_files_abs[] = $file_path;
350
                                        $link_updates[$my_file_path][] = ['orig' => $doc_info[0], 'dest' => $file_path];
351
                                        $my_dep_file->setAttribute('href', 'document/'.$file_path);
352
                                        $my_dep->setAttribute('xml:base', '');
353
                                    } elseif (empty($file_path)) {
354
                                        // Probably this is an image inside "/main" directory
355
                                        $file_path = api_get_path(SYS_PATH).$abs_img_path_without_subdir;
356
                                        $abs_path = api_get_path(SYS_PATH).str_replace(api_get_path(WEB_PATH), '', $doc_info[0]);
357
358
                                        if (file_exists($file_path)) {
359
                                            if (false !== strstr($file_path, 'main/default_course_document')) {
360
                                                // We get the relative path.
361
                                                $pos = strpos($file_path, 'main/default_course_document/');
362
                                                if (false !== $pos) {
363
                                                    $onlyDirectory = str_replace(
364
                                                        'main/default_course_document/',
365
                                                        '',
366
                                                        substr($file_path, $pos, strlen($file_path))
367
                                                    );
368
                                                }
369
370
                                                $destinationFile = 'default_course_document/'.$onlyDirectory;
371
                                                $fileAbs = substr($file_path, strlen(api_get_path(SYS_PATH)));
372
                                                $zip_files_abs[] = $fileAbs;
373
                                                $link_updates[$my_file_path][] = [
374
                                                    'orig' => $doc_info[0],
375
                                                    'dest' => $destinationFile,
376
                                                ];
377
                                                $my_dep_file->setAttribute('href', 'document/'.$file_path);
378
                                                $my_dep->setAttribute('xml:base', '');
379
                                            }
380
                                        }
381
                                    }
382
                                    break;
383
                                case 'rel':
384
                                    // Path relative to the current document.
385
                                    // Save xml:base as current document's directory and save file in zip as subdir.file_path
386
                                    if ('..' === substr($doc_info[0], 0, 2)) {
387
                                        // Relative path going up.
388
                                        $current_dir = dirname($current_course_path.'/'.$item->get_file_path()).'/';
389
                                        $current_dir = str_replace('\\', '/', $current_dir);
390
                                        $file_path = realpath($current_dir.$doc_info[0]);
391
                                        $file_path = str_replace('\\', '/', $file_path);
392
                                        if (false !== strstr($file_path, $main_path)) {
393
                                            // The calculated real path is really inside Chamilo's root path.
394
                                            // Reduce file path to what's under the DocumentRoot.
395
                                            $file_path = substr($file_path, strlen($root_path));
396
                                            $zip_files_abs[] = $file_path;
397
                                            $link_updates[$my_file_path][] = ['orig' => $doc_info[0], 'dest' => $file_path];
398
                                            $my_dep_file->setAttribute('href', 'document/'.$file_path);
399
                                            $my_dep->setAttribute('xml:base', '');
400
                                        }
401
                                    } else {
402
                                        $zip_files[] = $my_sub_dir.'/'.$doc_info[0];
403
                                        $my_dep_file->setAttribute('href', $doc_info[0]);
404
                                        $my_dep->setAttribute('xml:base', $my_xml_sub_dir);
405
                                    }
406
                                    break;
407
                                default:
408
                                    $my_dep_file->setAttribute('href', $doc_info[0]);
409
                                    $my_dep->setAttribute('xml:base', '');
410
                                    break;
411
                            }
412
                        }
413
                        $my_dep->appendChild($my_dep_file);
414
                        $resources->appendChild($my_dep);
415
                        $dependency = $xmldoc->createElement('dependency');
416
                        $dependency->setAttribute('identifierref', $res_id);
417
                        $my_resource->appendChild($dependency);
418
                        $i++;
419
                    }
420
                }
421
                $resources->appendChild($my_resource);
422
                $zip_files[] = $my_file_path;
423
            } else {
424
                // If the item is a quiz or a link or whatever non-exportable, we include a step indicating it.
425
                switch ($item->type) {
426
                    case TOOL_LINK:
427
                        $my_item = $xmldoc->createElement('item');
428
                        $my_item->setAttribute('identifier', 'ITEM_'.$item->get_id());
429
                        $my_item->setAttribute('identifierref', 'RESOURCE_'.$item->get_id());
430
                        $my_item->setAttribute('isvisible', 'true');
431
                        // Give a child element <title> to the <item> element.
432
                        $my_title = $xmldoc->createElement(
433
                            'title',
434
                            htmlspecialchars(
435
                                api_utf8_encode($item->get_title()),
436
                                ENT_QUOTES,
437
                                'UTF-8'
438
                            )
439
                        );
440
                        $my_item->appendChild($my_title);
441
                        // Give a child element <adlcp:prerequisites> to the <item> element.
442
                        $my_prereqs = $xmldoc->createElement('adlcp:prerequisites', $item->get_prereq_string());
443
                        $my_prereqs->setAttribute('type', 'aicc_script');
444
                        $my_item->appendChild($my_prereqs);
445
                        // Give a child element <adlcp:maxtimeallowed> to the <item> element - not yet supported.
446
                        //$xmldoc->createElement('adlcp:maxtimeallowed', '');
447
                        // Give a child element <adlcp:timelimitaction> to the <item> element - not yet supported.
448
                        //$xmldoc->createElement('adlcp:timelimitaction', '');
449
                        // Give a child element <adlcp:datafromlms> to the <item> element - not yet supported.
450
                        //$xmldoc->createElement('adlcp:datafromlms', '');
451
                        // Give a child element <adlcp:masteryscore> to the <item> element.
452
                        $my_masteryscore = $xmldoc->createElement('adlcp:masteryscore', $item->get_mastery_score());
453
                        $my_item->appendChild($my_masteryscore);
454
455
                        // Attach this item to the organization element or its parent if there is one.
456
                        if (!empty($item->parent) && 0 != $item->parent) {
457
                            $children = $organization->childNodes;
458
                            for ($i = 0; $i < $children->length; $i++) {
459
                                $item_temp = $children->item($i);
460
                                if ('item' == $item_temp->nodeName) {
461
                                    if ($item_temp->getAttribute('identifier') == 'ITEM_'.$item->parent) {
462
                                        $item_temp->appendChild($my_item);
463
                                    }
464
                                }
465
                            }
466
                        } else {
467
                            $organization->appendChild($my_item);
468
                        }
469
470
                        $my_file_path = 'link_'.$item->get_id().'.html';
471
                        $sql = 'SELECT url, title FROM '.Database::get_course_table(TABLE_LINK).'
472
                                WHERE c_id = '.$course_id.' AND id = '.$item->path;
473
                        $rs = Database::query($sql);
474
                        if ($link = Database::fetch_array($rs)) {
475
                            $url = $link['url'];
476
                            $title = stripslashes($link['title']);
477
                            $links_to_create[$my_file_path] = ['title' => $title, 'url' => $url];
478
                            $my_xml_file_path = $my_file_path;
479
                            $my_sub_dir = dirname($my_file_path);
480
                            $my_sub_dir = str_replace('\\', '/', $my_sub_dir);
481
                            $my_xml_sub_dir = $my_sub_dir;
482
                            // Give a <resource> child to the <resources> element.
483
                            $my_resource = $xmldoc->createElement('resource');
484
                            $my_resource->setAttribute('identifier', 'RESOURCE_'.$item->get_id());
485
                            $my_resource->setAttribute('type', 'webcontent');
486
                            $my_resource->setAttribute('href', $my_xml_file_path);
487
                            // adlcp:scormtype can be either 'sco' or 'asset'.
488
                            $my_resource->setAttribute('adlcp:scormtype', 'asset');
489
                            // xml:base is the base directory to find the files declared in this resource.
490
                            $my_resource->setAttribute('xml:base', '');
491
                            // give a <file> child to the <resource> element.
492
                            $my_file = $xmldoc->createElement('file');
493
                            $my_file->setAttribute('href', $my_xml_file_path);
494
                            $my_resource->appendChild($my_file);
495
                            $resources->appendChild($my_resource);
496
                        }
497
                        break;
498
                    case TOOL_QUIZ:
499
                        $exe_id = $item->path;
500
                        // Should be using ref when everything will be cleaned up in this regard.
501
                        $exe = new Exercise();
502
                        $exe->read($exe_id);
503
                        $my_item = $xmldoc->createElement('item');
504
                        $my_item->setAttribute('identifier', 'ITEM_'.$item->get_id());
505
                        $my_item->setAttribute('identifierref', 'RESOURCE_'.$item->get_id());
506
                        $my_item->setAttribute('isvisible', 'true');
507
                        // Give a child element <title> to the <item> element.
508
                        $my_title = $xmldoc->createElement(
509
                            'title',
510
                            htmlspecialchars(
511
                                api_utf8_encode($item->get_title()),
512
                                ENT_QUOTES,
513
                                'UTF-8'
514
                            )
515
                        );
516
                        $my_item->appendChild($my_title);
517
                        $my_max_score = $xmldoc->createElement('max_score', $item->get_max());
518
                        $my_item->appendChild($my_max_score);
519
                        // Give a child element <adlcp:prerequisites> to the <item> element.
520
                        $my_prereqs = $xmldoc->createElement('adlcp:prerequisites', $item->get_prereq_string());
521
                        $my_prereqs->setAttribute('type', 'aicc_script');
522
                        $my_item->appendChild($my_prereqs);
523
                        // Give a child element <adlcp:masteryscore> to the <item> element.
524
                        $my_masteryscore = $xmldoc->createElement('adlcp:masteryscore', $item->get_mastery_score());
525
                        $my_item->appendChild($my_masteryscore);
526
527
                        // Attach this item to the organization element or hits parent if there is one.
528
                        if (!empty($item->parent) && 0 != $item->parent) {
529
                            $children = $organization->childNodes;
530
                            $possible_parent = $lp->get_scorm_xml_node($children, 'ITEM_'.$item->parent);
531
                            if ($possible_parent) {
532
                                if ($possible_parent->getAttribute('identifier') === 'ITEM_'.$item->parent) {
533
                                    $possible_parent->appendChild($my_item);
534
                                }
535
                            }
536
                        } else {
537
                            $organization->appendChild($my_item);
538
                        }
539
540
                        // Get the path of the file(s) from the course directory root
541
                        //$my_file_path = $item->get_file_path('scorm/'.$lp->path.'/');
542
                        $my_file_path = 'quiz_'.$item->get_id().'.html';
543
                        // Write the contents of the exported exercise into a (big) html file
544
                        // to later pack it into the exported SCORM. The file will be removed afterwards.
545
                        $scormExercise = new ScormExercise($exe, true);
546
                        $contents = $scormExercise->export();
547
548
                        $tmp_file_path = $archivePath.$temp_dir_short.'/'.$my_file_path;
549
                        $res = file_put_contents($tmp_file_path, $contents);
550
                        if (false === $res) {
551
                            error_log('Could not write into file '.$tmp_file_path.' '.__FILE__.' '.__LINE__, 0);
552
                        }
553
                        $files_cleanup[] = $tmp_file_path;
554
                        $my_xml_file_path = $my_file_path;
555
                        $my_sub_dir = dirname($my_file_path);
556
                        $my_sub_dir = str_replace('\\', '/', $my_sub_dir);
557
                        $my_xml_sub_dir = $my_sub_dir;
558
                        // Give a <resource> child to the <resources> element.
559
                        $my_resource = $xmldoc->createElement('resource');
560
                        $my_resource->setAttribute('identifier', 'RESOURCE_'.$item->get_id());
561
                        $my_resource->setAttribute('type', 'webcontent');
562
                        $my_resource->setAttribute('href', $my_xml_file_path);
563
                        // adlcp:scormtype can be either 'sco' or 'asset'.
564
                        $my_resource->setAttribute('adlcp:scormtype', 'sco');
565
                        // xml:base is the base directory to find the files declared in this resource.
566
                        $my_resource->setAttribute('xml:base', '');
567
                        // Give a <file> child to the <resource> element.
568
                        $my_file = $xmldoc->createElement('file');
569
                        $my_file->setAttribute('href', $my_xml_file_path);
570
                        $my_resource->appendChild($my_file);
571
572
                        // Get included docs.
573
                        $inc_docs = $item->get_resources_from_source(null, $tmp_file_path);
574
575
                        // Dependency to other files - not yet supported.
576
                        $i = 1;
577
                        foreach ($inc_docs as $doc_info) {
578
                            if (count($doc_info) < 1 || empty($doc_info[0])) {
579
                                continue;
580
                            }
581
                            $my_dep = $xmldoc->createElement('resource');
582
                            $res_id = 'RESOURCE_'.$item->get_id().'_'.$i;
583
                            $my_dep->setAttribute('identifier', $res_id);
584
                            $my_dep->setAttribute('type', 'webcontent');
585
                            $my_dep->setAttribute('adlcp:scormtype', 'asset');
586
                            $my_dep_file = $xmldoc->createElement('file');
587
                            // Check type of URL.
588
                            if ('remote' == $doc_info[1]) {
589
                                // Remote file. Save url as is.
590
                                $my_dep_file->setAttribute('href', $doc_info[0]);
591
                                $my_dep->setAttribute('xml:base', '');
592
                            } elseif ('local' == $doc_info[1]) {
593
                                switch ($doc_info[2]) {
594
                                    case 'url': // Local URL - save path as url for now, don't zip file.
595
                                        // Save file but as local file (retrieve from URL).
596
                                        $abs_path = api_get_path(SYS_PATH).
597
                                            str_replace(api_get_path(WEB_PATH), '', $doc_info[0]);
598
                                        $current_dir = dirname($abs_path);
599
                                        $current_dir = str_replace('\\', '/', $current_dir);
600
                                        $file_path = realpath($abs_path);
601
                                        $file_path = str_replace('\\', '/', $file_path);
602
                                        $my_dep_file->setAttribute('href', 'document/'.$file_path);
603
                                        $my_dep->setAttribute('xml:base', '');
604
                                        if (false !== strstr($file_path, $main_path)) {
605
                                            // The calculated real path is really inside the chamilo root path.
606
                                            // Reduce file path to what's under the DocumentRoot.
607
                                            $file_path = substr($file_path, strlen($root_path));
608
                                            $zip_files_abs[] = $file_path;
609
                                            $link_updates[$my_file_path][] = [
610
                                                'orig' => $doc_info[0],
611
                                                'dest' => 'document/'.$file_path,
612
                                            ];
613
                                            $my_dep_file->setAttribute('href', 'document/'.$file_path);
614
                                            $my_dep->setAttribute('xml:base', '');
615
                                        } elseif (empty($file_path)) {
616
                                            $file_path = $_SERVER['DOCUMENT_ROOT'].$abs_path;
617
                                            $file_path = str_replace('//', '/', $file_path);
618
                                            if (file_exists($file_path)) {
619
                                                $file_path = substr($file_path, strlen($current_dir));
620
                                                // We get the relative path.
621
                                                $zip_files[] = $my_sub_dir.'/'.$file_path;
622
                                                $link_updates[$my_file_path][] = [
623
                                                    'orig' => $doc_info[0],
624
                                                    'dest' => 'document/'.$file_path,
625
                                                ];
626
                                                $my_dep_file->setAttribute('href', 'document/'.$file_path);
627
                                                $my_dep->setAttribute('xml:base', '');
628
                                            }
629
                                        }
630
                                        break;
631
                                    case 'abs':
632
                                        // Absolute path from DocumentRoot. Save file and leave path as is in the zip.
633
                                        $current_dir = dirname($current_course_path.'/'.$item->get_file_path()).'/';
634
                                        $current_dir = str_replace('\\', '/', $current_dir);
635
                                        $file_path = realpath($doc_info[0]);
636
                                        $file_path = str_replace('\\', '/', $file_path);
637
                                        $my_dep_file->setAttribute('href', $file_path);
638
                                        $my_dep->setAttribute('xml:base', '');
639
640
                                        if (false !== strstr($file_path, $main_path)) {
641
                                            // The calculated real path is really inside the chamilo root path.
642
                                            // Reduce file path to what's under the DocumentRoot.
643
                                            $file_path = substr($file_path, strlen($root_path));
644
                                            $zip_files_abs[] = $file_path;
645
                                            $link_updates[$my_file_path][] = [
646
                                                'orig' => $doc_info[0],
647
                                                'dest' => $file_path,
648
                                            ];
649
                                            $my_dep_file->setAttribute('href', 'document/'.$file_path);
650
                                            $my_dep->setAttribute('xml:base', '');
651
                                        } elseif (empty($file_path)) {
652
                                            $docSysPartPath = str_replace(
653
                                                api_get_path(REL_COURSE_PATH),
654
                                                '',
655
                                                $doc_info[0]
656
                                            );
657
658
                                            $docSysPartPathNoCourseCode = str_replace(
659
                                                $_course['directory'].'/',
660
                                                '',
661
                                                $docSysPartPath
662
                                            );
663
664
                                            $docSysPath = api_get_path(SYS_COURSE_PATH).$docSysPartPath;
665
                                            if (file_exists($docSysPath)) {
666
                                                $file_path = $docSysPartPathNoCourseCode;
667
                                                $zip_files[] = $my_sub_dir.'/'.$file_path;
668
                                                $link_updates[$my_file_path][] = [
669
                                                    'orig' => $doc_info[0],
670
                                                    'dest' => $file_path,
671
                                                ];
672
                                                $my_dep_file->setAttribute('href', 'document/'.$file_path);
673
                                                $my_dep->setAttribute('xml:base', '');
674
                                            }
675
                                        }
676
                                        break;
677
                                    case 'rel':
678
                                        // Path relative to the current document. Save xml:base as current document's
679
                                        // directory and save file in zip as subdir.file_path
680
                                        if ('..' === substr($doc_info[0], 0, 2)) {
681
                                            // Relative path going up.
682
                                            $current_dir = dirname($current_course_path.'/'.$item->get_file_path()).'/';
683
                                            $current_dir = str_replace('\\', '/', $current_dir);
684
                                            $file_path = realpath($current_dir.$doc_info[0]);
685
                                            $file_path = str_replace('\\', '/', $file_path);
686
                                            if (false !== strstr($file_path, $main_path)) {
687
                                                // The calculated real path is really inside Chamilo's root path.
688
                                                // Reduce file path to what's under the DocumentRoot.
689
690
                                                $file_path = substr($file_path, strlen($root_path));
691
                                                $file_path_dest = $file_path;
692
693
                                                // File path is courses/CHAMILO/document/....
694
                                                $info_file_path = explode('/', $file_path);
695
                                                if ('courses' == $info_file_path[0]) {
696
                                                    // Add character "/" in file path.
697
                                                    $file_path_dest = 'document/'.$file_path;
698
                                                }
699
                                                $zip_files_abs[] = $file_path;
700
701
                                                $link_updates[$my_file_path][] = [
702
                                                    'orig' => $doc_info[0],
703
                                                    'dest' => $file_path_dest,
704
                                                ];
705
                                                $my_dep_file->setAttribute('href', 'document/'.$file_path);
706
                                                $my_dep->setAttribute('xml:base', '');
707
                                            }
708
                                        } else {
709
                                            $zip_files[] = $my_sub_dir.'/'.$doc_info[0];
710
                                            $my_dep_file->setAttribute('href', $doc_info[0]);
711
                                            $my_dep->setAttribute('xml:base', $my_xml_sub_dir);
712
                                        }
713
                                        break;
714
                                    default:
715
                                        $my_dep_file->setAttribute('href', $doc_info[0]); // ../../courses/
716
                                        $my_dep->setAttribute('xml:base', '');
717
                                        break;
718
                                }
719
                            }
720
                            $my_dep->appendChild($my_dep_file);
721
                            $resources->appendChild($my_dep);
722
                            $dependency = $xmldoc->createElement('dependency');
723
                            $dependency->setAttribute('identifierref', $res_id);
724
                            $my_resource->appendChild($dependency);
725
                            $i++;
726
                        }
727
                        $resources->appendChild($my_resource);
728
                        $zip_files[] = $my_file_path;
729
                        break;
730
                    default:
731
                        // Get the path of the file(s) from the course directory root
732
                        $my_file_path = 'non_exportable.html';
733
                        //$my_xml_file_path = api_htmlentities(api_utf8_encode($my_file_path), ENT_COMPAT, 'UTF-8');
734
                        $my_xml_file_path = $my_file_path;
735
                        $my_sub_dir = dirname($my_file_path);
736
                        $my_sub_dir = str_replace('\\', '/', $my_sub_dir);
737
                        //$my_xml_sub_dir = api_htmlentities(api_utf8_encode($my_sub_dir), ENT_COMPAT, 'UTF-8');
738
                        $my_xml_sub_dir = $my_sub_dir;
739
                        // Give a <resource> child to the <resources> element.
740
                        $my_resource = $xmldoc->createElement('resource');
741
                        $my_resource->setAttribute('identifier', 'RESOURCE_'.$item->get_id());
742
                        $my_resource->setAttribute('type', 'webcontent');
743
                        $my_resource->setAttribute('href', $folder_name.'/'.$my_xml_file_path);
744
                        // adlcp:scormtype can be either 'sco' or 'asset'.
745
                        $my_resource->setAttribute('adlcp:scormtype', 'asset');
746
                        // xml:base is the base directory to find the files declared in this resource.
747
                        $my_resource->setAttribute('xml:base', '');
748
                        // Give a <file> child to the <resource> element.
749
                        $my_file = $xmldoc->createElement('file');
750
                        $my_file->setAttribute('href', 'document/'.$my_xml_file_path);
751
                        $my_resource->appendChild($my_file);
752
                        $resources->appendChild($my_resource);
753
                        break;
754
                }
755
            }
756
        }
757
        $organizations->appendChild($organization);
758
        $root->appendChild($organizations);
759
        $root->appendChild($resources);
760
        $xmldoc->appendChild($root);
761
762
        $copyAll = api_get_configuration_value('add_all_files_in_lp_export');
763
764
        // then add the file to the zip, then destroy the file (this is done automatically).
765
        // http://www.reload.ac.uk/scormplayer.html - once done, don't forget to close FS#138
766
        foreach ($zip_files as $file_path) {
767
            if (empty($file_path)) {
768
                continue;
769
            }
770
771
            $filePath = $sys_course_path.$_course['path'].'/'.$file_path;
772
            $dest_file = $archivePath.$temp_dir_short.'/'.$file_path;
773
774
            if (!empty($path_to_remove) && !empty($path_to_replace)) {
775
                $dest_file = str_replace($path_to_remove, $path_to_replace, $dest_file);
776
            }
777
778
            $lp->create_path($dest_file);
779
            @copy($filePath, $dest_file);
780
781
            // Check if the file needs a link update.
782
            if (in_array($file_path, array_keys($link_updates))) {
783
                $string = file_get_contents($dest_file);
784
                unlink($dest_file);
785
                foreach ($link_updates[$file_path] as $old_new) {
786
                    // This is an ugly hack that allows .flv files to be found by the flv player that
787
                    // will be added in document/main/inc/lib/flv_player/flv_player.swf and that needs
788
                    // to find the flv to play in document/main/, so we replace main/ in the flv path by
789
                    // ../../.. to return from inc/lib/flv_player to the document/main path.
790
                    if ('flv' === substr($old_new['dest'], -3) &&
791
                        'main/' === substr($old_new['dest'], 0, 5)
792
                    ) {
793
                        $old_new['dest'] = str_replace('main/', '../../../', $old_new['dest']);
794
                    } elseif ('flv' === substr($old_new['dest'], -3) &&
795
                        'video/' === substr($old_new['dest'], 0, 6)
796
                    ) {
797
                        $old_new['dest'] = str_replace('video/', '../../../../video/', $old_new['dest']);
798
                    }
799
800
                    // Fix to avoid problems with default_course_document
801
                    if (false === strpos('main/default_course_document', $old_new['dest'])) {
802
                        $newDestination = $old_new['dest'];
803
                        if (isset($old_new['replace']) && !empty($old_new['replace'])) {
804
                            $newDestination = $old_new['replace'];
805
                        }
806
                    } else {
807
                        $newDestination = str_replace('document/', '', $old_new['dest']);
808
                    }
809
                    $string = str_replace($old_new['orig'], $newDestination, $string);
810
811
                    // Add files inside the HTMLs
812
                    $new_path = str_replace(api_get_path(REL_COURSE_PATH), '', $old_new['orig']);
813
                    $destinationFile = $archivePath.$temp_dir_short.'/'.$old_new['dest'];
814
                    if (file_exists($sys_course_path.$new_path) && is_file($sys_course_path.$new_path)) {
815
                        copy(
816
                            $sys_course_path.$new_path,
817
                            $destinationFile
818
                        );
819
                    }
820
                }
821
                file_put_contents($dest_file, $string);
822
            }
823
824
            if (file_exists($filePath) && $copyAll) {
825
                $extension = $lp->get_extension($filePath);
826
                if (in_array($extension, ['html', 'html'])) {
827
                    $containerOrigin = dirname($filePath);
828
                    $containerDestination = dirname($dest_file);
829
830
                    $finder = new Finder();
831
                    $finder->files()->in($containerOrigin)
832
                        ->notName('*_DELETED_*')
833
                        ->exclude('share_folder')
834
                        ->exclude('chat_files')
835
                        ->exclude('certificates')
836
                    ;
837
838
                    if (is_dir($containerOrigin) &&
839
                        is_dir($containerDestination)
840
                    ) {
841
                        $fs = new Filesystem();
842
                        $fs->mirror(
843
                            $containerOrigin,
844
                            $containerDestination,
845
                            $finder
846
                        );
847
                    }
848
                }
849
            }
850
        }
851
852
        foreach ($zip_files_abs as $file_path) {
853
            if (empty($file_path)) {
854
                continue;
855
            }
856
857
            if (!is_file($main_path.$file_path) || !is_readable($main_path.$file_path)) {
858
                continue;
859
            }
860
861
            $dest_file = $archivePath.$temp_dir_short.'/document/'.$file_path;
862
            if (false !== strstr($file_path, 'upload/users')) {
863
                $pos = strpos($file_path, 'my_files/');
864
                if (false !== $pos) {
865
                    $onlyDirectory = str_replace(
866
                        'upload/users/',
867
                        '',
868
                        substr($file_path, $pos, strlen($file_path))
869
                    );
870
                    $dest_file = $archivePath.$temp_dir_short.'/document/'.$onlyDirectory;
871
                }
872
            }
873
874
            if (false !== strstr($file_path, 'default_course_document/')) {
875
                $replace = str_replace('/main', '', $file_path);
876
                $dest_file = $archivePath.$temp_dir_short.'/document/'.$replace;
877
            }
878
879
            if (empty($dest_file)) {
880
                continue;
881
            }
882
883
            $lp->create_path($dest_file);
884
            copy($main_path.$file_path, $dest_file);
885
            // Check if the file needs a link update.
886
            if (in_array($file_path, array_keys($link_updates))) {
887
                $string = file_get_contents($dest_file);
888
                unlink($dest_file);
889
                foreach ($link_updates[$file_path] as $old_new) {
890
                    // This is an ugly hack that allows .flv files to be found by the flv player that
891
                    // will be added in document/main/inc/lib/flv_player/flv_player.swf and that needs
892
                    // to find the flv to play in document/main/, so we replace main/ in the flv path by
893
                    // ../../.. to return from inc/lib/flv_player to the document/main path.
894
                    if ('flv' == substr($old_new['dest'], -3) &&
895
                        'main/' == substr($old_new['dest'], 0, 5)
896
                    ) {
897
                        $old_new['dest'] = str_replace('main/', '../../../', $old_new['dest']);
898
                    }
899
                    $string = str_replace($old_new['orig'], $old_new['dest'], $string);
900
                }
901
                file_put_contents($dest_file, $string);
902
            }
903
        }
904
905
        if (is_array($links_to_create)) {
906
            foreach ($links_to_create as $file => $link) {
907
                $content = '<!DOCTYPE html><head>
908
                            <meta charset="'.api_get_language_isocode().'" />
909
                            <title>'.$link['title'].'</title>
910
                            </head>
911
                            <body dir="'.api_get_text_direction().'">
912
                            <div style="text-align:center">
913
                            <a href="'.$link['url'].'">'.$link['title'].'</a></div>
914
                            </body>
915
                            </html>';
916
                file_put_contents($archivePath.$temp_dir_short.'/'.$file, $content);
917
            }
918
        }
919
920
        // Add non exportable message explanation.
921
        $lang_not_exportable = get_lang('This learning object or activity is not SCORM compliant. That\'s why it is not exportable.');
922
        $file_content = '<!DOCTYPE html><head>
923
                        <meta charset="'.api_get_language_isocode().'" />
924
                        <title>'.$lang_not_exportable.'</title>
925
                        <meta http-equiv="Content-Type" content="text/html; charset='.api_get_system_encoding().'" />
926
                        </head>
927
                        <body dir="'.api_get_text_direction().'">';
928
        $file_content .=
929
            <<<EOD
930
                    <style>
931
            .error-message {
932
                font-family: arial, verdana, helvetica, sans-serif;
933
                border-width: 1px;
934
                border-style: solid;
935
                left: 50%;
936
                margin: 10px auto;
937
                min-height: 30px;
938
                padding: 5px;
939
                right: 50%;
940
                width: 500px;
941
                background-color: #FFD1D1;
942
                border-color: #FF0000;
943
                color: #000;
944
            }
945
        </style>
946
    <body>
947
        <div class="error-message">
948
            $lang_not_exportable
949
        </div>
950
    </body>
951
</html>
952
EOD;
953
        if (!is_dir($archivePath.$temp_dir_short.'/document')) {
954
            @mkdir($archivePath.$temp_dir_short.'/document', api_get_permissions_for_new_directories());
955
        }
956
        file_put_contents($archivePath.$temp_dir_short.'/document/non_exportable.html', $file_content);
957
958
        // Add the extra files that go along with a SCORM package.
959
        $main_code_path = api_get_path(SYS_CODE_PATH).'lp/packaging/';
960
961
        $fs = new Filesystem();
962
        $fs->mirror($main_code_path, $archivePath.$temp_dir_short);
963
964
        // Finalize the imsmanifest structure, add to the zip, then return the zip.
965
        $manifest = @$xmldoc->saveXML();
966
        $manifest = api_utf8_decode_xml($manifest); // The manifest gets the system encoding now.
967
        file_put_contents($archivePath.'/'.$temp_dir_short.'/imsmanifest.xml', $manifest);
968
        $zip_folder->add(
969
            $archivePath.'/'.$temp_dir_short,
970
            PCLZIP_OPT_REMOVE_PATH,
971
            $archivePath.'/'.$temp_dir_short.'/'
972
        );
973
974
        // Clean possible temporary files.
975
        foreach ($files_cleanup as $file) {
976
            $res = unlink($file);
977
            if (false === $res) {
978
                error_log(
979
                    'Could not delete temp file '.$file.' '.__FILE__.' '.__LINE__,
980
                    0
981
                );
982
            }
983
        }
984
        $name = api_replace_dangerous_char($lp->get_name()).'.zip';
985
        DocumentManager::file_send_for_download($temp_zip_file, true, $name);
986
    }
987
988
    public static function exportToPdf($lp_id, $courseInfo)
989
    {
990
        // @todo fix exportToPdf
991
        $lp_id = (int) $lp_id;
992
        /** @var CLp $lp */
993
        $lp = Container::getLpRepository()->find($lp_id);
994
995
        $lpItemRepo = Container::getLpItemRepository();
996
997
        $files_to_export = [];
998
999
        $sessionId = api_get_session_id();
1000
        $courseCode = $courseInfo['code'];
1001
        $scorm_path = null;
1002
1003
        if (!empty($courseInfo)) {
1004
            //$scorm_path = api_get_path(SYS_COURSE_PATH).$courseInfo['path'].'/scorm/'.$this->path;
1005
            $list = learnpath::get_flat_ordered_items_list($lp);
1006
            if (!empty($list)) {
1007
                foreach ($list as $item_id) {
1008
                    /** @var CLpItem $item */
1009
                    $item = $lpItemRepo->find($item_id);
1010
                    $type = $item->getItemType();
1011
                    switch ($type) {
1012
                        case 'document':
1013
                            // Getting documents from a LP with chamilo documents
1014
                            $file_data = DocumentManager::get_document_data_by_id($item->getPath(), $courseCode);
1015
                            // Try loading document from the base course.
1016
                            if (empty($file_data) && !empty($sessionId)) {
1017
                                $file_data = DocumentManager::get_document_data_by_id(
1018
                                    $item->getPath(),
1019
                                    $courseCode,
1020
                                    false,
1021
                                    0
1022
                                );
1023
                            }
1024
                            $file_path = api_get_path(SYS_COURSE_PATH).$courseCode['path'].'/document'.$file_data['path'];
1025
                            if (file_exists($file_path)) {
1026
                                $files_to_export[] = [
1027
                                    'title' => $item->get_title(),
1028
                                    'path' => $file_path,
1029
                                ];
1030
                            }
1031
                            break;
1032
                        case 'asset': //commes from a scorm package generated by chamilo
1033
                        case 'sco':
1034
                            $file_path = $scorm_path.'/'.$item->getPath();
1035
                            if (file_exists($file_path)) {
1036
                                $files_to_export[] = [
1037
                                    'title' => $item->get_title(),
1038
                                    'path' => $file_path,
1039
                                ];
1040
                            }
1041
                            break;
1042
                        case 'dir':
1043
                            $files_to_export[] = [
1044
                                'title' => $item->get_title(),
1045
                                'path' => null,
1046
                            ];
1047
                            break;
1048
                    }
1049
                }
1050
            }
1051
1052
            $pdf = new PDF();
1053
            $result = $pdf->html_to_pdf(
1054
                $files_to_export,
1055
                $lp->getName(),
1056
                $courseCode,
1057
                true,
1058
                true,
1059
                true,
1060
                $lp->getName()
1061
            );
1062
1063
            return $result;
1064
        }
1065
1066
        return false;
1067
    }
1068
}
1069