Passed
Push — 1.11.x ( 1068fc...2c4fea )
by Angel Fernando Quiroz
10:34 queued 11s
created

CourseRestorer::restore_learnpaths()   F

Complexity

Conditions 67

Size

Total Lines 365
Code Lines 248

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 67
eloc 248
c 0
b 0
f 0
nop 2
dl 0
loc 365
rs 3.3333

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
namespace Chamilo\CourseBundle\Component\CourseCopy;
6
7
use Chamilo\CourseBundle\Component\CourseCopy\Resources\GradeBookBackup;
8
use Chamilo\CourseBundle\Component\CourseCopy\Resources\LearnPathCategory;
9
use Chamilo\CourseBundle\Component\CourseCopy\Resources\QuizQuestion;
10
use Chamilo\CourseBundle\Component\CourseCopy\Resources\XapiTool;
11
use Chamilo\CourseBundle\Entity\CLpCategory;
12
use Chamilo\CourseBundle\Entity\CQuizAnswer;
13
use CourseManager;
14
use Database;
15
use DocumentManager;
16
use Question;
17
use stdClass;
18
use SurveyManager;
19
use TestCategory;
20
21
/**
22
 * Class CourseRestorer.
23
 *
24
 * Class to restore items from a course object to a Chamilo-course
25
 *
26
 * @author Bart Mollet <[email protected]>
27
 * @author Julio Montoya <[email protected]> Several fixes/improvements
28
 */
29
class CourseRestorer
30
{
31
    /**
32
     * The course-object.
33
     */
34
    public $course;
35
    public $destination_course_info;
36
37
    /**
38
     * What to do with files with same name (FILE_SKIP, FILE_RENAME or
39
     * FILE_OVERWRITE).
40
     */
41
    public $file_option;
42
    public $set_tools_invisible_by_default;
43
    public $skip_content;
44
    public $tools_to_restore = [
45
        'documents', // first restore documents
46
        'announcements',
47
        'attendance',
48
        'course_descriptions',
49
        'events',
50
        'forum_category',
51
        'forums',
52
       // 'forum_topics',
53
        'glossary',
54
        'quizzes',
55
        'test_category',
56
        'links',
57
        'works',
58
        'xapi_tool',
59
        'surveys',
60
        'learnpath_category',
61
        'learnpaths',
62
        //'scorm_documents', ??
63
        'tool_intro',
64
        'thematic',
65
        'wiki',
66
        'gradebook',
67
        'assets',
68
    ];
69
70
    /** Setting per tool */
71
    public $tool_copy_settings = [];
72
    public $isXapiEnabled = false;
73
74
    /**
75
     * If true adds the text "copy" in the title of an item (only for LPs right now).
76
     */
77
    public $add_text_in_items = false;
78
    public $destination_course_id;
79
80
    /**
81
     * CourseRestorer constructor.
82
     *
83
     * @param Course $course
84
     */
85
    public function __construct($course)
86
    {
87
        $this->course = $course;
88
        $courseInfo = api_get_course_info($this->course->code);
89
        $this->course_origin_id = null;
90
        if (!empty($courseInfo)) {
91
            $this->course_origin_id = $courseInfo['real_id'];
92
        }
93
        $this->file_option = FILE_RENAME;
94
        $this->set_tools_invisible_by_default = false;
95
        $this->skip_content = [];
96
97
        $forceImport = api_get_configuration_value('allow_import_scorm_package_in_course_builder');
98
        if ($forceImport) {
99
            $this->tools_to_restore[] = 'scorm_documents';
100
        }
101
    }
102
103
    /**
104
     * Set the file-option.
105
     *
106
     * @param int $option (optional) What to do with files with same name
107
     *                    FILE_SKIP, FILE_RENAME or FILE_OVERWRITE
108
     */
109
    public function set_file_option($option = FILE_OVERWRITE)
110
    {
111
        $this->file_option = $option;
112
    }
113
114
    /**
115
     * @param bool $status
116
     */
117
    public function set_add_text_in_items($status)
118
    {
119
        $this->add_text_in_items = $status;
120
    }
121
122
    /**
123
     * @param array $array
124
     */
125
    public function set_tool_copy_settings($array)
126
    {
127
        $this->tool_copy_settings = $array;
128
    }
129
130
    /**
131
     * Restore a course.
132
     *
133
     * @param string $destination_course_code code of the Chamilo-course in
134
     * @param int    $session_id
135
     * @param bool   $update_course_settings  Course settings are going to be restore?
136
     * @param bool   $respect_base_content
137
     *
138
     * @return false|null
139
     */
140
    public function restore(
141
        $destination_course_code = '',
142
        $session_id = 0,
143
        $update_course_settings = false,
144
        $respect_base_content = false
145
    ) {
146
        if ($destination_course_code == '') {
147
            $course_info = api_get_course_info();
148
            $this->destination_course_info = $course_info;
149
            $this->course->destination_path = $course_info['path'];
150
        } else {
151
            $course_info = api_get_course_info($destination_course_code);
152
            $this->destination_course_info = $course_info;
153
            $this->course->destination_path = $course_info['path'];
154
        }
155
        $this->destination_course_id = $course_info['real_id'];
156
        // Getting first teacher (for the forums)
157
        $teacher_list = CourseManager::get_teacher_list_from_course_code($course_info['code']);
158
        $this->first_teacher_id = api_get_user_id();
159
        $this->isXapiEnabled = \XApiPlugin::create()->isEnabled();
160
161
        if (!empty($teacher_list)) {
162
            foreach ($teacher_list as $teacher) {
163
                $this->first_teacher_id = $teacher['user_id'];
164
                break;
165
            }
166
        }
167
168
        if (empty($this->course)) {
169
            return false;
170
        }
171
172
        // Source platform encoding - reading/detection
173
        // The correspondent data field has been added as of version 1.8.6.1
174
        if (empty($this->course->encoding)) {
175
            // The archive has been created by a system which is prior to 1.8.6.1 version.
176
            // In this case we have to detect the encoding.
177
            $sample_text = $this->course->get_sample_text()."\n";
178
            // Let us exclude ASCII lines, probably they are English texts.
179
            $sample_text = explode("\n", $sample_text);
180
            foreach ($sample_text as $key => &$line) {
181
                if (api_is_valid_ascii($line)) {
182
                    unset($sample_text[$key]);
183
                }
184
            }
185
            $sample_text = implode("\n", $sample_text);
186
            $this->course->encoding = api_detect_encoding(
187
                $sample_text,
188
                $course_info['language']
189
            );
190
        }
191
192
        // Encoding conversion of the course, if it is needed.
193
        $this->course->to_system_encoding();
194
195
        foreach ($this->tools_to_restore as $tool) {
196
            if ('xapi_tool' == $tool && !$this->isXapiEnabled) {
197
                continue;
198
            }
199
            $function_build = 'restore_'.$tool;
200
            $this->$function_build(
201
                $session_id,
202
                $respect_base_content,
203
                $destination_course_code
204
            );
205
        }
206
207
        if ($update_course_settings) {
208
            $this->restore_course_settings($destination_course_code);
209
        }
210
211
        // Restore the item properties
212
        $table = Database::get_course_table(TABLE_ITEM_PROPERTY);
213
        foreach ($this->course->resources as $type => $resources) {
214
            if (is_array($resources)) {
215
                foreach ($resources as $id => $resource) {
216
                    if (isset($resource->item_properties)) {
217
                        foreach ($resource->item_properties as $property) {
218
                            // First check if there isn't already a record for this resource
219
                            $sql = "SELECT * FROM $table
220
                                    WHERE
221
                                        c_id = ".$this->destination_course_id." AND
222
                                        tool = '".$property['tool']."' AND
223
                                        ref = '".$resource->destination_id."'";
224
225
                            $params = [];
226
                            if (!empty($session_id)) {
227
                                $params['session_id'] = (int) $session_id;
228
                            }
229
230
                            $res = Database::query($sql);
231
                            if (Database::num_rows($res) == 0) {
232
                                /* The to_group_id and to_user_id are set to default
233
                                values as users/groups possibly not exist in
234
                                the target course*/
235
236
                                $params['c_id'] = $this->destination_course_id;
237
                                $params['tool'] = self::DBUTF8($property['tool']);
238
                                $params['insert_user_id'] = $this->checkUserId($property['insert_user_id']) ?: null;
239
                                $params['insert_date'] = self::DBUTF8($property['insert_date']);
240
                                $params['lastedit_date'] = self::DBUTF8($property['lastedit_date']);
241
                                $params['ref'] = $resource->destination_id;
242
                                $params['lastedit_type'] = self::DBUTF8($property['lastedit_type']);
243
                                $params['lastedit_user_id'] = $this->checkUserId($property['lastedit_user_id']);
244
                                $params['visibility'] = self::DBUTF8($property['visibility']);
245
                                $params['start_visible'] = self::DBUTF8($property['start_visible']);
246
                                $params['end_visible'] = self::DBUTF8($property['end_visible']);
247
                                $params['to_user_id'] = $this->checkUserId($property['to_user_id']) ?: null;
248
249
                                $id = Database::insert($table, $params);
250
                                if ($id) {
251
                                    $sql = "UPDATE $table SET id = iid WHERE iid = $id";
252
                                    Database::query($sql);
253
                                }
254
                            }
255
                        }
256
                    }
257
                }
258
            }
259
        }
260
    }
261
262
    /**
263
     * Restore only harmless course settings:
264
     * course_language, visibility, department_name,department_url,
265
     * subscribe, unsubscribe ,category_code.
266
     *
267
     * @param string $destination_course_code
268
     */
269
    public function restore_course_settings($destination_course_code)
270
    {
271
        $origin_course_info = api_get_course_info($destination_course_code);
272
        $course_info = $this->course->info;
273
        $params['course_language'] = $course_info['language'];
274
        $params['visibility'] = $course_info['visibility'];
275
        $params['department_name'] = $course_info['department_name'];
276
        $params['department_url'] = $course_info['department_url'];
277
        $params['category_code'] = $course_info['categoryCode'];
278
        $params['subscribe'] = $course_info['subscribe_allowed'];
279
        $params['unsubscribe'] = $course_info['unsubscribe'];
280
        CourseManager::update_attributes($origin_course_info['real_id'], $params);
281
    }
282
283
    /**
284
     * Restore documents.
285
     *
286
     * @param int    $session_id
287
     * @param bool   $respect_base_content
288
     * @param string $destination_course_code
289
     */
290
    public function restore_documents(
291
        $session_id = 0,
292
        $respect_base_content = false,
293
        $destination_course_code = ''
294
    ) {
295
        $course_info = api_get_course_info($destination_course_code);
296
297
        if (!$this->course->has_resources(RESOURCE_DOCUMENT)) {
298
            return;
299
        }
300
301
        $webEditorCss = api_get_path(WEB_CSS_PATH).'editor.css';
302
        $table = Database::get_course_table(TABLE_DOCUMENT);
303
        $resources = $this->course->resources;
304
        $path = api_get_path(SYS_COURSE_PATH).$this->course->destination_path.'/';
305
        $originalFolderNameList = [];
306
        foreach ($resources[RESOURCE_DOCUMENT] as $id => $document) {
307
            $my_session_id = empty($document->item_properties[0]['session_id']) ? 0 : $session_id;
308
309
            if (false === $respect_base_content && $session_id) {
310
                if (empty($my_session_id)) {
311
                    $my_session_id = $session_id;
312
                }
313
            }
314
315
            if ($document->file_type == FOLDER) {
316
                $visibility = isset($document->item_properties[0]['visibility']) ? $document->item_properties[0]['visibility'] : '';
317
                $new = substr($document->path, 8);
318
                $folderList = explode('/', $new);
319
                $tempFolder = '';
320
321
                // Check if the parent path exists.
322
                foreach ($folderList as $folder) {
323
                    $folderToCreate = $tempFolder.$folder;
324
                    $sysFolderPath = $path.'document'.$folderToCreate;
325
                    $tempFolder .= $folder.'/';
326
327
                    if (empty($folderToCreate)) {
328
                        continue;
329
                    }
330
                    $title = $document->title;
331
                    $originalFolderNameList[basename($document->path)] = $document->title;
332
                    if (empty($title)) {
333
                        $title = basename($sysFolderPath);
334
                    }
335
                    //error_log($title); error_log($sysFolderPath);
336
                    // File doesn't exist in file system.
337
                    if (!is_dir($sysFolderPath)) {
338
                        /*error_log('Creating directory');
339
                        error_log("Creating $folderToCreate");*/
340
                        // Creating directory
341
                        create_unexisting_directory(
342
                            $course_info,
343
                            api_get_user_id(),
344
                            $my_session_id,
345
                            0,
346
                            0,
347
                            $path.'document',
348
                            $folderToCreate,
349
                            $title,
350
                            $visibility
351
                        );
352
                        continue;
353
                    }
354
355
                    // File exist in file system.
356
                    $documentData = DocumentManager::get_document_id(
357
                        $course_info,
358
                        $folderToCreate,
359
                        $session_id
360
                    );
361
362
                    //error_log("session_id $session_id");
363
                    if (empty($documentData)) {
364
                        if (!is_dir($sysFolderPath)) {
365
                            //error_log('$documentData empty');
366
                            //error_log('$folderToCreate '.$folderToCreate);
367
                            /* This means the folder exists in the
368
                            filesystem but not in the DB, trying to fix it */
369
                            add_document(
370
                                $course_info,
371
                                $folderToCreate,
372
                                'folder',
373
                                0,
374
                                $title,
375
                                null,
376
                                null,
377
                                false,
378
                                null,
379
                                $session_id,
380
                                0,
381
                                false
382
                            );
383
                        }
384
                    } else {
385
                        $insertUserId = isset($document->item_properties[0]['insert_user_id']) ? $document->item_properties[0]['insert_user_id'] : api_get_user_id();
386
                        $insertUserId = $this->checkUserId($insertUserId);
387
                        // Check if user exists in platform
388
                        $toUserId = isset($document->item_properties[0]['to_user_id']) ? $document->item_properties[0]['to_user_id'] : null;
389
                        $toUserId = $this->checkUserId($toUserId, true);
390
                        $groupId = isset($document->item_properties[0]['to_group_id']) ? $document->item_properties[0]['to_group_id'] : null;
391
                        $groupInfo = $this->checkGroupId($groupId);
392
                        //error_log(" if folder exists then just refresh it");
393
                        // if folder exists then just refresh it
394
                        api_item_property_update(
395
                            $course_info,
396
                            TOOL_DOCUMENT,
397
                            $documentData,
398
                            'FolderUpdated',
399
                            $insertUserId,
400
                            $groupInfo,
401
                            $toUserId,
402
                            null,
403
                            null,
404
                            $my_session_id
405
                        );
406
                    }
407
                }
408
            } elseif ($document->file_type == DOCUMENT) {
409
                // Checking if folder exists in the database otherwise we created it
410
                $dir_to_create = dirname($document->path);
411
                $originalFolderNameList[basename($document->path)] = $document->title;
412
                if (!empty($dir_to_create) && $dir_to_create != 'document' && $dir_to_create != '/') {
413
                    // it creates folder images if it doesn't exist , used for hotspot pictures.
414
                    if (false !== strpos($document->path, '/images/') && !is_dir(dirname($path.$document->path))) {
415
                        $perm = api_get_permissions_for_new_directories();
416
                        mkdir(dirname($path.$document->path), $perm, true);
417
                    }
418
                    if (is_dir($path.dirname($document->path))) {
419
                        $sql = "SELECT id FROM $table
420
                                WHERE
421
                                    c_id = ".$this->destination_course_id." AND
422
                                    path = '/".self::DBUTF8escapestring(substr(dirname($document->path), 9))."'";
423
                        $res = Database::query($sql);
424
425
                        if (Database::num_rows($res) == 0) {
426
                            $new = '/'.substr(dirname($document->path), 9);
427
                            // It adds the folder name as title
428
                            $title = str_replace('/', '', $new);
429
430
                            // This code fixes the possibility for a file without a directory entry to be
431
                            $document_id = add_document(
432
                                $course_info,
433
                                $new,
434
                                'folder',
435
                                0,
436
                                $title,
437
                                null,
438
                                null,
439
                                false,
440
                                0,
441
                                0,
442
                                0,
443
                                false
444
                            );
445
446
                            $itemProperty = isset($document->item_properties[0]) ? $document->item_properties[0] : '';
447
                            $insertUserId = isset($itemProperty['insert_user_id']) ? $itemProperty['insert_user_id'] : api_get_user_id();
448
                            $toGroupId = isset($itemProperty['to_group_id']) ? $itemProperty['to_group_id'] : 0;
449
                            $toUserId = isset($itemProperty['to_user_id']) ? $itemProperty['to_user_id'] : null;
450
                            $groupInfo = $this->checkGroupId($toGroupId);
451
                            $insertUserId = $this->checkUserId($insertUserId);
452
                            $toUserId = $this->checkUserId($toUserId, true);
453
454
                            api_item_property_update(
455
                                $course_info,
456
                                TOOL_DOCUMENT,
457
                                $document_id,
458
                                'FolderCreated',
459
                                $insertUserId,
460
                                $groupInfo,
461
                                $toUserId,
462
                                null,
463
                                null,
464
                                $my_session_id
465
                            );
466
                        }
467
                    }
468
                }
469
470
                //error_log(print_r($originalFolderNameList, 1));
471
                if (file_exists($path.$document->path)) {
472
                    switch ($this->file_option) {
473
                        case FILE_OVERWRITE:
474
                            $origin_path = $this->course->backup_path.'/'.$document->path;
475
                            if (file_exists($origin_path)) {
476
                                copy($origin_path, $path.$document->path);
477
                                $this->fixEditorHtmlContent($path.$document->path, $webEditorCss);
478
                                $sql = "SELECT id FROM $table
479
                                        WHERE
480
                                            c_id = ".$this->destination_course_id." AND
481
                                            path = '/".self::DBUTF8escapestring(substr($document->path, 9))."'";
482
483
                                $res = Database::query($sql);
484
                                $count = Database::num_rows($res);
485
486
                                if ($count == 0) {
487
                                    $params = [
488
                                        'path' => "/".self::DBUTF8(substr($document->path, 9)),
489
                                        'c_id' => $this->destination_course_id,
490
                                        'comment' => self::DBUTF8($document->comment),
491
                                        'title' => self::DBUTF8($document->title),
492
                                        'filetype' => self::DBUTF8($document->file_type),
493
                                        'size' => self::DBUTF8($document->size),
494
                                        'session_id' => $my_session_id,
495
                                        'readonly' => 0,
496
                                    ];
497
498
                                    $document_id = Database::insert($table, $params);
499
500
                                    if ($document_id) {
501
                                        $sql = "UPDATE $table SET id = iid WHERE iid = $document_id";
502
                                        Database::query($sql);
503
                                    }
504
                                    $this->course->resources[RESOURCE_DOCUMENT][$id]->destination_id = $document_id;
505
506
                                    $itemProperty = isset($document->item_properties[0]) ? $document->item_properties[0] : '';
507
                                    $insertUserId = isset($itemProperty['insert_user_id']) ? $itemProperty['insert_user_id'] : api_get_user_id();
508
                                    $toGroupId = isset($itemProperty['to_group_id']) ? $itemProperty['to_group_id'] : 0;
509
                                    $toUserId = isset($itemProperty['to_user_id']) ? $itemProperty['to_user_id'] : null;
510
511
                                    $insertUserId = $this->checkUserId($insertUserId);
512
                                    $toUserId = $this->checkUserId($toUserId, true);
513
                                    $groupInfo = $this->checkGroupId($toGroupId);
514
515
                                    api_item_property_update(
516
                                        $course_info,
517
                                        TOOL_DOCUMENT,
518
                                        $document_id,
519
                                        'DocumentAdded',
520
                                        $insertUserId,
521
                                        $groupInfo,
522
                                        $toUserId,
523
                                        null,
524
                                        null,
525
                                        $my_session_id
526
                                    );
527
                                } else {
528
                                    $obj = Database::fetch_object($res);
529
                                    $document_id = $obj->id;
530
                                    $params = [
531
                                        'path' => "/".self::DBUTF8(substr($document->path, 9)),
532
                                        'c_id' => $this->destination_course_id,
533
                                        'comment' => self::DBUTF8($document->comment),
534
                                        'title' => self::DBUTF8($document->title),
535
                                        'filetype' => self::DBUTF8($document->file_type),
536
                                        'size' => self::DBUTF8($document->size),
537
                                        'session_id' => $my_session_id,
538
                                    ];
539
540
                                    Database::update(
541
                                        $table,
542
                                        $params,
543
                                        [
544
                                            'c_id = ? AND path = ?' => [
545
                                                $this->destination_course_id,
546
                                                "/".self::DBUTF8escapestring(substr($document->path, 9)),
547
                                            ],
548
                                        ]
549
                                    );
550
551
                                    $this->course->resources[RESOURCE_DOCUMENT][$id]->destination_id = $obj->id;
552
553
                                    $itemProperty = isset($document->item_properties[0]) ? $document->item_properties[0] : '';
554
                                    $insertUserId = isset($itemProperty['insert_user_id']) ? $itemProperty['insert_user_id'] : api_get_user_id();
555
                                    $toGroupId = isset($itemProperty['to_group_id']) ? $itemProperty['to_group_id'] : 0;
556
                                    $toUserId = isset($itemProperty['to_user_id']) ? $itemProperty['to_user_id'] : null;
557
558
                                    $insertUserId = $this->checkUserId($insertUserId);
559
                                    $toUserId = $this->checkUserId($toUserId, true);
560
                                    $groupInfo = $this->checkGroupId($toGroupId);
561
562
                                    api_item_property_update(
563
                                        $course_info,
564
                                        TOOL_DOCUMENT,
565
                                        $obj->id,
566
                                        'default',
567
                                        $insertUserId,
568
                                        $groupInfo,
569
                                        $toUserId,
570
                                        null,
571
                                        null,
572
                                        $my_session_id
573
                                    );
574
                                }
575
576
                                // Replace old course code with the new destination code
577
                                $file_info = pathinfo($path.$document->path);
578
579
                                if (isset($file_info['extension']) && in_array($file_info['extension'], ['html', 'htm'])) {
580
                                    $content = file_get_contents($path.$document->path);
581
                                    if (UTF8_CONVERT) {
582
                                        $content = utf8_encode($content);
583
                                    }
584
                                    $content = DocumentManager::replaceUrlWithNewCourseCode(
585
                                        $content,
586
                                        $this->course->code,
587
                                        $this->course->destination_path,
588
                                        $this->course->backup_path,
589
                                        $this->course->info['path']
590
                                    );
591
                                    file_put_contents($path.$document->path, $content);
592
                                }
593
594
                                $params = [
595
                                    'comment' => self::DBUTF8($document->comment),
596
                                    'title' => self::DBUTF8($document->title),
597
                                    'size' => self::DBUTF8($document->size),
598
                                ];
599
                                Database::update(
600
                                    $table,
601
                                    $params,
602
                                    [
603
                                        'c_id = ? AND id = ?' => [
604
                                            $this->destination_course_id,
605
                                            $document_id,
606
                                        ],
607
                                    ]
608
                                );
609
                            }
610
                            break;
611
                        case FILE_SKIP:
612
                            $sql = "SELECT id FROM $table
613
                                    WHERE
614
                                        c_id = ".$this->destination_course_id." AND
615
                                        path='/".self::DBUTF8escapestring(substr($document->path, 9))."'";
616
                            $res = Database::query($sql);
617
                            $obj = Database::fetch_object($res);
618
                            $this->course->resources[RESOURCE_DOCUMENT][$id]->destination_id = $obj->id;
619
                            break;
620
                        case FILE_RENAME:
621
                            //error_log("Rename: ".$path.$document->path);
622
                            $i = 1;
623
                            $ext = explode('.', basename($document->path));
624
                            if (count($ext) > 1) {
625
                                $ext = array_pop($ext);
626
                                $file_name_no_ext = substr($document->path, 0, -(strlen($ext) + 1));
627
                                $ext = '.'.$ext;
628
                            } else {
629
                                $ext = '';
630
                                $file_name_no_ext = $document->path;
631
                            }
632
                            $new_file_name = $file_name_no_ext.'_'.$i.$ext;
633
                            $file_exists = file_exists($path.$new_file_name);
634
                            while ($file_exists) {
635
                                $i++;
636
                                $new_file_name = $file_name_no_ext.'_'.$i.$ext;
637
                                $file_exists = file_exists($path.$new_file_name);
638
                            }
639
640
                            if (!empty($session_id)) {
641
                                $originalPath = $document->path;
642
                                //error_log("document->path: ".$document->path);
643
                                $document_path = explode('/', $document->path, 3);
644
                                $course_path = $path;
645
                                $orig_base_folder = $document_path[1];
646
                                $orig_base_path = $course_path.$document_path[0].'/'.$document_path[1];
647
648
                                if (is_dir($orig_base_path)) {
649
                                    $new_base_foldername = $orig_base_folder;
650
                                    $new_base_path = $orig_base_path;
651
652
                                    if (isset($_SESSION['orig_base_foldername']) &&
653
                                        $_SESSION['orig_base_foldername'] != $new_base_foldername
654
                                    ) {
655
                                        unset($_SESSION['new_base_foldername']);
656
                                        unset($_SESSION['orig_base_foldername']);
657
                                        unset($_SESSION['new_base_path']);
658
                                    }
659
660
                                    $folder_exists = file_exists($new_base_path);
661
                                    if ($folder_exists) {
662
                                        // e.g: carpeta1 in session
663
                                        $_SESSION['orig_base_foldername'] = $new_base_foldername;
664
                                        $x = 0;
665
                                        while ($folder_exists) {
666
                                            $x = $x + 1;
667
                                            $new_base_foldername = $document_path[1].'_'.$x;
668
                                            $new_base_path = $orig_base_path.'_'.$x;
669
                                            if (isset($_SESSION['new_base_foldername']) &&
670
                                                $_SESSION['new_base_foldername'] == $new_base_foldername
671
                                            ) {
672
                                                break;
673
                                            }
674
                                            $folder_exists = file_exists($new_base_path);
675
                                        }
676
                                        $_SESSION['new_base_foldername'] = $new_base_foldername;
677
                                        $_SESSION['new_base_path'] = $new_base_path;
678
                                    }
679
680
                                    if (isset($_SESSION['new_base_foldername']) && isset($_SESSION['new_base_path'])) {
681
                                        $new_base_foldername = $_SESSION['new_base_foldername'];
682
                                        $new_base_path = $_SESSION['new_base_path'];
683
                                    }
684
685
                                    $dest_document_path = $new_base_path.'/'.$document_path[2]; // e.g: "/var/www/wiener/courses/CURSO4/document/carpeta1_1/subcarpeta1/collaborative.png"
686
                                    $basedir_dest_path = dirname($dest_document_path); // e.g: "/var/www/wiener/courses/CURSO4/document/carpeta1_1/subcarpeta1"
687
                                    $base_path_document = $course_path.$document_path[0]; // e.g: "/var/www/wiener/courses/CURSO4/document"
688
                                    $path_title = '/'.$new_base_foldername.'/'.$document_path[2];
689
690
                                    /*error_log("copy_folder_course_session");
691
                                    error_log("original: $orig_base_path");
692
                                    error_log($basedir_dest_path);
693
                                    error_log($document->title);*/
694
695
                                    copy_folder_course_session(
696
                                        $basedir_dest_path,
697
                                        $base_path_document,
698
                                        $session_id,
699
                                        $course_info,
700
                                        $document,
701
                                        $this->course_origin_id,
702
                                        $originalFolderNameList,
703
                                        $originalPath
704
                                    );
705
706
                                    if (file_exists($course_path.$document->path)) {
707
                                        copy($course_path.$document->path, $dest_document_path);
708
                                    }
709
710
                                    // Replace old course code with the new destination code see BT#1985
711
                                    if (file_exists($dest_document_path)) {
712
                                        $file_info = pathinfo($dest_document_path);
713
                                        if (in_array($file_info['extension'], ['html', 'htm'])) {
714
                                            $content = file_get_contents($dest_document_path);
715
                                            if (UTF8_CONVERT) {
716
                                                $content = utf8_encode($content);
717
                                            }
718
                                            $content = DocumentManager::replaceUrlWithNewCourseCode(
719
                                                $content,
720
                                                $this->course->code,
721
                                                $this->course->destination_path,
722
                                                $this->course->backup_path,
723
                                                $this->course->info['path']
724
                                            );
725
                                            file_put_contents($dest_document_path, $content);
726
                                            $this->fixEditorHtmlContent($dest_document_path, $webEditorCss);
727
                                        }
728
                                    }
729
730
                                    $title = basename($path_title);
731
                                    if (isset($originalFolderNameList[basename($path_title)])) {
732
                                        $title = $originalFolderNameList[basename($path_title)];
733
                                    }
734
735
                                    $params = [
736
                                        'path' => self::DBUTF8($path_title),
737
                                        'c_id' => $this->destination_course_id,
738
                                        'comment' => self::DBUTF8($document->comment),
739
                                        'title' => self::DBUTF8($title),
740
                                        'filetype' => self::DBUTF8($document->file_type),
741
                                        'size' => self::DBUTF8($document->size),
742
                                        'session_id' => $my_session_id,
743
                                    ];
744
745
                                    $document_id = Database::insert($table, $params);
746
747
                                    if ($document_id) {
748
                                        $sql = "UPDATE $table SET id = iid WHERE iid = $document_id";
749
                                        Database::query($sql);
750
751
                                        $this->course->resources[RESOURCE_DOCUMENT][$id]->destination_id = $document_id;
752
753
                                        $itemProperty = isset($document->item_properties[0]) ? $document->item_properties[0] : '';
754
                                        $insertUserId = isset($itemProperty['insert_user_id']) ? $itemProperty['insert_user_id'] : api_get_user_id();
755
                                        $toGroupId = isset($itemProperty['to_group_id']) ? $itemProperty['to_group_id'] : 0;
756
                                        $toUserId = isset($itemProperty['to_user_id']) ? $itemProperty['to_user_id'] : null;
757
758
                                        $insertUserId = $this->checkUserId($insertUserId);
759
                                        $toUserId = $this->checkUserId($toUserId, true);
760
                                        $groupInfo = $this->checkGroupId($toGroupId);
761
762
                                        api_item_property_update(
763
                                            $course_info,
764
                                            TOOL_DOCUMENT,
765
                                            $document_id,
766
                                            'DocumentAdded',
767
                                            $insertUserId,
768
                                            $groupInfo,
769
                                            $toUserId,
770
                                            null,
771
                                            null,
772
                                            $my_session_id
773
                                        );
774
                                    }
775
                                } else {
776
                                    if (file_exists($path.$document->path)) {
777
                                        copy($path.$document->path, $path.$new_file_name);
778
                                    }
779
                                    // Replace old course code with the new destination code see BT#1985
780
                                    if (file_exists($path.$new_file_name)) {
781
                                        $file_info = pathinfo($path.$new_file_name);
782
                                        if (in_array($file_info['extension'], ['html', 'htm'])) {
783
                                            $content = file_get_contents($path.$new_file_name);
784
                                            if (UTF8_CONVERT) {
785
                                                $content = utf8_encode($content);
786
                                            }
787
                                            $content = DocumentManager::replaceUrlWithNewCourseCode(
788
                                                $content,
789
                                                $this->course->code,
790
                                                $this->course->destination_path,
791
                                                $this->course->backup_path,
792
                                                $this->course->info['path']
793
                                            );
794
                                            file_put_contents($path.$new_file_name, $content);
795
                                            $this->fixEditorHtmlContent($path.$new_file_name, $webEditorCss);
796
                                        }
797
                                    }
798
799
                                    $params = [
800
                                        'path' => "/".self::DBUTF8escapestring(substr($new_file_name, 9)),
801
                                        'c_id' => $this->destination_course_id,
802
                                        'comment' => self::DBUTF8($document->comment),
803
                                        'title' => self::DBUTF8($document->title),
804
                                        'filetype' => self::DBUTF8($document->file_type),
805
                                        'size' => self::DBUTF8($document->size),
806
                                        'session_id' => $my_session_id,
807
                                    ];
808
809
                                    $document_id = Database::insert($table, $params);
810
811
                                    if ($document_id) {
812
                                        $sql = "UPDATE $table SET id = iid WHERE iid = $document_id";
813
                                        Database::query($sql);
814
815
                                        $this->course->resources[RESOURCE_DOCUMENT][$id]->destination_id = $document_id;
816
817
                                        $itemProperty = isset($document->item_properties[0]) ? $document->item_properties[0] : '';
818
                                        $insertUserId = isset($itemProperty['insert_user_id']) ? $itemProperty['insert_user_id'] : api_get_user_id();
819
                                        $toGroupId = isset($itemProperty['to_group_id']) ? $itemProperty['to_group_id'] : 0;
820
                                        $toUserId = isset($itemProperty['to_user_id']) ? $itemProperty['to_user_id'] : null;
821
822
                                        $insertUserId = $this->checkUserId($insertUserId);
823
                                        $toUserId = $this->checkUserId($toUserId, true);
824
                                        $groupInfo = $this->checkGroupId($toGroupId);
825
826
                                        api_item_property_update(
827
                                            $course_info,
828
                                            TOOL_DOCUMENT,
829
                                            $document_id,
830
                                            'DocumentAdded',
831
                                            $insertUserId,
832
                                            $groupInfo,
833
                                            $toUserId,
834
                                            null,
835
                                            null,
836
                                            $my_session_id
837
                                        );
838
                                    }
839
                                }
840
                            } else {
841
                                copy(
842
                                    $this->course->backup_path.'/'.$document->path,
843
                                    $path.$new_file_name
844
                                );
845
846
                                // Replace old course code with the new destination code see BT#1985
847
                                if (file_exists($path.$new_file_name)) {
848
                                    $file_info = pathinfo($path.$new_file_name);
849
                                    if (in_array($file_info['extension'], ['html', 'htm'])) {
850
                                        $content = file_get_contents($path.$new_file_name);
851
                                        if (UTF8_CONVERT) {
852
                                            $content = utf8_encode($content);
853
                                        }
854
                                        $content = DocumentManager::replaceUrlWithNewCourseCode(
855
                                            $content,
856
                                            $this->course->code,
857
                                            $this->course->destination_path,
858
                                            $this->course->backup_path,
859
                                            $this->course->info['path']
860
                                        );
861
                                        file_put_contents($path.$new_file_name, $content);
862
                                        $this->fixEditorHtmlContent($path.$new_file_name, $webEditorCss);
863
                                    }
864
                                }
865
866
                                $params = [
867
                                    'c_id' => $this->destination_course_id,
868
                                    'path' => "/".self::DBUTF8escapestring(substr($new_file_name, 9)),
869
                                    'comment' => self::DBUTF8($document->comment),
870
                                    'title' => self::DBUTF8($document->title),
871
                                    'filetype' => self::DBUTF8($document->file_type),
872
                                    'size' => self::DBUTF8($document->size),
873
                                    'session_id' => $my_session_id,
874
                                ];
875
876
                                $document_id = Database::insert($table, $params);
877
878
                                if ($document_id) {
879
                                    $sql = "UPDATE $table SET id = iid WHERE iid = $document_id";
880
                                    Database::query($sql);
881
                                    $this->course->resources[RESOURCE_DOCUMENT][$id]->destination_id = $document_id;
882
883
                                    $itemProperty = isset($document->item_properties[0]) ? $document->item_properties[0] : '';
884
                                    $insertUserId = isset($itemProperty['insert_user_id']) ? $itemProperty['insert_user_id'] : api_get_user_id();
885
                                    $toGroupId = isset($itemProperty['to_group_id']) ? $itemProperty['to_group_id'] : 0;
886
                                    $toUserId = isset($itemProperty['to_user_id']) ? $itemProperty['to_user_id'] : null;
887
888
                                    $insertUserId = $this->checkUserId($insertUserId);
889
                                    $toUserId = $this->checkUserId($toUserId, true);
890
                                    $groupInfo = $this->checkGroupId($toGroupId);
891
892
                                    api_item_property_update(
893
                                        $course_info,
894
                                        TOOL_DOCUMENT,
895
                                        $document_id,
896
                                        'DocumentAdded',
897
                                        $insertUserId,
898
                                        $groupInfo,
899
                                        $toUserId,
900
                                        null,
901
                                        null,
902
                                        $my_session_id
903
                                    );
904
                                }
905
                            }
906
                            break;
907
                    } // end switch
908
                } else {
909
                    // end if file exists
910
911
                    //make sure the source file actually exists
912
                    if (is_file($this->course->backup_path.'/'.$document->path) &&
913
                        is_readable($this->course->backup_path.'/'.$document->path) &&
914
                        is_dir(dirname($path.$document->path)) &&
915
                        is_writeable(dirname($path.$document->path))
916
                    ) {
917
                        copy(
918
                            $this->course->backup_path.'/'.$document->path,
919
                            $path.$document->path
920
                        );
921
922
                        // Replace old course code with the new destination code see BT#1985
923
                        if (file_exists($path.$document->path)) {
924
                            $file_info = pathinfo($path.$document->path);
925
                            if (isset($file_info['extension']) && in_array($file_info['extension'], ['html', 'htm'])) {
926
                                $content = file_get_contents($path.$document->path);
927
                                if (UTF8_CONVERT) {
928
                                    $content = utf8_encode($content);
929
                                }
930
                                $content = DocumentManager::replaceUrlWithNewCourseCode(
931
                                    $content,
932
                                    $this->course->code,
933
                                    $this->course->destination_path,
934
                                    $this->course->backup_path,
935
                                    $this->course->info['path']
936
                                );
937
                                file_put_contents($path.$document->path, $content);
938
                                $this->fixEditorHtmlContent($path.$document->path, $webEditorCss);
939
                            }
940
                        }
941
942
                        $params = [
943
                            'c_id' => $this->destination_course_id,
944
                            'path' => "/".self::DBUTF8(substr($document->path, 9)),
945
                            'comment' => self::DBUTF8($document->comment),
946
                            'title' => self::DBUTF8($document->title),
947
                            'filetype' => self::DBUTF8($document->file_type),
948
                            'size' => self::DBUTF8($document->size),
949
                            'session_id' => $my_session_id,
950
                            'readonly' => 0,
951
                        ];
952
953
                        $document_id = Database::insert($table, $params);
954
955
                        if ($document_id) {
956
                            $sql = "UPDATE $table SET id = iid WHERE iid = $document_id";
957
                            Database::query($sql);
958
959
                            $this->course->resources[RESOURCE_DOCUMENT][$id]->destination_id = $document_id;
960
961
                            $itemProperty = isset($document->item_properties[0]) ? $document->item_properties[0] : '';
962
                            $insertUserId = isset($itemProperty['insert_user_id']) ? $itemProperty['insert_user_id'] : api_get_user_id();
963
                            $toGroupId = isset($itemProperty['to_group_id']) ? $itemProperty['to_group_id'] : 0;
964
                            $toUserId = isset($itemProperty['to_user_id']) ? $itemProperty['to_user_id'] : null;
965
966
                            $insertUserId = $this->checkUserId($insertUserId);
967
                            $toUserId = $this->checkUserId($toUserId, true);
968
                            $groupInfo = $this->checkGroupId($toGroupId);
969
970
                            api_item_property_update(
971
                                $course_info,
972
                                TOOL_DOCUMENT,
973
                                $document_id,
974
                                'DocumentAdded',
975
                                $insertUserId,
976
                                $groupInfo,
977
                                $toUserId,
978
                                null,
979
                                null,
980
                                $my_session_id
981
                            );
982
                        }
983
                    } else {
984
                        // There was an error in checking existence and
985
                        // permissions for files to copy. Try to determine
986
                        // the exact issue
987
                        // Issue with origin document?
988
                        if (!is_file($this->course->backup_path.'/'.$document->path)) {
989
                            error_log(
990
                                'Course copy generated an ignorable error while trying to copy '.
991
                                $this->course->backup_path.'/'.$document->path.': origin file not found'
992
                            );
993
                        } elseif (!is_readable($this->course->backup_path.'/'.$document->path)) {
994
                            error_log(
995
                                'Course copy generated an ignorable error while trying to copy '.
996
                                $this->course->backup_path.'/'.$document->path.': origin file not readable'
997
                            );
998
                        }
999
                        // Issue with destination directories?
1000
                        if (!is_dir(dirname($path.$document->path))) {
1001
                            error_log(
1002
                                'Course copy generated an ignorable error while trying to copy '.
1003
                                $this->course->backup_path.'/'.$document->path.' to '.
1004
                                dirname($path.$document->path).': destination directory not found'
1005
                            );
1006
                        }
1007
                        if (!is_writeable(dirname($path.$document->path))) {
1008
                            error_log(
1009
                                'Course copy generated an ignorable error while trying to copy '.
1010
                                $this->course->backup_path.'/'.$document->path.' to '.
1011
                                dirname($path.$document->path).': destination directory not writable'
1012
                            );
1013
                        }
1014
                    }
1015
                } // end file doesn't exist
1016
            }
1017
1018
            // add image information for area questions
1019
            if (preg_match('/^quiz-.*$/', $document->title) &&
1020
                preg_match('/^document\/images\/.*$/', $document->path)
1021
            ) {
1022
                $this->course->resources[RESOURCE_DOCUMENT]['image_quiz'][$document->title] = [
1023
                    'path' => $document->path,
1024
                    'title' => $document->title,
1025
                    'source_id' => $document->source_id,
1026
                    'destination_id' => $document->destination_id,
1027
                ];
1028
            }
1029
        } // end for each
1030
1031
        // Delete sessions for the copy the new folder in session
1032
        unset($_SESSION['new_base_foldername']);
1033
        unset($_SESSION['orig_base_foldername']);
1034
        unset($_SESSION['new_base_path']);
1035
    }
1036
1037
    /**
1038
     * Restore scorm documents
1039
     * TODO @TODO check that the restore function with renaming doesn't break the scorm structure!
1040
     * see #7029.
1041
     */
1042
    public function restore_scorm_documents()
1043
    {
1044
        $perm = api_get_permissions_for_new_directories();
1045
        if ($this->course->has_resources(RESOURCE_SCORM)) {
1046
            $resources = $this->course->resources;
1047
            foreach ($resources[RESOURCE_SCORM] as $document) {
1048
                $path = api_get_path(SYS_COURSE_PATH).$this->course->destination_path.'/';
1049
                @mkdir(dirname($path.$document->path), $perm, true);
1050
                if (file_exists($path.$document->path)) {
1051
                    switch ($this->file_option) {
1052
                        case FILE_OVERWRITE:
1053
                            rmdirr($path.$document->path);
1054
                            copyDirTo(
1055
                                $this->course->backup_path.'/'.$document->path,
1056
                                $path.$document->path,
1057
                                false
1058
                            );
1059
                            break;
1060
                        case FILE_SKIP:
1061
                            break;
1062
                        case FILE_RENAME:
1063
                            $i = 1;
1064
                            $ext = explode('.', basename($document->path));
1065
                            if (count($ext) > 1) {
1066
                                $ext = array_pop($ext);
1067
                                $file_name_no_ext = substr($document->path, 0, -(strlen($ext) + 1));
1068
                                $ext = '.'.$ext;
1069
                            } else {
1070
                                $ext = '';
1071
                                $file_name_no_ext = $document->path;
1072
                            }
1073
1074
                            $new_file_name = $file_name_no_ext.'_'.$i.$ext;
1075
                            $file_exists = file_exists($path.$new_file_name);
1076
1077
                            while ($file_exists) {
1078
                                $i++;
1079
                                $new_file_name = $file_name_no_ext.'_'.$i.$ext;
1080
                                $file_exists = file_exists($path.$new_file_name);
1081
                            }
1082
1083
                            rename(
1084
                                $this->course->backup_path.'/'.$document->path,
1085
                                $this->course->backup_path.'/'.$new_file_name
1086
                            );
1087
                            copyDirTo(
1088
                                $this->course->backup_path.'/'.$new_file_name,
1089
                                $path.dirname($new_file_name),
1090
                                false
1091
                            );
1092
                            rename(
1093
                                $this->course->backup_path.'/'.$new_file_name,
1094
                                $this->course->backup_path.'/'.$document->path
1095
                            );
1096
                            break;
1097
                    } // end switch
1098
                } else {
1099
                    // end if file exists
1100
                    copyDirTo(
1101
                        $this->course->backup_path.'/'.$document->path,
1102
                        $path.$document->path,
1103
                        false
1104
                    );
1105
                }
1106
            } // end for each
1107
        }
1108
    }
1109
1110
    /**
1111
     * Restore forums.
1112
     *
1113
     * @param int $sessionId
1114
     */
1115
    public function restore_forums($sessionId = 0)
1116
    {
1117
        if ($this->course->has_resources(RESOURCE_FORUM)) {
1118
            $sessionId = (int) $sessionId;
1119
            $table_forum = Database::get_course_table(TABLE_FORUM);
1120
            $resources = $this->course->resources;
1121
            foreach ($resources[RESOURCE_FORUM] as $id => $forum) {
1122
                $params = (array) $forum->obj;
1123
                $cat_id = '';
1124
                if (isset($this->course->resources[RESOURCE_FORUMCATEGORY]) &&
1125
                    isset($this->course->resources[RESOURCE_FORUMCATEGORY][$params['forum_category']])) {
1126
                    if ($this->course->resources[RESOURCE_FORUMCATEGORY][$params['forum_category']]->destination_id == -1) {
1127
                        $cat_id = $this->restore_forum_category($params['forum_category'], $sessionId);
1128
                    } else {
1129
                        $cat_id = $this->course->resources[RESOURCE_FORUMCATEGORY][$params['forum_category']]->destination_id;
1130
                    }
1131
                }
1132
1133
                $params = self::DBUTF8_array($params);
1134
                $params['c_id'] = $this->destination_course_id;
1135
                $params['forum_category'] = $cat_id;
1136
                $params['session_id'] = $sessionId;
1137
                $params['start_time'] = isset($params['start_time']) && $params['start_time'] === '0000-00-00 00:00:00' ? null : $params['start_time'];
1138
                $params['end_time'] = isset($params['end_time']) && $params['end_time'] === '0000-00-00 00:00:00' ? null : $params['end_time'];
1139
                $params['forum_id'] = 0;
1140
                unset($params['iid']);
1141
1142
                $params['forum_comment'] = DocumentManager::replaceUrlWithNewCourseCode(
1143
                    $params['forum_comment'],
1144
                    $this->course->code,
1145
                    $this->course->destination_path,
1146
                    $this->course->backup_path,
1147
                    $this->course->info['path']
1148
                );
1149
1150
                if (!empty($params['forum_image'])) {
1151
                    $original_forum_image = $this->course->path.'upload/forum/images/'.$params['forum_image'];
1152
                    if (file_exists($original_forum_image)) {
1153
                        $new_forum_image = api_get_path(SYS_COURSE_PATH).
1154
                            $this->destination_course_info['path'].'/upload/forum/images/'.$params['forum_image'];
1155
                        @copy($original_forum_image, $new_forum_image);
1156
                    }
1157
                }
1158
1159
                $new_id = Database::insert($table_forum, $params);
1160
1161
                if ($new_id) {
1162
                    $sql = "UPDATE $table_forum SET forum_id = iid WHERE iid = $new_id";
1163
                    Database::query($sql);
1164
1165
                    api_item_property_update(
1166
                        $this->destination_course_info,
1167
                        TOOL_FORUM,
1168
                        $new_id,
1169
                        'ForumUpdated',
1170
                        api_get_user_id(),
1171
                        null,
1172
                        null,
1173
                        null,
1174
                        null,
1175
                        $sessionId
1176
                    );
1177
1178
                    $this->course->resources[RESOURCE_FORUM][$id]->destination_id = $new_id;
1179
                    $forum_topics = 0;
1180
                    if (isset($this->course->resources[RESOURCE_FORUMTOPIC]) &&
1181
                        is_array($this->course->resources[RESOURCE_FORUMTOPIC])
1182
                    ) {
1183
                        foreach ($this->course->resources[RESOURCE_FORUMTOPIC] as $topic_id => $topic) {
1184
                            if ($topic->obj->forum_id == $id) {
1185
                                $this->restore_topic($topic_id, $new_id, $sessionId);
1186
                                $forum_topics++;
1187
                            }
1188
                        }
1189
                    }
1190
                    if ($forum_topics > 0) {
1191
                        $sql = "UPDATE ".$table_forum." SET forum_threads = ".$forum_topics."
1192
                                WHERE c_id = {$this->destination_course_id} AND forum_id = ".(int) $new_id;
1193
                        Database::query($sql);
1194
                    }
1195
                }
1196
            }
1197
        }
1198
    }
1199
1200
    /**
1201
     * Restore forum-categories.
1202
     */
1203
    public function restore_forum_category($my_id = null, $sessionId = 0)
1204
    {
1205
        $forum_cat_table = Database::get_course_table(TABLE_FORUM_CATEGORY);
1206
        $resources = $this->course->resources;
1207
        $sessionId = (int) $sessionId;
1208
        if (!empty($resources[RESOURCE_FORUMCATEGORY])) {
1209
            foreach ($resources[RESOURCE_FORUMCATEGORY] as $id => $forum_cat) {
1210
                if (!empty($my_id)) {
1211
                    if ($my_id != $id) {
1212
                        continue;
1213
                    }
1214
                }
1215
                if ($forum_cat && !$forum_cat->is_restored()) {
1216
                    $params = (array) $forum_cat->obj;
1217
                    $params['c_id'] = $this->destination_course_id;
1218
                    $params['cat_comment'] = DocumentManager::replaceUrlWithNewCourseCode(
1219
                        $params['cat_comment'],
1220
                        $this->course->code,
1221
                        $this->course->destination_path,
1222
                        $this->course->backup_path,
1223
                        $this->course->info['path']
1224
                    );
1225
                    $params['session_id'] = $sessionId;
1226
                    $params['cat_id'] = 0;
1227
                    unset($params['iid']);
1228
1229
                    $params = self::DBUTF8_array($params);
1230
                    $new_id = Database::insert($forum_cat_table, $params);
1231
1232
                    if ($new_id) {
1233
                        $sql = "UPDATE $forum_cat_table SET cat_id = iid WHERE iid = $new_id";
1234
                        Database::query($sql);
1235
1236
                        api_item_property_update(
1237
                            $this->destination_course_info,
1238
                            TOOL_FORUM_CATEGORY,
1239
                            $new_id,
1240
                            'ForumCategoryUpdated',
1241
                            api_get_user_id(),
1242
                            null,
1243
                            null,
1244
                            null,
1245
                            null,
1246
                            $sessionId
1247
                        );
1248
                        $this->course->resources[RESOURCE_FORUMCATEGORY][$id]->destination_id = $new_id;
1249
                    }
1250
1251
                    if (!empty($my_id)) {
1252
                        return $new_id;
1253
                    }
1254
                }
1255
            }
1256
        }
1257
    }
1258
1259
    /**
1260
     * Restore a forum-topic.
1261
     *
1262
     * @param false|string $forum_id
1263
     *
1264
     * @return int
1265
     */
1266
    public function restore_topic($thread_id, $forum_id, $sessionId = 0)
1267
    {
1268
        $table = Database::get_course_table(TABLE_FORUM_THREAD);
1269
        $topic = $this->course->resources[RESOURCE_FORUMTOPIC][$thread_id];
1270
1271
        $sessionId = (int) $sessionId;
1272
        $params = (array) $topic->obj;
1273
1274
        $params = self::DBUTF8_array($params);
1275
        $params['c_id'] = $this->destination_course_id;
1276
        $params['forum_id'] = $forum_id;
1277
        $params['thread_poster_id'] = $this->first_teacher_id;
1278
        $params['thread_date'] = api_get_utc_datetime();
1279
        $params['thread_close_date'] = null;
1280
        $params['thread_last_post'] = 0;
1281
        $params['thread_replies'] = 0;
1282
        $params['thread_views'] = 0;
1283
        $params['session_id'] = $sessionId;
1284
        $params['thread_id'] = 0;
1285
1286
        unset($params['iid']);
1287
1288
        $new_id = Database::insert($table, $params);
1289
1290
        if ($new_id) {
1291
            $sql = "UPDATE $table SET thread_id = iid WHERE iid = $new_id";
1292
            Database::query($sql);
1293
1294
            api_item_property_update(
1295
                $this->destination_course_info,
1296
                TOOL_FORUM_THREAD,
1297
                $new_id,
1298
                'ThreadAdded',
1299
                api_get_user_id(),
1300
                0,
1301
                0,
1302
                null,
1303
                null,
1304
                $sessionId
1305
            );
1306
1307
            $this->course->resources[RESOURCE_FORUMTOPIC][$thread_id]->destination_id = $new_id;
1308
            $topic_replies = -1;
1309
1310
            foreach ($this->course->resources[RESOURCE_FORUMPOST] as $post_id => $post) {
1311
                if ($post->obj->thread_id == $thread_id) {
1312
                    $topic_replies++;
1313
                    $this->restore_post($post_id, $new_id, $forum_id, $sessionId);
1314
                }
1315
            }
1316
        }
1317
1318
        return $new_id;
1319
    }
1320
1321
    /**
1322
     * Restore a forum-post.
1323
     *
1324
     * @TODO Restore tree-structure of posts. For example: attachments to posts.
1325
     *
1326
     * @param false|string $topic_id
1327
     *
1328
     * @return int
1329
     */
1330
    public function restore_post($id, $topic_id, $forum_id, $sessionId = 0)
1331
    {
1332
        $table_post = Database::get_course_table(TABLE_FORUM_POST);
1333
        $post = $this->course->resources[RESOURCE_FORUMPOST][$id];
1334
        $params = (array) $post->obj;
1335
        $params['c_id'] = $this->destination_course_id;
1336
        $params['forum_id'] = $forum_id;
1337
        $params['thread_id'] = $topic_id;
1338
        $params['poster_id'] = $this->first_teacher_id;
1339
        $params['post_date'] = api_get_utc_datetime();
1340
        $params['post_id'] = 0;
1341
        unset($params['iid']);
1342
1343
        $params['post_text'] = DocumentManager::replaceUrlWithNewCourseCode(
1344
            $params['post_text'],
1345
            $this->course->code,
1346
            $this->course->destination_path,
1347
            $this->course->backup_path,
1348
            $this->course->info['path']
1349
        );
1350
        $new_id = Database::insert($table_post, $params);
1351
1352
        if ($new_id) {
1353
            $sql = "UPDATE $table_post SET post_id = iid WHERE iid = $new_id";
1354
            Database::query($sql);
1355
1356
            api_item_property_update(
1357
                $this->destination_course_info,
1358
                TOOL_FORUM_POST,
1359
                $new_id,
1360
                'PostAdded',
1361
                api_get_user_id(),
1362
                0,
1363
                0,
1364
                null,
1365
                null,
1366
                $sessionId
1367
            );
1368
            $this->course->resources[RESOURCE_FORUMPOST][$id]->destination_id = $new_id;
1369
        }
1370
1371
        return $new_id;
1372
    }
1373
1374
    /**
1375
     * Restore links.
1376
     */
1377
    public function restore_links($session_id = 0)
1378
    {
1379
        if ($this->course->has_resources(RESOURCE_LINK)) {
1380
            $link_table = Database::get_course_table(TABLE_LINK);
1381
            $resources = $this->course->resources;
1382
1383
            foreach ($resources[RESOURCE_LINK] as $oldLinkId => $link) {
1384
                $cat_id = (int) $this->restore_link_category($link->category_id, $session_id);
1385
                $sql = "SELECT MAX(display_order)
1386
                        FROM $link_table
1387
                        WHERE
1388
                            c_id = ".$this->destination_course_id." AND
1389
                            category_id='".$cat_id."'";
1390
                $result = Database::query($sql);
1391
                [$max_order] = Database::fetch_array($result);
1392
1393
                $params = [];
1394
                if (!empty($session_id)) {
1395
                    $params['session_id'] = $session_id;
1396
                }
1397
1398
                $params['c_id'] = $this->destination_course_id;
1399
                $params['url'] = self::DBUTF8($link->url);
1400
                $params['title'] = self::DBUTF8($link->title);
1401
                $params['description'] = self::DBUTF8($link->description);
1402
                $params['category_id'] = $cat_id;
1403
                $params['on_homepage'] = $link->on_homepage;
1404
                $params['display_order'] = $max_order + 1;
1405
                $params['target'] = $link->target;
1406
1407
                $id = Database::insert($link_table, $params);
1408
1409
                if ($id) {
1410
                    $sql = "UPDATE $link_table SET id = iid WHERE iid = $id";
1411
                    Database::query($sql);
1412
1413
                    api_item_property_update(
1414
                        $this->destination_course_info,
1415
                        TOOL_LINK,
1416
                        $id,
1417
                        'LinkAdded',
1418
                        api_get_user_id(),
1419
                        null,
1420
                        null,
1421
                        null,
1422
                        null,
1423
                        $session_id
1424
                    );
1425
1426
                    if (!isset($this->course->resources[RESOURCE_LINK][$oldLinkId])) {
1427
                        $this->course->resources[RESOURCE_LINK][$oldLinkId] = new stdClass();
1428
                    }
1429
                    $this->course->resources[RESOURCE_LINK][$oldLinkId]->destination_id = $id;
1430
                }
1431
            }
1432
        }
1433
    }
1434
1435
    /**
1436
     * Restore a link-category.
1437
     *
1438
     * @param int
1439
     * @param int
1440
     *
1441
     * @return bool
1442
     */
1443
    public function restore_link_category($id, $sessionId = 0)
1444
    {
1445
        $params = [];
1446
        $sessionId = (int) $sessionId;
1447
        if (!empty($sessionId)) {
1448
            $params['session_id'] = $sessionId;
1449
        }
1450
1451
        if ($id == 0) {
1452
            return 0;
1453
        }
1454
        $link_cat_table = Database::get_course_table(TABLE_LINK_CATEGORY);
1455
        $resources = $this->course->resources;
1456
        $link_cat = $resources[RESOURCE_LINKCATEGORY][$id];
1457
        if (is_object($link_cat) && !$link_cat->is_restored()) {
1458
            $sql = "SELECT MAX(display_order) FROM  $link_cat_table
1459
                    WHERE c_id = ".$this->destination_course_id;
1460
            $result = Database::query($sql);
1461
            [$orderMax] = Database::fetch_array($result, 'NUM');
1462
            $display_order = $orderMax + 1;
1463
1464
            $params['c_id'] = $this->destination_course_id;
1465
            $params['category_title'] = self::DBUTF8($link_cat->title);
1466
            $params['description'] = self::DBUTF8($link_cat->description);
1467
            $params['display_order'] = $display_order;
1468
            $new_id = Database::insert($link_cat_table, $params);
1469
1470
            if ($new_id) {
1471
                $sql = "UPDATE $link_cat_table
1472
                        SET id = iid
1473
                        WHERE iid = $new_id";
1474
                Database::query($sql);
1475
1476
                $courseInfo = api_get_course_info_by_id($this->destination_course_id);
1477
                api_item_property_update(
1478
                    $courseInfo,
1479
                    TOOL_LINK_CATEGORY,
1480
                    $new_id,
1481
                    'LinkCategoryAdded',
1482
                    api_get_user_id(),
1483
                    null,
1484
                    null,
1485
                    null,
1486
                    null,
1487
                    $sessionId
1488
                );
1489
                api_set_default_visibility(
1490
                    $new_id,
1491
                    TOOL_LINK_CATEGORY,
1492
                    0,
1493
                    $courseInfo,
1494
                    $sessionId
1495
                );
1496
            }
1497
1498
            $this->course->resources[RESOURCE_LINKCATEGORY][$id]->destination_id = $new_id;
1499
1500
            return $new_id;
1501
        }
1502
1503
        return $this->course->resources[RESOURCE_LINKCATEGORY][$id]->destination_id;
1504
    }
1505
1506
    /**
1507
     * Restore tool intro.
1508
     *
1509
     * @param int
1510
     */
1511
    public function restore_tool_intro($sessionId = 0)
1512
    {
1513
        if ($this->course->has_resources(RESOURCE_TOOL_INTRO)) {
1514
            $sessionId = (int) $sessionId;
1515
            $tool_intro_table = Database::get_course_table(TABLE_TOOL_INTRO);
1516
            $resources = $this->course->resources;
1517
            foreach ($resources[RESOURCE_TOOL_INTRO] as $id => $tool_intro) {
1518
                $sql = "DELETE FROM $tool_intro_table
1519
                        WHERE
1520
                            c_id = ".$this->destination_course_id." AND
1521
                            id='".self::DBUTF8escapestring($tool_intro->id)."'";
1522
                Database::query($sql);
1523
1524
                $tool_intro->intro_text = DocumentManager::replaceUrlWithNewCourseCode(
1525
                    $tool_intro->intro_text,
1526
                    $this->course->code,
1527
                    $this->course->destination_path,
1528
                    $this->course->backup_path,
1529
                    $this->course->info['path']
1530
                );
1531
1532
                $params = [
1533
                    'c_id' => $this->destination_course_id,
1534
                    'id' => ($tool_intro->id === false ? '' : self::DBUTF8($tool_intro->id)),
1535
                    'intro_text' => self::DBUTF8($tool_intro->intro_text),
1536
                    'session_id' => $sessionId,
1537
                ];
1538
1539
                $id = Database::insert($tool_intro_table, $params);
1540
                if ($id) {
1541
                    if (!isset($this->course->resources[RESOURCE_TOOL_INTRO][$id])) {
1542
                        $this->course->resources[RESOURCE_TOOL_INTRO][$id] = new stdClass();
1543
                    }
1544
1545
                    $this->course->resources[RESOURCE_TOOL_INTRO][$id]->destination_id = $id;
1546
                }
1547
            }
1548
        }
1549
    }
1550
1551
    /**
1552
     * Restore events.
1553
     *
1554
     * @param int
1555
     */
1556
    public function restore_events($sessionId = 0)
1557
    {
1558
        if ($this->course->has_resources(RESOURCE_EVENT)) {
1559
            $sessionId = (int) $sessionId;
1560
            $table = Database::get_course_table(TABLE_AGENDA);
1561
            $resources = $this->course->resources;
1562
            foreach ($resources[RESOURCE_EVENT] as $id => $event) {
1563
                // check resources inside html from ckeditor tool and copy correct urls into recipient course
1564
                $event->content = DocumentManager::replaceUrlWithNewCourseCode(
1565
                    $event->content,
1566
                    $this->course->code,
1567
                    $this->course->destination_path,
1568
                    $this->course->backup_path,
1569
                    $this->course->info['path']
1570
                );
1571
1572
                $params = [
1573
                    'c_id' => $this->destination_course_id,
1574
                    'title' => self::DBUTF8($event->title),
1575
                    'content' => ($event->content === false ? '' : self::DBUTF8($event->content)),
1576
                    'all_day' => $event->all_day,
1577
                    'start_date' => $event->start_date,
1578
                    'end_date' => $event->end_date,
1579
                    'session_id' => $sessionId,
1580
                ];
1581
                $new_event_id = Database::insert($table, $params);
1582
1583
                if ($new_event_id) {
1584
                    $sql = "UPDATE $table SET id = iid WHERE iid = $new_event_id";
1585
                    Database::query($sql);
1586
1587
                    if (!isset($this->course->resources[RESOURCE_EVENT][$id])) {
1588
                        $this->course->resources[RESOURCE_EVENT][$id] = new stdClass();
1589
                    }
1590
                    $this->course->resources[RESOURCE_EVENT][$id]->destination_id = $new_event_id;
1591
                }
1592
1593
                // Copy event attachment
1594
                $origin_path = $this->course->backup_path.'/upload/calendar/';
1595
                $destination_path = api_get_path(SYS_COURSE_PATH).$this->course->destination_path.'/upload/calendar/';
1596
1597
                if (!empty($this->course->orig)) {
1598
                    $table_attachment = Database::get_course_table(TABLE_AGENDA_ATTACHMENT);
1599
                    $sql = 'SELECT path, comment, size, filename
1600
                            FROM '.$table_attachment.'
1601
                            WHERE c_id = '.$this->destination_course_id.' AND agenda_id = '.$id;
1602
                    $attachment_event = Database::query($sql);
1603
                    $attachment_event = Database::fetch_object($attachment_event);
1604
1605
                    if (file_exists($origin_path.$attachment_event->path) &&
1606
                        !is_dir($origin_path.$attachment_event->path)
1607
                    ) {
1608
                        $new_filename = uniqid(''); //ass seen in the add_agenda_attachment_file() function in agenda.inc.php
1609
                        $copy_result = copy(
1610
                            $origin_path.$attachment_event->path,
1611
                            $destination_path.$new_filename
1612
                        );
1613
                        //$copy_result = true;
1614
                        if ($copy_result) {
1615
                            $table_attachment = Database::get_course_table(TABLE_AGENDA_ATTACHMENT);
1616
1617
                            $params = [
1618
                                'c_id' => $this->destination_course_id,
1619
                                'path' => self::DBUTF8($new_filename),
1620
                                'comment' => self::DBUTF8($attachment_event->comment),
1621
                                'size' => isset($attachment_event->size) ? $attachment_event->size : '',
1622
                                'filename' => isset($attachment_event->filename) ? $attachment_event->filename : '',
1623
                                'agenda_id' => $new_event_id,
1624
                            ];
1625
                            $id = Database::insert($table_attachment, $params);
1626
                            if ($id) {
1627
                                $sql = "UPDATE $table_attachment SET id = iid WHERE iid = $id";
1628
                                Database::query($sql);
1629
                            }
1630
                        }
1631
                    }
1632
                } else {
1633
                    // get the info of the file
1634
                    if (!empty($event->attachment_path) &&
1635
                        is_file($origin_path.$event->attachment_path) &&
1636
                        is_readable($origin_path.$event->attachment_path)
1637
                    ) {
1638
                        $new_filename = uniqid(''); //ass seen in the add_agenda_attachment_file() function in agenda.inc.php
1639
                        $copy_result = copy(
1640
                            $origin_path.$event->attachment_path,
1641
                            $destination_path.$new_filename
1642
                        );
1643
                        if ($copy_result) {
1644
                            $table_attachment = Database::get_course_table(TABLE_AGENDA_ATTACHMENT);
1645
1646
                            $params = [
1647
                                'c_id' => $this->destination_course_id,
1648
                                'path' => self::DBUTF8($new_filename),
1649
                                'comment' => self::DBUTF8($event->attachment_comment),
1650
                                'size' => isset($event->size) ? $event->size : '',
1651
                                'filename' => isset($event->filename) ? $event->filename : '',
1652
                                'agenda_id' => $new_event_id,
1653
                            ];
1654
                            $id = Database::insert($table_attachment, $params);
1655
1656
                            if ($id) {
1657
                                $sql = "UPDATE $table_attachment SET id = iid WHERE iid = $id";
1658
                                Database::query($sql);
1659
                            }
1660
                        }
1661
                    }
1662
                }
1663
            }
1664
        }
1665
    }
1666
1667
    /**
1668
     * Restore course-description.
1669
     *
1670
     * @param int
1671
     */
1672
    public function restore_course_descriptions($session_id = 0)
1673
    {
1674
        if ($this->course->has_resources(RESOURCE_COURSEDESCRIPTION)) {
1675
            $table = Database::get_course_table(TABLE_COURSE_DESCRIPTION);
1676
            $resources = $this->course->resources;
1677
            foreach ($resources[RESOURCE_COURSEDESCRIPTION] as $id => $cd) {
1678
                $courseDescription = (array) $cd;
1679
1680
                $content = isset($courseDescription['content']) ? $courseDescription['content'] : '';
1681
                $descriptionType = isset($courseDescription['description_type']) ? $courseDescription['description_type'] : '';
1682
                $title = isset($courseDescription['title']) ? $courseDescription['title'] : '';
1683
1684
                // check resources inside html from ckeditor tool and copy correct urls into recipient course
1685
                $description_content = DocumentManager::replaceUrlWithNewCourseCode(
1686
                    $content,
1687
                    $this->course->code,
1688
                    $this->course->destination_path,
1689
                    $this->course->backup_path,
1690
                    $this->course->info['path']
1691
                );
1692
1693
                $params = [];
1694
                $session_id = (int) $session_id;
1695
                $params['session_id'] = $session_id;
1696
                $params['c_id'] = $this->destination_course_id;
1697
                $params['description_type'] = self::DBUTF8($descriptionType);
1698
                $params['title'] = self::DBUTF8($title);
1699
                $params['content'] = ($description_content === false ? '' : self::DBUTF8($description_content));
1700
                $params['progress'] = 0;
1701
1702
                $id = Database::insert($table, $params);
1703
                if ($id) {
1704
                    $sql = "UPDATE $table SET id = iid WHERE iid = $id";
1705
                    Database::query($sql);
1706
1707
                    if (!isset($this->course->resources[RESOURCE_COURSEDESCRIPTION][$id])) {
1708
                        $this->course->resources[RESOURCE_COURSEDESCRIPTION][$id] = new stdClass();
1709
                    }
1710
                    $this->course->resources[RESOURCE_COURSEDESCRIPTION][$id]->destination_id = $id;
1711
                }
1712
            }
1713
        }
1714
    }
1715
1716
    /**
1717
     * Restore announcements.
1718
     *
1719
     * @param int
1720
     */
1721
    public function restore_announcements($sessionId = 0)
1722
    {
1723
        if ($this->course->has_resources(RESOURCE_ANNOUNCEMENT)) {
1724
            $sessionId = (int) $sessionId;
1725
            $table = Database::get_course_table(TABLE_ANNOUNCEMENT);
1726
            $resources = $this->course->resources;
1727
            foreach ($resources[RESOURCE_ANNOUNCEMENT] as $id => $announcement) {
1728
                // check resources inside html from ckeditor tool and copy correct urls into recipient course
1729
                $announcement->content = DocumentManager::replaceUrlWithNewCourseCode(
1730
                    $announcement->content,
1731
                    $this->course->code,
1732
                    $this->course->destination_path,
1733
                    $this->course->backup_path,
1734
                    $this->course->info['path']
1735
                );
1736
1737
                $params = [
1738
                    'c_id' => $this->destination_course_id,
1739
                    'title' => self::DBUTF8($announcement->title),
1740
                    'content' => ($announcement->content === false ? '' : self::DBUTF8($announcement->content)),
1741
                    'end_date' => $announcement->date,
1742
                    'display_order' => $announcement->display_order,
1743
                    'email_sent' => $announcement->email_sent,
1744
                    'session_id' => $sessionId,
1745
                ];
1746
1747
                $new_announcement_id = Database::insert($table, $params);
1748
1749
                if ($new_announcement_id) {
1750
                    $sql = "UPDATE $table SET id = iid WHERE iid = $new_announcement_id";
1751
                    Database::query($sql);
1752
1753
                    if (!isset($this->course->resources[RESOURCE_ANNOUNCEMENT][$id])) {
1754
                        $this->course->resources[RESOURCE_ANNOUNCEMENT][$id] = new stdClass();
1755
                    }
1756
                    $this->course->resources[RESOURCE_ANNOUNCEMENT][$id]->destination_id = $new_announcement_id;
1757
                }
1758
1759
                $origin_path = $this->course->backup_path.'/upload/announcements/';
1760
                $destination_path = api_get_path(SYS_COURSE_PATH).$this->course->destination_path.'/upload/announcements/';
1761
1762
                // Copy announcement attachment file
1763
                if (!empty($this->course->orig)) {
1764
                    $table_attachment = Database::get_course_table(TABLE_ANNOUNCEMENT_ATTACHMENT);
1765
                    $sql = 'SELECT path, comment, size, filename
1766
                            FROM '.$table_attachment.'
1767
                            WHERE
1768
                                c_id = '.$this->destination_course_id.' AND
1769
                                announcement_id = '.$id;
1770
                    $attachment_event = Database::query($sql);
1771
                    $attachment_event = Database::fetch_object($attachment_event);
1772
1773
                    if (file_exists($origin_path.$attachment_event->path) &&
1774
                        !is_dir($origin_path.$attachment_event->path)
1775
                    ) {
1776
                        $new_filename = uniqid(''); //ass seen in the add_agenda_attachment_file() function in agenda.inc.php
1777
                        $copy_result = copy(
1778
                            $origin_path.$attachment_event->path,
1779
                            $destination_path.$new_filename
1780
                        );
1781
1782
                        if ($copy_result) {
1783
                            $table_attachment = Database::get_course_table(TABLE_ANNOUNCEMENT_ATTACHMENT);
1784
1785
                            $params = [
1786
                                'c_id' => $this->destination_course_id,
1787
                                'path' => self::DBUTF8($new_filename),
1788
                                'comment' => self::DBUTF8($attachment_event->comment),
1789
                                'size' => $attachment_event->size,
1790
                                'filename' => $attachment_event->filename,
1791
                                'announcement_id' => $new_announcement_id,
1792
                            ];
1793
1794
                            $attachmentId = Database::insert($table_attachment, $params);
1795
1796
                            if ($attachmentId) {
1797
                                $sql = "UPDATE $table_attachment SET id = iid WHERE iid = $attachmentId";
1798
                                Database::query($sql);
1799
                            }
1800
                        }
1801
                    }
1802
                } else {
1803
                    // get the info of the file
1804
                    if (!empty($announcement->attachment_path) &&
1805
                        is_file($origin_path.$announcement->attachment_path) &&
1806
                        is_readable($origin_path.$announcement->attachment_path)
1807
                    ) {
1808
                        $new_filename = uniqid(''); //ass seen in the add_agenda_attachment_file() function in agenda.inc.php
1809
                        $copy_result = copy($origin_path.$announcement->attachment_path, $destination_path.$new_filename);
1810
1811
                        if ($copy_result) {
1812
                            $table_attachment = Database::get_course_table(TABLE_ANNOUNCEMENT_ATTACHMENT);
1813
1814
                            $params = [
1815
                                'c_id' => $this->destination_course_id,
1816
                                'path' => self::DBUTF8($new_filename),
1817
                                'comment' => self::DBUTF8($announcement->attachment_comment),
1818
                                'size' => $announcement->attachment_size,
1819
                                'filename' => $announcement->attachment_filename,
1820
                                'announcement_id' => $new_announcement_id,
1821
                            ];
1822
1823
                            $attachmentId = Database::insert($table_attachment, $params);
1824
1825
                            if ($attachmentId) {
1826
                                $sql = "UPDATE $table_attachment SET id = iid WHERE iid = $attachmentId";
1827
                                Database::query($sql);
1828
                            }
1829
                        }
1830
                    }
1831
                }
1832
            }
1833
        }
1834
    }
1835
1836
    /**
1837
     * Restore Quiz.
1838
     *
1839
     * @param int  $session_id
1840
     * @param bool $respect_base_content
1841
     */
1842
    public function restore_quizzes(
1843
        $session_id = 0,
1844
        $respect_base_content = false
1845
    ) {
1846
        if ($this->course->has_resources(RESOURCE_QUIZ)) {
1847
            $table_qui = Database::get_course_table(TABLE_QUIZ_TEST);
1848
            $table_rel = Database::get_course_table(TABLE_QUIZ_TEST_QUESTION);
1849
            $table_doc = Database::get_course_table(TABLE_DOCUMENT);
1850
            $resources = $this->course->resources;
1851
            // Check if the "id" column still exists
1852
            $idColumn = true;
1853
            $columns = Database::listTableColumns($table_qui);
1854
            if (!in_array('id', array_keys($columns))) {
1855
                $idColumn = false;
1856
            }
1857
1858
            foreach ($resources[RESOURCE_QUIZ] as $id => $quiz) {
1859
                if (isset($quiz->obj)) {
1860
                    // For new imports
1861
                    $quiz = $quiz->obj;
1862
                } else {
1863
                    // For backward compatibility
1864
                    $quiz->obj = $quiz;
1865
                }
1866
1867
                $doc = '';
1868
                if (!empty($quiz->sound)) {
1869
                    if (isset($this->course->resources[RESOURCE_DOCUMENT][$quiz->sound]) &&
1870
                        $this->course->resources[RESOURCE_DOCUMENT][$quiz->sound]->is_restored()) {
1871
                        $sql = "SELECT path FROM $table_doc
1872
                                WHERE
1873
                                    c_id = ".$this->destination_course_id." AND
1874
                                    id = ".$resources[RESOURCE_DOCUMENT][$quiz->sound]->destination_id;
1875
                        $doc = Database::query($sql);
1876
                        $doc = Database::fetch_object($doc);
1877
                        $doc = str_replace('/audio/', '', $doc->path);
1878
                    }
1879
                }
1880
1881
                if ($id != -1) {
1882
                    // check resources inside html from ckeditor tool and copy correct urls into recipient course
1883
                    $quiz->description = DocumentManager::replaceUrlWithNewCourseCode(
1884
                        $quiz->description,
1885
                        $this->course->code,
1886
                        $this->course->destination_path,
1887
                        $this->course->backup_path,
1888
                        $this->course->info['path']
1889
                    );
1890
1891
                    $quiz->start_time = $quiz->start_time == '0000-00-00 00:00:00' ? null : $quiz->start_time;
1892
                    $quiz->end_time = $quiz->end_time == '0000-00-00 00:00:00' ? null : $quiz->end_time;
1893
1894
                    global $_custom;
1895
                    if (isset($_custom['exercises_clean_dates_when_restoring']) &&
1896
                        $_custom['exercises_clean_dates_when_restoring']
1897
                    ) {
1898
                        $quiz->start_time = null;
1899
                        $quiz->end_time = null;
1900
                    }
1901
1902
                    $params = [
1903
                        'c_id' => $this->destination_course_id,
1904
                        'title' => self::DBUTF8($quiz->title),
1905
                        'description' => ($quiz->description === false ? '' : self::DBUTF8($quiz->description)),
1906
                        'type' => isset($quiz->quiz_type) ? (int) $quiz->quiz_type : $quiz->type,
1907
                        'random' => (int) $quiz->random,
1908
                        'active' => $quiz->active,
1909
                        'sound' => self::DBUTF8($doc),
1910
                        'max_attempt' => (int) $quiz->max_attempt,
1911
                        'results_disabled' => (int) $quiz->results_disabled,
1912
                        'access_condition' => $quiz->access_condition,
1913
                        'pass_percentage' => $quiz->pass_percentage,
1914
                        'feedback_type' => (int) $quiz->feedback_type,
1915
                        'random_answers' => (int) $quiz->random_answers,
1916
                        'random_by_category' => (int) $quiz->random_by_category,
1917
                        'review_answers' => (int) $quiz->review_answers,
1918
                        'propagate_neg' => (int) $quiz->propagate_neg,
1919
                        'text_when_finished' => (string) $quiz->text_when_finished,
1920
                        'expired_time' => (int) $quiz->expired_time,
1921
                        'start_time' => $quiz->start_time,
1922
                        'end_time' => $quiz->end_time,
1923
                        'display_category_name' => 0,
1924
                        'save_correct_answers' => isset($quiz->save_correct_answers) ? $quiz->save_correct_answers : 0,
1925
                        'hide_question_title' => isset($quiz->hide_question_title) ? $quiz->hide_question_title : 0,
1926
                    ];
1927
1928
                    $allow = api_get_configuration_value('allow_notification_setting_per_exercise');
1929
                    if ($allow) {
1930
                        $params['notifications'] = isset($quiz->notifications) ? $quiz->notifications : '';
1931
                    }
1932
1933
                    if ($respect_base_content) {
1934
                        $my_session_id = $quiz->session_id;
1935
                        if (!empty($quiz->session_id)) {
1936
                            $my_session_id = $session_id;
1937
                        }
1938
                        $params['session_id'] = $my_session_id;
1939
                    } else {
1940
                        if (!empty($session_id)) {
1941
                            $session_id = (int) $session_id;
1942
                            $params['session_id'] = $session_id;
1943
                        }
1944
                    }
1945
                    $new_id = Database::insert($table_qui, $params);
1946
1947
                    if ($new_id && $idColumn) {
1948
                        $sql = "UPDATE $table_qui SET id = iid WHERE iid = $new_id";
1949
                        Database::query($sql);
1950
                    }
1951
                } else {
1952
                    // $id = -1 identifies the fictional test for collecting
1953
                    // orphan questions. We do not store it in the database.
1954
                    $new_id = -1;
1955
                }
1956
1957
                $this->course->resources[RESOURCE_QUIZ][$id]->destination_id = $new_id;
1958
                $order = 0;
1959
                if (!empty($quiz->question_ids)) {
1960
                    foreach ($quiz->question_ids as $index => $question_id) {
1961
                        $qid = $this->restore_quiz_question($question_id, $idColumn);
1962
                        $question_order = $quiz->question_orders[$index] ? $quiz->question_orders[$index] : ++$order;
1963
                        $sql = "INSERT IGNORE INTO $table_rel SET
1964
                                c_id = ".$this->destination_course_id.",
1965
                                question_id = $qid ,
1966
                                exercice_id = $new_id ,
1967
                                question_order = ".$question_order;
1968
                        Database::query($sql);
1969
                    }
1970
                }
1971
            }
1972
        }
1973
    }
1974
1975
    /**
1976
     * Restore quiz-questions.
1977
     *
1978
     * @param int  $id       Question id
1979
     * @param bool $idColumn Whether the 'id' column still exists in this table
1980
     */
1981
    public function restore_quiz_question($id, $idColumn = true)
1982
    {
1983
        $em = Database::getManager();
1984
        $resources = $this->course->resources;
1985
        /** @var QuizQuestion $question */
1986
        $question = isset($resources[RESOURCE_QUIZQUESTION][$id]) ? $resources[RESOURCE_QUIZQUESTION][$id] : null;
1987
        $new_id = 0;
1988
1989
        if (is_object($question)) {
1990
            if ($question->is_restored()) {
1991
                return $question->destination_id;
1992
            }
1993
            $table_que = Database::get_course_table(TABLE_QUIZ_QUESTION);
1994
            $table_ans = Database::get_course_table(TABLE_QUIZ_ANSWER);
1995
            $table_options = Database::get_course_table(TABLE_QUIZ_QUESTION_OPTION);
1996
1997
            // check resources inside html from ckeditor tool and copy correct urls into recipient course
1998
            $question->description = DocumentManager::replaceUrlWithNewCourseCode(
1999
                $question->description,
2000
                $this->course->code,
2001
                $this->course->destination_path,
2002
                $this->course->backup_path,
2003
                $this->course->info['path']
2004
            );
2005
2006
            $imageNewId = '';
2007
            if (preg_match('/^quiz-.*$/', $question->picture) &&
2008
                isset($resources[RESOURCE_DOCUMENT]['image_quiz'][$question->picture])
2009
            ) {
2010
                $imageNewId = $resources[RESOURCE_DOCUMENT]['image_quiz'][$question->picture]['destination_id'];
2011
            } else {
2012
                if (isset($resources[RESOURCE_DOCUMENT][$question->picture])) {
2013
                    $documentsToRestore = $resources[RESOURCE_DOCUMENT][$question->picture];
2014
                    $imageNewId = $documentsToRestore->destination_id;
2015
                }
2016
            }
2017
            $question->question = DocumentManager::replaceUrlWithNewCourseCode(
2018
                $question->question,
2019
                $this->course->code,
2020
                $this->course->destination_path,
2021
                $this->course->backup_path,
2022
                $this->course->info['path']
2023
            );
2024
            $params = [
2025
                'c_id' => $this->destination_course_id,
2026
                'question' => self::DBUTF8($question->question),
2027
                'description' => ($question->description === false ? '' : self::DBUTF8($question->description)),
2028
                'ponderation' => self::DBUTF8($question->ponderation),
2029
                'position' => self::DBUTF8($question->position),
2030
                'type' => self::DBUTF8($question->quiz_type),
2031
                'picture' => self::DBUTF8($imageNewId),
2032
                'level' => self::DBUTF8($question->level),
2033
                'extra' => self::DBUTF8($question->extra),
2034
            ];
2035
2036
            $new_id = Database::insert($table_que, $params);
2037
2038
            if ($new_id) {
2039
                // If the ID column is still present, update it, otherwise just
2040
                // continue
2041
                if ($idColumn) {
2042
                    $sql = "UPDATE $table_que SET id = iid WHERE iid = $new_id";
2043
                    Database::query($sql);
2044
                }
2045
            } else {
2046
                // If no IID was generated, stop right there and return 0
2047
                return 0;
2048
            }
2049
2050
            $correctAnswers = [];
2051
            $allAnswers = [];
2052
            $onlyAnswers = [];
2053
2054
            if (in_array($question->quiz_type, [DRAGGABLE, MATCHING, MATCHING_DRAGGABLE])) {
2055
                $tempAnswerList = $question->answers;
2056
                foreach ($tempAnswerList as &$value) {
2057
                    $value['answer'] = DocumentManager::replaceUrlWithNewCourseCode(
2058
                        $value['answer'],
2059
                        $this->course->code,
2060
                        $this->course->destination_path,
2061
                        $this->course->backup_path,
2062
                        $this->course->info['path']
2063
                    );
2064
                }
2065
                $allAnswers = array_column($tempAnswerList, 'answer', 'id');
2066
            }
2067
2068
            if (in_array($question->quiz_type, [MATCHING, MATCHING_DRAGGABLE])) {
2069
                $temp = [];
2070
                foreach ($question->answers as $index => $answer) {
2071
                    $temp[$answer['position']] = $answer;
2072
                }
2073
2074
                foreach ($temp as $index => $answer) {
2075
                    // check resources inside html from ckeditor tool and copy correct urls into recipient course
2076
                    $answer['answer'] = DocumentManager::replaceUrlWithNewCourseCode(
2077
                        $answer['answer'],
2078
                        $this->course->code,
2079
                        $this->course->destination_path,
2080
                        $this->course->backup_path,
2081
                        $this->course->info['path']
2082
                    );
2083
2084
                    $answer['comment'] = DocumentManager::replaceUrlWithNewCourseCode(
2085
                        $answer['comment'],
2086
                        $this->course->code,
2087
                        $this->course->destination_path,
2088
                        $this->course->backup_path,
2089
                        $this->course->info['path']
2090
                    );
2091
2092
                    $quizAnswer = new CQuizAnswer();
2093
                    $quizAnswer
2094
                        ->setCId($this->destination_course_id)
2095
                        ->setQuestionId($new_id)
2096
                        ->setAnswer(self::DBUTF8($answer['answer']))
2097
                        ->setCorrect($answer['correct'])
2098
                        ->setComment($answer['comment'] === false ? '' : self::DBUTF8($answer['comment']))
2099
                        ->setPonderation($answer['ponderation'])
2100
                        ->setPosition($answer['position'])
2101
                        ->setHotspotCoordinates($answer['hotspot_coordinates'])
2102
                        ->setHotspotType($answer['hotspot_type'])
2103
                        ->setIdAuto(0);
2104
2105
                    $em->persist($quizAnswer);
2106
                    $em->flush();
2107
2108
                    $answerId = $quizAnswer->getId();
2109
2110
                    if ($answerId) {
2111
                        $quizAnswer
2112
                            ->setId($answerId)
2113
                            ->setIdAuto($answerId);
2114
                        $em->merge($quizAnswer);
2115
                        $em->flush();
2116
2117
                        $correctAnswers[$answerId] = $answer['correct'];
2118
                        $onlyAnswers[$answerId] = $answer['answer'];
2119
                    }
2120
                }
2121
            } else {
2122
                foreach ($question->answers as $index => $answer) {
2123
                    // check resources inside html from ckeditor tool and copy correct urls into recipient course
2124
                    $answer['answer'] = DocumentManager::replaceUrlWithNewCourseCode(
2125
                        $answer['answer'],
2126
                        $this->course->code,
2127
                        $this->course->destination_path,
2128
                        $this->course->backup_path,
2129
                        $this->course->info['path']
2130
                    );
2131
2132
                    $answer['comment'] = DocumentManager::replaceUrlWithNewCourseCode(
2133
                        $answer['comment'],
2134
                        $this->course->code,
2135
                        $this->course->destination_path,
2136
                        $this->course->backup_path,
2137
                        $this->course->info['path']
2138
                    );
2139
2140
                    $params = [
2141
                        'c_id' => $this->destination_course_id,
2142
                        'question_id' => $new_id,
2143
                        'answer' => self::DBUTF8($answer['answer']),
2144
                        'correct' => $answer['correct'],
2145
                        'comment' => ($answer['comment'] === false ? '' : self::DBUTF8($answer['comment'])),
2146
                        'ponderation' => $answer['ponderation'],
2147
                        'position' => $answer['position'],
2148
                        'hotspot_coordinates' => $answer['hotspot_coordinates'],
2149
                        'hotspot_type' => $answer['hotspot_type'],
2150
                        'id_auto' => 0,
2151
                        'destination' => '',
2152
                    ];
2153
2154
                    $answerId = Database::insert($table_ans, $params);
2155
2156
                    if ($answerId) {
2157
                        if ($idColumn) {
2158
                            $sql = "UPDATE $table_ans SET id = iid, id_auto = iid WHERE iid = $answerId";
2159
                            Database::query($sql);
2160
                        } else {
2161
                            $sql = "UPDATE $table_ans SET id_auto = iid WHERE iid = $answerId";
2162
                            Database::query($sql);
2163
                        }
2164
                    }
2165
2166
                    $correctAnswers[$answerId] = $answer['correct'];
2167
                    $onlyAnswers[$answerId] = $answer['answer'];
2168
                }
2169
            }
2170
2171
            // Current course id
2172
            $course_id = api_get_course_int_id();
2173
2174
            // Moving quiz_question_options
2175
            if ($question->quiz_type == MULTIPLE_ANSWER_TRUE_FALSE) {
2176
                if (count($question->question_options) < 3) {
2177
                    $options = [1 => 'True', 2 => 'False', 3 => 'DoubtScore'];
2178
                    $correct = [];
2179
                    for ($i = 1; $i <= 3; $i++) {
2180
                        $lastId = Question::saveQuestionOption(
2181
                            $new_id,
2182
                            $options[$i],
2183
                            $this->destination_course_id,
2184
                            $i
2185
                        );
2186
                        $correct[$i] = $lastId;
2187
                    }
2188
2189
                    $correctAnswerValues = Database::select(
2190
                        'DISTINCT(correct)',
2191
                        $table_ans,
2192
                        [
2193
                            'WHERE' => [
2194
                                'question_id = ? AND c_id = ? ' => [
2195
                                    $new_id,
2196
                                    $this->destination_course_id,
2197
                                ],
2198
                            ],
2199
                            'ORDER' => 'correct ASC',
2200
                        ]
2201
                    );
2202
                    $i = 1;
2203
                    foreach ($correctAnswerValues as $correctAnswer) {
2204
                        $params = [];
2205
                        $params['correct'] = $correct[$i];
2206
                        Database::update(
2207
                            $table_ans,
2208
                            $params,
2209
                            [
2210
                                'question_id = ? AND c_id = ? AND correct = ? ' => [
2211
                                    $new_id,
2212
                                    $this->destination_course_id,
2213
                                    $correctAnswer['correct'],
2214
                                ],
2215
                            ],
2216
                            false
2217
                        );
2218
                        $i++;
2219
                    }
2220
                } else {
2221
                    $question_option_list = Question::readQuestionOption($id, $course_id);
2222
2223
                    // Question copied from the current platform
2224
                    if ($question_option_list) {
2225
                        $old_option_ids = [];
2226
                        foreach ($question_option_list as $item) {
2227
                            if (isset($item['iid'])) {
2228
                                $old_id = $item['iid'];
2229
                                unset($item['iid']);
2230
                                unset($item['id']);
2231
                            } else {
2232
                                $old_id = $item['id'];
2233
                                unset($item['id']);
2234
                            }
2235
                            $item['question_id'] = $new_id;
2236
                            $item['c_id'] = $this->destination_course_id;
2237
                            $question_option_id = Database::insert($table_options, $item);
2238
                            if ($question_option_id && $idColumn) {
2239
                                $old_option_ids[$old_id] = $question_option_id;
2240
                                $sql = "UPDATE $table_options SET id = iid WHERE iid = $question_option_id";
2241
                                Database::query($sql);
2242
                            }
2243
                        }
2244
                        if ($old_option_ids) {
2245
                            $new_answers = Database::select(
2246
                                'iid, correct',
2247
                                $table_ans,
2248
                                [
2249
                                    'WHERE' => [
2250
                                        'question_id = ? AND c_id = ? ' => [
2251
                                            $new_id,
2252
                                            $this->destination_course_id,
2253
                                        ],
2254
                                    ],
2255
                                ]
2256
                            );
2257
2258
                            foreach ($new_answers as $answer_item) {
2259
                                $params = [];
2260
                                $params['correct'] = $old_option_ids[$answer_item['correct']];
2261
                                Database::update(
2262
                                    $table_ans,
2263
                                    $params,
2264
                                    [
2265
                                        'iid = ? AND c_id = ? AND question_id = ? ' => [
2266
                                            $answer_item['iid'],
2267
                                            $this->destination_course_id,
2268
                                            $new_id,
2269
                                        ],
2270
                                    ],
2271
                                    false
2272
                                );
2273
                            }
2274
                        }
2275
                    } else {
2276
                        $new_options = [];
2277
                        if (isset($question->question_options)) {
2278
                            foreach ($question->question_options as $obj) {
2279
                                $item = [];
2280
                                $item['question_id'] = $new_id;
2281
                                $item['c_id'] = $this->destination_course_id;
2282
                                $item['name'] = $obj->obj->name;
2283
                                $item['position'] = $obj->obj->position;
2284
                                $question_option_id = Database::insert($table_options, $item);
2285
2286
                                if ($question_option_id) {
2287
                                    $new_options[$obj->obj->id] = $question_option_id;
2288
                                    $sql = "UPDATE $table_options SET id = iid WHERE iid = $question_option_id";
2289
                                    Database::query($sql);
2290
                                }
2291
                            }
2292
2293
                            foreach ($correctAnswers as $answer_id => $correct_answer) {
2294
                                $params = [];
2295
                                $params['correct'] = isset($new_options[$correct_answer]) ? $new_options[$correct_answer] : '';
2296
                                Database::update(
2297
                                    $table_ans,
2298
                                    $params,
2299
                                    [
2300
                                        'iid = ? AND c_id = ? AND question_id = ? ' => [
2301
                                            $answer_id,
2302
                                            $this->destination_course_id,
2303
                                            $new_id,
2304
                                        ],
2305
                                    ],
2306
                                    false
2307
                                );
2308
                            }
2309
                        }
2310
                    }
2311
                }
2312
            }
2313
2314
            // Fix correct answers
2315
            if (in_array($question->quiz_type, [DRAGGABLE, MATCHING, MATCHING_DRAGGABLE])) {
2316
                foreach ($correctAnswers as $answer_id => $correct_answer) {
2317
                    $params = [];
2318
2319
                    if (isset($allAnswers[$correct_answer])) {
2320
                        $correct = '';
2321
                        foreach ($onlyAnswers as $key => $value) {
2322
                            if ($value == $allAnswers[$correct_answer]) {
2323
                                $correct = $key;
2324
                                break;
2325
                            }
2326
                        }
2327
2328
                        $params['correct'] = $correct;
2329
                        Database::update(
2330
                            $table_ans,
2331
                            $params,
2332
                            [
2333
                                'iid = ? AND c_id = ? AND question_id = ? ' => [
2334
                                    $answer_id,
2335
                                    $this->destination_course_id,
2336
                                    $new_id,
2337
                                ],
2338
                            ]
2339
                        );
2340
                    }
2341
                }
2342
            }
2343
2344
            $this->course->resources[RESOURCE_QUIZQUESTION][$id]->destination_id = $new_id;
2345
        }
2346
2347
        return $new_id;
2348
    }
2349
2350
    /**
2351
     * @todo : add session id when used for session
2352
     */
2353
    public function restore_test_category($session_id, $respect_base_content, $destination_course_code)
2354
    {
2355
        // Cannot restore a test category to a session.
2356
        if (!empty($session_id)) {
2357
            return false;
2358
        }
2359
2360
        $destinationCourseId = $this->destination_course_info['real_id'];
2361
        // Let's restore the categories
2362
        $categoryOldVsNewList = []; // used to build the quiz_question_rel_category table
2363
        if ($this->course->has_resources(RESOURCE_TEST_CATEGORY)) {
2364
            $resources = $this->course->resources;
2365
            foreach ($resources[RESOURCE_TEST_CATEGORY] as $id => $courseCopyTestCategory) {
2366
                $categoryOldVsNewList[$courseCopyTestCategory->source_id] = $id;
2367
                // check if this test_category already exist in the destination BDD
2368
                // do not Database::escape_string $title and $description, it will be done later
2369
                $title = $courseCopyTestCategory->title;
2370
                $description = $courseCopyTestCategory->description;
2371
                if (TestCategory::categoryTitleExists($title, $destinationCourseId)) {
2372
                    switch ($this->file_option) {
2373
                        case FILE_SKIP:
2374
                            //Do nothing
2375
                            break;
2376
                        case FILE_RENAME:
2377
                            $new_title = $title.'_';
2378
                            while (TestCategory::categoryTitleExists($new_title, $destinationCourseId)) {
2379
                                $new_title .= '_';
2380
                            }
2381
                            $test_category = new TestCategory();
2382
                            $test_category->name = $new_title;
2383
                            $test_category->description = $description;
2384
                            $new_id = $test_category->save($destinationCourseId);
2385
                            $categoryOldVsNewList[$courseCopyTestCategory->source_id] = $new_id;
2386
                            break;
2387
                        case FILE_OVERWRITE:
2388
                            // get category from source
2389
                            $destinationCategoryId = TestCategory::get_category_id_for_title(
2390
                                $title,
2391
                                $destinationCourseId
2392
                            );
2393
                            if ($destinationCategoryId) {
2394
                                $my_cat = new TestCategory();
2395
                                $my_cat = $my_cat->getCategory($destinationCategoryId, $destinationCourseId);
2396
                                $my_cat->name = $title;
2397
                                $my_cat->description = $description;
2398
                                $my_cat->modifyCategory($destinationCourseId);
2399
                                $categoryOldVsNewList[$courseCopyTestCategory->source_id] = $destinationCategoryId;
2400
                            }
2401
                            break;
2402
                    }
2403
                } else {
2404
                    // create a new test_category
2405
                    $test_category = new TestCategory();
2406
                    $test_category->name = $title;
2407
                    $test_category->description = $description;
2408
                    $new_id = $test_category->save($destinationCourseId);
2409
                    $categoryOldVsNewList[$courseCopyTestCategory->source_id] = $new_id;
2410
                }
2411
                $this->course->resources[RESOURCE_TEST_CATEGORY][$id]->destination_id = $categoryOldVsNewList[$courseCopyTestCategory->source_id];
2412
            }
2413
        }
2414
2415
        // lets check if quizzes-question are restored too,
2416
        // to redo the link between test_category and quizzes question for questions restored
2417
        // we can use the source_id field
2418
        // question source_id => category source_id
2419
        if ($this->course->has_resources(RESOURCE_QUIZQUESTION)) {
2420
            // check the category number of each question restored
2421
            if (!empty($resources[RESOURCE_QUIZQUESTION])) {
2422
                foreach ($resources[RESOURCE_QUIZQUESTION] as $id => $courseCopyQuestion) {
2423
                    $newQuestionId = $resources[RESOURCE_QUIZQUESTION][$id]->destination_id;
2424
                    $questionCategoryId = $courseCopyQuestion->question_category;
2425
                    if ($newQuestionId > 0 &&
2426
                        $questionCategoryId > 0 &&
2427
                        isset($categoryOldVsNewList[$questionCategoryId])
2428
                    ) {
2429
                        TestCategory::addCategoryToQuestion(
2430
                            $categoryOldVsNewList[$questionCategoryId],
2431
                            $newQuestionId,
2432
                            $destinationCourseId
2433
                        );
2434
                    }
2435
                }
2436
            }
2437
        }
2438
    }
2439
2440
    /**
2441
     * Restore surveys.
2442
     *
2443
     * @param int $sessionId Optional. The session id
2444
     */
2445
    public function restore_surveys($sessionId = 0)
2446
    {
2447
        $sessionId = (int) $sessionId;
2448
        if ($this->course->has_resources(RESOURCE_SURVEY)) {
2449
            $table_sur = Database::get_course_table(TABLE_SURVEY);
2450
            $table_que = Database::get_course_table(TABLE_SURVEY_QUESTION);
2451
            $table_ans = Database::get_course_table(TABLE_SURVEY_QUESTION_OPTION);
2452
            $resources = $this->course->resources;
2453
            foreach ($resources[RESOURCE_SURVEY] as $id => $survey) {
2454
                $sql = 'SELECT survey_id FROM '.$table_sur.'
2455
                        WHERE
2456
                            c_id = '.$this->destination_course_id.' AND
2457
                            code = "'.self::DBUTF8escapestring($survey->code).'" AND
2458
                            lang = "'.self::DBUTF8escapestring($survey->lang).'" ';
2459
2460
                $result_check = Database::query($sql);
2461
2462
                // check resources inside html from ckeditor tool and copy correct urls into recipient course
2463
                $survey->title = DocumentManager::replaceUrlWithNewCourseCode(
2464
                    $survey->title,
2465
                    $this->course->code,
2466
                    $this->course->destination_path,
2467
                    $this->course->backup_path,
2468
                    $this->course->info['path']
2469
                );
2470
2471
                $survey->subtitle = DocumentManager::replaceUrlWithNewCourseCode(
2472
                    $survey->subtitle,
2473
                    $this->course->code,
2474
                    $this->course->destination_path,
2475
                    $this->course->backup_path,
2476
                    $this->course->info['path']
2477
                );
2478
2479
                $survey->intro = DocumentManager::replaceUrlWithNewCourseCode(
2480
                    $survey->intro,
2481
                    $this->course->code,
2482
                    $this->course->destination_path,
2483
                    $this->course->backup_path,
2484
                    $this->course->info['path']
2485
                );
2486
2487
                $survey->surveythanks = DocumentManager::replaceUrlWithNewCourseCode(
2488
                    $survey->surveythanks,
2489
                    $this->course->code,
2490
                    $this->course->destination_path,
2491
                    $this->course->backup_path,
2492
                    $this->course->info['path']
2493
                );
2494
2495
                $params = [
2496
                    'c_id' => $this->destination_course_id,
2497
                    'code' => self::DBUTF8($survey->code),
2498
                    'title' => ($survey->title === false ? '' : self::DBUTF8($survey->title)),
2499
                    'subtitle' => ($survey->subtitle === false ? '' : self::DBUTF8($survey->subtitle)),
2500
                    'author' => self::DBUTF8($survey->author),
2501
                    'lang' => self::DBUTF8($survey->lang),
2502
                    'avail_from' => self::DBUTF8($survey->avail_from),
2503
                    'avail_till' => self::DBUTF8($survey->avail_till),
2504
                    'is_shared' => self::DBUTF8($survey->is_shared),
2505
                    'template' => self::DBUTF8($survey->template),
2506
                    'intro' => $survey->intro === false ? '' : self::DBUTF8($survey->intro),
2507
                    'surveythanks' => $survey->surveythanks === false ? '' : self::DBUTF8($survey->surveythanks),
2508
                    'creation_date' => self::DBUTF8($survey->creation_date),
2509
                    'invited' => '0',
2510
                    'answered' => '0',
2511
                    'invite_mail' => self::DBUTF8($survey->invite_mail),
2512
                    'reminder_mail' => self::DBUTF8($survey->reminder_mail),
2513
                    'session_id' => $sessionId,
2514
                    'one_question_per_page' => isset($survey->one_question_per_page) ? $survey->one_question_per_page : 0,
2515
                    'shuffle' => isset($survey->suffle) ? $survey->suffle : 0,
2516
                ];
2517
2518
                // An existing survey exists with the same code and the same language
2519
                if (Database::num_rows($result_check) == 1) {
2520
                    switch ($this->file_option) {
2521
                        case FILE_SKIP:
2522
                            //Do nothing
2523
                            break;
2524
                        case FILE_RENAME:
2525
                            $survey_code = $survey->code.'_';
2526
                            $i = 1;
2527
                            $temp_survey_code = $survey_code.$i;
2528
                            while (!$this->is_survey_code_available($temp_survey_code)) {
2529
                                $temp_survey_code = $survey_code.++$i;
2530
                            }
2531
                            $survey_code = $temp_survey_code;
2532
2533
                            $params['code'] = $survey_code;
2534
                            $new_id = Database::insert($table_sur, $params);
2535
                            if ($new_id) {
2536
                                $sql = "UPDATE $table_sur SET survey_id = iid WHERE iid = $new_id";
2537
                                Database::query($sql);
2538
2539
                                $this->course->resources[RESOURCE_SURVEY][$id]->destination_id = $new_id;
2540
                                foreach ($survey->question_ids as $index => $question_id) {
2541
                                    $qid = $this->restore_survey_question($question_id, $new_id);
2542
                                    $sql = "UPDATE $table_que SET survey_id = $new_id
2543
                                            WHERE c_id = ".$this->destination_course_id." AND question_id = $qid";
2544
                                    Database::query($sql);
2545
                                    $sql = "UPDATE $table_ans SET survey_id = $new_id
2546
                                            WHERE  c_id = ".$this->destination_course_id." AND  question_id = $qid";
2547
                                    Database::query($sql);
2548
                                }
2549
                            }
2550
                            break;
2551
                        case FILE_OVERWRITE:
2552
                            // Delete the existing survey with the same code and language and
2553
                            // import the one of the source course
2554
                            // getting the information of the survey (used for when the survey is shared)
2555
                            $sql = "SELECT * FROM $table_sur
2556
                                    WHERE
2557
                                        c_id = ".$this->destination_course_id." AND
2558
                                        survey_id='".self::DBUTF8escapestring(Database::result($result_check, 0, 0))."'";
2559
                            $result = Database::query($sql);
2560
                            $survey_data = Database::fetch_array($result, 'ASSOC');
2561
2562
                            // if the survey is shared => also delete the shared content
2563
                            if (isset($survey_data['survey_share']) && is_numeric($survey_data['survey_share'])) {
2564
                                SurveyManager::delete_survey(
2565
                                    $survey_data['survey_share'],
2566
                                    true,
2567
                                    $this->destination_course_id
2568
                                );
2569
                            }
2570
                            SurveyManager::delete_survey(
2571
                                $survey_data['survey_id'],
2572
                                false,
2573
                                $this->destination_course_id
2574
                            );
2575
2576
                            // Insert the new source survey
2577
                            $new_id = Database::insert($table_sur, $params);
2578
2579
                            if ($new_id) {
2580
                                $sql = "UPDATE $table_sur SET survey_id = iid WHERE iid = $new_id";
2581
                                Database::query($sql);
2582
2583
                                $this->course->resources[RESOURCE_SURVEY][$id]->destination_id = $new_id;
2584
                                foreach ($survey->question_ids as $index => $question_id) {
2585
                                    $qid = $this->restore_survey_question(
2586
                                        $question_id,
2587
                                        $new_id
2588
                                    );
2589
                                    $sql = "UPDATE $table_que SET survey_id = $new_id
2590
                                            WHERE c_id = ".$this->destination_course_id." AND question_id = $qid";
2591
                                    Database::query($sql);
2592
                                    $sql = "UPDATE $table_ans SET survey_id = $new_id
2593
                                            WHERE c_id = ".$this->destination_course_id." AND question_id = $qid";
2594
                                    Database::query($sql);
2595
                                }
2596
                            }
2597
                            break;
2598
                        default:
2599
                            break;
2600
                    }
2601
                } else {
2602
                    // No existing survey with the same language and the same code, we just copy the survey
2603
                    $new_id = Database::insert($table_sur, $params);
2604
2605
                    if ($new_id) {
2606
                        $sql = "UPDATE $table_sur SET survey_id = iid WHERE iid = $new_id";
2607
                        Database::query($sql);
2608
2609
                        $this->course->resources[RESOURCE_SURVEY][$id]->destination_id = $new_id;
2610
                        foreach ($survey->question_ids as $index => $question_id) {
2611
                            $qid = $this->restore_survey_question(
2612
                                $question_id,
2613
                                $new_id
2614
                            );
2615
                            $sql = "UPDATE $table_que SET survey_id = $new_id
2616
                                    WHERE c_id = ".$this->destination_course_id." AND question_id = $qid";
2617
                            Database::query($sql);
2618
                            $sql = "UPDATE $table_ans SET survey_id = $new_id
2619
                                    WHERE c_id = ".$this->destination_course_id." AND question_id = $qid";
2620
                            Database::query($sql);
2621
                        }
2622
                    }
2623
                }
2624
            }
2625
        }
2626
    }
2627
2628
    /**
2629
     * Check availability of a survey code.
2630
     *
2631
     * @param string $survey_code
2632
     *
2633
     * @return bool
2634
     */
2635
    public function is_survey_code_available($survey_code)
2636
    {
2637
        $table_sur = Database::get_course_table(TABLE_SURVEY);
2638
        $sql = "SELECT * FROM $table_sur
2639
                WHERE
2640
                    c_id = ".$this->destination_course_id." AND
2641
                    code = '".self::DBUTF8escapestring($survey_code)."'";
2642
        $result = Database::query($sql);
2643
        if (Database::num_rows($result) > 0) {
2644
            return false;
2645
        } else {
2646
            return true;
2647
        }
2648
    }
2649
2650
    /**
2651
     * Restore survey-questions.
2652
     *
2653
     * @param int    $id
2654
     * @param string $survey_id
2655
     */
2656
    public function restore_survey_question($id, $survey_id)
2657
    {
2658
        $resources = $this->course->resources;
2659
        $question = $resources[RESOURCE_SURVEYQUESTION][$id];
2660
        $new_id = 0;
2661
2662
        if (is_object($question)) {
2663
            if ($question->is_restored()) {
2664
                return $question->destination_id;
2665
            }
2666
            $table_que = Database::get_course_table(TABLE_SURVEY_QUESTION);
2667
            $table_ans = Database::get_course_table(TABLE_SURVEY_QUESTION_OPTION);
2668
2669
            // check resources inside html from ckeditor tool and copy correct urls into recipient course
2670
            $question->survey_question = DocumentManager::replaceUrlWithNewCourseCode(
2671
                $question->survey_question,
2672
                $this->course->code,
2673
                $this->course->destination_path,
2674
                $this->course->backup_path,
2675
                $this->course->info['path']
2676
            );
2677
2678
            $params = [
2679
                'c_id' => $this->destination_course_id,
2680
                'survey_id' => self::DBUTF8($survey_id),
2681
                'survey_question' => ($question->survey_question === false ? '' : self::DBUTF8($question->survey_question)),
2682
                'survey_question_comment' => self::DBUTF8($question->survey_question_comment),
2683
                'type' => self::DBUTF8($question->survey_question_type),
2684
                'display' => self::DBUTF8($question->display),
2685
                'sort' => self::DBUTF8($question->sort),
2686
                'shared_question_id' => self::DBUTF8($question->shared_question_id),
2687
                'max_value' => self::DBUTF8($question->max_value),
2688
            ];
2689
            if (api_get_configuration_value('allow_required_survey_questions')) {
2690
                if (isset($question->is_required)) {
2691
                    $params['is_required'] = $question->is_required;
2692
                }
2693
            }
2694
2695
            $new_id = Database::insert($table_que, $params);
2696
            if ($new_id) {
2697
                $sql = "UPDATE $table_que SET question_id = iid WHERE iid = $new_id";
2698
                Database::query($sql);
2699
2700
                foreach ($question->answers as $index => $answer) {
2701
                    // check resources inside html from ckeditor tool and copy correct urls into recipient course
2702
                    $answer['option_text'] = DocumentManager::replaceUrlWithNewCourseCode(
2703
                        $answer['option_text'],
2704
                        $this->course->code,
2705
                        $this->course->destination_path,
2706
                        $this->course->backup_path,
2707
                        $this->course->info['path']
2708
                    );
2709
2710
                    $params = [
2711
                        'c_id' => $this->destination_course_id,
2712
                        'question_id' => $new_id,
2713
                        'option_text' => ($answer['option_text'] === false ? '' : self::DBUTF8($answer['option_text'])),
2714
                        'sort' => $answer['sort'],
2715
                        'survey_id' => self::DBUTF8($survey_id),
2716
                    ];
2717
                    $answerId = Database::insert($table_ans, $params);
2718
                    if ($answerId) {
2719
                        $sql = "UPDATE $table_ans SET question_option_id = iid
2720
                                WHERE iid = $answerId";
2721
                        Database::query($sql);
2722
                    }
2723
                }
2724
                $this->course->resources[RESOURCE_SURVEYQUESTION][$id]->destination_id = $new_id;
2725
            }
2726
        }
2727
2728
        return $new_id;
2729
    }
2730
2731
    /**
2732
     * @param int  $sessionId
2733
     * @param bool $baseContent
2734
     */
2735
    public function restore_learnpath_category($sessionId = 0, $baseContent = false)
2736
    {
2737
        $reuseExisting = false;
2738
2739
        if (isset($this->tool_copy_settings['learnpath_category']) &&
2740
            isset($this->tool_copy_settings['learnpath_category']['reuse_existing']) &&
2741
            true === $this->tool_copy_settings['learnpath_category']['reuse_existing']
2742
        ) {
2743
            $reuseExisting = true;
2744
        }
2745
2746
        $tblLpCategory = Database::get_course_table(TABLE_LP_CATEGORY);
2747
2748
        if ($this->course->has_resources(RESOURCE_LEARNPATH_CATEGORY)) {
2749
            $resources = $this->course->resources;
2750
            /** @var LearnPathCategory $item */
2751
            foreach ($resources[RESOURCE_LEARNPATH_CATEGORY] as $id => $item) {
2752
                /** @var CLpCategory $lpCategory */
2753
                $lpCategory = $item->object;
2754
2755
                if ($lpCategory) {
2756
                    $existingLpCategory = Database::select(
2757
                        'iid',
2758
                        $tblLpCategory,
2759
                        [
2760
                            'WHERE' => [
2761
                                'c_id = ? AND name = ?' => [$this->destination_course_id, $lpCategory->getName()],
2762
                            ],
2763
                        ],
2764
                        'first'
2765
                    );
2766
2767
                    if ($reuseExisting && !empty($existingLpCategory)) {
2768
                        $categoryId = $existingLpCategory['iid'];
2769
                    } else {
2770
                        $values = [
2771
                            'c_id' => $this->destination_course_id,
2772
                            'name' => $lpCategory->getName(),
2773
                        ];
2774
                        $categoryId = \learnpath::createCategory($values);
2775
                    }
2776
2777
                    if ($categoryId) {
2778
                        $this->course->resources[RESOURCE_LEARNPATH_CATEGORY][$id]->destination_id = $categoryId;
2779
                    }
2780
                }
2781
            }
2782
        }
2783
    }
2784
2785
    /**
2786
     * Restoring learning paths.
2787
     *
2788
     * @param int        $session_id
2789
     * @param bool|false $respect_base_content
2790
     */
2791
    public function restore_learnpaths($session_id = 0, $respect_base_content = false)
2792
    {
2793
        $session_id = (int) $session_id;
2794
        if ($this->course->has_resources(RESOURCE_LEARNPATH)) {
2795
            $table_main = Database::get_course_table(TABLE_LP_MAIN);
2796
            $table_item = Database::get_course_table(TABLE_LP_ITEM);
2797
            $table_tool = Database::get_course_table(TABLE_TOOL_LIST);
2798
2799
            $resources = $this->course->resources;
2800
            $origin_path = $this->course->backup_path.'/upload/learning_path/images/';
2801
            $destination_path = api_get_path(SYS_COURSE_PATH).
2802
                $this->course->destination_path.'/upload/learning_path/images/';
2803
2804
            // Choose default visibility
2805
            $toolVisibility = api_get_setting('tool_visible_by_default_at_creation');
2806
            $defaultLpVisibility = 'invisible';
2807
            if (isset($toolVisibility['learning_path']) && $toolVisibility['learning_path'] == 'true') {
2808
                $defaultLpVisibility = 'visible';
2809
            }
2810
2811
            foreach ($resources[RESOURCE_LEARNPATH] as $id => $lp) {
2812
                $condition_session = '';
2813
                if (!empty($session_id)) {
2814
                    if ($respect_base_content) {
2815
                        $my_session_id = $lp->session_id;
2816
                        if (!empty($lp->session_id)) {
2817
                            $my_session_id = $session_id;
2818
                        }
2819
                        $condition_session = $my_session_id;
2820
                    } else {
2821
                        $session_id = (int) $session_id;
2822
                        $condition_session = $session_id;
2823
                    }
2824
                }
2825
2826
                // Adding the LP image
2827
                if (!empty($lp->preview_image)) {
2828
                    $new_filename = uniqid('').substr(
2829
                        $lp->preview_image,
2830
                        strlen($lp->preview_image) - 7,
2831
                        strlen($lp->preview_image)
2832
                    );
2833
2834
                    if (file_exists($origin_path.$lp->preview_image) &&
2835
                        !is_dir($origin_path.$lp->preview_image)
2836
                    ) {
2837
                        $copy_result = copy(
2838
                            $origin_path.$lp->preview_image,
2839
                            $destination_path.$new_filename
2840
                        );
2841
                        if ($copy_result) {
2842
                            $lp->preview_image = $new_filename;
2843
                            // Create 64 version from original
2844
                            $temp = new \Image($destination_path.$new_filename);
2845
                            $temp->resize(64);
2846
                            $pathInfo = pathinfo($new_filename);
2847
                            if ($pathInfo) {
2848
                                $filename = $pathInfo['filename'];
2849
                                $extension = $pathInfo['extension'];
2850
                                $temp->send_image($destination_path.'/'.$filename.'.64.'.$extension);
2851
                            }
2852
                        } else {
2853
                            $lp->preview_image = '';
2854
                        }
2855
                    }
2856
                }
2857
2858
                if ($this->add_text_in_items) {
2859
                    $lp->name = $lp->name.' '.get_lang('CopyLabelSuffix');
2860
                }
2861
2862
                if (isset($this->tool_copy_settings['learnpaths'])) {
2863
                    if (isset($this->tool_copy_settings['learnpaths']['reset_dates']) &&
2864
                        $this->tool_copy_settings['learnpaths']['reset_dates']
2865
                    ) {
2866
                        $lp->created_on = api_get_utc_datetime();
2867
                        $lp->modified_on = api_get_utc_datetime();
2868
                        $lp->publicated_on = null;
2869
                    }
2870
                }
2871
2872
                $lp->expired_on = isset($lp->expired_on) && $lp->expired_on === '0000-00-00 00:00:00' ? null : $lp->expired_on;
2873
                $lp->publicated_on = isset($lp->publicated_on) && $lp->publicated_on === '0000-00-00 00:00:00' ? null : $lp->publicated_on;
2874
2875
                if (isset($lp->categoryId)) {
2876
                    $lp->categoryId = (int) $lp->categoryId;
2877
                }
2878
2879
                $categoryId = 0;
2880
                if (!empty($lp->categoryId)) {
2881
                    if (isset($resources[RESOURCE_LEARNPATH_CATEGORY][$lp->categoryId])) {
2882
                        $categoryId = $resources[RESOURCE_LEARNPATH_CATEGORY][$lp->categoryId]->destination_id;
2883
                    }
2884
                }
2885
                $params = [
2886
                    'c_id' => $this->destination_course_id,
2887
                    'lp_type' => $lp->lp_type,
2888
                    'name' => self::DBUTF8($lp->name),
2889
                    'path' => self::DBUTF8($lp->path),
2890
                    'ref' => $lp->ref,
2891
                    'description' => self::DBUTF8($lp->description),
2892
                    'content_local' => self::DBUTF8($lp->content_local),
2893
                    'default_encoding' => self::DBUTF8($lp->default_encoding),
2894
                    'default_view_mod' => self::DBUTF8($lp->default_view_mod),
2895
                    'prevent_reinit' => self::DBUTF8($lp->prevent_reinit),
2896
                    'force_commit' => self::DBUTF8($lp->force_commit),
2897
                    'content_maker' => self::DBUTF8($lp->content_maker),
2898
                    'display_order' => self::DBUTF8($lp->display_order),
2899
                    'js_lib' => self::DBUTF8($lp->js_lib),
2900
                    'content_license' => self::DBUTF8($lp->content_license),
2901
                    'author' => self::DBUTF8($lp->author),
2902
                    'preview_image' => self::DBUTF8($lp->preview_image),
2903
                    'use_max_score' => self::DBUTF8($lp->use_max_score),
2904
                    'autolaunch' => self::DBUTF8(isset($lp->autolaunch) ? $lp->autolaunch : ''),
2905
                    'created_on' => empty($lp->created_on) ? api_get_utc_datetime() : self::DBUTF8($lp->created_on),
2906
                    'modified_on' => empty($lp->modified_on) ? api_get_utc_datetime() : self::DBUTF8($lp->modified_on),
2907
                    'publicated_on' => empty($lp->publicated_on) ? api_get_utc_datetime() : self::DBUTF8($lp->publicated_on),
2908
                    'expired_on' => self::DBUTF8($lp->expired_on),
2909
                    'debug' => self::DBUTF8($lp->debug),
2910
                    'theme' => '',
2911
                    'session_id' => $session_id,
2912
                    'prerequisite' => 0,
2913
                    'hide_toc_frame' => self::DBUTF8(isset($lp->hideTableOfContents) ? $lp->hideTableOfContents : 0),
2914
                    'subscribe_users' => self::DBUTF8(isset($lp->subscribeUsers) ? $lp->subscribeUsers : 0),
2915
                    'seriousgame_mode' => 0,
2916
                    'category_id' => $categoryId,
2917
                    'max_attempts' => 0,
2918
                ];
2919
2920
                if (api_get_configuration_value('lp_minimum_time')) {
2921
                    if (isset($lp->accumulateWorkTime) && !empty($lp->accumulateWorkTime)) {
2922
                        $params['accumulate_work_time'] = $lp->accumulateWorkTime;
2923
                    }
2924
                }
2925
2926
                if (!empty($condition_session)) {
2927
                    $params['session_id'] = $condition_session;
2928
                }
2929
2930
                $new_lp_id = Database::insert($table_main, $params);
2931
2932
                if ($new_lp_id) {
2933
                    // The following only makes sense if a new LP was
2934
                    // created in the destination course
2935
                    $sql = "UPDATE $table_main SET id = iid WHERE iid = $new_lp_id";
2936
                    Database::query($sql);
2937
2938
                    if ($lp->visibility) {
2939
                        $params = [
2940
                            'c_id' => $this->destination_course_id,
2941
                            'name' => self::DBUTF8($lp->name),
2942
                            'link' => "lp/lp_controller.php?action=view&lp_id=$new_lp_id&id_session=$session_id",
2943
                            'image' => 'scormbuilder.gif',
2944
                            'visibility' => '0',
2945
                            'admin' => '0',
2946
                            'address' => 'squaregrey.gif',
2947
                            'session_id' => $session_id,
2948
                        ];
2949
                        $insertId = Database::insert($table_tool, $params);
2950
                        if ($insertId) {
2951
                            $sql = "UPDATE $table_tool SET id = iid WHERE iid = $insertId";
2952
                            Database::query($sql);
2953
                        }
2954
                    }
2955
2956
                    if (isset($lp->extraFields) && !empty($lp->extraFields)) {
2957
                        $extraFieldValue = new \ExtraFieldValue('lp');
2958
                        foreach ($lp->extraFields as $extraField) {
2959
                            $params = [
2960
                                'item_id' => $new_lp_id,
2961
                                'value' => $extraField['value'],
2962
                                'variable' => $extraField['variable'],
2963
                            ];
2964
                            $extraFieldValue->save($params);
2965
                        }
2966
                    }
2967
2968
                    api_item_property_update(
2969
                        $this->destination_course_info,
2970
                        TOOL_LEARNPATH,
2971
                        $new_lp_id,
2972
                        'LearnpathAdded',
2973
                        api_get_user_id(),
2974
                        0,
2975
                        0,
2976
                        0,
2977
                        0,
2978
                        $session_id
2979
                    );
2980
2981
                    // Set the new LP to visible
2982
                    api_item_property_update(
2983
                        $this->destination_course_info,
2984
                        TOOL_LEARNPATH,
2985
                        $new_lp_id,
2986
                        $defaultLpVisibility,
2987
                        api_get_user_id(),
2988
                        0,
2989
                        0,
2990
                        0,
2991
                        0,
2992
                        $session_id
2993
                    );
2994
2995
                    $new_item_ids = [];
2996
                    $parent_item_ids = [];
2997
                    $previous_item_ids = [];
2998
                    $next_item_ids = [];
2999
                    $old_prerequisite = [];
3000
                    $old_refs = [];
3001
                    $prerequisite_ids = [];
3002
3003
                    foreach ($lp->get_items() as $index => $item) {
3004
                        // we set the ref code here and then we update in a for loop
3005
                        $ref = $item['ref'];
3006
3007
                        // Dealing with path the same way as ref as some data has
3008
                        // been put into path when it's a local resource
3009
                        // Only fix the path for no scos
3010
                        if ($item['item_type'] === 'sco') {
3011
                            $path = $item['path'];
3012
                        } else {
3013
                            $path = $this->get_new_id($item['item_type'], $item['path']);
3014
                        }
3015
3016
                        $item['item_type'] = $item['item_type'] === 'dokeos_chapter' ? 'dir' : $item['item_type'];
3017
3018
                        $masteryScore = $item['mastery_score'];
3019
                        // If item is a chamilo quiz, then use the max score as mastery_score.
3020
                        if ($item['item_type'] === 'quiz') {
3021
                            if (empty($masteryScore)) {
3022
                                $masteryScore = $item['max_score'];
3023
                            }
3024
                        }
3025
3026
                        $prerequisiteMinScore = $item['prerequisite_min_score'] ?? null;
3027
                        $prerequisiteMaxScore = $item['prerequisite_max_score'] ?? null;
3028
3029
                        $params = [
3030
                            'c_id' => $this->destination_course_id,
3031
                            'lp_id' => self::DBUTF8($new_lp_id),
3032
                            'item_type' => self::DBUTF8($item['item_type']),
3033
                            'ref' => self::DBUTF8($ref),
3034
                            'path' => self::DBUTF8($path),
3035
                            'title' => self::DBUTF8($item['title']),
3036
                            'description' => self::DBUTF8($item['description']),
3037
                            'min_score' => self::DBUTF8($item['min_score']),
3038
                            'max_score' => self::DBUTF8($item['max_score']),
3039
                            'mastery_score' => self::DBUTF8($masteryScore),
3040
                            'prerequisite_min_score' => $prerequisiteMinScore,
3041
                            'prerequisite_max_score' => $prerequisiteMaxScore,
3042
                            'parent_item_id' => self::DBUTF8($item['parent_item_id']),
3043
                            'previous_item_id' => self::DBUTF8($item['previous_item_id']),
3044
                            'next_item_id' => self::DBUTF8($item['next_item_id']),
3045
                            'display_order' => self::DBUTF8($item['display_order']),
3046
                            'prerequisite' => self::DBUTF8($item['prerequisite']),
3047
                            'parameters' => self::DBUTF8($item['parameters']),
3048
                            'audio' => self::DBUTF8($item['audio']),
3049
                            'launch_data' => self::DBUTF8($item['launch_data']),
3050
                        ];
3051
3052
                        $new_item_id = Database::insert($table_item, $params);
3053
                        if ($new_item_id) {
3054
                            $sql = "UPDATE $table_item SET id = iid WHERE iid = $new_item_id";
3055
                            Database::query($sql);
3056
3057
                            //save a link between old and new item IDs
3058
                            $new_item_ids[$item['id']] = $new_item_id;
3059
                            //save a reference of items that need a parent_item_id refresh
3060
                            $parent_item_ids[$new_item_id] = $item['parent_item_id'];
3061
                            //save a reference of items that need a previous_item_id refresh
3062
                            $previous_item_ids[$new_item_id] = $item['previous_item_id'];
3063
                            //save a reference of items that need a next_item_id refresh
3064
                            $next_item_ids[$new_item_id] = $item['next_item_id'];
3065
3066
                            if (!empty($item['prerequisite'])) {
3067
                                if ($lp->lp_type == '2') {
3068
                                    // if is an sco
3069
                                    $old_prerequisite[$new_item_id] = $item['prerequisite'];
3070
                                } else {
3071
                                    $old_prerequisite[$new_item_id] = isset($new_item_ids[$item['prerequisite']]) ? $new_item_ids[$item['prerequisite']] : '';
3072
                                }
3073
                            }
3074
3075
                            if (!empty($ref)) {
3076
                                if ($lp->lp_type == '2') {
3077
                                    // if is an sco
3078
                                    $old_refs[$new_item_id] = $ref;
3079
                                } elseif (isset($new_item_ids[$ref])) {
3080
                                    $old_refs[$new_item_id] = $new_item_ids[$ref];
3081
                                }
3082
                            }
3083
                            $prerequisite_ids[$new_item_id] = $item['prerequisite'];
3084
                        }
3085
                    }
3086
3087
                    // Updating prerequisites
3088
                    foreach ($old_prerequisite as $key => $my_old_prerequisite) {
3089
                        if ($my_old_prerequisite != '') {
3090
                            $my_old_prerequisite = Database::escape_string($my_old_prerequisite);
3091
                            $sql = "UPDATE $table_item SET prerequisite = '$my_old_prerequisite'
3092
                                    WHERE c_id = ".$this->destination_course_id." AND id = '".$key."'  ";
3093
                            Database::query($sql);
3094
                        }
3095
                    }
3096
3097
                    // Updating refs
3098
                    foreach ($old_refs as $key => $my_old_ref) {
3099
                        if ($my_old_ref != '') {
3100
                            $my_old_ref = Database::escape_string($my_old_ref);
3101
                            $sql = "UPDATE $table_item SET ref = '$my_old_ref'
3102
                                    WHERE c_id = ".$this->destination_course_id." AND id = $key";
3103
                            Database::query($sql);
3104
                        }
3105
                    }
3106
3107
                    foreach ($parent_item_ids as $new_item_id => $parent_item_old_id) {
3108
                        $new_item_id = (int) $new_item_id;
3109
                        $parent_new_id = 0;
3110
                        if ($parent_item_old_id != 0) {
3111
                            $parent_new_id = isset($new_item_ids[$parent_item_old_id]) ? $new_item_ids[$parent_item_old_id] : 0;
3112
                        }
3113
3114
                        $parent_new_id = Database::escape_string($parent_new_id);
3115
                        $sql = "UPDATE $table_item SET parent_item_id = '$parent_new_id'
3116
                                WHERE c_id = ".$this->destination_course_id." AND id = $new_item_id";
3117
                        Database::query($sql);
3118
                    }
3119
3120
                    foreach ($previous_item_ids as $new_item_id => $previous_item_old_id) {
3121
                        $new_item_id = (int) $new_item_id;
3122
                        $previous_new_id = 0;
3123
                        if ($previous_item_old_id != 0) {
3124
                            $previous_new_id = isset($new_item_ids[$previous_item_old_id]) ? $new_item_ids[$previous_item_old_id] : 0;
3125
                        }
3126
                        $previous_new_id = Database::escape_string($previous_new_id);
3127
                        $sql = "UPDATE $table_item SET previous_item_id = '$previous_new_id'
3128
                                WHERE c_id = ".$this->destination_course_id." AND id = '".$new_item_id."'";
3129
                        Database::query($sql);
3130
                    }
3131
3132
                    foreach ($next_item_ids as $new_item_id => $next_item_old_id) {
3133
                        $new_item_id = (int) $new_item_id;
3134
                        $next_new_id = 0;
3135
                        if ($next_item_old_id != 0) {
3136
                            $next_new_id = isset($new_item_ids[$next_item_old_id]) ? $new_item_ids[$next_item_old_id] : 0;
3137
                        }
3138
                        $next_new_id = Database::escape_string($next_new_id);
3139
                        $sql = "UPDATE $table_item SET next_item_id = '$next_new_id'
3140
                                WHERE c_id = ".$this->destination_course_id." AND id = '".$new_item_id."'";
3141
                        Database::query($sql);
3142
                    }
3143
3144
                    foreach ($prerequisite_ids as $new_item_id => $prerequisite_old_id) {
3145
                        $new_item_id = (int) $new_item_id;
3146
                        $prerequisite_new_id = 0;
3147
                        if ($prerequisite_old_id != 0) {
3148
                            $prerequisite_new_id = $new_item_ids[$prerequisite_old_id];
3149
                        }
3150
                        $prerequisite_new_id = Database::escape_string($prerequisite_new_id);
3151
                        $sql = "UPDATE $table_item SET prerequisite = '$prerequisite_new_id'
3152
                                WHERE c_id = ".$this->destination_course_id." AND id = $new_item_id";
3153
                        Database::query($sql);
3154
                    }
3155
                    $this->course->resources[RESOURCE_LEARNPATH][$id]->destination_id = $new_lp_id;
3156
                }
3157
            }
3158
        }
3159
    }
3160
3161
    /**
3162
     * Copy all directory and sub directory.
3163
     *
3164
     * @param string $source The path origin
3165
     * @param string $dest   The path destination
3166
     * @param bool Option Overwrite
3167
     *
3168
     * @deprecated
3169
     */
3170
    public function allow_create_all_directory($source, $dest, $overwrite = false)
3171
    {
3172
        if (!is_dir($dest)) {
3173
            mkdir($dest, api_get_permissions_for_new_directories());
3174
        }
3175
        if ($handle = opendir($source)) {
3176
            // if the folder exploration is sucsessful, continue
3177
            while (false !== ($file = readdir($handle))) {
3178
                // as long as storing the next file to $file is successful, continue
3179
                if ($file != '.' && $file != '..') {
3180
                    $path = $source.'/'.$file;
3181
                    if (is_file($path)) {
3182
                        /* if (!is_file($dest . '/' . $file) || $overwrite)
3183
                         if (!@copy($path, $dest . '/' . $file)) {
3184
                             echo '<font color="red">File ('.$path.') '.get_lang('NotHavePermission').'</font>';
3185
                         }*/
3186
                    } elseif (is_dir($path)) {
3187
                        if (!is_dir($dest.'/'.$file)) {
3188
                            mkdir($dest.'/'.$file);
3189
                        }
3190
                        self:: allow_create_all_directory($path, $dest.'/'.$file, $overwrite);
3191
                    }
3192
                }
3193
            }
3194
            closedir($handle);
3195
        }
3196
    }
3197
3198
    /**
3199
     * Gets the new ID of one specific tool item from the tool name and the old ID.
3200
     *
3201
     * @param	string	Tool name
3202
     * @param	int	Old ID
3203
     *
3204
     * @return int New ID
3205
     */
3206
    public function get_new_id($tool, $ref)
3207
    {
3208
        // Check if the value exist in the current array.
3209
        if ($tool === 'hotpotatoes') {
3210
            $tool = 'document';
3211
        }
3212
3213
        if ($tool === 'student_publication') {
3214
            $tool = RESOURCE_WORK;
3215
        }
3216
3217
        if ('xapi' === $tool && $this->isXapiEnabled) {
3218
            $tool = RESOURCE_XAPI_TOOL;
3219
        }
3220
3221
        if (isset($this->course->resources[$tool][$ref]) &&
3222
            isset($this->course->resources[$tool][$ref]->destination_id) &&
3223
            !empty($this->course->resources[$tool][$ref]->destination_id)
3224
        ) {
3225
            return $this->course->resources[$tool][$ref]->destination_id;
3226
        }
3227
3228
        // Check if the course is the same (last hope).
3229
        if ($this->course_origin_id == $this->destination_course_id) {
3230
            return $ref;
3231
        }
3232
3233
        return '';
3234
    }
3235
3236
    /**
3237
     * Restore glossary.
3238
     */
3239
    public function restore_glossary($sessionId = 0)
3240
    {
3241
        $sessionId = (int) $sessionId;
3242
        if ($this->course->has_resources(RESOURCE_GLOSSARY)) {
3243
            $table_glossary = Database::get_course_table(TABLE_GLOSSARY);
3244
            $resources = $this->course->resources;
3245
            foreach ($resources[RESOURCE_GLOSSARY] as $id => $glossary) {
3246
                $params = [];
3247
                if (!empty($sessionId)) {
3248
                    $params['session_id'] = $sessionId;
3249
                }
3250
3251
                // check resources inside html from ckeditor tool and copy correct urls into recipient course
3252
                $glossary->description = DocumentManager::replaceUrlWithNewCourseCode(
3253
                    $glossary->description,
3254
                    $this->course->code,
3255
                    $this->course->destination_path,
3256
                    $this->course->backup_path,
3257
                    $this->course->info['path']
3258
                );
3259
3260
                $params['c_id'] = $this->destination_course_id;
3261
                $params['description'] = ($glossary->description === false ? '' : self::DBUTF8($glossary->description));
3262
                $params['display_order'] = $glossary->display_order;
3263
                $params['name'] = self::DBUTF8($glossary->name);
3264
                $params['glossary_id'] = 0;
3265
                $my_id = Database::insert($table_glossary, $params);
3266
                if ($my_id) {
3267
                    $sql = "UPDATE $table_glossary SET glossary_id = iid WHERE iid = $my_id";
3268
                    Database::query($sql);
3269
3270
                    api_item_property_update(
3271
                        $this->destination_course_info,
3272
                        TOOL_GLOSSARY,
3273
                        $my_id,
3274
                        'GlossaryAdded',
3275
                        api_get_user_id(),
3276
                        null,
3277
                        null,
3278
                        null,
3279
                        null,
3280
                        $sessionId
3281
                    );
3282
3283
                    if (!isset($this->course->resources[RESOURCE_GLOSSARY][$id])) {
3284
                        $this->course->resources[RESOURCE_GLOSSARY][$id] = new stdClass();
3285
                    }
3286
3287
                    $this->course->resources[RESOURCE_GLOSSARY][$id]->destination_id = $my_id;
3288
                }
3289
            }
3290
        }
3291
    }
3292
3293
    /**
3294
     * @param int $sessionId
3295
     */
3296
    public function restore_wiki($sessionId = 0)
3297
    {
3298
        if ($this->course->has_resources(RESOURCE_WIKI)) {
3299
            // wiki table of the target course
3300
            $table_wiki = Database::get_course_table(TABLE_WIKI);
3301
            $table_wiki_conf = Database::get_course_table(TABLE_WIKI_CONF);
3302
3303
            // storing all the resources that have to be copied in an array
3304
            $resources = $this->course->resources;
3305
3306
            foreach ($resources[RESOURCE_WIKI] as $id => $wiki) {
3307
                // the sql statement to insert the groups from the old course to the new course
3308
                // check resources inside html from ckeditor tool and copy correct urls into recipient course
3309
                $wiki->content = DocumentManager::replaceUrlWithNewCourseCode(
3310
                    $wiki->content,
3311
                    $this->course->code,
3312
                    $this->course->destination_path,
3313
                    $this->course->backup_path,
3314
                    $this->course->info['path']
3315
                );
3316
3317
                $params = [
3318
                    'c_id' => $this->destination_course_id,
3319
                    'page_id' => self::DBUTF8($wiki->page_id),
3320
                    'reflink' => self::DBUTF8($wiki->reflink),
3321
                    'title' => self::DBUTF8($wiki->title),
3322
                    'content' => ($wiki->content === false ? '' : self::DBUTF8($wiki->content)),
3323
                    'user_id' => intval($wiki->user_id),
3324
                    'group_id' => intval($wiki->group_id),
3325
                    'dtime' => self::DBUTF8($wiki->dtime),
3326
                    'progress' => self::DBUTF8($wiki->progress),
3327
                    'version' => intval($wiki->version),
3328
                    'session_id' => !empty($sessionId) ? intval($sessionId) : 0,
3329
                    'addlock' => 0,
3330
                    'editlock' => 0,
3331
                    'visibility' => 0,
3332
                    'addlock_disc' => 0,
3333
                    'visibility_disc' => 0,
3334
                    'ratinglock_disc' => 0,
3335
                    'assignment' => 0,
3336
                    'comment' => '',
3337
                    'is_editing' => 0,
3338
                    'linksto' => 0,
3339
                    'tag' => '',
3340
                    'user_ip' => '',
3341
                ];
3342
3343
                $new_id = Database::insert($table_wiki, $params);
3344
3345
                if ($new_id) {
3346
                    $sql = "UPDATE $table_wiki SET page_id = '$new_id', id = iid
3347
                            WHERE c_id = ".$this->destination_course_id." AND iid = '$new_id'";
3348
                    Database::query($sql);
3349
3350
                    $this->course->resources[RESOURCE_WIKI][$id]->destination_id = $new_id;
3351
3352
                    // we also add an entry in wiki_conf
3353
                    $params = [
3354
                        'c_id' => $this->destination_course_id,
3355
                        'page_id' => $new_id,
3356
                        'task' => '',
3357
                        'feedback1' => '',
3358
                        'feedback2' => '',
3359
                        'feedback3' => '',
3360
                        'fprogress1' => '',
3361
                        'fprogress2' => '',
3362
                        'fprogress3' => '',
3363
                        'max_size' => 0,
3364
                        'max_text' => 0,
3365
                        'max_version' => 0,
3366
                        'startdate_assig' => null,
3367
                        'enddate_assig' => null,
3368
                        'delayedsubmit' => 0,
3369
                    ];
3370
3371
                    Database::insert($table_wiki_conf, $params);
3372
                }
3373
            }
3374
        }
3375
    }
3376
3377
    /**
3378
     * Restore xapi tool
3379
     *
3380
     * @param int $sessionId
3381
     */
3382
3383
    public function restore_xapi_tool()
3384
    {
3385
        if ($this->course->has_resources(RESOURCE_XAPI_TOOL) && $this->isXapiEnabled) {
3386
            $resources = $this->course->resources;
3387
            foreach ($resources[RESOURCE_XAPI_TOOL] as $id => $xapiTool) {
3388
3389
                $launchPath = str_replace(
3390
                    api_get_path(WEB_COURSE_PATH).$this->course->info['path'].'/',
3391
                    '',
3392
                    dirname($xapiTool->params['launch_url'])
3393
                );
3394
3395
                $originPath = $this->course->backup_path.'/'.$launchPath;
3396
                $destinationPath = api_get_path(SYS_COURSE_PATH).$this->course->destination_path.'/'.$launchPath;
3397
                $xapiDir = dirname($destinationPath);
3398
                @mkdir($xapiDir, api_get_permissions_for_new_directories(), true);
3399
                if (copyDirTo($originPath, $destinationPath, false)) {
3400
                    $xapiTool->params['launch_url'] = str_replace(
3401
                        '/'.$this->course->info['path'].'/',
3402
                        '/'.$this->course->destination_path.'/',
3403
                        $xapiTool->params['launch_url']
3404
                    );
3405
                    $ref = $xapiTool->params['id'];
3406
                    $xapiTool->params['c_id'] = $this->destination_course_id;
3407
                    unset($xapiTool->params['id']);
3408
3409
                    $lastId = Database::insert('xapi_tool_launch', $xapiTool->params, false);
3410
                    $this->course->resources[RESOURCE_XAPI_TOOL][$ref]->destination_id = $lastId;
3411
                }
3412
            }
3413
        }
3414
    }
3415
3416
    /**
3417
     * Restore Thematics.
3418
     *
3419
     * @param int $sessionId
3420
     */
3421
    public function restore_thematic($sessionId = 0)
3422
    {
3423
        if ($this->course->has_resources(RESOURCE_THEMATIC)) {
3424
            $table_thematic = Database::get_course_table(TABLE_THEMATIC);
3425
            $table_thematic_advance = Database::get_course_table(TABLE_THEMATIC_ADVANCE);
3426
            $table_thematic_plan = Database::get_course_table(TABLE_THEMATIC_PLAN);
3427
3428
            $resources = $this->course->resources;
3429
            foreach ($resources[RESOURCE_THEMATIC] as $id => $thematic) {
3430
                // check resources inside html from ckeditor tool and copy correct urls into recipient course
3431
                $thematic->params['content'] = DocumentManager::replaceUrlWithNewCourseCode(
3432
                    $thematic->params['content'],
3433
                    $this->course->code,
3434
                    $this->course->destination_path,
3435
                    $this->course->backup_path,
3436
                    $this->course->info['path']
3437
                );
3438
                $thematic->params['c_id'] = $this->destination_course_id;
3439
                unset($thematic->params['id']);
3440
                unset($thematic->params['iid']);
3441
3442
                $last_id = Database::insert($table_thematic, $thematic->params, false);
3443
3444
                if ($last_id) {
3445
                    $sql = "UPDATE $table_thematic SET id = iid WHERE iid = $last_id";
3446
                    Database::query($sql);
3447
3448
                    api_item_property_update(
3449
                        $this->destination_course_info,
3450
                        'thematic',
3451
                        $last_id,
3452
                        'ThematicAdded',
3453
                        api_get_user_id(),
3454
                        null,
3455
                        null,
3456
                        null,
3457
                        null,
3458
                        $sessionId
3459
                    );
3460
3461
                    foreach ($thematic->thematic_advance_list as $thematic_advance) {
3462
                        unset($thematic_advance['id']);
3463
                        unset($thematic_advance['iid']);
3464
                        $thematic_advance['attendance_id'] = 0;
3465
                        $thematic_advance['thematic_id'] = $last_id;
3466
                        $thematic_advance['c_id'] = $this->destination_course_id;
3467
3468
                        $my_id = Database::insert(
3469
                            $table_thematic_advance,
3470
                            $thematic_advance,
3471
                            false
3472
                        );
3473
3474
                        if ($my_id) {
3475
                            $sql = "UPDATE $table_thematic_advance SET id = iid WHERE iid = $my_id";
3476
                            Database::query($sql);
3477
3478
                            api_item_property_update(
3479
                                $this->destination_course_info,
3480
                                'thematic_advance',
3481
                                $my_id,
3482
                                'ThematicAdvanceAdded',
3483
                                api_get_user_id(),
3484
                                null,
3485
                                null,
3486
                                null,
3487
                                null,
3488
                                $sessionId
3489
                            );
3490
                        }
3491
                    }
3492
3493
                    foreach ($thematic->thematic_plan_list as $thematic_plan) {
3494
                        unset($thematic_plan['id']);
3495
                        unset($thematic_plan['iid']);
3496
                        $thematic_plan['thematic_id'] = $last_id;
3497
                        $thematic_plan['c_id'] = $this->destination_course_id;
3498
                        $my_id = Database::insert($table_thematic_plan, $thematic_plan, false);
3499
3500
                        if ($my_id) {
3501
                            $sql = "UPDATE $table_thematic_plan SET id = iid WHERE iid = $my_id";
3502
                            Database::query($sql);
3503
3504
                            api_item_property_update(
3505
                                $this->destination_course_info,
3506
                                'thematic_plan',
3507
                                $my_id,
3508
                                'ThematicPlanAdded',
3509
                                api_get_user_id(),
3510
                                null,
3511
                                null,
3512
                                null,
3513
                                null,
3514
                                $sessionId
3515
                            );
3516
                        }
3517
                    }
3518
                }
3519
            }
3520
        }
3521
    }
3522
3523
    /**
3524
     * Restore Attendance.
3525
     *
3526
     * @param int $sessionId
3527
     */
3528
    public function restore_attendance($sessionId = 0)
3529
    {
3530
        if ($this->course->has_resources(RESOURCE_ATTENDANCE)) {
3531
            $table_attendance = Database::get_course_table(TABLE_ATTENDANCE);
3532
            $table_attendance_calendar = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR);
3533
3534
            $resources = $this->course->resources;
3535
            foreach ($resources[RESOURCE_ATTENDANCE] as $id => $obj) {
3536
                // check resources inside html from ckeditor tool and copy correct urls into recipient course
3537
                $obj->params['description'] = DocumentManager::replaceUrlWithNewCourseCode(
3538
                    $obj->params['description'],
3539
                    $this->course->code,
3540
                    $this->course->destination_path,
3541
                    $this->course->backup_path,
3542
                    $this->course->info['path']
3543
                );
3544
3545
                unset($obj->params['id']);
3546
                unset($obj->params['iid']);
3547
                $obj->params['c_id'] = $this->destination_course_id;
3548
                $last_id = Database::insert($table_attendance, $obj->params);
3549
3550
                if (is_numeric($last_id)) {
3551
                    $sql = "UPDATE $table_attendance SET id = iid WHERE iid = $last_id";
3552
                    Database::query($sql);
3553
3554
                    $this->course->resources[RESOURCE_ATTENDANCE][$id]->destination_id = $last_id;
3555
3556
                    api_item_property_update(
3557
                        $this->destination_course_info,
3558
                        TOOL_ATTENDANCE,
3559
                        $last_id,
3560
                        'AttendanceAdded',
3561
                        api_get_user_id(),
3562
                        null,
3563
                        null,
3564
                        null,
3565
                        null,
3566
                        $sessionId
3567
                    );
3568
3569
                    foreach ($obj->attendance_calendar as $attendance_calendar) {
3570
                        unset($attendance_calendar['id']);
3571
                        unset($attendance_calendar['iid']);
3572
3573
                        $attendance_calendar['attendance_id'] = $last_id;
3574
                        $attendance_calendar['c_id'] = $this->destination_course_id;
3575
                        $attendanceCalendarId = Database::insert(
3576
                            $table_attendance_calendar,
3577
                            $attendance_calendar
3578
                        );
3579
3580
                        $sql = "UPDATE $table_attendance_calendar SET id = iid WHERE iid = $attendanceCalendarId";
3581
                        Database::query($sql);
3582
                    }
3583
                }
3584
            }
3585
        }
3586
    }
3587
3588
    /**
3589
     * Restore Works.
3590
     *
3591
     * @param int $sessionId
3592
     */
3593
    public function restore_works($sessionId = 0)
3594
    {
3595
        require_once api_get_path(SYS_CODE_PATH).'work/work.lib.php';
3596
        if ($this->course->has_resources(RESOURCE_WORK)) {
3597
            $table = Database::get_course_table(TABLE_STUDENT_PUBLICATION_ASSIGNMENT);
3598
3599
            $resources = $this->course->resources;
3600
            foreach ($resources[RESOURCE_WORK] as $obj) {
3601
                // check resources inside html from ckeditor tool and copy correct urls into recipient course
3602
                $obj->params['description'] = DocumentManager::replaceUrlWithNewCourseCode(
3603
                    $obj->params['description'],
3604
                    $this->course->code,
3605
                    $this->course->destination_path,
3606
                    $this->course->backup_path,
3607
                    $this->course->info['path']
3608
                );
3609
3610
                $id_work = $obj->params['id'];
3611
                $obj->params['id'] = null;
3612
                $obj->params['c_id'] = $this->destination_course_info['real_id'];
3613
3614
                // re-create dir
3615
                // @todo check security against injection of dir in crafted course backup here!
3616
                $path = $obj->params['url'];
3617
                $path = '/'.str_replace('/', '', substr($path, 1));
3618
3619
                $workData = [];
3620
3621
                switch ($this->file_option) {
3622
                    case FILE_SKIP:
3623
                        $workData = get_work_data_by_path(
3624
                            $path,
3625
                            $this->destination_course_info['real_id']
3626
                        );
3627
                        if (!empty($workData)) {
3628
                            break;
3629
                        }
3630
                        break;
3631
                    case FILE_OVERWRITE:
3632
                        if (!empty($this->course_origin_id)) {
3633
                            $sql = 'SELECT * FROM '.$table.'
3634
                                    WHERE
3635
                                        c_id = '.$this->course_origin_id.' AND
3636
                                        publication_id = '.$id_work;
3637
                            $result = Database::query($sql);
3638
                            $cant = Database::num_rows($result);
3639
                            if ($cant > 0) {
3640
                                $row = Database::fetch_assoc($result);
3641
                            }
3642
3643
                            $obj->params['enableExpiryDate'] = empty($row['expires_on']) ? false : true;
3644
                            $obj->params['enableEndDate'] = empty($row['ends_on']) ? false : true;
3645
                            $obj->params['expires_on'] = $row['expires_on'];
3646
                            $obj->params['ends_on'] = $row['ends_on'];
3647
                            $obj->params['enable_qualification'] = $row['enable_qualification'];
3648
                            $obj->params['add_to_calendar'] = !empty($row['add_to_calendar']) ? 1 : 0;
3649
                        }
3650
                        //no break
3651
                    case FILE_RENAME:
3652
                        $workData = get_work_data_by_path(
3653
                            $path,
3654
                            $this->destination_course_info['real_id']
3655
                        );
3656
                        break;
3657
                }
3658
3659
                $obj->params['work_title'] = $obj->params['title'];
3660
                $obj->params['new_dir'] = $obj->params['title'];
3661
3662
                if (empty($workData)) {
3663
                    $workId = addDir(
3664
                        $obj->params,
3665
                        api_get_user_id(),
3666
                        $this->destination_course_info,
3667
                        0,
3668
                        $sessionId
3669
                    );
3670
                    $this->course->resources[RESOURCE_WORK][$id_work]->destination_id = $workId;
3671
                } else {
3672
                    $workId = $workData['iid'];
3673
                    updateWork(
3674
                        $workId,
3675
                        $obj->params,
3676
                        $this->destination_course_info,
3677
                        $sessionId
3678
                    );
3679
                    updatePublicationAssignment(
3680
                        $workId,
3681
                        $obj->params,
3682
                        $this->destination_course_info,
3683
                        0
3684
                    );
3685
                    $this->course->resources[RESOURCE_WORK][$id_work]->destination_id = $workId;
3686
                }
3687
            }
3688
        }
3689
    }
3690
3691
    /**
3692
     * Restore gradebook.
3693
     *
3694
     * @param int $sessionId
3695
     *
3696
     * @return bool
3697
     */
3698
    public function restore_gradebook($sessionId = 0)
3699
    {
3700
        if (in_array($this->file_option, [FILE_SKIP, FILE_RENAME])) {
3701
            return false;
3702
        }
3703
        // if overwrite
3704
        if ($this->course->has_resources(RESOURCE_GRADEBOOK)) {
3705
            $resources = $this->course->resources;
3706
            $destinationCourseCode = $this->destination_course_info['code'];
3707
            // Delete destination gradebook
3708
            $cats = \Category:: load(
3709
                null,
3710
                null,
3711
                $destinationCourseCode,
3712
                null,
3713
                null,
3714
                $sessionId
3715
            );
3716
3717
            if (!empty($cats)) {
3718
                /** @var \Category $cat */
3719
                foreach ($cats as $cat) {
3720
                    $cat->delete_all();
3721
                }
3722
            }
3723
3724
            /** @var GradeBookBackup $obj */
3725
            foreach ($resources[RESOURCE_GRADEBOOK] as $id => $obj) {
3726
                if (!empty($obj->categories)) {
3727
                    $categoryIdList = [];
3728
                    /** @var \Category $cat */
3729
                    foreach ($obj->categories as $cat) {
3730
                        $cat->set_course_code($destinationCourseCode);
3731
                        $cat->set_session_id($sessionId);
3732
3733
                        $parentId = $cat->get_parent_id();
3734
                        if (!empty($parentId)) {
3735
                            if (isset($categoryIdList[$parentId])) {
3736
                                $cat->set_parent_id($categoryIdList[$parentId]);
3737
                            }
3738
                        }
3739
                        $oldId = $cat->get_id();
3740
                        $categoryId = $cat->add();
3741
                        $categoryIdList[$oldId] = $categoryId;
3742
                        if (!empty($cat->evaluations)) {
3743
                            /** @var \Evaluation $evaluation */
3744
                            foreach ($cat->evaluations as $evaluation) {
3745
                                $evaluation->set_category_id($categoryId);
3746
                                $evaluation->set_course_code($destinationCourseCode);
3747
                                $evaluation->setSessionId($sessionId);
3748
                                $evaluation->add();
3749
                            }
3750
                        }
3751
3752
                        if (!empty($cat->links)) {
3753
                            /** @var \AbstractLink $link */
3754
                            foreach ($cat->links as $link) {
3755
                                $link->set_category_id($categoryId);
3756
                                $link->set_course_code($destinationCourseCode);
3757
                                $link->set_session_id($sessionId);
3758
                                $import = false;
3759
                                $itemId = $link->get_ref_id();
3760
                                switch ($link->get_type()) {
3761
                                    case LINK_EXERCISE:
3762
                                        $type = RESOURCE_QUIZ;
3763
                                        break;
3764
                                    /*case LINK_DROPBOX:
3765
                                        break;*/
3766
                                    case LINK_STUDENTPUBLICATION:
3767
                                        $type = RESOURCE_WORK;
3768
                                        break;
3769
                                    case LINK_LEARNPATH:
3770
                                        $type = RESOURCE_LEARNPATH;
3771
                                        break;
3772
                                    case LINK_FORUM_THREAD:
3773
                                        $type = RESOURCE_FORUMTOPIC;
3774
                                        break;
3775
                                    case LINK_ATTENDANCE:
3776
                                        $type = RESOURCE_ATTENDANCE;
3777
                                        break;
3778
                                    case LINK_SURVEY:
3779
                                        $type = RESOURCE_ATTENDANCE;
3780
                                        break;
3781
                                    case LINK_HOTPOTATOES:
3782
                                        $type = RESOURCE_QUIZ;
3783
                                        break;
3784
                                }
3785
3786
                                if ($this->course->has_resources($type) &&
3787
                                    isset($this->course->resources[$type][$itemId])
3788
                                ) {
3789
                                    $item = $this->course->resources[$type][$itemId];
3790
                                    if ($item && $item->is_restored()) {
3791
                                        $link->set_ref_id($item->destination_id);
3792
                                        $import = true;
3793
                                    }
3794
                                }
3795
3796
                                if ($import) {
3797
                                    $link->add();
3798
                                }
3799
                            }
3800
                        }
3801
                    }
3802
                }
3803
            }
3804
        }
3805
    }
3806
3807
    /**
3808
     * Restore course assets (not included in documents).
3809
     */
3810
    public function restore_assets()
3811
    {
3812
        if ($this->course->has_resources(RESOURCE_ASSET)) {
3813
            $resources = $this->course->resources;
3814
            $path = api_get_path(SYS_COURSE_PATH).$this->course->destination_path.'/';
3815
3816
            foreach ($resources[RESOURCE_ASSET] as $asset) {
3817
                if (is_file($this->course->backup_path.'/'.$asset->path) &&
3818
                    is_readable($this->course->backup_path.'/'.$asset->path) &&
3819
                    is_dir(dirname($path.$asset->path)) &&
3820
                    is_writeable(dirname($path.$asset->path))
3821
                ) {
3822
                    switch ($this->file_option) {
3823
                        case FILE_SKIP:
3824
                            break;
3825
                        case FILE_OVERWRITE:
3826
                            copy(
3827
                                $this->course->backup_path.'/'.$asset->path,
3828
                                $path.$asset->path
3829
                            );
3830
                            break;
3831
                    }
3832
                }
3833
            }
3834
        }
3835
    }
3836
3837
    /**
3838
     * @param string $str
3839
     *
3840
     * @return string
3841
     */
3842
    public function DBUTF8($str)
3843
    {
3844
        if (UTF8_CONVERT) {
3845
            $str = utf8_encode($str);
3846
        }
3847
3848
        return $str;
3849
    }
3850
3851
    /**
3852
     * @param string $str
3853
     *
3854
     * @return string
3855
     */
3856
    public function DBUTF8escapestring($str)
3857
    {
3858
        if (UTF8_CONVERT) {
3859
            $str = utf8_encode($str);
3860
        }
3861
3862
        return Database::escape_string($str);
3863
    }
3864
3865
    /**
3866
     * @param array $array
3867
     *
3868
     * @return mixed
3869
     */
3870
    public function DBUTF8_array($array)
3871
    {
3872
        if (UTF8_CONVERT) {
3873
            foreach ($array as &$item) {
3874
                $item = utf8_encode($item);
3875
            }
3876
3877
            return $array;
3878
        } else {
3879
            return $array;
3880
        }
3881
    }
3882
3883
    /**
3884
     * @param int $groupId
3885
     *
3886
     * @return array
3887
     */
3888
    public function checkGroupId($groupId)
3889
    {
3890
        return \GroupManager::get_group_properties($groupId);
3891
    }
3892
3893
    /**
3894
     * @param string $documentPath
3895
     * @param string $webEditorCss
3896
     */
3897
    public function fixEditorHtmlContent($documentPath, $webEditorCss = '')
3898
    {
3899
        $extension = pathinfo(basename($documentPath), PATHINFO_EXTENSION);
3900
3901
        switch ($extension) {
3902
            case 'html':
3903
            case 'htm':
3904
                $contents = file_get_contents($documentPath);
3905
                $contents = str_replace(
3906
                    '{{css_editor}}',
3907
                    $webEditorCss,
3908
                    $contents
3909
                );
3910
                file_put_contents($documentPath, $contents);
3911
                break;
3912
        }
3913
    }
3914
3915
    /**
3916
     * Check if user exist otherwise use current user.
3917
     *
3918
     * @param int  $userId
3919
     * @param bool $returnNull
3920
     *
3921
     * @return int
3922
     */
3923
    private function checkUserId($userId, $returnNull = false)
3924
    {
3925
        if (!empty($userId)) {
3926
            $userInfo = api_get_user_info($userId);
3927
            if (empty($userInfo)) {
3928
                return api_get_user_id();
3929
            }
3930
        }
3931
3932
        if ($returnNull) {
3933
            return null;
3934
        }
3935
3936
        if (empty($userId)) {
3937
            return api_get_user_id();
3938
        }
3939
3940
        return $userId;
3941
    }
3942
}
3943