Completed
Push — master ( bd22e5...ae5621 )
by Julito
12:43
created

CourseRestorer::restore_documents()   F

Complexity

Conditions 98
Paths > 20000

Size

Total Lines 712
Code Lines 503

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 98
eloc 503
nc 545874
nop 3
dl 0
loc 712
rs 2
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

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

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

Commonly applied refactorings include:

1
<?php
2
/* 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\QuizQuestion;
8
use Chamilo\CourseBundle\Entity\CQuizAnswer;
9
use CourseManager;
10
use Database;
11
use DocumentManager;
12
use Question;
13
use stdClass;
14
use SurveyManager;
15
use TestCategory;
16
17
/**
18
 * Class CourseRestorer.
19
 *
20
 * Class to restore items from a course object to a Chamilo-course
21
 *
22
 * @author Bart Mollet <[email protected]>
23
 * @author Julio Montoya <[email protected]> Several fixes/improvements
24
 *
25
 * @package chamilo.backup
26
 */
27
class CourseRestorer
28
{
29
    /**
30
     * The course-object.
31
     */
32
    public $course;
33
    public $destination_course_info;
34
35
    /**
36
     * What to do with files with same name (FILE_SKIP, FILE_RENAME or
37
     * FILE_OVERWRITE).
38
     */
39
    public $file_option;
40
    public $set_tools_invisible_by_default;
41
    public $skip_content;
42
    public $tools_to_restore = [
43
        'documents', // first restore documents
44
        'announcements',
45
        'attendance',
46
        'course_descriptions',
47
        'events',
48
        'forum_category',
49
        'forums',
50
       // 'forum_topics',
51
        'glossary',
52
        'quizzes',
53
        'test_category',
54
        'links',
55
        'works',
56
        'surveys',
57
        'learnpaths',
58
        //'scorm_documents', ??
59
        'tool_intro',
60
        'thematic',
61
        'wiki',
62
        'gradebook',
63
        'assets',
64
    ];
65
66
    /** Setting per tool */
67
    public $tool_copy_settings = [];
68
69
    /**
70
     * If true adds the text "copy" in the title of an item (only for LPs right now).
71
     */
72
    public $add_text_in_items = false;
73
    public $destination_course_id;
74
75
    /**
76
     * CourseRestorer constructor.
77
     *
78
     * @param Course $course
79
     */
80
    public function __construct($course)
81
    {
82
        $this->course = $course;
83
        $courseInfo = api_get_course_info($this->course->code);
84
        $this->course_origin_id = null;
85
        if (!empty($courseInfo)) {
86
            $this->course_origin_id = $courseInfo['real_id'];
87
        }
88
        $this->file_option = FILE_RENAME;
89
        $this->set_tools_invisible_by_default = false;
90
        $this->skip_content = [];
91
    }
92
93
    /**
94
     * Set the file-option.
95
     *
96
     * @param int $option (optional) What to do with files with same name
97
     *                    FILE_SKIP, FILE_RENAME or FILE_OVERWRITE
98
     */
99
    public function set_file_option($option = FILE_OVERWRITE)
100
    {
101
        $this->file_option = $option;
102
    }
103
104
    /**
105
     * @param bool $status
106
     */
107
    public function set_add_text_in_items($status)
108
    {
109
        $this->add_text_in_items = $status;
110
    }
111
112
    /**
113
     * @param array $array
114
     */
115
    public function set_tool_copy_settings($array)
116
    {
117
        $this->tool_copy_settings = $array;
118
    }
119
120
    /**
121
     * Restore a course.
122
     *
123
     * @param string $destination_course_code code of the Chamilo-course in
124
     * @param int    $session_id
125
     * @param bool   $update_course_settings  Course settings are going to be restore?
126
     * @param bool   $respect_base_content
127
     *
128
     * @return false|null
129
     */
130
    public function restore(
131
        $destination_course_code = '',
132
        $session_id = 0,
133
        $update_course_settings = false,
134
        $respect_base_content = false
135
    ) {
136
        if ($destination_course_code == '') {
137
            $course_info = api_get_course_info();
138
            $this->destination_course_info = $course_info;
139
            $this->course->destination_path = $course_info['path'];
140
        } else {
141
            $course_info = api_get_course_info($destination_course_code);
142
            $this->destination_course_info = $course_info;
143
            $this->course->destination_path = $course_info['path'];
144
        }
145
        $this->destination_course_id = $course_info['real_id'];
146
147
        //Getting first teacher (for the forums)
148
        $teacher_list = CourseManager::get_teacher_list_from_course_code(
149
            $course_info['code']
150
        );
151
        $this->first_teacher_id = api_get_user_id();
152
153
        if (!empty($teacher_list)) {
154
            foreach ($teacher_list as $teacher) {
155
                $this->first_teacher_id = $teacher['user_id'];
156
                break;
157
            }
158
        }
159
160
        if (empty($this->course)) {
161
            return false;
162
        }
163
164
        // Source platform encoding - reading/detection
165
        // The correspondent data field has been added as of version 1.8.6.1
166
        if (empty($this->course->encoding)) {
167
            // The archive has been created by a system which is prior to 1.8.6.1 version.
168
            // In this case we have to detect the encoding.
169
            $sample_text = $this->course->get_sample_text()."\n";
170
            // Let us exclude ASCII lines, probably they are English texts.
171
            $sample_text = explode("\n", $sample_text);
172
            foreach ($sample_text as $key => &$line) {
173
                if (api_is_valid_ascii($line)) {
174
                    unset($sample_text[$key]);
175
                }
176
            }
177
            $sample_text = implode("\n", $sample_text);
178
            $this->course->encoding = api_detect_encoding(
179
                $sample_text,
180
                $course_info['language']
181
            );
182
        }
183
184
        // Encoding conversion of the course, if it is needed.
185
        $this->course->to_system_encoding();
186
187
        foreach ($this->tools_to_restore as $tool) {
188
            $function_build = 'restore_'.$tool;
189
            $this->$function_build(
190
                $session_id,
191
                $respect_base_content,
192
                $destination_course_code
193
            );
194
        }
195
196
        if ($update_course_settings) {
197
            $this->restore_course_settings($destination_course_code);
198
        }
199
200
        // Restore the item properties
201
        $table = Database::get_course_table(TABLE_ITEM_PROPERTY);
202
203
        foreach ($this->course->resources as $type => $resources) {
204
            if (is_array($resources)) {
205
                foreach ($resources as $id => $resource) {
206
                    if (isset($resource->item_properties)) {
207
                        foreach ($resource->item_properties as $property) {
208
                            // First check if there isn't already a record for this resource
209
                            $sql = "SELECT * FROM $table
210
                                    WHERE
211
                                        c_id = ".$this->destination_course_id." AND
212
                                        tool = '".$property['tool']."' AND
213
                                        ref = '".$resource->destination_id."'";
214
215
                            $params = [];
216
                            if (!empty($session_id)) {
217
                                $params['session_id'] = intval($session_id);
218
                            }
219
220
                            $res = Database::query($sql);
221
                            if (Database::num_rows($res) == 0) {
222
                                /* The to_group_id and to_user_id are set to default
223
                                values as users/groups possibly not exist in
224
                                the target course*/
225
226
                                $params['c_id'] = $this->destination_course_id;
227
                                $params['tool'] = self::DBUTF8($property['tool']);
228
                                $params['insert_user_id'] = $this->checkUserId($property['insert_user_id']);
229
                                $params['insert_date'] = self::DBUTF8($property['insert_date']);
230
                                $params['lastedit_date'] = self::DBUTF8($property['lastedit_date']);
231
                                $params['ref'] = $resource->destination_id;
232
                                $params['lastedit_type'] = self::DBUTF8($property['lastedit_type']);
233
                                $params['lastedit_user_id'] = $this->checkUserId($property['lastedit_user_id']);
234
                                $params['visibility'] = self::DBUTF8($property['visibility']);
235
                                $params['start_visible'] = self::DBUTF8($property['start_visible']);
236
                                $params['end_visible'] = self::DBUTF8($property['end_visible']);
237
                                $params['to_user_id'] = $this->checkUserId($property['to_user_id']);
238
239
                                $id = Database::insert($table, $params);
240
                                if ($id) {
241
                                    $sql = "UPDATE $table SET id = iid WHERE iid = $id";
242
                                    Database::query($sql);
243
                                }
244
                            }
245
                        }
246
                    }
247
                }
248
            }
249
        }
250
    }
251
252
    /**
253
     * Restore only harmless course settings:
254
     * course_language, visibility, department_name,department_url,
255
     * subscribe, unsubscribe ,category_code.
256
     *
257
     * @param string $destination_course_code
258
     */
259
    public function restore_course_settings($destination_course_code)
260
    {
261
        $origin_course_info = api_get_course_info($destination_course_code);
262
        $course_info = $this->course->info;
263
        $params['course_language'] = $course_info['language'];
264
        $params['visibility'] = $course_info['visibility'];
265
        $params['department_name'] = $course_info['department_name'];
266
        $params['department_url'] = $course_info['department_url'];
267
        $params['category_code'] = $course_info['categoryCode'];
268
        $params['subscribe'] = $course_info['subscribe_allowed'];
269
        $params['unsubscribe'] = $course_info['unsubscribe'];
270
        CourseManager::update_attributes($origin_course_info['real_id'], $params);
271
    }
272
273
    /**
274
     * Restore documents.
275
     *
276
     * @param int    $session_id
277
     * @param bool   $respect_base_content
278
     * @param string $destination_course_code
279
     */
280
    public function restore_documents(
281
        $session_id = 0,
282
        $respect_base_content = false,
283
        $destination_course_code = ''
284
    ) {
285
        $course_info = api_get_course_info($destination_course_code);
286
287
        if (!$this->course->has_resources(RESOURCE_DOCUMENT)) {
288
            return;
289
        }
290
291
        $webEditorCss = api_get_path(WEB_CSS_PATH).'editor.css';
292
        $table = Database::get_course_table(TABLE_DOCUMENT);
293
        $resources = $this->course->resources;
294
        $path = api_get_path(SYS_COURSE_PATH).$this->course->destination_path.'/';
295
296
        foreach ($resources[RESOURCE_DOCUMENT] as $id => $document) {
297
            $my_session_id = empty($document->item_properties[0]['id_session']) ? 0 : $session_id;
298
299
            if ($document->file_type == FOLDER) {
300
                $visibility = isset($document->item_properties[0]['visibility']) ? $document->item_properties[0]['visibility'] : '';
301
                $new = substr($document->path, 8);
302
303
                $folderList = explode('/', $new);
304
                $tempFolder = '';
305
306
                // Check if the parent path exists.
307
                foreach ($folderList as $folder) {
308
                    $folderToCreate = $tempFolder.$folder;
309
                    $sysFolderPath = $path.'document'.$folderToCreate;
310
                    $tempFolder .= $folder.'/';
311
312
                    if (empty($folderToCreate)) {
313
                        continue;
314
                    }
315
316
                    $title = $document->title;
317
                    if (empty($title)) {
318
                        $title = basename($sysFolderPath);
319
                    }
320
321
                    // File doesn't exist in file system.
322
                    if (!is_dir($sysFolderPath)) {
323
                        // Creating directory
324
                        create_unexisting_directory(
325
                            $course_info,
326
                            api_get_user_id(),
327
                            $my_session_id,
328
                            0,
329
                            0,
330
                            $path.'document',
331
                            $folderToCreate,
332
                            $title,
333
                            $visibility
334
                        );
335
                        continue;
336
                    }
337
338
                    // File exist in file system.
339
                    $documentData = DocumentManager::get_document_id(
340
                        $course_info,
341
                        $folderToCreate,
342
                        $my_session_id
343
                    );
344
345
                    if (empty($documentData)) {
346
                        /* This means the folder exists in the
347
                        filesystem but not in the DB, trying to fix it */
348
                        add_document(
349
                            $course_info,
350
                            $folderToCreate,
351
                            'folder',
352
                            0,
353
                            $title,
354
                            null,
355
                            null,
356
                            false,
357
                            null,
358
                            $my_session_id,
359
                            0,
360
                            false
361
                        );
362
                    } else {
363
                        $insertUserId = isset($document->item_properties[0]['insert_user_id']) ? $document->item_properties[0]['insert_user_id'] : api_get_user_id();
364
                        $insertUserId = $this->checkUserId($insertUserId);
365
366
                        // Check if user exists in platform
367
                        $toUserId = isset($document->item_properties[0]['to_user_id']) ? $document->item_properties[0]['to_user_id'] : null;
368
                        $toUserId = $this->checkUserId($toUserId, true);
369
370
                        $groupId = isset($document->item_properties[0]['to_group_id']) ? $document->item_properties[0]['to_group_id'] : null;
371
                        $groupInfo = $this->checkGroupId($groupId);
372
373
                        // if folder exists then just refresh it
374
                        api_item_property_update(
375
                            $course_info,
376
                            TOOL_DOCUMENT,
377
                            $documentData,
378
                            'FolderUpdated',
379
                            $insertUserId,
380
                            $groupInfo,
381
                            $toUserId,
382
                            null,
383
                            null,
384
                            $my_session_id
385
                        );
386
                    }
387
                }
388
            } elseif ($document->file_type == DOCUMENT) {
389
                // Checking if folder exists in the database otherwise we created it
390
                $dir_to_create = dirname($document->path);
391
                if (!empty($dir_to_create) && $dir_to_create != 'document' && $dir_to_create != '/') {
392
                    if (is_dir($path.dirname($document->path))) {
393
                        $sql = "SELECT id FROM $table
394
                                WHERE
395
                                    c_id = ".$this->destination_course_id." AND
396
                                    path = '/".self::DBUTF8escapestring(substr(dirname($document->path), 9))."'";
397
                        $res = Database::query($sql);
398
399
                        if (Database::num_rows($res) == 0) {
400
                            //continue;
401
                            $visibility = $document->item_properties[0]['visibility'];
402
                            $new = '/'.substr(dirname($document->path), 9);
403
                            $title = $document->title;
404
                            if (empty($title)) {
405
                                $title = str_replace('/', '', $new);
406
                            }
407
408
                            // This code fixes the possibility for a file without a directory entry to be
409
                            $document_id = add_document(
410
                                $course_info,
411
                                $new,
412
                                'folder',
413
                                0,
414
                                $title,
415
                                null,
416
                                null,
417
                                false,
418
                                0,
419
                                0,
420
                                0,
421
                                false
422
                            );
423
424
                            $itemProperty = isset($document->item_properties[0]) ? $document->item_properties[0] : '';
425
                            $insertUserId = isset($itemProperty['insert_user_id']) ? $itemProperty['insert_user_id'] : api_get_user_id();
426
                            $toGroupId = isset($itemProperty['to_group_id']) ? $itemProperty['to_group_id'] : 0;
427
                            $toUserId = isset($itemProperty['to_user_id']) ? $itemProperty['to_user_id'] : null;
428
                            $groupInfo = $this->checkGroupId($toGroupId);
429
                            $insertUserId = $this->checkUserId($insertUserId);
430
                            $toUserId = $this->checkUserId($toUserId, true);
431
432
                            api_item_property_update(
433
                                $course_info,
434
                                TOOL_DOCUMENT,
435
                                $document_id,
436
                                'FolderCreated',
437
                                $insertUserId,
438
                                $groupInfo,
439
                                $toUserId,
440
                                null,
441
                                null,
442
                                $my_session_id
443
                            );
444
                        }
445
                    }
446
                }
447
448
                if (file_exists($path.$document->path)) {
449
                    switch ($this->file_option) {
450
                        case FILE_OVERWRITE:
451
                            $origin_path = $this->course->backup_path.'/'.$document->path;
452
                            if (file_exists($origin_path)) {
453
                                copy($origin_path, $path.$document->path);
454
                                $this->fixEditorHtmlContent($path.$document->path, $webEditorCss);
455
                                $sql = "SELECT id FROM $table
456
                                        WHERE
457
                                            c_id = ".$this->destination_course_id." AND
458
                                            path = '/".self::DBUTF8escapestring(substr($document->path, 9))."'";
459
460
                                $res = Database::query($sql);
461
                                $count = Database::num_rows($res);
462
463
                                if ($count == 0) {
464
                                    $params = [
465
                                        'path' => "/".self::DBUTF8(substr($document->path, 9)),
466
                                        'c_id' => $this->destination_course_id,
467
                                        'comment' => self::DBUTF8($document->comment),
468
                                        'title' => self::DBUTF8($document->title),
469
                                        'filetype' => self::DBUTF8($document->file_type),
470
                                        'size' => self::DBUTF8($document->size),
471
                                        'session_id' => $my_session_id,
472
                                        'readonly' => 0,
473
                                    ];
474
475
                                    $document_id = Database::insert($table, $params);
476
477
                                    if ($document_id) {
478
                                        $sql = "UPDATE $table SET id = iid WHERE iid = $document_id";
479
                                        Database::query($sql);
480
                                    }
481
                                    $this->course->resources[RESOURCE_DOCUMENT][$id]->destination_id = $document_id;
482
483
                                    $itemProperty = isset($document->item_properties[0]) ? $document->item_properties[0] : '';
484
                                    $insertUserId = isset($itemProperty['insert_user_id']) ? $itemProperty['insert_user_id'] : api_get_user_id();
485
                                    $toGroupId = isset($itemProperty['to_group_id']) ? $itemProperty['to_group_id'] : 0;
486
                                    $toUserId = isset($itemProperty['to_user_id']) ? $itemProperty['to_user_id'] : null;
487
488
                                    $insertUserId = $this->checkUserId($insertUserId);
489
                                    $toUserId = $this->checkUserId($toUserId, true);
490
                                    $groupInfo = $this->checkGroupId($toGroupId);
491
492
                                    api_item_property_update(
493
                                        $course_info,
494
                                        TOOL_DOCUMENT,
495
                                        $document_id,
496
                                        'DocumentAdded',
497
                                        $insertUserId,
498
                                        $groupInfo,
499
                                        $toUserId,
500
                                        null,
501
                                        null,
502
                                        $my_session_id
503
                                    );
504
                                } else {
505
                                    $obj = Database::fetch_object($res);
506
                                    $document_id = $obj->id;
507
                                    $params = [
508
                                        'path' => "/".self::DBUTF8(substr($document->path, 9)),
509
                                        'c_id' => $this->destination_course_id,
510
                                        'comment' => self::DBUTF8($document->comment),
511
                                        'title' => self::DBUTF8($document->title),
512
                                        'filetype' => self::DBUTF8($document->file_type),
513
                                        'size' => self::DBUTF8($document->size),
514
                                        'session_id' => $my_session_id,
515
                                    ];
516
517
                                    Database::update(
518
                                        $table,
519
                                        $params,
520
                                        [
521
                                            'c_id = ? AND path = ?' => [
522
                                                $this->destination_course_id,
523
                                                "/".self::DBUTF8escapestring(substr($document->path, 9)),
524
                                            ],
525
                                        ]
526
                                    );
527
528
                                    $this->course->resources[RESOURCE_DOCUMENT][$id]->destination_id = $obj->id;
529
530
                                    $itemProperty = isset($document->item_properties[0]) ? $document->item_properties[0] : '';
531
                                    $insertUserId = isset($itemProperty['insert_user_id']) ? $itemProperty['insert_user_id'] : api_get_user_id();
532
                                    $toGroupId = isset($itemProperty['to_group_id']) ? $itemProperty['to_group_id'] : 0;
533
                                    $toUserId = isset($itemProperty['to_user_id']) ? $itemProperty['to_user_id'] : null;
534
535
                                    $insertUserId = $this->checkUserId($insertUserId);
536
                                    $toUserId = $this->checkUserId($toUserId, true);
537
                                    $groupInfo = $this->checkGroupId($toGroupId);
538
539
                                    api_item_property_update(
540
                                        $course_info,
541
                                        TOOL_DOCUMENT,
542
                                        $obj->id,
543
                                        'default',
544
                                        $insertUserId,
545
                                        $groupInfo,
546
                                        $toUserId,
547
                                        null,
548
                                        null,
549
                                        $my_session_id
550
                                    );
551
                                }
552
553
                                // Replace old course code with the new destination code
554
                                $file_info = pathinfo($path.$document->path);
555
556
                                if (isset($file_info['extension']) && in_array($file_info['extension'], ['html', 'htm'])) {
557
                                    $content = file_get_contents($path.$document->path);
558
                                    if (UTF8_CONVERT) {
559
                                        $content = utf8_encode($content);
560
                                    }
561
                                    $content = DocumentManager::replaceUrlWithNewCourseCode(
562
                                        $content,
563
                                        $this->course->code,
564
                                        $this->course->destination_path,
565
                                        $this->course->backup_path,
566
                                        $this->course->info['path']
567
                                    );
568
                                    file_put_contents($path.$document->path, $content);
569
                                }
570
571
                                $params = [
572
                                    'comment' => self::DBUTF8($document->comment),
573
                                    'title' => self::DBUTF8($document->title),
574
                                    'size' => self::DBUTF8($document->size),
575
                                ];
576
                                Database::update(
577
                                    $table,
578
                                    $params,
579
                                    [
580
                                        'c_id = ? AND id = ?' => [
581
                                            $this->destination_course_id,
582
                                            $document_id,
583
                                        ],
584
                                    ]
585
                                );
586
                            }
587
                            break;
588
                        case FILE_SKIP:
589
                            $sql = "SELECT id FROM $table
590
                                    WHERE
591
                                        c_id = ".$this->destination_course_id." AND
592
                                        path='/".self::DBUTF8escapestring(substr($document->path, 9))."'";
593
                            $res = Database::query($sql);
594
                            $obj = Database::fetch_object($res);
595
                            $this->course->resources[RESOURCE_DOCUMENT][$id]->destination_id = $obj->id;
596
                            break;
597
                        case FILE_RENAME:
598
                            $i = 1;
599
                            $ext = explode('.', basename($document->path));
600
                            if (count($ext) > 1) {
601
                                $ext = array_pop($ext);
602
                                $file_name_no_ext = substr($document->path, 0, -(strlen($ext) + 1));
603
                                $ext = '.'.$ext;
604
                            } else {
605
                                $ext = '';
606
                                $file_name_no_ext = $document->path;
607
                            }
608
                            $new_file_name = $file_name_no_ext.'_'.$i.$ext;
609
                            $file_exists = file_exists($path.$new_file_name);
610
                            while ($file_exists) {
611
                                $i++;
612
                                $new_file_name = $file_name_no_ext.'_'.$i.$ext;
613
                                $file_exists = file_exists($path.$new_file_name);
614
                            }
615
616
                            if (!empty($session_id)) {
617
                                $document_path = explode('/', $document->path, 3);
618
                                $course_path = $path;
619
                                $orig_base_folder = $document_path[1];
620
                                $orig_base_path = $course_path.$document_path[0].'/'.$document_path[1];
621
622
                                if (is_dir($orig_base_path)) {
623
                                    $new_base_foldername = $orig_base_folder;
624
                                    $new_base_path = $orig_base_path;
625
626
                                    if ($_SESSION['orig_base_foldername'] != $new_base_foldername) {
627
                                        unset($_SESSION['new_base_foldername']);
628
                                        unset($_SESSION['orig_base_foldername']);
629
                                        unset($_SESSION['new_base_path']);
630
                                    }
631
632
                                    $folder_exists = file_exists($new_base_path);
633
                                    if ($folder_exists) {
634
                                        // e.g: carpeta1 in session
635
                                        $_SESSION['orig_base_foldername'] = $new_base_foldername;
636
                                        $x = '';
637
                                        while ($folder_exists) {
638
                                            $x = $x + 1;
639
                                            $new_base_foldername = $document_path[1].'_'.$x;
640
                                            $new_base_path = $orig_base_path.'_'.$x;
641
                                            if ($_SESSION['new_base_foldername'] == $new_base_foldername) {
642
                                                break;
643
                                            }
644
                                            $folder_exists = file_exists($new_base_path);
645
                                        }
646
                                        $_SESSION['new_base_foldername'] = $new_base_foldername;
647
                                        $_SESSION['new_base_path'] = $new_base_path;
648
                                    }
649
650
                                    if (isset($_SESSION['new_base_foldername']) && isset($_SESSION['new_base_path'])) {
651
                                        $new_base_foldername = $_SESSION['new_base_foldername'];
652
                                        $new_base_path = $_SESSION['new_base_path'];
653
                                    }
654
655
                                    $dest_document_path = $new_base_path.'/'.$document_path[2]; // e.g: "/var/www/wiener/courses/CURSO4/document/carpeta1_1/subcarpeta1/collaborative.png"
656
                                    $basedir_dest_path = dirname($dest_document_path); // e.g: "/var/www/wiener/courses/CURSO4/document/carpeta1_1/subcarpeta1"
657
                                    $base_path_document = $course_path.$document_path[0]; // e.g: "/var/www/wiener/courses/CURSO4/document"
658
                                    $path_title = '/'.$new_base_foldername.'/'.$document_path[2];
659
660
                                    copy_folder_course_session(
661
                                        $basedir_dest_path,
662
                                        $base_path_document,
663
                                        $session_id,
664
                                        $course_info,
665
                                        $document,
666
                                        $this->course_origin_id
667
                                    );
668
669
                                    if (file_exists($course_path.$document->path)) {
670
                                        copy($course_path.$document->path, $dest_document_path);
671
                                    }
672
673
                                    // Replace old course code with the new destination code see BT#1985
674
                                    if (file_exists($dest_document_path)) {
675
                                        $file_info = pathinfo($dest_document_path);
676
                                        if (in_array($file_info['extension'], ['html', 'htm'])) {
677
                                            $content = file_get_contents($dest_document_path);
678
                                            if (UTF8_CONVERT) {
679
                                                $content = utf8_encode($content);
680
                                            }
681
                                            $content = DocumentManager::replaceUrlWithNewCourseCode(
682
                                                $content,
683
                                                $this->course->code,
684
                                                $this->course->destination_path,
685
                                                $this->course->backup_path,
686
                                                $this->course->info['path']
687
                                            );
688
                                            file_put_contents($dest_document_path, $content);
689
                                            $this->fixEditorHtmlContent($dest_document_path, $webEditorCss);
690
                                        }
691
                                    }
692
693
                                    $params = [
694
                                        'path' => self::DBUTF8($path_title),
695
                                        'c_id' => $this->destination_course_id,
696
                                        'comment' => self::DBUTF8($document->comment),
697
                                        'title' => self::DBUTF8(basename($path_title)),
698
                                        'filetype' => self::DBUTF8($document->file_type),
699
                                        'size' => self::DBUTF8($document->size),
700
                                        'session_id' => $my_session_id,
701
                                    ];
702
703
                                    $document_id = Database::insert($table, $params);
704
705
                                    if ($document_id) {
706
                                        $sql = "UPDATE $table SET id = iid WHERE iid = $document_id";
707
                                        Database::query($sql);
708
709
                                        $this->course->resources[RESOURCE_DOCUMENT][$id]->destination_id = $document_id;
710
711
                                        $itemProperty = isset($document->item_properties[0]) ? $document->item_properties[0] : '';
712
                                        $insertUserId = isset($itemProperty['insert_user_id']) ? $itemProperty['insert_user_id'] : api_get_user_id();
713
                                        $toGroupId = isset($itemProperty['to_group_id']) ? $itemProperty['to_group_id'] : 0;
714
                                        $toUserId = isset($itemProperty['to_user_id']) ? $itemProperty['to_user_id'] : null;
715
716
                                        $insertUserId = $this->checkUserId($insertUserId);
717
                                        $toUserId = $this->checkUserId($toUserId, true);
718
                                        $groupInfo = $this->checkGroupId($toGroupId);
719
720
                                        api_item_property_update(
721
                                            $course_info,
722
                                            TOOL_DOCUMENT,
723
                                            $document_id,
724
                                            'DocumentAdded',
725
                                            $insertUserId,
726
                                            $groupInfo,
727
                                            $toUserId,
728
                                            null,
729
                                            null,
730
                                            $my_session_id
731
                                        );
732
                                    }
733
                                } else {
734
                                    if (file_exists($path.$document->path)) {
735
                                        copy($path.$document->path, $path.$new_file_name);
736
                                    }
737
                                    // Replace old course code with the new destination code see BT#1985
738
                                    if (file_exists($path.$new_file_name)) {
739
                                        $file_info = pathinfo($path.$new_file_name);
740
                                        if (in_array($file_info['extension'], ['html', 'htm'])) {
741
                                            $content = file_get_contents($path.$new_file_name);
742
                                            if (UTF8_CONVERT) {
743
                                                $content = utf8_encode($content);
744
                                            }
745
                                            $content = DocumentManager::replaceUrlWithNewCourseCode(
746
                                                $content,
747
                                                $this->course->code,
748
                                                $this->course->destination_path,
749
                                                $this->course->backup_path,
750
                                                $this->course->info['path']
751
                                            );
752
                                            file_put_contents($path.$new_file_name, $content);
753
                                            $this->fixEditorHtmlContent($path.$new_file_name, $webEditorCss);
754
                                        }
755
                                    }
756
757
                                    $params = [
758
                                        'path' => "/".self::DBUTF8escapestring(substr($new_file_name, 9)),
759
                                        'c_id' => $this->destination_course_id,
760
                                        'comment' => self::DBUTF8($document->comment),
761
                                        'title' => self::DBUTF8($document->title),
762
                                        'filetype' => self::DBUTF8($document->file_type),
763
                                        'size' => self::DBUTF8($document->size),
764
                                        'session_id' => $my_session_id,
765
                                    ];
766
767
                                    $document_id = Database::insert($table, $params);
768
769
                                    if ($document_id) {
770
                                        $sql = "UPDATE $table SET id = iid WHERE iid = $document_id";
771
                                        Database::query($sql);
772
773
                                        $this->course->resources[RESOURCE_DOCUMENT][$id]->destination_id = $document_id;
774
775
                                        $itemProperty = isset($document->item_properties[0]) ? $document->item_properties[0] : '';
776
                                        $insertUserId = isset($itemProperty['insert_user_id']) ? $itemProperty['insert_user_id'] : api_get_user_id();
777
                                        $toGroupId = isset($itemProperty['to_group_id']) ? $itemProperty['to_group_id'] : 0;
778
                                        $toUserId = isset($itemProperty['to_user_id']) ? $itemProperty['to_user_id'] : null;
779
780
                                        $insertUserId = $this->checkUserId($insertUserId);
781
                                        $toUserId = $this->checkUserId($toUserId, true);
782
                                        $groupInfo = $this->checkGroupId($toGroupId);
783
784
                                        api_item_property_update(
785
                                            $course_info,
786
                                            TOOL_DOCUMENT,
787
                                            $document_id,
788
                                            'DocumentAdded',
789
                                            $insertUserId,
790
                                            $groupInfo,
791
                                            $toUserId,
792
                                            null,
793
                                            null,
794
                                            $my_session_id
795
                                        );
796
                                    }
797
                                }
798
                            } else {
799
                                copy(
800
                                    $this->course->backup_path.'/'.$document->path,
801
                                    $path.$new_file_name
802
                                );
803
804
                                // Replace old course code with the new destination code see BT#1985
805
                                if (file_exists($path.$new_file_name)) {
806
                                    $file_info = pathinfo($path.$new_file_name);
807
                                    if (in_array($file_info['extension'], ['html', 'htm'])) {
808
                                        $content = file_get_contents($path.$new_file_name);
809
                                        if (UTF8_CONVERT) {
810
                                            $content = utf8_encode($content);
811
                                        }
812
                                        $content = DocumentManager::replaceUrlWithNewCourseCode(
813
                                            $content,
814
                                            $this->course->code,
815
                                            $this->course->destination_path,
816
                                            $this->course->backup_path,
817
                                            $this->course->info['path']
818
                                        );
819
                                        file_put_contents($path.$new_file_name, $content);
820
                                        $this->fixEditorHtmlContent($path.$new_file_name, $webEditorCss);
821
                                    }
822
                                }
823
824
                                $params = [
825
                                    'c_id' => $this->destination_course_id,
826
                                    'path' => "/".self::DBUTF8escapestring(substr($new_file_name, 9)),
827
                                    'comment' => self::DBUTF8($document->comment),
828
                                    'title' => self::DBUTF8($document->title),
829
                                    'filetype' => self::DBUTF8($document->file_type),
830
                                    'size' => self::DBUTF8($document->size),
831
                                    'session_id' => $my_session_id,
832
                                ];
833
834
                                $document_id = Database::insert($table, $params);
835
836
                                if ($document_id) {
837
                                    $sql = "UPDATE $table SET id = iid WHERE iid = $document_id";
838
                                    Database::query($sql);
839
                                    $this->course->resources[RESOURCE_DOCUMENT][$id]->destination_id = $document_id;
840
841
                                    $itemProperty = isset($document->item_properties[0]) ? $document->item_properties[0] : '';
842
                                    $insertUserId = isset($itemProperty['insert_user_id']) ? $itemProperty['insert_user_id'] : api_get_user_id();
843
                                    $toGroupId = isset($itemProperty['to_group_id']) ? $itemProperty['to_group_id'] : 0;
844
                                    $toUserId = isset($itemProperty['to_user_id']) ? $itemProperty['to_user_id'] : null;
845
846
                                    $insertUserId = $this->checkUserId($insertUserId);
847
                                    $toUserId = $this->checkUserId($toUserId, true);
848
                                    $groupInfo = $this->checkGroupId($toGroupId);
849
850
                                    api_item_property_update(
851
                                        $course_info,
852
                                        TOOL_DOCUMENT,
853
                                        $document_id,
854
                                        'DocumentAdded',
855
                                        $insertUserId,
856
                                        $groupInfo,
857
                                        $toUserId,
858
                                        null,
859
                                        null,
860
                                        $my_session_id
861
                                    );
862
                                }
863
                            }
864
                            break;
865
                    } // end switch
866
                } else {
867
                    // end if file exists
868
                    //make sure the source file actually exists
869
                    if (is_file($this->course->backup_path.'/'.$document->path) &&
870
                        is_readable($this->course->backup_path.'/'.$document->path) &&
871
                        is_dir(dirname($path.$document->path)) &&
872
                        is_writeable(dirname($path.$document->path))
873
                    ) {
874
                        copy(
875
                            $this->course->backup_path.'/'.$document->path,
876
                            $path.$document->path
877
                        );
878
879
                        // Replace old course code with the new destination code see BT#1985
880
                        if (file_exists($path.$document->path)) {
881
                            $file_info = pathinfo($path.$document->path);
882
                            if (isset($file_info['extension']) && in_array($file_info['extension'], ['html', 'htm'])) {
883
                                $content = file_get_contents($path.$document->path);
884
                                if (UTF8_CONVERT) {
885
                                    $content = utf8_encode($content);
886
                                }
887
                                $content = DocumentManager::replaceUrlWithNewCourseCode(
888
                                    $content,
889
                                    $this->course->code,
890
                                    $this->course->destination_path,
891
                                    $this->course->backup_path,
892
                                    $this->course->info['path']
893
                                );
894
                                file_put_contents($path.$document->path, $content);
895
                                $this->fixEditorHtmlContent($path.$document->path, $webEditorCss);
896
                            }
897
                        }
898
899
                        $params = [
900
                            'c_id' => $this->destination_course_id,
901
                            'path' => "/".self::DBUTF8(substr($document->path, 9)),
902
                            'comment' => self::DBUTF8($document->comment),
903
                            'title' => self::DBUTF8($document->title),
904
                            'filetype' => self::DBUTF8($document->file_type),
905
                            'size' => self::DBUTF8($document->size),
906
                            'session_id' => $my_session_id,
907
                            'readonly' => 0,
908
                        ];
909
910
                        $document_id = Database::insert($table, $params);
911
912
                        if ($document_id) {
913
                            $sql = "UPDATE $table SET id = iid WHERE iid = $document_id";
914
                            Database::query($sql);
915
916
                            $this->course->resources[RESOURCE_DOCUMENT][$id]->destination_id = $document_id;
917
918
                            $itemProperty = isset($document->item_properties[0]) ? $document->item_properties[0] : '';
919
                            $insertUserId = isset($itemProperty['insert_user_id']) ? $itemProperty['insert_user_id'] : api_get_user_id();
920
                            $toGroupId = isset($itemProperty['to_group_id']) ? $itemProperty['to_group_id'] : 0;
921
                            $toUserId = isset($itemProperty['to_user_id']) ? $itemProperty['to_user_id'] : null;
922
923
                            $insertUserId = $this->checkUserId($insertUserId);
924
                            $toUserId = $this->checkUserId($toUserId, true);
925
                            $groupInfo = $this->checkGroupId($toGroupId);
926
927
                            api_item_property_update(
928
                                $course_info,
929
                                TOOL_DOCUMENT,
930
                                $document_id,
931
                                'DocumentAdded',
932
                                $insertUserId,
933
                                $groupInfo,
934
                                $toUserId,
935
                                null,
936
                                null,
937
                                $my_session_id
938
                            );
939
                        }
940
                    } else {
941
                        // There was an error in checking existence and
942
                        // permissions for files to copy. Try to determine
943
                        // the exact issue
944
                        // Issue with origin document?
945
                        if (!is_file($this->course->backup_path.'/'.$document->path)) {
946
                            error_log(
947
                                'Course copy generated an ignorable error while trying to copy '.
948
                                $this->course->backup_path.'/'.$document->path.': origin file not found'
949
                            );
950
                        } elseif (!is_readable($this->course->backup_path.'/'.$document->path)) {
951
                            error_log(
952
                                'Course copy generated an ignorable error while trying to copy '.
953
                                $this->course->backup_path.'/'.$document->path.': origin file not readable'
954
                            );
955
                        }
956
                        // Issue with destination directories?
957
                        if (!is_dir(dirname($path.$document->path))) {
958
                            error_log(
959
                                'Course copy generated an ignorable error while trying to copy '.
960
                                $this->course->backup_path.'/'.$document->path.' to '.
961
                                dirname($path.$document->path).': destination directory not found'
962
                            );
963
                        }
964
                        if (!is_writeable(dirname($path.$document->path))) {
965
                            error_log(
966
                                'Course copy generated an ignorable error while trying to copy '.
967
                                $this->course->backup_path.'/'.$document->path.' to '.
968
                                dirname($path.$document->path).': destination directory not writable'
969
                            );
970
                        }
971
                    }
972
                } // end file doesn't exist
973
            }
974
975
            // add image information for area questions
976
            if (preg_match('/^quiz-.*$/', $document->title) &&
977
                preg_match('/^document\/images\/.*$/', $document->path)
978
            ) {
979
                $this->course->resources[RESOURCE_DOCUMENT]['image_quiz'][$document->title] = [
980
                    'path' => $document->path,
981
                    'title' => $document->title,
982
                    'source_id' => $document->source_id,
983
                    'destination_id' => $document->destination_id,
984
                ];
985
            }
986
        } // end for each
987
988
        // Delete sessions for the copy the new folder in session
989
        unset($_SESSION['new_base_foldername']);
990
        unset($_SESSION['orig_base_foldername']);
991
        unset($_SESSION['new_base_path']);
992
    }
993
994
    /**
995
     * Restore scorm documents
996
     * TODO @TODO check that the restore function with renaming doesn't break the scorm structure!
997
     * see #7029.
998
     */
999
    public function restore_scorm_documents()
1000
    {
1001
        $perm = api_get_permissions_for_new_directories();
1002
1003
        if ($this->course->has_resources(RESOURCE_SCORM)) {
1004
            $resources = $this->course->resources;
1005
            foreach ($resources[RESOURCE_SCORM] as $document) {
1006
                $path = api_get_path(SYS_COURSE_PATH).$this->course->destination_path.'/';
1007
                @mkdir(dirname($path.$document->path), $perm, true);
1008
1009
                if (file_exists($path.$document->path)) {
1010
                    switch ($this->file_option) {
1011
                        case FILE_OVERWRITE:
1012
                            rmdirr($path.$document->path);
1013
                            copyDirTo(
1014
                                $this->course->backup_path.'/'.$document->path,
1015
                                $path.dirname($document->path),
1016
                                false
1017
                            );
1018
                            break;
1019
                        case FILE_SKIP:
1020
                            break;
1021
                        case FILE_RENAME:
1022
                            $i = 1;
1023
                            $ext = explode('.', basename($document->path));
1024
                            if (count($ext) > 1) {
1025
                                $ext = array_pop($ext);
1026
                                $file_name_no_ext = substr($document->path, 0, -(strlen($ext) + 1));
1027
                                $ext = '.'.$ext;
1028
                            } else {
1029
                                $ext = '';
1030
                                $file_name_no_ext = $document->path;
1031
                            }
1032
1033
                            $new_file_name = $file_name_no_ext.'_'.$i.$ext;
1034
                            $file_exists = file_exists($path.$new_file_name);
1035
1036
                            while ($file_exists) {
1037
                                $i++;
1038
                                $new_file_name = $file_name_no_ext.'_'.$i.$ext;
1039
                                $file_exists = file_exists($path.$new_file_name);
1040
                            }
1041
1042
                            rename(
1043
                                $this->course->backup_path.'/'.$document->path,
1044
                                $this->course->backup_path.'/'.$new_file_name
1045
                            );
1046
                            copyDirTo(
1047
                                $this->course->backup_path.'/'.$new_file_name,
1048
                                $path.dirname($new_file_name),
1049
                                false
1050
                            );
1051
                            rename(
1052
                                $this->course->backup_path.'/'.$new_file_name,
1053
                                $this->course->backup_path.'/'.$document->path
1054
                            );
1055
                            break;
1056
                    } // end switch
1057
                } else {
1058
                    // end if file exists
1059
                    copyDirTo(
1060
                        $this->course->backup_path.'/'.$document->path,
1061
                        $path.dirname($document->path),
1062
                        false
1063
                    );
1064
                }
1065
            } // end for each
1066
        }
1067
    }
1068
1069
    /**
1070
     * Restore forums.
1071
     *
1072
     * @param int $sessionId
1073
     */
1074
    public function restore_forums($sessionId = 0)
1075
    {
1076
        if ($this->course->has_resources(RESOURCE_FORUM)) {
1077
            $sessionId = intval($sessionId);
1078
            $table_forum = Database::get_course_table(TABLE_FORUM);
1079
            $resources = $this->course->resources;
1080
            foreach ($resources[RESOURCE_FORUM] as $id => $forum) {
1081
                $params = (array) $forum->obj;
1082
                $cat_id = '';
1083
                if (isset($this->course->resources[RESOURCE_FORUMCATEGORY]) &&
1084
                    isset($this->course->resources[RESOURCE_FORUMCATEGORY][$params['forum_category']])) {
1085
                    if ($this->course->resources[RESOURCE_FORUMCATEGORY][$params['forum_category']]->destination_id == -1) {
1086
                        $cat_id = $this->restore_forum_category(
1087
                            $params['forum_category'],
1088
                            $sessionId
1089
                        );
1090
                    } else {
1091
                        $cat_id = $this->course->resources[RESOURCE_FORUMCATEGORY][$params['forum_category']]->destination_id;
1092
                    }
1093
                }
1094
1095
                $params = self::DBUTF8_array($params);
1096
                $params['c_id'] = $this->destination_course_id;
1097
                $params['forum_category'] = $cat_id;
1098
                $params['session_id'] = $sessionId;
1099
                $params['start_time'] = isset($params['start_time']) && $params['start_time'] === '0000-00-00 00:00:00' ? null : $params['start_time'];
1100
                $params['end_time'] = isset($params['end_time']) && $params['end_time'] === '0000-00-00 00:00:00' ? null : $params['end_time'];
1101
                $params['forum_id'] = 0;
1102
                unset($params['iid']);
1103
1104
                $params['forum_comment'] = DocumentManager::replaceUrlWithNewCourseCode(
1105
                    $params['forum_comment'],
1106
                    $this->course->code,
1107
                    $this->course->destination_path,
1108
                    $this->course->backup_path,
1109
                    $this->course->info['path']
1110
                );
1111
1112
                if (!empty($params['forum_image'])) {
1113
                    $original_forum_image = $this->course->path.'upload/forum/images/'.$params['forum_image'];
1114
                    if (file_exists($original_forum_image)) {
1115
                        $new_forum_image = api_get_path(SYS_COURSE_PATH).
1116
                            $this->destination_course_info['path'].'/upload/forum/images/'.$params['forum_image'];
1117
                        @copy($original_forum_image, $new_forum_image);
1118
                    }
1119
                }
1120
1121
                $new_id = Database::insert($table_forum, $params);
1122
1123
                if ($new_id) {
1124
                    $sql = "UPDATE $table_forum SET forum_id = iid WHERE iid = $new_id";
1125
                    Database::query($sql);
1126
1127
                    api_item_property_update(
1128
                        $this->destination_course_info,
1129
                        TOOL_FORUM,
1130
                        $new_id,
1131
                        'ForumUpdated',
1132
                        api_get_user_id()
1133
                    );
1134
1135
                    $this->course->resources[RESOURCE_FORUM][$id]->destination_id = $new_id;
1136
1137
                    $forum_topics = 0;
1138
                    if (isset($this->course->resources[RESOURCE_FORUMTOPIC]) &&
1139
                        is_array($this->course->resources[RESOURCE_FORUMTOPIC])
1140
                    ) {
1141
                        foreach ($this->course->resources[RESOURCE_FORUMTOPIC] as $topic_id => $topic) {
1142
                            if ($topic->obj->forum_id == $id) {
1143
                                $this->restore_topic($topic_id, $new_id, $sessionId);
1144
                                $forum_topics++;
1145
                            }
1146
                        }
1147
                    }
1148
                    if ($forum_topics > 0) {
1149
                        $sql = "UPDATE ".$table_forum." SET forum_threads = ".$forum_topics."
1150
                                WHERE c_id = {$this->destination_course_id} AND forum_id = ".(int) $new_id;
1151
                        Database::query($sql);
1152
                    }
1153
                }
1154
            }
1155
        }
1156
    }
1157
1158
    /**
1159
     * Restore forum-categories.
1160
     */
1161
    public function restore_forum_category($my_id = null, $sessionId = 0)
1162
    {
1163
        $forum_cat_table = Database::get_course_table(TABLE_FORUM_CATEGORY);
1164
        $resources = $this->course->resources;
1165
        if (!empty($resources[RESOURCE_FORUMCATEGORY])) {
1166
            foreach ($resources[RESOURCE_FORUMCATEGORY] as $id => $forum_cat) {
1167
                if (!empty($my_id)) {
1168
                    if ($my_id != $id) {
1169
                        continue;
1170
                    }
1171
                }
1172
                if ($forum_cat && !$forum_cat->is_restored()) {
1173
                    $params = (array) $forum_cat->obj;
1174
                    $params['c_id'] = $this->destination_course_id;
1175
                    $params['cat_comment'] = DocumentManager::replaceUrlWithNewCourseCode(
1176
                        $params['cat_comment'],
1177
                        $this->course->code,
1178
                        $this->course->destination_path,
1179
                        $this->course->backup_path,
1180
                        $this->course->info['path']
1181
                    );
1182
                    $params['session_id'] = intval($sessionId);
1183
                    $params['cat_id'] = 0;
1184
                    unset($params['iid']);
1185
1186
                    $params = self::DBUTF8_array($params);
1187
                    $new_id = Database::insert($forum_cat_table, $params);
1188
1189
                    if ($new_id) {
1190
                        $sql = "UPDATE $forum_cat_table SET cat_id = iid WHERE iid = $new_id";
1191
                        Database::query($sql);
1192
1193
                        api_item_property_update(
1194
                            $this->destination_course_info,
1195
                            TOOL_FORUM_CATEGORY,
1196
                            $new_id,
1197
                            'ForumCategoryUpdated',
1198
                            api_get_user_id()
1199
                        );
1200
                        $this->course->resources[RESOURCE_FORUMCATEGORY][$id]->destination_id = $new_id;
1201
                    }
1202
1203
                    if (!empty($my_id)) {
1204
                        return $new_id;
1205
                    }
1206
                }
1207
            }
1208
        }
1209
    }
1210
1211
    /**
1212
     * Restore a forum-topic.
1213
     *
1214
     * @param false|string $forum_id
1215
     *
1216
     * @return int
1217
     */
1218
    public function restore_topic($thread_id, $forum_id, $sessionId = 0)
1219
    {
1220
        $table = Database::get_course_table(TABLE_FORUM_THREAD);
1221
        $topic = $this->course->resources[RESOURCE_FORUMTOPIC][$thread_id];
1222
1223
        $params = (array) $topic->obj;
1224
        $params = self::DBUTF8_array($params);
1225
        $params['c_id'] = $this->destination_course_id;
1226
        $params['forum_id'] = $forum_id;
1227
        $params['thread_poster_id'] = $this->first_teacher_id;
1228
        $params['thread_date'] = api_get_utc_datetime();
1229
        $params['thread_close_date'] = null;
1230
        $params['thread_last_post'] = 0;
1231
        $params['thread_replies'] = 0;
1232
        $params['thread_views'] = 0;
1233
        $params['session_id'] = intval($sessionId);
1234
        $params['thread_id'] = 0;
1235
1236
        unset($params['iid']);
1237
1238
        $new_id = Database::insert($table, $params);
1239
1240
        if ($new_id) {
1241
            $sql = "UPDATE $table SET thread_id = iid WHERE iid = $new_id";
1242
            Database::query($sql);
1243
1244
            api_item_property_update(
1245
                $this->destination_course_info,
1246
                TOOL_FORUM_THREAD,
1247
                $new_id,
1248
                'ThreadAdded',
1249
                api_get_user_id(),
1250
                0,
1251
                0,
1252
                null,
1253
                null,
1254
                $sessionId
1255
            );
1256
1257
            $this->course->resources[RESOURCE_FORUMTOPIC][$thread_id]->destination_id = $new_id;
1258
            $topic_replies = -1;
1259
1260
            foreach ($this->course->resources[RESOURCE_FORUMPOST] as $post_id => $post) {
1261
                if ($post->obj->thread_id == $thread_id) {
1262
                    $topic_replies++;
1263
                    $this->restore_post($post_id, $new_id, $forum_id, $sessionId);
1264
                }
1265
            }
1266
        }
1267
1268
        return $new_id;
1269
    }
1270
1271
    /**
1272
     * Restore a forum-post.
1273
     *
1274
     * @TODO Restore tree-structure of posts. For example: attachments to posts.
1275
     *
1276
     * @param false|string $topic_id
1277
     *
1278
     * @return int
1279
     */
1280
    public function restore_post($id, $topic_id, $forum_id, $sessionId = 0)
1281
    {
1282
        $table_post = Database::get_course_table(TABLE_FORUM_POST);
1283
        $post = $this->course->resources[RESOURCE_FORUMPOST][$id];
1284
        $params = (array) $post->obj;
1285
        $params['c_id'] = $this->destination_course_id;
1286
        $params['forum_id'] = $forum_id;
1287
        $params['thread_id'] = $topic_id;
1288
        $params['poster_id'] = $this->first_teacher_id;
1289
        $params['post_date'] = api_get_utc_datetime();
1290
        $params['post_id'] = 0;
1291
        unset($params['iid']);
1292
1293
        $params['post_text'] = DocumentManager::replaceUrlWithNewCourseCode(
1294
            $params['post_text'],
1295
            $this->course->code,
1296
            $this->course->destination_path,
1297
            $this->course->backup_path,
1298
            $this->course->info['path']
1299
        );
1300
        $new_id = Database::insert($table_post, $params);
1301
1302
        if ($new_id) {
1303
            $sql = "UPDATE $table_post SET post_id = iid WHERE iid = $new_id";
1304
            Database::query($sql);
1305
1306
            api_item_property_update(
1307
                $this->destination_course_info,
1308
                TOOL_FORUM_POST,
1309
                $new_id,
1310
                'PostAdded',
1311
                api_get_user_id(),
1312
                0,
1313
                0,
1314
                null,
1315
                null,
1316
                $sessionId
1317
            );
1318
            $this->course->resources[RESOURCE_FORUMPOST][$id]->destination_id = $new_id;
1319
        }
1320
1321
        return $new_id;
1322
    }
1323
1324
    /**
1325
     * Restore links.
1326
     */
1327
    public function restore_links($session_id = 0)
1328
    {
1329
        if ($this->course->has_resources(RESOURCE_LINK)) {
1330
            $link_table = Database::get_course_table(TABLE_LINK);
1331
            $resources = $this->course->resources;
1332
1333
            foreach ($resources[RESOURCE_LINK] as $oldLinkId => $link) {
1334
                $cat_id = $this->restore_link_category(
1335
                    $link->category_id,
1336
                    $session_id
1337
                );
1338
                $sql = "SELECT MAX(display_order)
1339
                        FROM $link_table
1340
                        WHERE
1341
                            c_id = ".$this->destination_course_id." AND
1342
                            category_id='".intval($cat_id)."'";
1343
                $result = Database::query($sql);
1344
                list($max_order) = Database::fetch_array($result);
1345
1346
                $params = [];
1347
                if (!empty($session_id)) {
1348
                    $params['session_id'] = $session_id;
1349
                }
1350
1351
                $params['c_id'] = $this->destination_course_id;
1352
                $params['url'] = self::DBUTF8($link->url);
1353
                $params['title'] = self::DBUTF8($link->title);
1354
                $params['description'] = self::DBUTF8($link->description);
1355
                $params['category_id'] = $cat_id;
1356
                $params['on_homepage'] = $link->on_homepage;
1357
                $params['display_order'] = $max_order + 1;
1358
                $params['target'] = $link->target;
1359
1360
                $id = Database::insert($link_table, $params);
1361
1362
                if ($id) {
1363
                    $sql = "UPDATE $link_table SET id = iid WHERE iid = $id";
1364
                    Database::query($sql);
1365
1366
                    api_item_property_update(
1367
                        $this->destination_course_info,
1368
                        TOOL_LINK,
1369
                        $id,
1370
                        'LinkAdded',
1371
                        api_get_user_id()
1372
                    );
1373
1374
                    if (!isset($this->course->resources[RESOURCE_LINK][$oldLinkId])) {
1375
                        $this->course->resources[RESOURCE_LINK][$oldLinkId] = new stdClass();
1376
                    }
1377
                    $this->course->resources[RESOURCE_LINK][$oldLinkId]->destination_id = $id;
1378
                }
1379
            }
1380
        }
1381
    }
1382
1383
    /**
1384
     * Restore a link-category.
1385
     *
1386
     * @param int
1387
     * @param int
1388
     *
1389
     * @return bool
1390
     */
1391
    public function restore_link_category($id, $session_id = 0)
1392
    {
1393
        $params = [];
1394
        if (!empty($session_id)) {
1395
            $params['session_id'] = $session_id;
1396
        }
1397
1398
        if ($id == 0) {
1399
            return 0;
1400
        }
1401
        $link_cat_table = Database::get_course_table(TABLE_LINK_CATEGORY);
1402
        $resources = $this->course->resources;
1403
        $link_cat = $resources[RESOURCE_LINKCATEGORY][$id];
1404
        if (is_object($link_cat) && !$link_cat->is_restored()) {
1405
            $sql = "SELECT MAX(display_order) FROM  $link_cat_table
1406
                    WHERE c_id = ".$this->destination_course_id;
1407
            $result = Database::query($sql);
1408
            list($orderMax) = Database::fetch_array($result, 'NUM');
1409
            $display_order = $orderMax + 1;
1410
1411
            $params['c_id'] = $this->destination_course_id;
1412
            $params['category_title'] = self::DBUTF8($link_cat->title);
1413
            $params['description'] = self::DBUTF8($link_cat->description);
1414
            $params['display_order'] = $display_order;
1415
            $new_id = Database::insert($link_cat_table, $params);
1416
1417
            if ($new_id) {
1418
                $sql = "UPDATE $link_cat_table 
1419
                        SET id = iid 
1420
                        WHERE iid = $new_id";
1421
                Database::query($sql);
1422
1423
                $courseInfo = api_get_course_info_by_id($this->destination_course_id);
1424
                api_item_property_update(
1425
                    $courseInfo,
1426
                    TOOL_LINK_CATEGORY,
1427
                    $new_id,
1428
                    'LinkCategoryAdded',
1429
                    api_get_user_id()
1430
                );
1431
                api_set_default_visibility(
1432
                    $new_id,
1433
                    TOOL_LINK_CATEGORY,
1434
                    0,
1435
                    $courseInfo
1436
                );
1437
            }
1438
1439
            $this->course->resources[RESOURCE_LINKCATEGORY][$id]->destination_id = $new_id;
1440
1441
            return $new_id;
1442
        }
1443
1444
        return $this->course->resources[RESOURCE_LINKCATEGORY][$id]->destination_id;
1445
    }
1446
1447
    /**
1448
     * Restore tool intro.
1449
     *
1450
     * @param int
1451
     */
1452
    public function restore_tool_intro($sessionId = 0)
1453
    {
1454
        if ($this->course->has_resources(RESOURCE_TOOL_INTRO)) {
1455
            $sessionId = intval($sessionId);
1456
            $tool_intro_table = Database::get_course_table(TABLE_TOOL_INTRO);
1457
            $resources = $this->course->resources;
1458
            foreach ($resources[RESOURCE_TOOL_INTRO] as $id => $tool_intro) {
1459
                $sql = "DELETE FROM $tool_intro_table
1460
                        WHERE
1461
                            c_id = ".$this->destination_course_id." AND
1462
                            id='".self::DBUTF8escapestring($tool_intro->id)."'";
1463
                Database::query($sql);
1464
1465
                $tool_intro->intro_text = DocumentManager::replaceUrlWithNewCourseCode(
1466
                    $tool_intro->intro_text,
1467
                    $this->course->code,
1468
                    $this->course->destination_path,
1469
                    $this->course->backup_path,
1470
                    $this->course->info['path']
1471
                );
1472
1473
                $params = [
1474
                    'c_id' => $this->destination_course_id,
1475
                    'id' => ($tool_intro->id === false ? '' : self::DBUTF8($tool_intro->id)),
1476
                    'intro_text' => self::DBUTF8($tool_intro->intro_text),
1477
                    'session_id' => $sessionId,
1478
                ];
1479
1480
                $id = Database::insert($tool_intro_table, $params);
1481
                if ($id) {
1482
                    if (!isset($this->course->resources[RESOURCE_TOOL_INTRO][$id])) {
1483
                        $this->course->resources[RESOURCE_TOOL_INTRO][$id] = new stdClass();
1484
                    }
1485
1486
                    $this->course->resources[RESOURCE_TOOL_INTRO][$id]->destination_id = $id;
1487
                }
1488
            }
1489
        }
1490
    }
1491
1492
    /**
1493
     * Restore events.
1494
     *
1495
     * @param int
1496
     */
1497
    public function restore_events($sessionId = 0)
1498
    {
1499
        if ($this->course->has_resources(RESOURCE_EVENT)) {
1500
            $sessionId = intval($sessionId);
1501
            $table = Database::get_course_table(TABLE_AGENDA);
1502
            $resources = $this->course->resources;
1503
            foreach ($resources[RESOURCE_EVENT] as $id => $event) {
1504
                // check resources inside html from ckeditor tool and copy correct urls into recipient course
1505
                $event->content = DocumentManager::replaceUrlWithNewCourseCode(
1506
                    $event->content,
1507
                    $this->course->code,
1508
                    $this->course->destination_path,
1509
                    $this->course->backup_path,
1510
                    $this->course->info['path']
1511
                );
1512
1513
                $params = [
1514
                    'c_id' => $this->destination_course_id,
1515
                    'title' => self::DBUTF8($event->title),
1516
                    'content' => ($event->content === false ? '' : self::DBUTF8($event->content)),
1517
                    'all_day' => $event->all_day,
1518
                    'start_date' => $event->start_date,
1519
                    'end_date' => $event->end_date,
1520
                    'session_id' => $sessionId,
1521
                ];
1522
                $new_event_id = Database::insert($table, $params);
1523
1524
                if ($new_event_id) {
1525
                    $sql = "UPDATE $table SET id = iid WHERE iid = $new_event_id";
1526
                    Database::query($sql);
1527
1528
                    if (!isset($this->course->resources[RESOURCE_EVENT][$id])) {
1529
                        $this->course->resources[RESOURCE_EVENT][$id] = new stdClass();
1530
                    }
1531
                    $this->course->resources[RESOURCE_EVENT][$id]->destination_id = $new_event_id;
1532
                }
1533
1534
                // Copy event attachment
1535
                $origin_path = $this->course->backup_path.'/upload/calendar/';
1536
                $destination_path = api_get_path(SYS_COURSE_PATH).$this->course->destination_path.'/upload/calendar/';
1537
1538
                if (!empty($this->course->orig)) {
1539
                    $table_attachment = Database::get_course_table(TABLE_AGENDA_ATTACHMENT);
1540
                    $sql = 'SELECT path, comment, size, filename
1541
                            FROM '.$table_attachment.'
1542
                            WHERE c_id = '.$this->destination_course_id.' AND agenda_id = '.$id;
1543
                    $attachment_event = Database::query($sql);
1544
                    $attachment_event = Database::fetch_object($attachment_event);
1545
1546
                    if (file_exists($origin_path.$attachment_event->path) &&
1547
                        !is_dir($origin_path.$attachment_event->path)
1548
                    ) {
1549
                        $new_filename = uniqid(''); //ass seen in the add_agenda_attachment_file() function in agenda.inc.php
1550
                        $copy_result = copy(
1551
                            $origin_path.$attachment_event->path,
1552
                            $destination_path.$new_filename
1553
                        );
1554
                        //$copy_result = true;
1555
                        if ($copy_result) {
1556
                            $table_attachment = Database::get_course_table(TABLE_AGENDA_ATTACHMENT);
1557
1558
                            $params = [
1559
                                'c_id' => $this->destination_course_id,
1560
                                'path' => self::DBUTF8($new_filename),
1561
                                'comment' => self::DBUTF8($attachment_event->comment),
1562
                                'size' => isset($attachment_event->size) ? $attachment_event->size : '',
1563
                                'filename' => isset($attachment_event->filename) ? $attachment_event->filename : '',
1564
                                'agenda_id' => $new_event_id,
1565
                            ];
1566
                            $id = Database::insert($table_attachment, $params);
1567
                            if ($id) {
1568
                                $sql = "UPDATE $table_attachment SET id = iid WHERE iid = $id";
1569
                                Database::query($sql);
1570
                            }
1571
                        }
1572
                    }
1573
                } else {
1574
                    // get the info of the file
1575
                    if (!empty($event->attachment_path) &&
1576
                        is_file($origin_path.$event->attachment_path) &&
1577
                        is_readable($origin_path.$event->attachment_path)
1578
                    ) {
1579
                        $new_filename = uniqid(''); //ass seen in the add_agenda_attachment_file() function in agenda.inc.php
1580
                        $copy_result = copy(
1581
                            $origin_path.$event->attachment_path,
1582
                            $destination_path.$new_filename
1583
                        );
1584
                        if ($copy_result) {
1585
                            $table_attachment = Database::get_course_table(TABLE_AGENDA_ATTACHMENT);
1586
1587
                            $params = [
1588
                                'c_id' => $this->destination_course_id,
1589
                                'path' => self::DBUTF8($new_filename),
1590
                                'comment' => self::DBUTF8($event->attachment_comment),
1591
                                'size' => isset($event->size) ? $event->size : '',
1592
                                'filename' => isset($event->filename) ? $event->filename : '',
1593
                                'agenda_id' => $new_event_id,
1594
                            ];
1595
                            $id = Database::insert($table_attachment, $params);
1596
1597
                            if ($id) {
1598
                                $sql = "UPDATE $table_attachment SET id = iid WHERE iid = $id";
1599
                                Database::query($sql);
1600
                            }
1601
                        }
1602
                    }
1603
                }
1604
            }
1605
        }
1606
    }
1607
1608
    /**
1609
     * Restore course-description.
1610
     *
1611
     * @param int
1612
     */
1613
    public function restore_course_descriptions($session_id = 0)
1614
    {
1615
        if ($this->course->has_resources(RESOURCE_COURSEDESCRIPTION)) {
1616
            $table = Database::get_course_table(TABLE_COURSE_DESCRIPTION);
1617
            $resources = $this->course->resources;
1618
            foreach ($resources[RESOURCE_COURSEDESCRIPTION] as $id => $cd) {
1619
                $courseDescription = (array) $cd;
1620
1621
                $content = isset($courseDescription['content']) ? $courseDescription['content'] : '';
1622
                $descriptionType = isset($courseDescription['description_type']) ? $courseDescription['description_type'] : '';
1623
                $title = isset($courseDescription['title']) ? $courseDescription['title'] : '';
1624
1625
                // check resources inside html from ckeditor tool and copy correct urls into recipient course
1626
                $description_content = DocumentManager::replaceUrlWithNewCourseCode(
1627
                    $content,
1628
                    $this->course->code,
1629
                    $this->course->destination_path,
1630
                    $this->course->backup_path,
1631
                    $this->course->info['path']
1632
                );
1633
1634
                $params = [];
1635
                $session_id = intval($session_id);
1636
                $params['session_id'] = $session_id;
1637
                $params['c_id'] = $this->destination_course_id;
1638
                $params['description_type'] = self::DBUTF8($descriptionType);
1639
                $params['title'] = self::DBUTF8($title);
1640
                $params['content'] = ($description_content === false ? '' : self::DBUTF8($description_content));
1641
                $params['progress'] = 0;
1642
1643
                $id = Database::insert($table, $params);
1644
                if ($id) {
1645
                    $sql = "UPDATE $table SET id = iid WHERE iid = $id";
1646
                    Database::query($sql);
1647
1648
                    if (!isset($this->course->resources[RESOURCE_COURSEDESCRIPTION][$id])) {
1649
                        $this->course->resources[RESOURCE_COURSEDESCRIPTION][$id] = new stdClass();
1650
                    }
1651
                    $this->course->resources[RESOURCE_COURSEDESCRIPTION][$id]->destination_id = $id;
1652
                }
1653
            }
1654
        }
1655
    }
1656
1657
    /**
1658
     * Restore announcements.
1659
     *
1660
     * @param int
1661
     */
1662
    public function restore_announcements($sessionId = 0)
1663
    {
1664
        if ($this->course->has_resources(RESOURCE_ANNOUNCEMENT)) {
1665
            $sessionId = intval($sessionId);
1666
            $table = Database::get_course_table(TABLE_ANNOUNCEMENT);
1667
            $resources = $this->course->resources;
1668
            foreach ($resources[RESOURCE_ANNOUNCEMENT] as $id => $announcement) {
1669
                // check resources inside html from ckeditor tool and copy correct urls into recipient course
1670
                $announcement->content = DocumentManager::replaceUrlWithNewCourseCode(
1671
                    $announcement->content,
1672
                    $this->course->code,
1673
                    $this->course->destination_path,
1674
                    $this->course->backup_path,
1675
                    $this->course->info['path']
1676
                );
1677
1678
                $params = [
1679
                    'c_id' => $this->destination_course_id,
1680
                    'title' => self::DBUTF8($announcement->title),
1681
                    'content' => ($announcement->content === false ? '' : self::DBUTF8($announcement->content)),
1682
                    'end_date' => $announcement->date,
1683
                    'display_order' => $announcement->display_order,
1684
                    'email_sent' => $announcement->email_sent,
1685
                    'session_id' => $sessionId,
1686
                ];
1687
1688
                $new_announcement_id = Database::insert($table, $params);
1689
1690
                if ($new_announcement_id) {
1691
                    $sql = "UPDATE $table SET id = iid WHERE iid = $new_announcement_id";
1692
                    Database::query($sql);
1693
1694
                    if (!isset($this->course->resources[RESOURCE_ANNOUNCEMENT][$id])) {
1695
                        $this->course->resources[RESOURCE_ANNOUNCEMENT][$id] = new stdClass();
1696
                    }
1697
                    $this->course->resources[RESOURCE_ANNOUNCEMENT][$id]->destination_id = $new_announcement_id;
1698
                }
1699
1700
                $origin_path = $this->course->backup_path.'/upload/announcements/';
1701
                $destination_path = api_get_path(SYS_COURSE_PATH).$this->course->destination_path.'/upload/announcements/';
1702
1703
                // Copy announcement attachment file
1704
                if (!empty($this->course->orig)) {
1705
                    $table_attachment = Database::get_course_table(TABLE_ANNOUNCEMENT_ATTACHMENT);
1706
                    $sql = 'SELECT path, comment, size, filename
1707
                            FROM '.$table_attachment.'
1708
                            WHERE
1709
                                c_id = '.$this->destination_course_id.' AND
1710
                                announcement_id = '.$id;
1711
                    $attachment_event = Database::query($sql);
1712
                    $attachment_event = Database::fetch_object($attachment_event);
1713
1714
                    if (file_exists($origin_path.$attachment_event->path) &&
1715
                        !is_dir($origin_path.$attachment_event->path)
1716
                    ) {
1717
                        $new_filename = uniqid(''); //ass seen in the add_agenda_attachment_file() function in agenda.inc.php
1718
                        $copy_result = copy(
1719
                            $origin_path.$attachment_event->path,
1720
                            $destination_path.$new_filename
1721
                        );
1722
1723
                        if ($copy_result) {
1724
                            $table_attachment = Database::get_course_table(TABLE_ANNOUNCEMENT_ATTACHMENT);
1725
1726
                            $params = [
1727
                                'c_id' => $this->destination_course_id,
1728
                                'path' => self::DBUTF8($new_filename),
1729
                                'comment' => self::DBUTF8($attachment_event->comment),
1730
                                'size' => $attachment_event->size,
1731
                                'filename' => $attachment_event->filename,
1732
                                'announcement_id' => $new_announcement_id,
1733
                            ];
1734
1735
                            $attachmentId = Database::insert($table_attachment, $params);
1736
1737
                            if ($attachmentId) {
1738
                                $sql = "UPDATE $table_attachment SET id = iid WHERE iid = $attachmentId";
1739
                                Database::query($sql);
1740
                            }
1741
                        }
1742
                    }
1743
                } else {
1744
                    // get the info of the file
1745
                    if (!empty($announcement->attachment_path) &&
1746
                        is_file($origin_path.$announcement->attachment_path) &&
1747
                        is_readable($origin_path.$announcement->attachment_path)
1748
                    ) {
1749
                        $new_filename = uniqid(''); //ass seen in the add_agenda_attachment_file() function in agenda.inc.php
1750
                        $copy_result = copy($origin_path.$announcement->attachment_path, $destination_path.$new_filename);
1751
1752
                        if ($copy_result) {
1753
                            $table_attachment = Database::get_course_table(TABLE_ANNOUNCEMENT_ATTACHMENT);
1754
1755
                            $params = [
1756
                                'c_id' => $this->destination_course_id,
1757
                                'path' => self::DBUTF8($new_filename),
1758
                                'comment' => self::DBUTF8($announcement->attachment_comment),
1759
                                'size' => $announcement->attachment_size,
1760
                                'filename' => $announcement->attachment_filename,
1761
                                'announcement_id' => $new_announcement_id,
1762
                            ];
1763
1764
                            $attachmentId = Database::insert($table_attachment, $params);
1765
1766
                            if ($attachmentId) {
1767
                                $sql = "UPDATE $table_attachment SET id = iid WHERE iid = $attachmentId";
1768
                                Database::query($sql);
1769
                            }
1770
                        }
1771
                    }
1772
                }
1773
            }
1774
        }
1775
    }
1776
1777
    /**
1778
     * Restore Quiz.
1779
     *
1780
     * @param int  $session_id
1781
     * @param bool $respect_base_content
1782
     */
1783
    public function restore_quizzes(
1784
        $session_id = 0,
1785
        $respect_base_content = false
1786
    ) {
1787
        if ($this->course->has_resources(RESOURCE_QUIZ)) {
1788
            $table_qui = Database::get_course_table(TABLE_QUIZ_TEST);
1789
            $table_rel = Database::get_course_table(TABLE_QUIZ_TEST_QUESTION);
1790
            $table_doc = Database::get_course_table(TABLE_DOCUMENT);
1791
            $resources = $this->course->resources;
1792
1793
            foreach ($resources[RESOURCE_QUIZ] as $id => $quiz) {
1794
                if (isset($quiz->obj)) {
1795
                    // For new imports
1796
                    $quiz = $quiz->obj;
1797
                } else {
1798
                    // For backward compatibility
1799
                    $quiz->obj = $quiz;
1800
                }
1801
1802
                $doc = '';
1803
                if (!empty($quiz->sound)) {
1804
                    if (isset($this->course->resources[RESOURCE_DOCUMENT][$quiz->sound]) &&
1805
                        $this->course->resources[RESOURCE_DOCUMENT][$quiz->sound]->is_restored()) {
1806
                        $sql = "SELECT path FROM $table_doc
1807
                                WHERE
1808
                                    c_id = ".$this->destination_course_id."  AND
1809
                                    id = ".$resources[RESOURCE_DOCUMENT][$quiz->sound]->destination_id;
1810
                        $doc = Database::query($sql);
1811
                        $doc = Database::fetch_object($doc);
1812
                        $doc = str_replace('/audio/', '', $doc->path);
1813
                    }
1814
                }
1815
1816
                if ($id != -1) {
1817
                    // check resources inside html from ckeditor tool and copy correct urls into recipient course
1818
                    $quiz->description = DocumentManager::replaceUrlWithNewCourseCode(
1819
                        $quiz->description,
1820
                        $this->course->code,
1821
                        $this->course->destination_path,
1822
                        $this->course->backup_path,
1823
                        $this->course->info['path']
1824
                    );
1825
1826
                    $quiz->start_time = $quiz->start_time == '0000-00-00 00:00:00' ? null : $quiz->start_time;
1827
                    $quiz->end_time = $quiz->end_time == '0000-00-00 00:00:00' ? null : $quiz->end_time;
1828
1829
                    global $_custom;
1830
                    if (isset($_custom['exercises_clean_dates_when_restoring']) &&
1831
                        $_custom['exercises_clean_dates_when_restoring']
1832
                    ) {
1833
                        $quiz->start_time = null;
1834
                        $quiz->end_time = null;
1835
                    }
1836
1837
                    $params = [
1838
                        'c_id' => $this->destination_course_id,
1839
                        'title' => self::DBUTF8($quiz->title),
1840
                        'description' => ($quiz->description === false ? '' : self::DBUTF8($quiz->description)),
1841
                        'type' => isset($quiz->quiz_type) ? (int) $quiz->quiz_type : $quiz->type,
1842
                        'random' => (int) $quiz->random,
1843
                        'active' => $quiz->active,
1844
                        'sound' => self::DBUTF8($doc),
1845
                        'max_attempt' => (int) $quiz->max_attempt,
1846
                        'results_disabled' => (int) $quiz->results_disabled,
1847
                        'access_condition' => $quiz->access_condition,
1848
                        'pass_percentage' => $quiz->pass_percentage,
1849
                        'feedback_type' => (int) $quiz->feedback_type,
1850
                        'random_answers' => (int) $quiz->random_answers,
1851
                        'random_by_category' => (int) $quiz->random_by_category,
1852
                        'review_answers' => (int) $quiz->review_answers,
1853
                        'propagate_neg' => (int) $quiz->propagate_neg,
1854
                        'text_when_finished' => (string) $quiz->text_when_finished,
1855
                        'expired_time' => (int) $quiz->expired_time,
1856
                        'start_time' => $quiz->start_time,
1857
                        'end_time' => $quiz->end_time,
1858
                        'save_correct_answers' => 0,
1859
                        'display_category_name' => 0,
1860
                        'save_correct_answers' => isset($quiz->save_correct_answers) ? $quiz->save_correct_answers : 0,
1861
                        'hide_question_title' => isset($quiz->hide_question_title) ? $quiz->hide_question_title : 0,
1862
                    ];
1863
1864
                    $allow = api_get_configuration_value('allow_notification_setting_per_exercise');
1865
                    if ($allow) {
1866
                        $params['notifications'] = $quiz->notifications;
1867
                    }
1868
1869
                    if ($respect_base_content) {
1870
                        $my_session_id = $quiz->session_id;
1871
                        if (!empty($quiz->session_id)) {
1872
                            $my_session_id = $session_id;
1873
                        }
1874
                        $params['session_id'] = $my_session_id;
1875
                    } else {
1876
                        if (!empty($session_id)) {
1877
                            $session_id = intval($session_id);
1878
                            $params['session_id'] = $session_id;
1879
                        }
1880
                    }
1881
                    $new_id = Database::insert($table_qui, $params);
1882
1883
                    if ($new_id) {
1884
                        $sql = "UPDATE $table_qui SET id = iid WHERE iid = $new_id";
1885
                        Database::query($sql);
1886
                    }
1887
                } else {
1888
                    // $id = -1 identifies the fictionary test for collecting
1889
                    // orphan questions. We do not store it in the database.
1890
                    $new_id = -1;
1891
                }
1892
1893
                $this->course->resources[RESOURCE_QUIZ][$id]->destination_id = $new_id;
1894
1895
                $order = 0;
1896
                if (!empty($quiz->question_ids)) {
1897
                    foreach ($quiz->question_ids as $index => $question_id) {
1898
                        $qid = $this->restore_quiz_question($question_id);
1899
                        $question_order = $quiz->question_orders[$index] ? $quiz->question_orders[$index] : ++$order;
1900
                        $sql = "INSERT IGNORE INTO $table_rel SET
1901
                                c_id = ".$this->destination_course_id.",
1902
                                question_id = $qid ,
1903
                                exercice_id = $new_id ,
1904
                                question_order = ".$question_order;
1905
                        Database::query($sql);
1906
                    }
1907
                }
1908
            }
1909
        }
1910
    }
1911
1912
    /**
1913
     * Restore quiz-questions.
1914
     *
1915
     * @params int $id question id
1916
     */
1917
    public function restore_quiz_question($id)
1918
    {
1919
        $em = Database::getManager();
1920
        $resources = $this->course->resources;
1921
        /** @var QuizQuestion $question */
1922
        $question = isset($resources[RESOURCE_QUIZQUESTION][$id]) ? $resources[RESOURCE_QUIZQUESTION][$id] : null;
1923
        $new_id = 0;
1924
1925
        if (is_object($question)) {
1926
            if ($question->is_restored()) {
1927
                return $question->destination_id;
1928
            }
1929
            $table_que = Database::get_course_table(TABLE_QUIZ_QUESTION);
1930
            $table_ans = Database::get_course_table(TABLE_QUIZ_ANSWER);
1931
            $table_options = Database::get_course_table(TABLE_QUIZ_QUESTION_OPTION);
1932
1933
            // check resources inside html from ckeditor tool and copy correct urls into recipient course
1934
            $question->description = DocumentManager::replaceUrlWithNewCourseCode(
1935
                $question->description,
1936
                $this->course->code,
1937
                $this->course->destination_path,
1938
                $this->course->backup_path,
1939
                $this->course->info['path']
1940
            );
1941
1942
            $imageNewId = '';
1943
            if (preg_match('/^quiz-.*$/', $question->picture) &&
1944
                isset($resources[RESOURCE_DOCUMENT]['image_quiz'][$question->picture])
1945
            ) {
1946
                $imageNewId = $resources[RESOURCE_DOCUMENT]['image_quiz'][$question->picture]['destination_id'];
1947
            } else {
1948
                if (isset($resources[RESOURCE_DOCUMENT][$question->picture])) {
1949
                    $documentsToRestore = $resources[RESOURCE_DOCUMENT][$question->picture];
1950
                    $imageNewId = $documentsToRestore->destination_id;
1951
                }
1952
            }
1953
1954
            $params = [
1955
                'c_id' => $this->destination_course_id,
1956
                'question' => self::DBUTF8($question->question),
1957
                'description' => ($question->description === false ? '' : self::DBUTF8($question->description)),
1958
                'ponderation' => self::DBUTF8($question->ponderation),
1959
                'position' => self::DBUTF8($question->position),
1960
                'type' => self::DBUTF8($question->quiz_type),
1961
                'picture' => self::DBUTF8($imageNewId),
1962
                'level' => self::DBUTF8($question->level),
1963
                'extra' => self::DBUTF8($question->extra),
1964
            ];
1965
1966
            $new_id = Database::insert($table_que, $params);
1967
1968
            if ($new_id) {
1969
                $sql = "UPDATE $table_que SET id = iid WHERE iid = $new_id";
1970
                Database::query($sql);
1971
            }
1972
1973
            $correctAnswers = [];
1974
            $allAnswers = [];
1975
            $onlyAnswers = [];
1976
1977
            if (in_array($question->quiz_type, [DRAGGABLE, MATCHING, MATCHING_DRAGGABLE])) {
1978
                $allAnswers = array_column($question->answers, 'answer', 'id');
1979
            }
1980
1981
            if (in_array($question->quiz_type, [MATCHING, MATCHING_DRAGGABLE])) {
1982
                $temp = [];
1983
                foreach ($question->answers as $index => $answer) {
1984
                    $temp[$answer['position']] = $answer;
1985
                }
1986
1987
                foreach ($temp as $index => $answer) {
1988
                    // check resources inside html from ckeditor tool and copy correct urls into recipient course
1989
                    $answer['answer'] = DocumentManager::replaceUrlWithNewCourseCode(
1990
                        $answer['answer'],
1991
                        $this->course->code,
1992
                        $this->course->destination_path,
1993
                        $this->course->backup_path,
1994
                        $this->course->info['path']
1995
                    );
1996
1997
                    $answer['comment'] = DocumentManager::replaceUrlWithNewCourseCode(
1998
                        $answer['comment'],
1999
                        $this->course->code,
2000
                        $this->course->destination_path,
2001
                        $this->course->backup_path,
2002
                        $this->course->info['path']
2003
                    );
2004
2005
                    $quizAnswer = new CQuizAnswer();
2006
                    $quizAnswer
2007
                        ->setCId($this->destination_course_id)
2008
                        ->setQuestionId($new_id)
2009
                        ->setAnswer(self::DBUTF8($answer['answer']))
2010
                        ->setCorrect($answer['correct'])
2011
                        ->setComment($answer['comment'] === false ? '' : self::DBUTF8($answer['comment']))
2012
                        ->setPonderation($answer['ponderation'])
2013
                        ->setPosition($answer['position'])
2014
                        ->setHotspotCoordinates($answer['hotspot_coordinates'])
2015
                        ->setHotspotType($answer['hotspot_type'])
2016
                        ->setIdAuto(0);
2017
2018
                    $em->persist($quizAnswer);
2019
                    $em->flush();
2020
2021
                    $answerId = $quizAnswer->getIid();
2022
2023
                    if ($answerId) {
2024
                        $quizAnswer
2025
                            ->setId($answerId)
2026
                            ->setIdAuto($answerId);
2027
2028
                        $em->merge($quizAnswer);
2029
                        $em->flush();
2030
2031
                        $correctAnswers[$answerId] = $answer['correct'];
2032
                        $onlyAnswers[$answerId] = $answer['answer'];
2033
                    }
2034
                }
2035
            } else {
2036
                foreach ($question->answers as $index => $answer) {
2037
                    // check resources inside html from ckeditor tool and copy correct urls into recipient course
2038
                    $answer['answer'] = DocumentManager::replaceUrlWithNewCourseCode(
2039
                        $answer['answer'],
2040
                        $this->course->code,
2041
                        $this->course->destination_path,
2042
                        $this->course->backup_path,
2043
                        $this->course->info['path']
2044
                    );
2045
2046
                    $answer['comment'] = DocumentManager::replaceUrlWithNewCourseCode(
2047
                        $answer['comment'],
2048
                        $this->course->code,
2049
                        $this->course->destination_path,
2050
                        $this->course->backup_path,
2051
                        $this->course->info['path']
2052
                    );
2053
2054
                    $params = [
2055
                        'c_id' => $this->destination_course_id,
2056
                        'question_id' => $new_id,
2057
                        'answer' => self::DBUTF8($answer['answer']),
2058
                        'correct' => $answer['correct'],
2059
                        'comment' => ($answer['comment'] === false ? '' : self::DBUTF8($answer['comment'])),
2060
                        'ponderation' => $answer['ponderation'],
2061
                        'position' => $answer['position'],
2062
                        'hotspot_coordinates' => $answer['hotspot_coordinates'],
2063
                        'hotspot_type' => $answer['hotspot_type'],
2064
                        'id_auto' => 0,
2065
                        'destination' => '',
2066
                    ];
2067
2068
                    $answerId = Database::insert($table_ans, $params);
2069
2070
                    if ($answerId) {
2071
                        $sql = "UPDATE $table_ans SET id = iid, id_auto = iid WHERE iid = $answerId";
2072
                        Database::query($sql);
2073
                    }
2074
2075
                    $correctAnswers[$answerId] = $answer['correct'];
2076
                    $onlyAnswers[$answerId] = $answer['answer'];
2077
                }
2078
            }
2079
2080
            // Current course id
2081
            $course_id = api_get_course_int_id();
2082
2083
            // Moving quiz_question_options
2084
            if ($question->quiz_type == MULTIPLE_ANSWER_TRUE_FALSE) {
2085
                $question_option_list = Question::readQuestionOption($id, $course_id);
2086
2087
                // Question copied from the current platform
2088
                if ($question_option_list) {
2089
                    $old_option_ids = [];
2090
                    foreach ($question_option_list as $item) {
2091
                        $old_id = $item['id'];
2092
                        unset($item['id']);
2093
                        if (isset($item['iid'])) {
2094
                            unset($item['iid']);
2095
                        }
2096
                        $item['question_id'] = $new_id;
2097
                        $item['c_id'] = $this->destination_course_id;
2098
                        $question_option_id = Database::insert($table_options, $item);
2099
                        if ($question_option_id) {
2100
                            $old_option_ids[$old_id] = $question_option_id;
2101
                            $sql = "UPDATE $table_options SET id = iid WHERE iid = $question_option_id";
2102
                            Database::query($sql);
2103
                        }
2104
                    }
2105
                    if ($old_option_ids) {
2106
                        $new_answers = Database::select(
2107
                            'iid, correct',
2108
                            $table_ans,
2109
                            [
2110
                                'WHERE' => [
2111
                                    'question_id = ? AND c_id = ? ' => [
2112
                                        $new_id,
2113
                                        $this->destination_course_id,
2114
                                    ],
2115
                                ],
2116
                            ]
2117
                        );
2118
2119
                        foreach ($new_answers as $answer_item) {
2120
                            $params = [];
2121
                            $params['correct'] = $old_option_ids[$answer_item['correct']];
2122
                            Database::update(
2123
                                $table_ans,
2124
                                $params,
2125
                                [
2126
                                    'iid = ? AND c_id = ? AND question_id = ? ' => [
2127
                                        $answer_item['iid'],
2128
                                        $this->destination_course_id,
2129
                                        $new_id,
2130
                                    ],
2131
                                ],
2132
                                false
2133
                            );
2134
                        }
2135
                    }
2136
                } else {
2137
                    $new_options = [];
2138
                    if (isset($question->question_options)) {
2139
                        foreach ($question->question_options as $obj) {
2140
                            $item = [];
2141
                            $item['question_id'] = $new_id;
2142
                            $item['c_id'] = $this->destination_course_id;
2143
                            $item['name'] = $obj->obj->name;
2144
                            $item['position'] = $obj->obj->position;
2145
                            $question_option_id = Database::insert($table_options, $item);
2146
2147
                            if ($question_option_id) {
2148
                                $new_options[$obj->obj->id] = $question_option_id;
2149
                                $sql = "UPDATE $table_options SET id = iid WHERE iid = $question_option_id";
2150
                                Database::query($sql);
2151
                            }
2152
                        }
2153
2154
                        foreach ($correctAnswers as $answer_id => $correct_answer) {
2155
                            $params = [];
2156
                            $params['correct'] = $new_options[$correct_answer];
2157
                            Database::update(
2158
                                $table_ans,
2159
                                $params,
2160
                                [
2161
                                    'id = ? AND c_id = ? AND question_id = ? ' => [
2162
                                        $answer_id,
2163
                                        $this->destination_course_id,
2164
                                        $new_id,
2165
                                    ],
2166
                                ],
2167
                                false
2168
                            );
2169
                        }
2170
                    }
2171
                }
2172
            }
2173
2174
            // Fix correct answers
2175
            if (in_array($question->quiz_type, [DRAGGABLE, MATCHING, MATCHING_DRAGGABLE])) {
2176
                $onlyAnswersFlip = array_flip($onlyAnswers);
2177
                foreach ($correctAnswers as $answer_id => $correct_answer) {
2178
                    $params = [];
2179
                    if (isset($allAnswers[$correct_answer]) &&
2180
                        isset($onlyAnswersFlip[$allAnswers[$correct_answer]])
2181
                    ) {
2182
                        $params['correct'] = $onlyAnswersFlip[$allAnswers[$correct_answer]];
2183
                        Database::update(
2184
                            $table_ans,
2185
                            $params,
2186
                            [
2187
                                'id = ? AND c_id = ? AND question_id = ? ' => [
2188
                                    $answer_id,
2189
                                    $this->destination_course_id,
2190
                                    $new_id,
2191
                                ],
2192
                            ]
2193
                        );
2194
                    }
2195
                }
2196
            }
2197
2198
            $this->course->resources[RESOURCE_QUIZQUESTION][$id]->destination_id = $new_id;
2199
        }
2200
2201
        return $new_id;
2202
    }
2203
2204
    /**
2205
     * @todo : add session id when used for session
2206
     */
2207
    public function restore_test_category($session_id, $respect_base_content, $destination_course_code)
2208
    {
2209
        $destinationCourseId = $this->destination_course_info['real_id'];
2210
        // Let's restore the categories
2211
        $categoryOldVsNewList = []; // used to build the quiz_question_rel_category table
2212
        if ($this->course->has_resources(RESOURCE_TEST_CATEGORY)) {
2213
            $resources = $this->course->resources;
2214
            foreach ($resources[RESOURCE_TEST_CATEGORY] as $id => $courseCopyTestCategory) {
2215
                $categoryOldVsNewList[$courseCopyTestCategory->source_id] = $id;
2216
                // check if this test_category already exist in the destination BDD
2217
                // do not Database::escape_string $title and $description, it will be done later
2218
                $title = $courseCopyTestCategory->title;
2219
                $description = $courseCopyTestCategory->description;
2220
                if (TestCategory::categoryTitleExists($title, $destinationCourseId)) {
2221
                    switch ($this->file_option) {
2222
                        case FILE_SKIP:
2223
                            //Do nothing
2224
                            break;
2225
                        case FILE_RENAME:
2226
                            $new_title = $title.'_';
2227
                            while (TestCategory::categoryTitleExists($new_title, $destinationCourseId)) {
2228
                                $new_title .= '_';
2229
                            }
2230
                            $test_category = new TestCategory();
2231
                            $test_category->name = $new_title;
2232
                            $test_category->description = $description;
2233
                            $new_id = $test_category->save($destinationCourseId);
2234
                            $categoryOldVsNewList[$courseCopyTestCategory->source_id] = $new_id;
2235
                            break;
2236
                        case FILE_OVERWRITE:
2237
                            // get category from source
2238
                            $destinationCategoryId = TestCategory::get_category_id_for_title(
2239
                                $title,
2240
                                $destinationCourseId
2241
                            );
2242
                            if ($destinationCategoryId) {
2243
                                $my_cat = new TestCategory();
2244
                                $my_cat = $my_cat->getCategory($destinationCategoryId, $destinationCourseId);
2245
                                $my_cat->name = $title;
2246
                                $my_cat->description = $description;
2247
                                $my_cat->modifyCategory($destinationCourseId);
2248
                                $categoryOldVsNewList[$courseCopyTestCategory->source_id] = $destinationCategoryId;
2249
                            }
2250
                            break;
2251
                    }
2252
                } else {
2253
                    // create a new test_category
2254
                    $test_category = new TestCategory();
2255
                    $test_category->name = $title;
2256
                    $test_category->description = $description;
2257
                    $new_id = $test_category->save($destinationCourseId);
2258
                    $categoryOldVsNewList[$courseCopyTestCategory->source_id] = $new_id;
2259
                }
2260
                $this->course->resources[RESOURCE_TEST_CATEGORY][$id]->destination_id = $categoryOldVsNewList[$courseCopyTestCategory->source_id];
2261
            }
2262
        }
2263
2264
        // lets check if quizzes-question are restored too,
2265
        // to redo the link between test_category and quizzes question for questions restored
2266
        // we can use the source_id field
2267
        // question source_id => category source_id
2268
        if ($this->course->has_resources(RESOURCE_QUIZQUESTION)) {
2269
            // check the category number of each question restored
2270
            if (!empty($resources[RESOURCE_QUIZQUESTION])) {
2271
                foreach ($resources[RESOURCE_QUIZQUESTION] as $id => $courseCopyQuestion) {
2272
                    $newQuestionId = $resources[RESOURCE_QUIZQUESTION][$id]->destination_id;
2273
                    $questionCategoryId = $courseCopyQuestion->question_category;
2274
                    if ($newQuestionId > 0 &&
2275
                        $questionCategoryId > 0 &&
2276
                        isset($categoryOldVsNewList[$questionCategoryId])
2277
                    ) {
2278
                        TestCategory::addCategoryToQuestion(
2279
                            $categoryOldVsNewList[$questionCategoryId],
2280
                            $newQuestionId,
2281
                            $destinationCourseId
2282
                        );
2283
                    }
2284
                }
2285
            }
2286
        }
2287
    }
2288
2289
    /**
2290
     * Restore surveys.
2291
     *
2292
     * @param int $sessionId Optional. The session id
2293
     */
2294
    public function restore_surveys($sessionId = 0)
2295
    {
2296
        $sessionId = intval($sessionId);
2297
        if ($this->course->has_resources(RESOURCE_SURVEY)) {
2298
            $table_sur = Database::get_course_table(TABLE_SURVEY);
2299
            $table_que = Database::get_course_table(TABLE_SURVEY_QUESTION);
2300
            $table_ans = Database::get_course_table(TABLE_SURVEY_QUESTION_OPTION);
2301
            $resources = $this->course->resources;
2302
            foreach ($resources[RESOURCE_SURVEY] as $id => $survey) {
2303
                $sql = 'SELECT survey_id FROM '.$table_sur.'
2304
                        WHERE
2305
                            c_id = '.$this->destination_course_id.' AND
2306
                            code = "'.self::DBUTF8escapestring($survey->code).'" AND
2307
                            lang = "'.self::DBUTF8escapestring($survey->lang).'" ';
2308
2309
                $result_check = Database::query($sql);
2310
2311
                // check resources inside html from ckeditor tool and copy correct urls into recipient course
2312
                $survey->title = DocumentManager::replaceUrlWithNewCourseCode(
2313
                    $survey->title,
2314
                    $this->course->code,
2315
                    $this->course->destination_path,
2316
                    $this->course->backup_path,
2317
                    $this->course->info['path']
2318
                );
2319
2320
                $survey->subtitle = DocumentManager::replaceUrlWithNewCourseCode(
2321
                    $survey->subtitle,
2322
                    $this->course->code,
2323
                    $this->course->destination_path,
2324
                    $this->course->backup_path,
2325
                    $this->course->info['path']
2326
                );
2327
2328
                $survey->intro = DocumentManager::replaceUrlWithNewCourseCode(
2329
                    $survey->intro,
2330
                    $this->course->code,
2331
                    $this->course->destination_path,
2332
                    $this->course->backup_path,
2333
                    $this->course->info['path']
2334
                );
2335
2336
                $survey->surveythanks = DocumentManager::replaceUrlWithNewCourseCode(
2337
                    $survey->surveythanks,
2338
                    $this->course->code,
2339
                    $this->course->destination_path,
2340
                    $this->course->backup_path,
2341
                    $this->course->info['path']
2342
                );
2343
2344
                $params = [
2345
                    'c_id' => $this->destination_course_id,
2346
                    'code' => self::DBUTF8($survey->code),
2347
                    'title' => ($survey->title === false ? '' : self::DBUTF8($survey->title)),
2348
                    'subtitle' => ($survey->subtitle === false ? '' : self::DBUTF8($survey->subtitle)),
2349
                    'author' => self::DBUTF8($survey->author),
2350
                    'lang' => self::DBUTF8($survey->lang),
2351
                    'avail_from' => self::DBUTF8($survey->avail_from),
2352
                    'avail_till' => self::DBUTF8($survey->avail_till),
2353
                    'is_shared' => self::DBUTF8($survey->is_shared),
2354
                    'template' => self::DBUTF8($survey->template),
2355
                    'intro' => ($survey->intro === false ? '' : self::DBUTF8($survey->intro)),
2356
                    'surveythanks' => ($survey->surveythanks === false ? '' : self::DBUTF8($survey->surveythanks)),
2357
                    'creation_date' => self::DBUTF8($survey->creation_date),
2358
                    'invited' => '0',
2359
                    'answered' => '0',
2360
                    'invite_mail' => self::DBUTF8($survey->invite_mail),
2361
                    'reminder_mail' => self::DBUTF8($survey->reminder_mail),
2362
                    'session_id' => $sessionId,
2363
                ];
2364
2365
                // An existing survey exists with the same code and the same language
2366
                if (Database::num_rows($result_check) == 1) {
2367
                    switch ($this->file_option) {
2368
                        case FILE_SKIP:
2369
                            //Do nothing
2370
                            break;
2371
                        case FILE_RENAME:
2372
                            $survey_code = $survey->code.'_';
2373
                            $i = 1;
2374
                            $temp_survey_code = $survey_code.$i;
2375
                            while (!$this->is_survey_code_available($temp_survey_code)) {
2376
                                $temp_survey_code = $survey_code.++$i;
2377
                            }
2378
                            $survey_code = $temp_survey_code;
2379
2380
                            $params['code'] = $survey_code;
2381
                            $new_id = Database::insert($table_sur, $params);
2382
                            if ($new_id) {
2383
                                $sql = "UPDATE $table_sur SET survey_id = iid WHERE iid = $new_id";
2384
                                Database::query($sql);
2385
2386
                                $this->course->resources[RESOURCE_SURVEY][$id]->destination_id = $new_id;
2387
                                foreach ($survey->question_ids as $index => $question_id) {
2388
                                    $qid = $this->restore_survey_question($question_id, $new_id);
2389
                                    $sql = "UPDATE $table_que SET survey_id = $new_id
2390
                                            WHERE c_id = ".$this->destination_course_id." AND question_id = $qid";
2391
                                    Database::query($sql);
2392
                                    $sql = "UPDATE $table_ans SET survey_id = $new_id
2393
                                            WHERE  c_id = ".$this->destination_course_id." AND  question_id = $qid";
2394
                                    Database::query($sql);
2395
                                }
2396
                            }
2397
                            break;
2398
                        case FILE_OVERWRITE:
2399
                            // Delete the existing survey with the same code and language and
2400
                            // import the one of the source course
2401
                            // getting the information of the survey (used for when the survey is shared)
2402
2403
                            $sql = "SELECT * FROM $table_sur
2404
                                    WHERE
2405
                                        c_id = ".$this->destination_course_id." AND
2406
                                        survey_id='".self::DBUTF8escapestring(Database::result($result_check, 0, 0))."'";
2407
                            $result = Database::query($sql);
2408
                            $survey_data = Database::fetch_array($result, 'ASSOC');
2409
2410
                            // if the survey is shared => also delete the shared content
2411
                            if (isset($survey_data['survey_share']) && is_numeric($survey_data['survey_share'])) {
2412
                                SurveyManager::delete_survey(
2413
                                    $survey_data['survey_share'],
2414
                                    true,
2415
                                    $this->destination_course_id
2416
                                );
2417
                            }
2418
                            SurveyManager::delete_survey(
2419
                                $survey_data['survey_id'],
2420
                                false,
2421
                                $this->destination_course_id
2422
                            );
2423
2424
                            // Insert the new source survey
2425
                            $new_id = Database::insert($table_sur, $params);
2426
2427
                            if ($new_id) {
2428
                                $sql = "UPDATE $table_sur SET survey_id = iid WHERE iid = $new_id";
2429
                                Database::query($sql);
2430
2431
                                $this->course->resources[RESOURCE_SURVEY][$id]->destination_id = $new_id;
2432
                                foreach ($survey->question_ids as $index => $question_id) {
2433
                                    $qid = $this->restore_survey_question(
2434
                                        $question_id,
2435
                                        $new_id
2436
                                    );
2437
                                    $sql = "UPDATE $table_que SET survey_id = $new_id
2438
                                            WHERE c_id = ".$this->destination_course_id." AND question_id = $qid";
2439
                                    Database::query($sql);
2440
                                    $sql = "UPDATE $table_ans SET survey_id = $new_id
2441
                                            WHERE c_id = ".$this->destination_course_id." AND question_id = $qid";
2442
                                    Database::query($sql);
2443
                                }
2444
                            }
2445
                            break;
2446
                        default:
2447
                            break;
2448
                    }
2449
                } else {
2450
                    // No existing survey with the same language and the same code, we just copy the survey
2451
                    $new_id = Database::insert($table_sur, $params);
2452
2453
                    if ($new_id) {
2454
                        $sql = "UPDATE $table_sur SET survey_id = iid WHERE iid = $new_id";
2455
                        Database::query($sql);
2456
2457
                        $this->course->resources[RESOURCE_SURVEY][$id]->destination_id = $new_id;
2458
                        foreach ($survey->question_ids as $index => $question_id) {
2459
                            $qid = $this->restore_survey_question(
2460
                                $question_id,
2461
                                $new_id
2462
                            );
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
                }
2472
            }
2473
        }
2474
    }
2475
2476
    /**
2477
     * Check availability of a survey code.
2478
     *
2479
     * @param string $survey_code
2480
     *
2481
     * @return bool
2482
     */
2483
    public function is_survey_code_available($survey_code)
2484
    {
2485
        $table_sur = Database::get_course_table(TABLE_SURVEY);
2486
        $sql = "SELECT * FROM $table_sur
2487
                WHERE
2488
                    c_id = ".$this->destination_course_id." AND
2489
                    code = '".self::DBUTF8escapestring($survey_code)."'";
2490
        $result = Database::query($sql);
2491
        if (Database::num_rows($result) > 0) {
2492
            return false;
2493
        } else {
2494
            return true;
2495
        }
2496
    }
2497
2498
    /**
2499
     * Restore survey-questions.
2500
     *
2501
     * @param int    $id
2502
     * @param string $survey_id
2503
     */
2504
    public function restore_survey_question($id, $survey_id)
2505
    {
2506
        $resources = $this->course->resources;
2507
        $question = $resources[RESOURCE_SURVEYQUESTION][$id];
2508
        $new_id = 0;
2509
2510
        if (is_object($question)) {
2511
            if ($question->is_restored()) {
2512
                return $question->destination_id;
2513
            }
2514
            $table_que = Database::get_course_table(TABLE_SURVEY_QUESTION);
2515
            $table_ans = Database::get_course_table(TABLE_SURVEY_QUESTION_OPTION);
2516
2517
            // check resources inside html from ckeditor tool and copy correct urls into recipient course
2518
            $question->survey_question = DocumentManager::replaceUrlWithNewCourseCode(
2519
                $question->survey_question,
2520
                $this->course->code,
2521
                $this->course->destination_path,
2522
                $this->course->backup_path,
2523
                $this->course->info['path']
2524
            );
2525
2526
            $params = [
2527
                'c_id' => $this->destination_course_id,
2528
                'survey_id' => self::DBUTF8($survey_id),
2529
                'survey_question' => ($question->survey_question === false ? '' : self::DBUTF8($question->survey_question)),
2530
                'survey_question_comment' => self::DBUTF8($question->survey_question_comment),
2531
                'type' => self::DBUTF8($question->survey_question_type),
2532
                'display' => self::DBUTF8($question->display),
2533
                'sort' => self::DBUTF8($question->sort),
2534
                'shared_question_id' => self::DBUTF8($question->shared_question_id),
2535
                'max_value' => self::DBUTF8($question->max_value),
2536
            ];
2537
            if (api_get_configuration_value('allow_required_survey_questions')) {
2538
                if (isset($question->is_required)) {
2539
                    $params['is_required'] = $question->is_required;
2540
                }
2541
            }
2542
2543
            $new_id = Database::insert($table_que, $params);
2544
            if ($new_id) {
2545
                $sql = "UPDATE $table_que SET question_id = iid WHERE iid = $new_id";
2546
                Database::query($sql);
2547
2548
                foreach ($question->answers as $index => $answer) {
2549
                    // check resources inside html from ckeditor tool and copy correct urls into recipient course
2550
                    $answer['option_text'] = DocumentManager::replaceUrlWithNewCourseCode(
2551
                        $answer['option_text'],
2552
                        $this->course->code,
2553
                        $this->course->destination_path,
2554
                        $this->course->backup_path,
2555
                        $this->course->info['path']
2556
                    );
2557
2558
                    $params = [
2559
                        'c_id' => $this->destination_course_id,
2560
                        'question_id' => $new_id,
2561
                        'option_text' => ($answer['option_text'] === false ? '' : self::DBUTF8($answer['option_text'])),
2562
                        'sort' => $answer['sort'],
2563
                        'survey_id' => self::DBUTF8($survey_id),
2564
                    ];
2565
                    $answerId = Database::insert($table_ans, $params);
2566
                    if ($answerId) {
2567
                        $sql = "UPDATE $table_ans SET question_option_id = iid
2568
                                WHERE iid = $answerId";
2569
                        Database::query($sql);
2570
                    }
2571
                }
2572
                $this->course->resources[RESOURCE_SURVEYQUESTION][$id]->destination_id = $new_id;
2573
            }
2574
        }
2575
2576
        return $new_id;
2577
    }
2578
2579
    /**
2580
     * Restoring learning paths.
2581
     *
2582
     * @param int        $session_id
2583
     * @param bool|false $respect_base_content
2584
     */
2585
    public function restore_learnpaths($session_id = 0, $respect_base_content = false)
2586
    {
2587
        $session_id = (int) $session_id;
2588
        if ($this->course->has_resources(RESOURCE_LEARNPATH)) {
2589
            $table_main = Database::get_course_table(TABLE_LP_MAIN);
2590
            $table_item = Database::get_course_table(TABLE_LP_ITEM);
2591
            $table_tool = Database::get_course_table(TABLE_TOOL_LIST);
2592
2593
            $resources = $this->course->resources;
2594
2595
            $origin_path = $this->course->backup_path.'/upload/learning_path/images/';
2596
            $destination_path = api_get_path(SYS_COURSE_PATH).$this->course->destination_path.'/upload/learning_path/images/';
2597
2598
            foreach ($resources[RESOURCE_LEARNPATH] as $id => $lp) {
2599
                $condition_session = '';
2600
                if (!empty($session_id)) {
2601
                    if ($respect_base_content) {
2602
                        $my_session_id = $lp->session_id;
2603
                        if (!empty($lp->session_id)) {
2604
                            $my_session_id = $session_id;
2605
                        }
2606
                        $condition_session = $my_session_id;
2607
                    } else {
2608
                        $session_id = intval($session_id);
2609
                        $condition_session = $session_id;
2610
                    }
2611
                }
2612
2613
                // Adding the author's image
2614
                if (!empty($lp->preview_image)) {
2615
                    $new_filename = uniqid('').substr(
2616
                        $lp->preview_image,
2617
                        strlen($lp->preview_image) - 7,
2618
                        strlen($lp->preview_image)
2619
                    );
2620
                    if (file_exists($origin_path.$lp->preview_image) &&
2621
                        !is_dir($origin_path.$lp->preview_image)
2622
                    ) {
2623
                        $copy_result = copy(
2624
                            $origin_path.$lp->preview_image,
2625
                            $destination_path.$new_filename
2626
                        );
2627
                        if ($copy_result) {
2628
                            $lp->preview_image = $new_filename;
2629
                        } else {
2630
                            $lp->preview_image = '';
2631
                        }
2632
                    }
2633
                }
2634
2635
                if ($this->add_text_in_items) {
2636
                    $lp->name = $lp->name.' '.get_lang('CopyLabelSuffix');
2637
                }
2638
2639
                if (isset($this->tool_copy_settings['learnpaths'])) {
2640
                    if (isset($this->tool_copy_settings['learnpaths']['reset_dates']) &&
2641
                        $this->tool_copy_settings['learnpaths']['reset_dates']
2642
                    ) {
2643
                        $lp->created_on = api_get_utc_datetime();
2644
                        $lp->modified_on = api_get_utc_datetime();
2645
                        $lp->publicated_on = null;
2646
                    }
2647
                }
2648
2649
                $lp->expired_on = isset($lp->expired_on) && $lp->expired_on === '0000-00-00 00:00:00' ? null : $lp->expired_on;
2650
                $lp->publicated_on = isset($lp->publicated_on) && $lp->publicated_on === '0000-00-00 00:00:00' ? null : $lp->publicated_on;
2651
2652
                $params = [
2653
                    'c_id' => $this->destination_course_id,
2654
                    'lp_type' => $lp->lp_type,
2655
                    'name' => self::DBUTF8($lp->name),
2656
                    'path' => self::DBUTF8($lp->path),
2657
                    'ref' => $lp->ref,
2658
                    'description' => self::DBUTF8($lp->description),
2659
                    'content_local' => self::DBUTF8($lp->content_local),
2660
                    'default_encoding' => self::DBUTF8($lp->default_encoding),
2661
                    'default_view_mod' => self::DBUTF8($lp->default_view_mod),
2662
                    'prevent_reinit' => self::DBUTF8($lp->prevent_reinit),
2663
                    'force_commit' => self::DBUTF8($lp->force_commit),
2664
                    'content_maker' => self::DBUTF8($lp->content_maker),
2665
                    'display_order' => self::DBUTF8($lp->display_order),
2666
                    'js_lib' => self::DBUTF8($lp->js_lib),
2667
                    'content_license' => self::DBUTF8($lp->content_license),
2668
                    'author' => self::DBUTF8($lp->author),
2669
                    'preview_image' => self::DBUTF8($lp->preview_image),
2670
                    'use_max_score' => self::DBUTF8($lp->use_max_score),
2671
                    'autolaunch' => self::DBUTF8(isset($lp->autolaunch) ? $lp->autolaunch : ''),
2672
                    'created_on' => self::DBUTF8($lp->created_on),
2673
                    'modified_on' => self::DBUTF8($lp->modified_on),
2674
                    'publicated_on' => empty($lp->publicated_on) ? api_get_utc_datetime() : self::DBUTF8($lp->publicated_on),
2675
                    'expired_on' => self::DBUTF8($lp->expired_on),
2676
                    'debug' => self::DBUTF8($lp->debug),
2677
                    'theme' => '',
2678
                    'session_id' => $session_id,
2679
                    'prerequisite' => 0,
2680
                    'hide_toc_frame' => 0,
2681
                    'seriousgame_mode' => 0,
2682
                    'category_id' => 0,
2683
                    'max_attempts' => 0,
2684
                    'subscribe_users' => 0,
2685
                ];
2686
2687
                if (!empty($condition_session)) {
2688
                    $params['session_id'] = $condition_session;
2689
                }
2690
2691
                $new_lp_id = Database::insert($table_main, $params);
2692
2693
                if ($new_lp_id) {
2694
                    // The following only makes sense if a new LP was
2695
                    // created in the destination course
2696
                    $sql = "UPDATE $table_main SET id = iid WHERE iid = $new_lp_id";
2697
                    Database::query($sql);
2698
2699
                    if ($lp->visibility) {
2700
                        $params = [
2701
                            'c_id' => $this->destination_course_id,
2702
                            'name' => self::DBUTF8($lp->name),
2703
                            'link' => "lp/lp_controller.php?action=view&lp_id=$new_lp_id&id_session=$session_id",
2704
                            'image' => 'scormbuilder.gif',
2705
                            'visibility' => '0',
2706
                            'admin' => '0',
2707
                            'address' => 'squaregrey.gif',
2708
                            'session_id' => $session_id,
2709
                        ];
2710
                        $insertId = Database::insert($table_tool, $params);
2711
                        if ($insertId) {
2712
                            $sql = "UPDATE $table_tool SET id = iid WHERE iid = $insertId";
2713
                            Database::query($sql);
2714
                        }
2715
                    }
2716
2717
                    api_item_property_update(
2718
                        $this->destination_course_info,
2719
                        TOOL_LEARNPATH,
2720
                        $new_lp_id,
2721
                        'LearnpathAdded',
2722
                        api_get_user_id(),
2723
                        0,
2724
                        0,
2725
                        0,
2726
                        0,
2727
                        $session_id
2728
                    );
2729
2730
                    // Set the new LP to visible
2731
                    api_item_property_update(
2732
                        $this->destination_course_info,
2733
                        TOOL_LEARNPATH,
2734
                        $new_lp_id,
2735
                        'invisible',
2736
                        api_get_user_id(),
2737
                        0,
2738
                        0,
2739
                        0,
2740
                        0,
2741
                        $session_id
2742
                    );
2743
2744
                    $new_item_ids = [];
2745
                    $parent_item_ids = [];
2746
                    $previous_item_ids = [];
2747
                    $next_item_ids = [];
2748
                    $old_prerequisite = [];
2749
                    $old_refs = [];
2750
                    $prerequisite_ids = [];
2751
2752
                    foreach ($lp->get_items() as $index => $item) {
2753
                        // we set the ref code here and then we update in a for loop
2754
                        $ref = $item['ref'];
2755
2756
                        // Dealing with path the same way as ref as some data has
2757
                        // been put into path when it's a local resource
2758
                        // Only fix the path for no scos
2759
                        if ($item['item_type'] == 'sco') {
2760
                            $path = $item['path'];
2761
                        } else {
2762
                            $path = $this->get_new_id($item['item_type'], $item['path']);
2763
                        }
2764
2765
                        $item['item_type'] = $item['item_type'] == 'dokeos_chapter' ? 'dir' : $item['item_type'];
2766
2767
                        $params = [
2768
                            'c_id' => $this->destination_course_id,
2769
                            'lp_id' => self::DBUTF8($new_lp_id),
2770
                            'item_type' => self::DBUTF8($item['item_type']),
2771
                            'ref' => self::DBUTF8($ref),
2772
                            'path' => self::DBUTF8($path),
2773
                            'title' => self::DBUTF8($item['title']),
2774
                            'description' => self::DBUTF8($item['description']),
2775
                            'min_score' => self::DBUTF8($item['min_score']),
2776
                            'max_score' => self::DBUTF8($item['max_score']),
2777
                            'mastery_score' => self::DBUTF8($item['mastery_score']),
2778
                            'parent_item_id' => self::DBUTF8($item['parent_item_id']),
2779
                            'previous_item_id' => self::DBUTF8($item['previous_item_id']),
2780
                            'next_item_id' => self::DBUTF8($item['next_item_id']),
2781
                            'display_order' => self::DBUTF8($item['display_order']),
2782
                            'prerequisite' => self::DBUTF8($item['prerequisite']),
2783
                            'parameters' => self::DBUTF8($item['parameters']),
2784
                            'audio' => self::DBUTF8($item['audio']),
2785
                            'launch_data' => self::DBUTF8($item['launch_data']),
2786
                        ];
2787
2788
                        $new_item_id = Database::insert($table_item, $params);
2789
                        if ($new_item_id) {
2790
                            $sql = "UPDATE $table_item SET id = iid WHERE iid = $new_item_id";
2791
                            Database::query($sql);
2792
2793
                            //save a link between old and new item IDs
2794
                            $new_item_ids[$item['id']] = $new_item_id;
2795
                            //save a reference of items that need a parent_item_id refresh
2796
                            $parent_item_ids[$new_item_id] = $item['parent_item_id'];
2797
                            //save a reference of items that need a previous_item_id refresh
2798
                            $previous_item_ids[$new_item_id] = $item['previous_item_id'];
2799
                            //save a reference of items that need a next_item_id refresh
2800
                            $next_item_ids[$new_item_id] = $item['next_item_id'];
2801
2802
                            if (!empty($item['prerequisite'])) {
2803
                                if ($lp->lp_type == '2') {
2804
                                    // if is an sco
2805
                                    $old_prerequisite[$new_item_id] = $item['prerequisite'];
2806
                                } else {
2807
                                    $old_prerequisite[$new_item_id] = isset($new_item_ids[$item['prerequisite']]) ? $new_item_ids[$item['prerequisite']] : '';
2808
                                }
2809
                            }
2810
2811
                            if (!empty($ref)) {
2812
                                if ($lp->lp_type == '2') {
2813
                                    // if is an sco
2814
                                    $old_refs[$new_item_id] = $ref;
2815
                                } elseif (isset($new_item_ids[$ref])) {
2816
                                    $old_refs[$new_item_id] = $new_item_ids[$ref];
2817
                                }
2818
                            }
2819
                            $prerequisite_ids[$new_item_id] = $item['prerequisite'];
2820
                        }
2821
                    }
2822
2823
                    // Updating prerequisites
2824
                    foreach ($old_prerequisite as $key => $my_old_prerequisite) {
2825
                        if ($my_old_prerequisite != '') {
2826
                            $sql = "UPDATE ".$table_item." SET prerequisite = '".$my_old_prerequisite."'
2827
                                    WHERE c_id = ".$this->destination_course_id." AND id = '".$key."'  ";
2828
                            Database::query($sql);
2829
                        }
2830
                    }
2831
2832
                    // Updating refs
2833
                    foreach ($old_refs as $key => $my_old_ref) {
2834
                        if ($my_old_ref != '') {
2835
                            $sql = "UPDATE ".$table_item." SET ref = '".$my_old_ref."'
2836
                                    WHERE c_id = ".$this->destination_course_id." AND id = '".$key."'  ";
2837
                            Database::query($sql);
2838
                        }
2839
                    }
2840
2841
                    foreach ($parent_item_ids as $new_item_id => $parent_item_old_id) {
2842
                        $parent_new_id = 0;
2843
                        if ($parent_item_old_id != 0) {
2844
                            $parent_new_id = $new_item_ids[$parent_item_old_id];
2845
                        }
2846
                        $sql = "UPDATE ".$table_item." SET parent_item_id = '".$parent_new_id."'
2847
                                WHERE c_id = ".$this->destination_course_id." AND id = '".$new_item_id."'";
2848
                        Database::query($sql);
2849
                    }
2850
2851
                    foreach ($previous_item_ids as $new_item_id => $previous_item_old_id) {
2852
                        $previous_new_id = 0;
2853
                        if ($previous_item_old_id != 0) {
2854
                            $previous_new_id = $new_item_ids[$previous_item_old_id];
2855
                        }
2856
                        $sql = "UPDATE ".$table_item." SET previous_item_id = '".$previous_new_id."'
2857
                                WHERE  c_id = ".$this->destination_course_id." AND id = '".$new_item_id."'";
2858
                        Database::query($sql);
2859
                    }
2860
2861
                    foreach ($next_item_ids as $new_item_id => $next_item_old_id) {
2862
                        $next_new_id = 0;
2863
                        if ($next_item_old_id != 0) {
2864
                            $next_new_id = $new_item_ids[$next_item_old_id];
2865
                        }
2866
                        $sql = "UPDATE ".$table_item." SET next_item_id = '".$next_new_id."'
2867
                                WHERE c_id = ".$this->destination_course_id." AND id = '".$new_item_id."'";
2868
                        Database::query($sql);
2869
                    }
2870
2871
                    foreach ($prerequisite_ids as $new_item_id => $prerequisite_old_id) {
2872
                        $prerequisite_new_id = 0;
2873
                        if ($prerequisite_old_id != 0) {
2874
                            $prerequisite_new_id = $new_item_ids[$prerequisite_old_id];
2875
                        }
2876
                        $sql = "UPDATE ".$table_item." SET prerequisite = '".$prerequisite_new_id."'
2877
                                WHERE c_id = ".$this->destination_course_id." AND id = '".$new_item_id."'";
2878
                        Database::query($sql);
2879
                    }
2880
                    $this->course->resources[RESOURCE_LEARNPATH][$id]->destination_id = $new_lp_id;
2881
                }
2882
            }
2883
        }
2884
    }
2885
2886
    /**
2887
     * Copy all directory and sub directory.
2888
     *
2889
     * @param string $source The path origin
2890
     * @param string $dest   The path destination
2891
     * @param bool Option Overwrite
2892
     *
2893
     * @deprecated
2894
     */
2895
    public function allow_create_all_directory($source, $dest, $overwrite = false)
2896
    {
2897
        if (!is_dir($dest)) {
2898
            mkdir($dest, api_get_permissions_for_new_directories());
2899
        }
2900
        if ($handle = opendir($source)) {
2901
            // if the folder exploration is sucsessful, continue
2902
            while (false !== ($file = readdir($handle))) {
2903
                // as long as storing the next file to $file is successful, continue
2904
                if ($file != '.' && $file != '..') {
2905
                    $path = $source.'/'.$file;
2906
                    if (is_file($path)) {
0 ignored issues
show
Unused Code introduced by
This if statement is empty and can be removed.

This check looks for the bodies of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These if bodies can be removed. If you have an empty if but statements in the else branch, consider inverting the condition.

if (rand(1, 6) > 3) {
//print "Check failed";
} else {
    print "Check succeeded";
}

could be turned into

if (rand(1, 6) <= 3) {
    print "Check succeeded";
}

This is much more concise to read.

Loading history...
2907
                        /* if (!is_file($dest . '/' . $file) || $overwrite)
2908
                         if (!@copy($path, $dest . '/' . $file)) {
2909
                             echo '<font color="red">File ('.$path.') '.get_lang('NotHavePermission').'</font>';
2910
                         }*/
2911
                    } elseif (is_dir($path)) {
2912
                        if (!is_dir($dest.'/'.$file)) {
2913
                            mkdir($dest.'/'.$file);
2914
                        }
2915
                        self:: allow_create_all_directory($path, $dest.'/'.$file, $overwrite);
2916
                    }
2917
                }
2918
            }
2919
            closedir($handle);
2920
        }
2921
    }
2922
2923
    /**
2924
     * Gets the new ID of one specific tool item from the tool name and the old ID.
2925
     *
2926
     * @param	string	Tool name
2927
     * @param	int	Old ID
2928
     *
2929
     * @return int New ID
2930
     */
2931
    public function get_new_id($tool, $ref)
2932
    {
2933
        // Check if the value exist in the current array.
2934
        if ($tool === 'hotpotatoes') {
2935
            $tool = 'document';
2936
        }
2937
2938
        if ($tool === 'student_publication') {
2939
            $tool = RESOURCE_WORK;
2940
        }
2941
2942
        if (isset($this->course->resources[$tool][$ref]) &&
2943
            isset($this->course->resources[$tool][$ref]->destination_id) &&
2944
            !empty($this->course->resources[$tool][$ref]->destination_id)
2945
        ) {
2946
            return $this->course->resources[$tool][$ref]->destination_id;
2947
        }
2948
2949
        // Check if the course is the same (last hope).
2950
        if ($this->course_origin_id == $this->destination_course_id) {
2951
            return $ref;
2952
        }
2953
2954
        return '';
2955
    }
2956
2957
    /**
2958
     * Restore glossary.
2959
     */
2960
    public function restore_glossary($session_id = 0)
2961
    {
2962
        if ($this->course->has_resources(RESOURCE_GLOSSARY)) {
2963
            $table_glossary = Database::get_course_table(TABLE_GLOSSARY);
2964
            $resources = $this->course->resources;
2965
            foreach ($resources[RESOURCE_GLOSSARY] as $id => $glossary) {
2966
                $params = [];
2967
                if (!empty($session_id)) {
2968
                    $session_id = intval($session_id);
2969
                    $params['session_id'] = $session_id;
2970
                }
2971
2972
                // check resources inside html from ckeditor tool and copy correct urls into recipient course
2973
                $glossary->description = DocumentManager::replaceUrlWithNewCourseCode(
2974
                    $glossary->description,
2975
                    $this->course->code,
2976
                    $this->course->destination_path,
2977
                    $this->course->backup_path,
2978
                    $this->course->info['path']
2979
                );
2980
2981
                $params['c_id'] = $this->destination_course_id;
2982
                $params['description'] = ($glossary->description === false ? '' : self::DBUTF8($glossary->description));
2983
                $params['display_order'] = $glossary->display_order;
2984
                $params['name'] = self::DBUTF8($glossary->name);
2985
                $params['glossary_id'] = 0;
2986
                $my_id = Database::insert($table_glossary, $params);
2987
                if ($my_id) {
2988
                    $sql = "UPDATE $table_glossary SET glossary_id = iid WHERE iid = $my_id";
2989
                    Database::query($sql);
2990
2991
                    api_item_property_update(
2992
                        $this->destination_course_info,
2993
                        TOOL_GLOSSARY,
2994
                        $my_id,
2995
                        'GlossaryAdded',
2996
                        api_get_user_id()
2997
                    );
2998
2999
                    if (!isset($this->course->resources[RESOURCE_GLOSSARY][$id])) {
3000
                        $this->course->resources[RESOURCE_GLOSSARY][$id] = new stdClass();
3001
                    }
3002
3003
                    $this->course->resources[RESOURCE_GLOSSARY][$id]->destination_id = $my_id;
3004
                }
3005
            }
3006
        }
3007
    }
3008
3009
    /**
3010
     * @param int $session_id
3011
     */
3012
    public function restore_wiki($session_id = 0)
3013
    {
3014
        if ($this->course->has_resources(RESOURCE_WIKI)) {
3015
            // wiki table of the target course
3016
            $table_wiki = Database::get_course_table(TABLE_WIKI);
3017
            $table_wiki_conf = Database::get_course_table(TABLE_WIKI_CONF);
3018
3019
            // storing all the resources that have to be copied in an array
3020
            $resources = $this->course->resources;
3021
3022
            foreach ($resources[RESOURCE_WIKI] as $id => $wiki) {
3023
                // the sql statement to insert the groups from the old course to the new course
3024
                // check resources inside html from ckeditor tool and copy correct urls into recipient course
3025
                $wiki->content = DocumentManager::replaceUrlWithNewCourseCode(
3026
                    $wiki->content,
3027
                    $this->course->code,
3028
                    $this->course->destination_path,
3029
                    $this->course->backup_path,
3030
                    $this->course->info['path']
3031
                );
3032
3033
                $params = [
3034
                    'c_id' => $this->destination_course_id,
3035
                    'page_id' => self::DBUTF8($wiki->page_id),
3036
                    'reflink' => self::DBUTF8($wiki->reflink),
3037
                    'title' => self::DBUTF8($wiki->title),
3038
                    'content' => ($wiki->content === false ? '' : self::DBUTF8($wiki->content)),
3039
                    'user_id' => intval($wiki->user_id),
3040
                    'group_id' => intval($wiki->group_id),
3041
                    'dtime' => self::DBUTF8($wiki->dtime),
3042
                    'progress' => self::DBUTF8($wiki->progress),
3043
                    'version' => intval($wiki->version),
3044
                    'session_id' => !empty($session_id) ? intval($session_id) : 0,
3045
                    'addlock' => 0,
3046
                    'editlock' => 0,
3047
                    'visibility' => 0,
3048
                    'addlock_disc' => 0,
3049
                    'visibility_disc' => 0,
3050
                    'ratinglock_disc' => 0,
3051
                    'assignment' => 0,
3052
                    'comment' => '',
3053
                    'is_editing' => 0,
3054
                    'linksto' => 0,
3055
                    'tag' => '',
3056
                    'user_ip' => '',
3057
                ];
3058
3059
                $new_id = Database::insert($table_wiki, $params);
3060
3061
                if ($new_id) {
3062
                    $sql = "UPDATE $table_wiki SET page_id = '$new_id', id = iid
3063
                            WHERE c_id = ".$this->destination_course_id." AND iid = '$new_id'";
3064
                    Database::query($sql);
3065
3066
                    $this->course->resources[RESOURCE_WIKI][$id]->destination_id = $new_id;
3067
3068
                    // we also add an entry in wiki_conf
3069
                    $params = [
3070
                        'c_id' => $this->destination_course_id,
3071
                        'page_id' => $new_id,
3072
                        'task' => '',
3073
                        'feedback1' => '',
3074
                        'feedback2' => '',
3075
                        'feedback3' => '',
3076
                        'fprogress1' => '',
3077
                        'fprogress2' => '',
3078
                        'fprogress3' => '',
3079
                        'max_size' => 0,
3080
                        'max_text' => 0,
3081
                        'max_version' => 0,
3082
                        'startdate_assig' => null,
3083
                        'enddate_assig' => null,
3084
                        'delayedsubmit' => 0,
3085
                    ];
3086
3087
                    Database::insert($table_wiki_conf, $params);
3088
                }
3089
            }
3090
        }
3091
    }
3092
3093
    /**
3094
     * Restore Thematics.
3095
     *
3096
     * @param int $session_id
3097
     */
3098
    public function restore_thematic($session_id = 0)
3099
    {
3100
        if ($this->course->has_resources(RESOURCE_THEMATIC)) {
3101
            $table_thematic = Database::get_course_table(TABLE_THEMATIC);
3102
            $table_thematic_advance = Database::get_course_table(TABLE_THEMATIC_ADVANCE);
3103
            $table_thematic_plan = Database::get_course_table(TABLE_THEMATIC_PLAN);
3104
3105
            $resources = $this->course->resources;
3106
            foreach ($resources[RESOURCE_THEMATIC] as $id => $thematic) {
3107
                // check resources inside html from ckeditor tool and copy correct urls into recipient course
3108
                $thematic->params['content'] = DocumentManager::replaceUrlWithNewCourseCode(
3109
                    $thematic->params['content'],
3110
                    $this->course->code,
3111
                    $this->course->destination_path,
3112
                    $this->course->backup_path,
3113
                    $this->course->info['path']
3114
                );
3115
                $thematic->params['c_id'] = $this->destination_course_id;
3116
                unset($thematic->params['id']);
3117
                unset($thematic->params['iid']);
3118
3119
                $last_id = Database::insert($table_thematic, $thematic->params, false);
3120
3121
                if ($last_id) {
3122
                    $sql = "UPDATE $table_thematic SET id = iid WHERE iid = $last_id";
3123
                    Database::query($sql);
3124
3125
                    api_item_property_update(
3126
                        $this->destination_course_info,
3127
                        'thematic',
3128
                        $last_id,
3129
                        "ThematicAdded",
3130
                        api_get_user_id()
3131
                    );
3132
3133
                    foreach ($thematic->thematic_advance_list as $thematic_advance) {
3134
                        unset($thematic_advance['id']);
3135
                        unset($thematic_advance['iid']);
3136
                        $thematic_advance['attendance_id'] = 0;
3137
                        $thematic_advance['thematic_id'] = $last_id;
3138
                        $thematic_advance['c_id'] = $this->destination_course_id;
3139
3140
                        $my_id = Database::insert(
3141
                            $table_thematic_advance,
3142
                            $thematic_advance,
3143
                            false
3144
                        );
3145
3146
                        if ($my_id) {
3147
                            $sql = "UPDATE $table_thematic_advance SET id = iid WHERE iid = $my_id";
3148
                            Database::query($sql);
3149
3150
                            api_item_property_update(
3151
                                $this->destination_course_info,
3152
                                'thematic_advance',
3153
                                $my_id,
3154
                                'ThematicAdvanceAdded',
3155
                                api_get_user_id()
3156
                            );
3157
                        }
3158
                    }
3159
3160
                    foreach ($thematic->thematic_plan_list as $thematic_plan) {
3161
                        unset($thematic_plan['id']);
3162
                        unset($thematic_plan['iid']);
3163
                        $thematic_plan['thematic_id'] = $last_id;
3164
                        $thematic_plan['c_id'] = $this->destination_course_id;
3165
                        $my_id = Database::insert($table_thematic_plan, $thematic_plan, false);
3166
3167
                        if ($my_id) {
3168
                            $sql = "UPDATE $table_thematic_plan SET id = iid WHERE iid = $my_id";
3169
                            Database::query($sql);
3170
3171
                            api_item_property_update(
3172
                                $this->destination_course_info,
3173
                                'thematic_plan',
3174
                                $my_id,
3175
                                'ThematicPlanAdded',
3176
                                api_get_user_id()
3177
                            );
3178
                        }
3179
                    }
3180
                }
3181
            }
3182
        }
3183
    }
3184
3185
    /**
3186
     * Restore Attendance.
3187
     *
3188
     * @param int $session_id
3189
     */
3190
    public function restore_attendance($session_id = 0)
3191
    {
3192
        if ($this->course->has_resources(RESOURCE_ATTENDANCE)) {
3193
            $table_attendance = Database::get_course_table(TABLE_ATTENDANCE);
3194
            $table_attendance_calendar = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR);
3195
3196
            $resources = $this->course->resources;
3197
            foreach ($resources[RESOURCE_ATTENDANCE] as $id => $obj) {
3198
                // check resources inside html from ckeditor tool and copy correct urls into recipient course
3199
                $obj->params['description'] = DocumentManager::replaceUrlWithNewCourseCode(
3200
                    $obj->params['description'],
3201
                    $this->course->code,
3202
                    $this->course->destination_path,
3203
                    $this->course->backup_path,
3204
                    $this->course->info['path']
3205
                );
3206
3207
                unset($obj->params['id']);
3208
                unset($obj->params['iid']);
3209
                $obj->params['c_id'] = $this->destination_course_id;
3210
                $last_id = Database::insert($table_attendance, $obj->params);
3211
3212
                if (is_numeric($last_id)) {
3213
                    $sql = "UPDATE $table_attendance SET id = iid WHERE iid = $last_id";
3214
                    Database::query($sql);
3215
3216
                    $this->course->resources[RESOURCE_ATTENDANCE][$id]->destination_id = $last_id;
3217
3218
                    api_item_property_update(
3219
                        $this->destination_course_info,
3220
                        TOOL_ATTENDANCE,
3221
                        $last_id,
3222
                        "AttendanceAdded",
3223
                        api_get_user_id()
3224
                    );
3225
3226
                    foreach ($obj->attendance_calendar as $attendance_calendar) {
3227
                        unset($attendance_calendar['id']);
3228
                        unset($attendance_calendar['iid']);
3229
3230
                        $attendance_calendar['attendance_id'] = $last_id;
3231
                        $attendance_calendar['c_id'] = $this->destination_course_id;
3232
                        $attendanceCalendarId = Database::insert(
3233
                            $table_attendance_calendar,
3234
                            $attendance_calendar
3235
                        );
3236
3237
                        $sql = "UPDATE $table_attendance_calendar SET id = iid WHERE iid = $attendanceCalendarId";
3238
                        Database::query($sql);
3239
                    }
3240
                }
3241
            }
3242
        }
3243
    }
3244
3245
    /**
3246
     * Restore Works.
3247
     *
3248
     * @param int $sessionId
3249
     */
3250
    public function restore_works($sessionId = 0)
3251
    {
3252
        require_once api_get_path(SYS_CODE_PATH).'work/work.lib.php';
3253
        if ($this->course->has_resources(RESOURCE_WORK)) {
3254
            $table = Database::get_course_table(TABLE_STUDENT_PUBLICATION_ASSIGNMENT);
3255
3256
            $resources = $this->course->resources;
3257
            foreach ($resources[RESOURCE_WORK] as $obj) {
3258
                // check resources inside html from ckeditor tool and copy correct urls into recipient course
3259
                $obj->params['description'] = DocumentManager::replaceUrlWithNewCourseCode(
3260
                    $obj->params['description'],
3261
                    $this->course->code,
3262
                    $this->course->destination_path,
3263
                    $this->course->backup_path,
3264
                    $this->course->info['path']
3265
                );
3266
3267
                $id_work = $obj->params['id'];
3268
                $obj->params['id'] = null;
3269
                $obj->params['c_id'] = $this->destination_course_info['real_id'];
3270
3271
                // re-create dir
3272
                // @todo check security against injection of dir in crafted course backup here!
3273
                $path = $obj->params['url'];
3274
                $path = '/'.str_replace('/', '', substr($path, 1));
3275
3276
                $workData = [];
3277
3278
                switch ($this->file_option) {
3279
                    case FILE_SKIP:
3280
                        $workData = get_work_data_by_path(
3281
                            $path,
3282
                            $this->destination_course_info['real_id']
3283
                        );
3284
                        if (!empty($workData)) {
3285
                            continue;
3286
                        }
3287
                        break;
3288
                    case FILE_OVERWRITE:
3289
                        if (!empty($this->course_origin_id)) {
3290
                            $sql = 'SELECT * FROM '.$table.'
3291
                                    WHERE
3292
                                        c_id = '.$this->course_origin_id.' AND
3293
                                        publication_id = '.$id_work;
3294
                            $result = Database::query($sql);
3295
                            $cant = Database::num_rows($result);
3296
                            if ($cant > 0) {
3297
                                $row = Database::fetch_assoc($result);
3298
                            }
3299
3300
                            $obj->params['enableExpiryDate'] = empty($row['expires_on']) ? false : true;
3301
                            $obj->params['enableEndDate'] = empty($row['ends_on']) ? false : true;
3302
                            $obj->params['expires_on'] = $row['expires_on'];
3303
                            $obj->params['ends_on'] = $row['ends_on'];
3304
                            $obj->params['enable_qualification'] = $row['enable_qualification'];
3305
                            $obj->params['add_to_calendar'] = !empty($row['add_to_calendar']) ? 1 : 0;
3306
                        }
3307
                        //no break
3308
                    case FILE_RENAME:
3309
                        $workData = get_work_data_by_path(
3310
                            $path,
3311
                            $this->destination_course_info['real_id']
3312
                        );
3313
                        break;
3314
                }
3315
3316
                $obj->params['work_title'] = $obj->params['title'];
3317
                $obj->params['new_dir'] = $obj->params['title'];
3318
3319
                if (empty($workData)) {
3320
                    $workId = addDir(
3321
                        $obj->params,
3322
                        api_get_user_id(),
3323
                        $this->destination_course_info,
3324
                        0,
3325
                        $sessionId
3326
                    );
3327
                    $this->course->resources[RESOURCE_WORK][$id_work]->destination_id = $workId;
3328
                } else {
3329
                    $workId = $workData['iid'];
3330
                    updateWork(
3331
                        $workId,
3332
                        $obj->params,
3333
                        $this->destination_course_info,
3334
                        $sessionId
3335
                    );
3336
                    updatePublicationAssignment(
3337
                        $workId,
3338
                        $obj->params,
3339
                        $this->destination_course_info,
3340
                        0
3341
                    );
3342
                    $this->course->resources[RESOURCE_WORK][$id_work]->destination_id = $workId;
3343
                }
3344
            }
3345
        }
3346
    }
3347
3348
    /**
3349
     * Restore gradebook.
3350
     *
3351
     * @param int $sessionId
3352
     *
3353
     * @return bool
3354
     */
3355
    public function restore_gradebook($sessionId = 0)
3356
    {
3357
        if (in_array($this->file_option, [FILE_SKIP, FILE_RENAME])) {
3358
            return false;
3359
        }
3360
        // if overwrite
3361
        if ($this->course->has_resources(RESOURCE_GRADEBOOK)) {
3362
            $resources = $this->course->resources;
3363
            $destinationCourseCode = $this->destination_course_info['code'];
3364
            // Delete destination gradebook
3365
            $cats = \Category:: load(
3366
                null,
3367
                null,
3368
                $destinationCourseCode,
3369
                null,
3370
                null,
3371
                $sessionId
3372
            );
3373
3374
            if (!empty($cats)) {
3375
                /** @var \Category $cat */
3376
                foreach ($cats as $cat) {
3377
                    $cat->delete_all();
3378
                }
3379
            }
3380
3381
            /** @var GradeBookBackup $obj */
3382
            foreach ($resources[RESOURCE_GRADEBOOK] as $id => $obj) {
3383
                if (!empty($obj->categories)) {
3384
                    $categoryIdList = [];
3385
                    /** @var \Category $cat */
3386
                    foreach ($obj->categories as $cat) {
3387
                        $cat->set_course_code($destinationCourseCode);
3388
                        $cat->set_session_id($sessionId);
3389
3390
                        $parentId = $cat->get_parent_id();
3391
                        if (!empty($parentId)) {
3392
                            if (isset($categoryIdList[$parentId])) {
3393
                                $cat->set_parent_id($categoryIdList[$parentId]);
3394
                            }
3395
                        }
3396
                        $oldId = $cat->get_id();
3397
                        $categoryId = $cat->add();
3398
                        $categoryIdList[$oldId] = $categoryId;
3399
                        if (!empty($cat->evaluations)) {
3400
                            /** @var \Evaluation $evaluation */
3401
                            foreach ($cat->evaluations as $evaluation) {
3402
                                $evaluation->set_category_id($categoryId);
3403
                                $evaluation->set_course_code($destinationCourseCode);
3404
                                $evaluation->setSessionId($sessionId);
3405
                                $evaluation->add();
3406
                            }
3407
                        }
3408
3409
                        if (!empty($cat->links)) {
3410
                            /** @var \AbstractLink $link */
3411
                            foreach ($cat->links as $link) {
3412
                                $link->set_category_id($categoryId);
3413
                                $link->set_course_code($destinationCourseCode);
3414
                                $link->set_session_id($sessionId);
3415
                                $import = false;
3416
                                $itemId = $link->get_ref_id();
3417
                                switch ($link->get_type()) {
3418
                                    case LINK_EXERCISE:
3419
                                        $type = RESOURCE_QUIZ;
3420
                                        break;
3421
                                    /*case LINK_DROPBOX:
3422
                                        break;*/
3423
                                    case LINK_STUDENTPUBLICATION:
3424
                                        $type = RESOURCE_WORK;
3425
                                        break;
3426
                                    case LINK_LEARNPATH:
3427
                                        $type = RESOURCE_LEARNPATH;
3428
                                        break;
3429
                                    case LINK_FORUM_THREAD:
3430
                                        $type = RESOURCE_FORUMTOPIC;
3431
                                        break;
3432
                                    case LINK_ATTENDANCE:
3433
                                        $type = RESOURCE_ATTENDANCE;
3434
                                        break;
3435
                                    case LINK_SURVEY:
3436
                                        $type = RESOURCE_ATTENDANCE;
3437
                                        break;
3438
                                    case LINK_HOTPOTATOES:
3439
                                        $type = RESOURCE_QUIZ;
3440
                                        break;
3441
                                }
3442
3443
                                if ($this->course->has_resources($type) &&
3444
                                    isset($this->course->resources[$type][$itemId])
3445
                                ) {
3446
                                    $item = $this->course->resources[$type][$itemId];
3447
                                    if ($item && $item->is_restored()) {
3448
                                        $link->set_ref_id($item->destination_id);
3449
                                        $import = true;
3450
                                    }
3451
                                }
3452
3453
                                if ($import) {
3454
                                    $link->add();
3455
                                }
3456
                            }
3457
                        }
3458
                    }
3459
                }
3460
            }
3461
        }
3462
    }
3463
3464
    /**
3465
     * Restore course assets (not included in documents).
3466
     */
3467
    public function restore_assets()
3468
    {
3469
        if ($this->course->has_resources(RESOURCE_ASSET)) {
3470
            $resources = $this->course->resources;
3471
            $path = api_get_path(SYS_COURSE_PATH).$this->course->destination_path.'/';
3472
3473
            foreach ($resources[RESOURCE_ASSET] as $asset) {
3474
                if (is_file($this->course->backup_path.'/'.$asset->path) &&
3475
                    is_readable($this->course->backup_path.'/'.$asset->path) &&
3476
                    is_dir(dirname($path.$asset->path)) &&
3477
                    is_writeable(dirname($path.$asset->path))
3478
                ) {
3479
                    switch ($this->file_option) {
3480
                        case FILE_SKIP:
3481
                            continue;
3482
                        case FILE_OVERWRITE:
3483
                            copy(
3484
                                $this->course->backup_path.'/'.$asset->path,
3485
                                $path.$asset->path
3486
                            );
3487
                            break;
3488
                    }
3489
                }
3490
            }
3491
        }
3492
    }
3493
3494
    /**
3495
     * @param string $str
3496
     *
3497
     * @return string
3498
     */
3499
    public function DBUTF8($str)
3500
    {
3501
        if (UTF8_CONVERT) {
3502
            $str = utf8_encode($str);
3503
        }
3504
3505
        return $str;
3506
    }
3507
3508
    /**
3509
     * @param string $str
3510
     *
3511
     * @return string
3512
     */
3513
    public function DBUTF8escapestring($str)
3514
    {
3515
        if (UTF8_CONVERT) {
3516
            $str = utf8_encode($str);
3517
        }
3518
3519
        return Database::escape_string($str);
3520
    }
3521
3522
    /**
3523
     * @param array $array
3524
     *
3525
     * @return mixed
3526
     */
3527
    public function DBUTF8_array($array)
3528
    {
3529
        if (UTF8_CONVERT) {
3530
            foreach ($array as &$item) {
3531
                $item = utf8_encode($item);
3532
            }
3533
3534
            return $array;
3535
        } else {
3536
            return $array;
3537
        }
3538
    }
3539
3540
    /**
3541
     * @param int $groupId
3542
     *
3543
     * @return array
3544
     */
3545
    public function checkGroupId($groupId)
3546
    {
3547
        return \GroupManager::get_group_properties($groupId);
3548
    }
3549
3550
    /**
3551
     * @param string $documentPath
3552
     * @param string $webEditorCss
3553
     */
3554
    public function fixEditorHtmlContent($documentPath, $webEditorCss = '')
3555
    {
3556
        $extension = pathinfo(basename($documentPath), PATHINFO_EXTENSION);
3557
3558
        switch ($extension) {
3559
            case 'html':
3560
            case 'htm':
3561
                $contents = file_get_contents($documentPath);
3562
                $contents = str_replace(
3563
                    '{{css_editor}}',
3564
                    $webEditorCss,
3565
                    $contents
3566
                );
3567
                file_put_contents($documentPath, $contents);
3568
                break;
3569
        }
3570
    }
3571
3572
    /**
3573
     * Check if user exist otherwise use current user.
3574
     *
3575
     * @param int  $userId
3576
     * @param bool $returnNull
3577
     *
3578
     * @return int
3579
     */
3580
    private function checkUserId($userId, $returnNull = false)
3581
    {
3582
        if (!empty($userId)) {
3583
            $userInfo = api_get_user_info($userId);
3584
            if (empty($userInfo)) {
3585
                return api_get_user_id();
3586
            }
3587
        }
3588
3589
        if ($returnNull) {
3590
            return null;
3591
        }
3592
3593
        if (empty($userId)) {
3594
            return api_get_user_id();
3595
        }
3596
3597
        return $userId;
3598
    }
3599
}
3600