Passed
Push — 1.11.x ( f6acf8...eea5cf )
by Julito
10:47
created

CourseRestorer   F

Complexity

Total Complexity 522

Size/Duplication

Total Lines 3767
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 2362
dl 0
loc 3767
rs 0.8
c 1
b 0
f 0
wmc 522

41 Methods

Rating   Name   Duplication   Size   Complexity  
A set_add_text_in_items() 0 3 1
A set_file_option() 0 3 1
A set_tool_copy_settings() 0 3 1
A __construct() 0 15 3
B restore_links() 0 53 6
F restore_surveys() 0 176 22
A restore_topic() 0 53 4
A checkGroupId() 0 3 1
B restore_scorm_documents() 0 62 9
F restore_learnpaths() 0 342 59
A checkUserId() 0 18 5
F restore_forums() 0 79 18
B restore_assets() 0 21 9
F restore_gradebook() 0 100 26
A DBUTF8() 0 7 2
C restore_announcements() 0 107 16
B restore_tool_intro() 0 35 6
B get_new_id() 0 24 7
B restore_glossary() 0 49 7
A is_survey_code_available() 0 12 2
A restore_post() 0 42 2
B restore_wiki() 0 76 6
B restore_link_category() 0 61 6
B restore_thematic() 0 94 8
F restore_events() 0 103 20
F restore_quizzes() 0 121 25
B restore_learnpath_category() 0 44 10
F restore() 0 109 20
F restore_quiz_question() 0 308 36
A DBUTF8escapestring() 0 7 2
B allow_create_all_directory() 0 25 9
B restore_course_descriptions() 0 39 9
A restore_course_settings() 0 12 1
B restore_forum_category() 0 50 9
B restore_survey_question() 0 73 10
F restore_documents() 0 743 105
C restore_works() 0 93 13
B restore_attendance() 0 54 5
C restore_test_category() 0 75 15
A fixEditorHtmlContent() 0 15 3
A DBUTF8_array() 0 10 3

How to fix   Complexity   

Complex Class

Complex classes like CourseRestorer often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use CourseRestorer, and based on these observations, apply Extract Interface, too.

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