Completed
Push — master ( 27e209...a08afa )
by Julito
186:04 queued 150:53
created

CourseRestorer::restore_quizzes()   F

Complexity

Conditions 23
Paths > 20000

Size

Total Lines 123
Code Lines 89

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 23
eloc 89
nc 24602
nop 2
dl 0
loc 123
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 DocumentManager;
10
use Database;
11
use CourseManager;
12
use stdClass;
13
use TestCategory;
14
use SurveyManager;
15
use Question;
16
17
/**
18
 * Class CourseRestorer
19
 *
20
 * Class to restore items from a course object to a Chamilo-course
21
 * @author Bart Mollet <[email protected]>
22
 * @author Julio Montoya <[email protected]> Several fixes/improvements
23
 * @package chamilo.backup
24
 */
25
class CourseRestorer
26
{
27
    /**
28
    * The course-object
29
    */
30
    public $course;
31
    public $destination_course_info;
32
33
    /**
34
     * What to do with files with same name (FILE_SKIP, FILE_RENAME or
35
     * FILE_OVERWRITE)
36
     */
37
    public $file_option;
38
    public $set_tools_invisible_by_default;
39
    public $skip_content;
40
    public $tools_to_restore = [
41
        'documents', // first restore documents
42
        'announcements',
43
        'attendance',
44
        'course_descriptions',
45
        'events',
46
        'forum_category',
47
        'forums',
48
       // 'forum_topics',
49
        'glossary',
50
        'quizzes',
51
        'test_category',
52
        'links',
53
        'learnpaths',
54
        'surveys',
55
        //'scorm_documents', ??
56
        'tool_intro',
57
        'thematic',
58
        'wiki',
59
        'works',
60
        'gradebook',
61
        'assets',
62
    ];
63
64
    /** Setting per tool */
65
    public $tool_copy_settings = [];
66
67
    /**
68
     * If true adds the text "copy" in the title of an item (only for LPs right now)
69
     **/
70
    public $add_text_in_items = false;
71
    public $destination_course_id;
72
73
    /**
74
     * CourseRestorer constructor.
75
     * @param Course $course
76
     */
77
    public function __construct($course)
78
    {
79
        $this->course = $course;
80
        $courseInfo = api_get_course_info($this->course->code);
81
        if (!empty($courseInfo)) {
82
            $this->course_origin_id = $courseInfo['real_id'];
0 ignored issues
show
Bug Best Practice introduced by
The property course_origin_id does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
83
        } else {
84
            $this->course_origin_id = null;
85
        }
86
        $this->file_option = FILE_RENAME;
87
        $this->set_tools_invisible_by_default = false;
88
        $this->skip_content = [];
89
    }
90
91
    /**
92
     * Set the file-option
93
     * @param int $option (optional) What to do with files with same name
94
     * FILE_SKIP, FILE_RENAME or FILE_OVERWRITE
95
     */
96
    public function set_file_option($option = FILE_OVERWRITE)
97
    {
98
        $this->file_option = $option;
99
    }
100
101
    /**
102
     * @param bool $status
103
     */
104
    public function set_add_text_in_items($status)
105
    {
106
        $this->add_text_in_items = $status;
107
    }
108
109
    /**
110
     * @param array $array
111
     */
112
    public function set_tool_copy_settings($array)
113
    {
114
        $this->tool_copy_settings = $array;
115
    }
116
117
    /**
118
     * Restore a course.
119
     *
120
     * @param string $destination_course_code code of the Chamilo-course in
121
     * @param int $session_id
122
     * @param bool $update_course_settings Course settings are going to be restore?
123
     * @param bool $respect_base_content
124
     * @return false|null
125
     */
126
    public function restore(
127
        $destination_course_code = '',
128
        $session_id = 0,
129
        $update_course_settings = false,
130
        $respect_base_content = false
131
    ) {
132
        if ($destination_course_code == '') {
133
            $course_info = api_get_course_info();
134
            $this->destination_course_info = $course_info;
135
            $this->course->destination_path = $course_info['path'];
136
        } else {
137
            $course_info = api_get_course_info($destination_course_code);
138
            $this->destination_course_info = $course_info;
139
            $this->course->destination_path = $course_info['path'];
140
        }
141
        $this->destination_course_id = $course_info['real_id'];
142
143
        //Getting first teacher (for the forums)
144
        $teacher_list = CourseManager::get_teacher_list_from_course_code(
145
            $course_info['code']
146
        );
147
        $this->first_teacher_id = api_get_user_id();
0 ignored issues
show
Bug Best Practice introduced by
The property first_teacher_id does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
148
149
        if (!empty($teacher_list)) {
150
            foreach ($teacher_list as $teacher) {
151
                $this->first_teacher_id = $teacher['user_id'];
152
                break;
153
            }
154
        }
155
156
        if (empty($this->course)) {
157
            return false;
158
        }
159
160
        // Source platform encoding - reading/detection
161
        // The correspondent data field has been added as of version 1.8.6.1
162
        if (empty($this->course->encoding)) {
163
            // The archive has been created by a system which is prior to 1.8.6.1 version.
164
            // In this case we have to detect the encoding.
165
            $sample_text = $this->course->get_sample_text()."\n";
166
            // Let us exclude ASCII lines, probably they are English texts.
167
            $sample_text = explode("\n", $sample_text);
168
            foreach ($sample_text as $key => &$line) {
169
                if (api_is_valid_ascii($line)) {
170
                    unset($sample_text[$key]);
171
                }
172
            }
173
            $sample_text = implode("\n", $sample_text);
174
            $this->course->encoding = api_detect_encoding(
175
                $sample_text,
176
                $course_info['language']
177
            );
178
        }
179
180
        // Encoding conversion of the course, if it is needed.
181
        $this->course->to_system_encoding();
182
183
        foreach ($this->tools_to_restore as $tool) {
184
            $function_build = 'restore_'.$tool;
185
            $this->$function_build(
186
                $session_id,
187
                $respect_base_content,
188
                $destination_course_code
189
            );
190
        }
191
192
        if ($update_course_settings) {
193
            $this->restore_course_settings($destination_course_code);
194
        }
195
196
        // Restore the item properties
197
        $table = Database::get_course_table(TABLE_ITEM_PROPERTY);
198
199
        foreach ($this->course->resources as $type => $resources) {
200
            if (is_array($resources)) {
201
                foreach ($resources as $id => $resource) {
202
                    if (isset($resource->item_properties)) {
203
                        foreach ($resource->item_properties as $property) {
204
                            // First check if there isn't already a record for this resource
205
                            $sql = "SELECT * FROM $table
206
                                    WHERE
207
                                        c_id = ".$this->destination_course_id." AND
208
                                        tool = '".$property['tool']."' AND
209
                                        ref = '".$resource->destination_id."'";
210
211
                            $params = [];
212
                            if (!empty($session_id)) {
213
                                $params['session_id'] = intval($session_id);
214
                            }
215
216
                            $res = Database::query($sql);
217
                            if (Database::num_rows($res) == 0) {
218
                                /* The to_group_id and to_user_id are set to default
219
                                values as users/groups possibly not exist in
220
                                the target course*/
221
222
                                $params['c_id'] = $this->destination_course_id;
223
                                $params['tool'] = self::DBUTF8($property['tool']);
0 ignored issues
show
Bug Best Practice introduced by
The method Chamilo\CourseBundle\Com...ourseRestorer::DBUTF8() is not static, but was called statically. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

223
                                /** @scrutinizer ignore-call */ 
224
                                $params['tool'] = self::DBUTF8($property['tool']);
Loading history...
224
                                $params['insert_user_id'] = $this->checkUserId($property['insert_user_id']);
225
                                $params['insert_date'] = self::DBUTF8($property['insert_date']);
226
                                $params['lastedit_date'] = self::DBUTF8($property['lastedit_date']);
227
                                $params['ref'] = $resource->destination_id;
228
                                $params['lastedit_type'] = self::DBUTF8($property['lastedit_type']);
229
                                $params['lastedit_user_id'] = $this->checkUserId($property['lastedit_user_id']);
230
                                $params['visibility'] = self::DBUTF8($property['visibility']);
231
                                $params['start_visible'] = self::DBUTF8($property['start_visible']);
232
                                $params['end_visible'] = self::DBUTF8($property['end_visible']);
233
                                $params['to_user_id'] = $this->checkUserId($property['to_user_id']);
234
235
                                $id = Database::insert($table, $params);
236
                                if ($id) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $id of type integer|false is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
237
                                    $sql = "UPDATE $table SET id = iid WHERE iid = $id";
238
                                    Database::query($sql);
239
                                }
240
                            }
241
                        }
242
                    }
243
                }
244
            }
245
        }
246
    }
247
248
    /**
249
     * Restore only harmless course settings:
250
     * course_language, visibility, department_name,department_url,
251
     * subscribe, unsubscribe ,category_code
252
     *
253
     * @param string $destination_course_code
254
     */
255
    public function restore_course_settings($destination_course_code)
256
    {
257
        $origin_course_info = api_get_course_info($destination_course_code);
258
        $course_info = $this->course->info;
0 ignored issues
show
Bug introduced by
The property info does not seem to exist on Chamilo\CourseBundle\Component\CourseCopy\Course.
Loading history...
259
        $params['course_language'] = $course_info['language'];
0 ignored issues
show
Comprehensibility Best Practice introduced by
$params was never initialized. Although not strictly required by PHP, it is generally a good practice to add $params = array(); before regardless.
Loading history...
260
        $params['visibility'] = $course_info['visibility'];
261
        $params['department_name'] = $course_info['department_name'];
262
        $params['department_url'] = $course_info['department_url'];
263
        $params['category_code'] = $course_info['categoryCode'];
264
        $params['subscribe'] = $course_info['subscribe_allowed'];
265
        $params['unsubscribe'] = $course_info['unsubscribe'];
266
        CourseManager::update_attributes($origin_course_info['real_id'], $params);
267
    }
268
269
    /**
270
     * Restore documents
271
     *
272
     * @param int $session_id
273
     * @param bool $respect_base_content
274
     * @param string $destination_course_code
275
     */
276
    public function restore_documents(
277
        $session_id = 0,
278
        $respect_base_content = false,
279
        $destination_course_code = ''
280
    ) {
281
        $course_info = api_get_course_info($destination_course_code);
282
283
        if (!$this->course->has_resources(RESOURCE_DOCUMENT)) {
284
            return;
285
        }
286
287
        $table = Database::get_course_table(TABLE_DOCUMENT);
288
        $resources = $this->course->resources;
289
        $path = api_get_path(SYS_COURSE_PATH).$this->course->destination_path.'/';
290
291
        foreach ($resources[RESOURCE_DOCUMENT] as $id => $document) {
292
            $my_session_id = empty($document->item_properties[0]['id_session']) ? 0 : $session_id;
293
294
            if ($document->file_type == FOLDER) {
295
                $visibility = $document->item_properties[0]['visibility'];
296
                $new = substr($document->path, 8);
297
298
                $folderList = explode('/', $new);
299
                $tempFolder = '';
300
301
                // Check if the parent path exists.
302
                foreach ($folderList as $folder) {
303
                    $folderToCreate = $tempFolder.$folder;
304
                    $sysFolderPath = $path.'document'.$folderToCreate;
305
                    $tempFolder .= $folder.'/';
306
307
                    if (empty($folderToCreate)) {
308
                        continue;
309
                    }
310
311
                    $title = $document->title;
312
                    if (empty($title)) {
313
                        $title = basename($sysFolderPath);
314
                    }
315
316
                    // File doesn't exist in file system.
317
                    if (!is_dir($sysFolderPath)) {
318
                        // Creating directory
319
                        create_unexisting_directory(
320
                            $course_info,
321
                            api_get_user_id(),
322
                            $my_session_id,
323
                            0,
324
                            0,
325
                            $path.'document',
326
                            $folderToCreate,
327
                            $title,
328
                            $visibility
329
                        );
330
331
                        continue;
332
                    }
333
334
                    // File exist in file system.
335
                    $documentData = DocumentManager::get_document_id(
336
                        $course_info,
337
                        $folderToCreate,
338
                        $my_session_id
339
                    );
340
341
                    if (empty($documentData)) {
342
                        /* This means the folder exists in the
343
                        filesystem but not in the DB, trying to fix it */
344
                        add_document(
345
                            $course_info,
346
                            $folderToCreate,
347
                            'folder',
348
                            0,
349
                            $title,
350
                            null,
351
                            null,
352
                            false,
353
                            null,
354
                            $my_session_id
355
                        );
356
                    } else {
357
                        $insertUserId = isset($document->item_properties[0]['insert_user_id']) ? $document->item_properties[0]['insert_user_id'] : api_get_user_id();
358
                        $insertUserId = $this->checkUserId($insertUserId);
359
360
                        // Check if user exists in platform
361
                        $toUserId = isset($document->item_properties[0]['to_user_id']) ? $document->item_properties[0]['to_user_id'] : null;
362
                        $toUserId = $this->checkUserId($toUserId, true);
363
364
                        $groupId = isset($document->item_properties[0]['to_group_id']) ? $document->item_properties[0]['to_group_id'] : null;
365
                        $groupInfo = $this->checkGroupId($groupId);
366
367
                        // if folder exists then just refresh it
368
                        api_item_property_update(
369
                            $course_info,
370
                            TOOL_DOCUMENT,
371
                            $documentData,
372
                            'FolderUpdated',
373
                            $insertUserId,
374
                            $groupInfo,
375
                            $toUserId,
376
                            null,
377
                            null,
378
                            $my_session_id
379
                        );
380
                    }
381
                }
382
            } elseif ($document->file_type == DOCUMENT) {
383
                //Checking if folder exists in the database otherwise we created it
384
                $dir_to_create = dirname($document->path);
385
386
                if (!empty($dir_to_create) && $dir_to_create != 'document' && $dir_to_create != '/') {
387
                    if (is_dir($path.dirname($document->path))) {
388
                        $sql = "SELECT id FROM $table
389
                                WHERE
390
                                    c_id = ".$this->destination_course_id." AND
391
                                    path = '/".self::DBUTF8escapestring(substr(dirname($document->path), 9))."'";
0 ignored issues
show
Bug Best Practice introduced by
The method Chamilo\CourseBundle\Com...r::DBUTF8escapestring() is not static, but was called statically. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

391
                                    path = '/".self::/** @scrutinizer ignore-call */ DBUTF8escapestring(substr(dirname($document->path), 9))."'";
Loading history...
392
                        $res = Database::query($sql);
393
                        if (Database::num_rows($res) == 0) {
394
                            //continue;
395
                            $visibility = $document->item_properties[0]['visibility'];
396
                            $new = '/'.substr(dirname($document->path), 9);
397
                            $title = $document->title;
398
                            if (empty($title)) {
399
                                $title = str_replace('/', '', $new);
400
                            }
401
402
                            // This code fixes the possibility for a file without a directory entry to be
403
                            $document_id = add_document(
404
                                $course_info,
405
                                $new,
406
                                'folder',
407
                                0,
408
                                $title,
409
                                null,
410
                                null,
411
                                false
412
                            );
413
414
                            $itemProperty = isset($document->item_properties[0]) ? $document->item_properties[0] : '';
415
                            $insertUserId = isset($itemProperty['insert_user_id']) ? $itemProperty['insert_user_id'] : api_get_user_id();
416
                            $toGroupId = isset($itemProperty['to_group_id']) ? $itemProperty['to_group_id'] : 0;
417
                            $toUserId = isset($itemProperty['to_user_id']) ? $itemProperty['to_user_id'] : null;
418
                            $groupInfo = $this->checkGroupId($toGroupId);
419
                            $insertUserId = $this->checkUserId($insertUserId);
420
                            $toUserId = $this->checkUserId($toUserId, true);
421
422
                            api_item_property_update(
423
                                $course_info,
424
                                TOOL_DOCUMENT,
425
                                $document_id,
426
                                'FolderCreated',
427
                                $insertUserId,
428
                                $groupInfo,
429
                                $toUserId,
430
                                null,
431
                                null,
432
                                $my_session_id
433
                            );
434
                        }
435
                    }
436
                }
437
438
                if (file_exists($path.$document->path)) {
439
                    switch ($this->file_option) {
440
                        case FILE_OVERWRITE:
441
                            $origin_path = $this->course->backup_path.'/'.$document->path;
442
443
                            if (file_exists($origin_path)) {
444
                                copy($origin_path, $path.$document->path);
445
                                $sql = "SELECT id FROM $table
446
                                        WHERE
447
                                            c_id = ".$this->destination_course_id." AND
448
                                            path = '/".self::DBUTF8escapestring(substr($document->path, 9))."'";
449
450
                                $res = Database::query($sql);
451
                                $count = Database::num_rows($res);
452
453
                                if ($count == 0) {
454
                                    $params = [
455
                                        'path' => "/".self::DBUTF8(substr($document->path, 9)),
0 ignored issues
show
Bug Best Practice introduced by
The method Chamilo\CourseBundle\Com...ourseRestorer::DBUTF8() is not static, but was called statically. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

455
                                        'path' => "/".self::/** @scrutinizer ignore-call */ DBUTF8(substr($document->path, 9)),
Loading history...
456
                                        'c_id' => $this->destination_course_id,
457
                                        'comment'=> self::DBUTF8($document->comment),
458
                                        'title' => self::DBUTF8($document->title),
459
                                        'filetype' => self::DBUTF8($document->file_type),
460
                                        'size' => self::DBUTF8($document->size),
461
                                        'session_id' => $my_session_id,
462
                                        'readonly' => 0,
463
                                    ];
464
465
                                    $document_id = Database::insert($table, $params);
466
467
                                    if ($document_id) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $document_id of type integer|false is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
468
                                        $sql = "UPDATE $table SET id = iid WHERE iid = $document_id";
469
                                        Database::query($sql);
470
                                    }
471
                                    $this->course->resources[RESOURCE_DOCUMENT][$id]->destination_id = $document_id;
472
473
                                    $itemProperty = isset($document->item_properties[0]) ? $document->item_properties[0] : '';
474
                                    $insertUserId = isset($itemProperty['insert_user_id']) ? $itemProperty['insert_user_id'] : api_get_user_id();
475
                                    $toGroupId = isset($itemProperty['to_group_id']) ? $itemProperty['to_group_id'] : 0;
476
                                    $toUserId = isset($itemProperty['to_user_id']) ? $itemProperty['to_user_id'] : null;
477
478
                                    $insertUserId = $this->checkUserId($insertUserId);
479
                                    $toUserId = $this->checkUserId($toUserId, true);
480
                                    $groupInfo = $this->checkGroupId($toGroupId);
481
482
                                    api_item_property_update(
483
                                        $course_info,
484
                                        TOOL_DOCUMENT,
485
                                        $document_id,
0 ignored issues
show
Bug introduced by
It seems like $document_id can also be of type false; however, parameter $item_id of api_item_property_update() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

485
                                        /** @scrutinizer ignore-type */ $document_id,
Loading history...
486
                                        'DocumentAdded',
487
                                        $insertUserId,
488
                                        $groupInfo,
489
                                        $toUserId,
490
                                        null,
491
                                        null,
492
                                        $my_session_id
493
                                    );
494
                                } else {
495
                                    $obj = Database::fetch_object($res);
496
                                    $document_id = $obj->id;
497
                                    $params = [
498
                                        'path' => "/".self::DBUTF8(substr($document->path, 9)),
499
                                        'c_id' => $this->destination_course_id,
500
                                        'comment'=> self::DBUTF8($document->comment),
501
                                        'title' => self::DBUTF8($document->title),
502
                                        'filetype' => self::DBUTF8($document->file_type),
503
                                        'size' => self::DBUTF8($document->size),
504
                                        'session_id' => $my_session_id,
505
                                    ];
506
507
                                    Database::update(
508
                                        $table,
509
                                        $params,
510
                                        [
511
                                            'c_id = ? AND path = ?' => [
512
                                                $this->destination_course_id,
513
                                                "/".self::DBUTF8escapestring(substr($document->path, 9)),
514
                                            ],
515
                                        ]
516
                                    );
517
518
                                    $this->course->resources[RESOURCE_DOCUMENT][$id]->destination_id = $obj->id;
519
520
                                    $itemProperty = isset($document->item_properties[0]) ? $document->item_properties[0] : '';
521
                                    $insertUserId = isset($itemProperty['insert_user_id']) ? $itemProperty['insert_user_id'] : api_get_user_id();
522
                                    $toGroupId = isset($itemProperty['to_group_id']) ? $itemProperty['to_group_id'] : 0;
523
                                    $toUserId = isset($itemProperty['to_user_id']) ? $itemProperty['to_user_id'] : null;
524
525
                                    $insertUserId = $this->checkUserId($insertUserId);
526
                                    $toUserId = $this->checkUserId($toUserId, true);
527
                                    $groupInfo = $this->checkGroupId($toGroupId);
528
529
                                    api_item_property_update(
530
                                        $course_info,
531
                                        TOOL_DOCUMENT,
532
                                        $obj->id,
533
                                        'default',
534
                                        $insertUserId,
535
                                        $groupInfo,
536
                                        $toUserId,
537
                                        null,
538
                                        null,
539
                                        $my_session_id
540
                                    );
541
                                }
542
543
                                // Replace old course code with the new destination code
544
                                $file_info = pathinfo($path.$document->path);
545
546
                                if (isset($file_info['extension']) && in_array($file_info['extension'], ['html', 'htm'])) {
547
                                    $content = file_get_contents($path.$document->path);
548
                                    if (UTF8_CONVERT) {
549
                                        $content = utf8_encode($content);
550
                                    }
551
                                    $content = DocumentManager::replaceUrlWithNewCourseCode(
552
                                        $content,
553
                                        $this->course->code,
554
                                        $this->course->destination_path,
555
                                        $this->course->backup_path,
556
                                        $this->course->info['path']
0 ignored issues
show
Bug introduced by
The property info does not seem to exist on Chamilo\CourseBundle\Component\CourseCopy\Course.
Loading history...
557
                                    );
558
                                    file_put_contents($path.$document->path, $content);
559
                                }
560
561
                                $params = [
562
                                    'comment'=> self::DBUTF8($document->comment),
563
                                    'title' => self::DBUTF8($document->title),
564
                                    'size' => self::DBUTF8($document->size),
565
                                ];
566
                                Database::update(
567
                                    $table,
568
                                    $params,
569
                                    [
570
                                        'c_id = ? AND id = ?' => [
571
                                            $this->destination_course_id,
572
                                            $document_id,
573
                                        ],
574
                                    ]
575
                                );
576
                            }
577
                            break;
578
                        case FILE_SKIP:
579
                            $sql = "SELECT id FROM $table
580
                                    WHERE
581
                                        c_id = ".$this->destination_course_id." AND
582
                                        path='/".self::DBUTF8escapestring(substr($document->path, 9))."'";
583
                            $res = Database::query($sql);
584
                            $obj = Database::fetch_object($res);
585
                            $this->course->resources[RESOURCE_DOCUMENT][$id]->destination_id = $obj->id;
586
                            break;
587
                        case FILE_RENAME:
588
                            $i = 1;
589
                            $ext = explode('.', basename($document->path));
590
                            if (count($ext) > 1) {
591
                                $ext = array_pop($ext);
592
                                $file_name_no_ext = substr($document->path, 0, - (strlen($ext) + 1));
593
                                $ext = '.'.$ext;
594
                            } else {
595
                                $ext = '';
596
                                $file_name_no_ext = $document->path;
597
                            }
598
                            $new_file_name = $file_name_no_ext.'_'.$i.$ext;
599
                            $file_exists = file_exists($path.$new_file_name);
600
                            while ($file_exists) {
601
                                $i++;
602
                                $new_file_name = $file_name_no_ext.'_'.$i.$ext;
603
                                $file_exists = file_exists($path.$new_file_name);
604
                            }
605
606
                            if (!empty($session_id)) {
607
                                $document_path = explode('/', $document->path, 3);
608
                                $course_path = $path;
609
                                $orig_base_folder = $document_path[1];
610
                                $orig_base_path   = $course_path.$document_path[0].'/'.$document_path[1];
611
612
                                if (is_dir($orig_base_path)) {
613
                                    $new_base_foldername = $orig_base_folder;
614
                                    $new_base_path = $orig_base_path;
615
616
                                    if ($_SESSION['orig_base_foldername'] != $new_base_foldername) {
617
                                        unset($_SESSION['new_base_foldername']);
618
                                        unset($_SESSION['orig_base_foldername']);
619
                                        unset($_SESSION['new_base_path']);
620
                                    }
621
622
                                    $folder_exists = file_exists($new_base_path);
623
                                    if ($folder_exists) {
624
                                        // e.g: carpeta1 in session
625
                                        $_SESSION['orig_base_foldername'] = $new_base_foldername;
626
                                        $x = '';
627
                                        while ($folder_exists) {
628
                                            $x = $x + 1;
629
                                            $new_base_foldername = $document_path[1].'_'.$x;
630
                                            $new_base_path = $orig_base_path.'_'.$x;
631
                                            if ($_SESSION['new_base_foldername'] == $new_base_foldername) {
632
                                                break;
633
                                            }
634
                                            $folder_exists = file_exists($new_base_path);
635
                                        }
636
                                        $_SESSION['new_base_foldername'] = $new_base_foldername;
637
                                        $_SESSION['new_base_path'] = $new_base_path;
638
                                    }
639
640
                                    if (isset($_SESSION['new_base_foldername']) && isset($_SESSION['new_base_path'])) {
641
                                        $new_base_foldername = $_SESSION['new_base_foldername'];
642
                                        $new_base_path = $_SESSION['new_base_path'];
643
                                    }
644
645
                                    $dest_document_path = $new_base_path.'/'.$document_path[2]; // e.g: "/var/www/wiener/courses/CURSO4/document/carpeta1_1/subcarpeta1/collaborative.png"
646
                                    $basedir_dest_path = dirname($dest_document_path); // e.g: "/var/www/wiener/courses/CURSO4/document/carpeta1_1/subcarpeta1"
647
                                    $base_path_document = $course_path.$document_path[0]; // e.g: "/var/www/wiener/courses/CURSO4/document"
648
                                    $path_title = '/'.$new_base_foldername.'/'.$document_path[2];
649
650
                                    copy_folder_course_session(
651
                                        $basedir_dest_path,
652
                                        $base_path_document,
653
                                        $session_id,
654
                                        $course_info,
655
                                        $document,
656
                                        $this->course_origin_id
657
                                    );
658
659
                                    if (file_exists($course_path.$document->path)) {
660
                                        copy($course_path.$document->path, $dest_document_path);
661
                                    }
662
663
                                    // Replace old course code with the new destination code see BT#1985
664
                                    if (file_exists($dest_document_path)) {
665
                                        $file_info = pathinfo($dest_document_path);
666
                                        if (in_array($file_info['extension'], ['html', 'htm'])) {
667
                                            $content = file_get_contents($dest_document_path);
668
                                            if (UTF8_CONVERT) {
669
                                                $content = utf8_encode($content);
670
                                            }
671
                                            $content = DocumentManager::replaceUrlWithNewCourseCode(
672
                                                $content,
673
                                                $this->course->code,
674
                                                $this->course->destination_path,
675
                                                $this->course->backup_path,
676
                                                $this->course->info['path']
677
                                            );
678
                                            file_put_contents($dest_document_path, $content);
679
                                        }
680
                                    }
681
682
                                    $params = [
683
                                        'path' => self::DBUTF8($path_title),
684
                                        'c_id' => $this->destination_course_id,
685
                                        'comment'=> self::DBUTF8($document->comment),
686
                                        'title' => self::DBUTF8(basename($path_title)),
687
                                        'filetype' => self::DBUTF8($document->file_type),
688
                                        'size' => self::DBUTF8($document->size),
689
                                        'session_id' => $my_session_id,
690
                                    ];
691
692
                                    $document_id = Database::insert($table, $params);
693
694
                                    if ($document_id) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $document_id of type integer|false is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
695
                                        $sql = "UPDATE $table SET id = iid WHERE iid = $document_id";
696
                                        Database::query($sql);
697
                                    }
698
699
                                    $this->course->resources[RESOURCE_DOCUMENT][$id]->destination_id = $document_id;
700
701
                                    $itemProperty = isset($document->item_properties[0]) ? $document->item_properties[0] : '';
702
                                    $insertUserId = isset($itemProperty['insert_user_id']) ? $itemProperty['insert_user_id'] : api_get_user_id();
703
                                    $toGroupId = isset($itemProperty['to_group_id']) ? $itemProperty['to_group_id'] : 0;
704
                                    $toUserId = isset($itemProperty['to_user_id']) ? $itemProperty['to_user_id'] : null;
705
706
                                    $insertUserId = $this->checkUserId($insertUserId);
707
                                    $toUserId = $this->checkUserId($toUserId, true);
708
                                    $groupInfo = $this->checkGroupId($toGroupId);
709
710
                                    api_item_property_update(
711
                                        $course_info,
712
                                        TOOL_DOCUMENT,
713
                                        $document_id,
714
                                        'DocumentAdded',
715
                                        $insertUserId,
716
                                        $groupInfo,
717
                                        $toUserId,
718
                                        null,
719
                                        null,
720
                                        $my_session_id
721
                                    );
722
                                } else {
723
                                    if (file_exists($path.$document->path)) {
724
                                        copy($path.$document->path, $path.$new_file_name);
725
                                    }
726
                                    //Replace old course code with the new destination code see BT#1985
727
                                    if (file_exists($path.$new_file_name)) {
728
                                        $file_info = pathinfo($path.$new_file_name);
729
                                        if (in_array($file_info['extension'], ['html', 'htm'])) {
730
                                            $content = file_get_contents($path.$new_file_name);
731
                                            if (UTF8_CONVERT) {
732
                                                $content = utf8_encode($content);
733
                                            }
734
                                            $content = DocumentManager::replaceUrlWithNewCourseCode(
735
                                                $content,
736
                                                $this->course->code,
737
                                                $this->course->destination_path,
738
                                                $this->course->backup_path,
739
                                                $this->course->info['path']
740
                                            );
741
                                            file_put_contents($path.$new_file_name, $content);
742
                                        }
743
                                    }
744
745
                                    $params = [
746
                                        'path' => "/".self::DBUTF8escapestring(substr($new_file_name, 9)),
747
                                        'c_id' => $this->destination_course_id,
748
                                        'comment'=> self::DBUTF8($document->comment),
749
                                        'title' => self::DBUTF8($document->title),
750
                                        'filetype' => self::DBUTF8($document->file_type),
751
                                        'size' => self::DBUTF8($document->size),
752
                                        'session_id' => $my_session_id,
753
                                    ];
754
755
                                    $document_id = Database::insert($table, $params);
756
757
                                    if ($document_id) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $document_id of type integer|false is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
758
                                        $sql = "UPDATE $table SET id = iid WHERE iid = $document_id";
759
                                        Database::query($sql);
760
761
                                        $this->course->resources[RESOURCE_DOCUMENT][$id]->destination_id = $document_id;
762
763
                                        $itemProperty = isset($document->item_properties[0]) ? $document->item_properties[0] : '';
764
                                        $insertUserId = isset($itemProperty['insert_user_id']) ? $itemProperty['insert_user_id'] : api_get_user_id();
765
                                        $toGroupId = isset($itemProperty['to_group_id']) ? $itemProperty['to_group_id'] : 0;
766
                                        $toUserId = isset($itemProperty['to_user_id']) ? $itemProperty['to_user_id'] : null;
767
768
                                        $insertUserId = $this->checkUserId($insertUserId);
769
                                        $toUserId = $this->checkUserId($toUserId, true);
770
                                        $groupInfo = $this->checkGroupId($toGroupId);
771
772
                                        api_item_property_update(
773
                                            $course_info,
774
                                            TOOL_DOCUMENT,
775
                                            $document_id,
776
                                            'DocumentAdded',
777
                                            $insertUserId,
778
                                            $groupInfo,
779
                                            $toUserId,
780
                                            null,
781
                                            null,
782
                                            $my_session_id
783
                                        );
784
                                    }
785
                                }
786
                            } else {
787
                                copy(
788
                                    $this->course->backup_path.'/'.$document->path,
789
                                    $path.$new_file_name
790
                                );
791
792
                                // Replace old course code with the new destination code see BT#1985
793
                                if (file_exists($path.$new_file_name)) {
794
                                    $file_info = pathinfo($path.$new_file_name);
795
                                    if (in_array($file_info['extension'], ['html', 'htm'])) {
796
                                        $content = file_get_contents($path.$new_file_name);
797
                                        if (UTF8_CONVERT) {
798
                                            $content = utf8_encode($content);
799
                                        }
800
                                        $content = DocumentManager::replaceUrlWithNewCourseCode(
801
                                            $content,
802
                                            $this->course->code,
803
                                            $this->course->destination_path,
804
                                            $this->course->backup_path,
805
                                            $this->course->info['path']
806
                                        );
807
                                        file_put_contents($path.$new_file_name, $content);
808
                                    }
809
                                }
810
811
                                $params = [
812
                                    'c_id' => $this->destination_course_id,
813
                                    'path' => "/".self::DBUTF8escapestring(substr($new_file_name, 9)),
814
                                    'comment'=> self::DBUTF8($document->comment),
815
                                    'title' => self::DBUTF8($document->title),
816
                                    'filetype' => self::DBUTF8($document->file_type),
817
                                    'size' => self::DBUTF8($document->size),
818
                                    'session_id' => $my_session_id,
819
                                ];
820
821
                                $document_id = Database::insert($table, $params);
822
823
                                if ($document_id) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $document_id of type integer|false is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
824
                                    $sql = "UPDATE $table SET id = iid WHERE iid = $document_id";
825
                                    Database::query($sql);
826
                                }
827
828
                                $this->course->resources[RESOURCE_DOCUMENT][$id]->destination_id = $document_id;
829
830
                                $itemProperty = isset($document->item_properties[0]) ? $document->item_properties[0] : '';
831
                                $insertUserId = isset($itemProperty['insert_user_id']) ? $itemProperty['insert_user_id'] : api_get_user_id();
832
                                $toGroupId = isset($itemProperty['to_group_id']) ? $itemProperty['to_group_id'] : 0;
833
                                $toUserId = isset($itemProperty['to_user_id']) ? $itemProperty['to_user_id'] : null;
834
835
                                $insertUserId = $this->checkUserId($insertUserId);
836
                                $toUserId = $this->checkUserId($toUserId, true);
837
                                $groupInfo = $this->checkGroupId($toGroupId);
838
839
                                api_item_property_update(
840
                                    $course_info,
841
                                    TOOL_DOCUMENT,
842
                                    $document_id,
843
                                    'DocumentAdded',
844
                                    $insertUserId,
845
                                    $groupInfo,
846
                                    $toUserId,
847
                                    null,
848
                                    null,
849
                                    $my_session_id
850
                                );
851
                            }
852
                            break;
853
854
                    } // end switch
855
                } else {
856
                    // end if file exists
857
                    //make sure the source file actually exists
858
                    if (is_file($this->course->backup_path.'/'.$document->path) &&
859
                        is_readable($this->course->backup_path.'/'.$document->path) &&
860
                        is_dir(dirname($path.$document->path)) &&
861
                        is_writeable(dirname($path.$document->path))
862
                    ) {
863
                        copy(
864
                            $this->course->backup_path.'/'.$document->path,
865
                            $path.$document->path
866
                        );
867
868
                        // Replace old course code with the new destination code see BT#1985
869
                        if (file_exists($path.$document->path)) {
870
                            $file_info = pathinfo($path.$document->path);
871
                            if (isset($file_info['extension']) && in_array($file_info['extension'], ['html', 'htm'])) {
872
                                $content = file_get_contents($path.$document->path);
873
                                if (UTF8_CONVERT) {
874
                                    $content = utf8_encode($content);
875
                                }
876
                                $content = DocumentManager::replaceUrlWithNewCourseCode(
877
                                    $content,
878
                                    $this->course->code,
879
                                    $this->course->destination_path,
880
                                    $this->course->backup_path,
881
                                    $this->course->info['path']
882
                                );
883
                                file_put_contents($path.$document->path, $content);
884
                            }
885
                        }
886
887
                        $params = [
888
                            'c_id' => $this->destination_course_id,
889
                            'path' => "/".self::DBUTF8(substr($document->path, 9)),
890
                            'comment'=> self::DBUTF8($document->comment),
891
                            'title' => self::DBUTF8($document->title),
892
                            'filetype' => self::DBUTF8($document->file_type),
893
                            'size' => self::DBUTF8($document->size),
894
                            'session_id' => $my_session_id,
895
                            'readonly' => 0,
896
                        ];
897
898
                        $document_id = Database::insert($table, $params);
899
900
                        if ($document_id) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $document_id of type integer|false is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
901
                            $sql = "UPDATE $table SET id = iid WHERE iid = $document_id";
902
                            Database::query($sql);
903
                        }
904
905
                        $this->course->resources[RESOURCE_DOCUMENT][$id]->destination_id = $document_id;
906
907
                        $itemProperty = isset($document->item_properties[0]) ? $document->item_properties[0] : '';
908
                        $insertUserId = isset($itemProperty['insert_user_id']) ? $itemProperty['insert_user_id'] : api_get_user_id();
909
                        $toGroupId = isset($itemProperty['to_group_id']) ? $itemProperty['to_group_id'] : 0;
910
                        $toUserId = isset($itemProperty['to_user_id']) ? $itemProperty['to_user_id'] : null;
911
912
                        $insertUserId = $this->checkUserId($insertUserId);
913
                        $toUserId = $this->checkUserId($toUserId, true);
914
                        $groupInfo = $this->checkGroupId($toGroupId);
915
916
                        api_item_property_update(
917
                            $course_info,
918
                            TOOL_DOCUMENT,
919
                            $document_id,
920
                            'DocumentAdded',
921
                            $insertUserId,
922
                            $groupInfo,
923
                            $toUserId,
924
                            null,
925
                            null,
926
                            $my_session_id
927
                        );
928
                    } else {
929
                        // There was an error in checking existence and
930
                        // permissions for files to copy. Try to determine
931
                        // the exact issue
932
                        // Issue with origin document?
933
                        if (!is_file($this->course->backup_path.'/'.$document->path)) {
934
                            error_log('Course copy generated an ignorable error while trying to copy '.$this->course->backup_path.'/'.$document->path.': origin file not found');
935
                        } elseif (!is_readable($this->course->backup_path.'/'.$document->path)) {
936
                            error_log('Course copy generated an ignorable error while trying to copy '.$this->course->backup_path.'/'.$document->path.': origin file not readable');
937
                        }
938
                        // Issue with destination directories?
939
                        if (!is_dir(dirname($path.$document->path))) {
940
                            error_log('Course copy generated an ignorable error while trying to copy '.$this->course->backup_path.'/'.$document->path.' to '.dirname($path.$document->path).': destination directory not found');
941
                        }
942
                        if (!is_writeable(dirname($path.$document->path))) {
943
                            error_log('Course copy generated an ignorable error while trying to copy '.$this->course->backup_path.'/'.$document->path.' to '.dirname($path.$document->path).': destination directory not writable');
944
                        }
945
                    }
946
                } // end file doesn't exist
947
            }
948
949
            // add image information for area questions
950
            if (preg_match('/^quiz-.*$/', $document->title) &&
951
                preg_match('/^document\/images\/.*$/', $document->path)
952
            ) {
953
                $this->course->resources[RESOURCE_DOCUMENT]['image_quiz'][$document->title] = [
954
                    'path' => $document->path,
955
                    'title' => $document->title,
956
                    'source_id' => $document->source_id,
957
                    'destination_id' => $document->destination_id,
958
                ];
959
            }
960
        } // end for each
961
962
        // Delete sessions for the copy the new folder in session
963
        unset($_SESSION['new_base_foldername']);
964
        unset($_SESSION['orig_base_foldername']);
965
        unset($_SESSION['new_base_path']);
966
    }
967
968
    /**
969
     * Restore scorm documents
970
     * TODO @TODO check that the restore function with renaming doesn't break the scorm structure!
971
     * see #7029
972
     */
973
    public function restore_scorm_documents()
974
    {
975
        $perm = api_get_permissions_for_new_directories();
976
977
        if ($this->course->has_resources(RESOURCE_SCORM)) {
978
            $resources = $this->course->resources;
979
            foreach ($resources[RESOURCE_SCORM] as $document) {
980
                $path = api_get_path(SYS_COURSE_PATH).$this->course->destination_path.'/';
981
                @mkdir(dirname($path.$document->path), $perm, true);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for mkdir(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unhandled  annotation

981
                /** @scrutinizer ignore-unhandled */ @mkdir(dirname($path.$document->path), $perm, true);

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
982
983
                if (file_exists($path.$document->path)) {
984
                    switch ($this->file_option) {
985
                        case FILE_OVERWRITE:
986
                            rmdirr($path.$document->path);
987
                            copyDirTo(
988
                                $this->course->backup_path.'/'.$document->path,
989
                                $path.dirname($document->path),
990
                                false
991
                            );
992
                            break;
993
                        case FILE_SKIP:
994
                            break;
995
                        case FILE_RENAME:
996
                            $i = 1;
997
                            $ext = explode('.', basename($document->path));
998
                            if (count($ext) > 1) {
999
                                $ext = array_pop($ext);
1000
                                $file_name_no_ext = substr($document->path, 0, - (strlen($ext) + 1));
1001
                                $ext = '.'.$ext;
1002
                            } else {
1003
                                $ext = '';
1004
                                $file_name_no_ext = $document->path;
1005
                            }
1006
1007
                            $new_file_name = $file_name_no_ext.'_'.$i.$ext;
1008
                            $file_exists = file_exists($path.$new_file_name);
1009
1010
                            while ($file_exists) {
1011
                                $i++;
1012
                                $new_file_name = $file_name_no_ext.'_'.$i.$ext;
1013
                                $file_exists = file_exists($path.$new_file_name);
1014
                            }
1015
1016
                            rename(
1017
                                $this->course->backup_path.'/'.$document->path,
1018
                                $this->course->backup_path.'/'.$new_file_name
1019
                            );
1020
                            copyDirTo(
1021
                                $this->course->backup_path.'/'.$new_file_name,
1022
                                $path.dirname($new_file_name),
1023
                                false
1024
                            );
1025
                            rename(
1026
                                $this->course->backup_path.'/'.$new_file_name,
1027
                                $this->course->backup_path.'/'.$document->path
1028
                            );
1029
1030
                            break;
1031
                    } // end switch
1032
                } else {
1033
                    // end if file exists
1034
                    copyDirTo(
1035
                        $this->course->backup_path.'/'.$document->path,
1036
                        $path.dirname($document->path),
1037
                        false
1038
                    );
1039
                }
1040
            } // end for each
1041
        }
1042
    }
1043
1044
    /**
1045
     * Restore forums
1046
     *
1047
     * @param int $sessionId
1048
     */
1049
    public function restore_forums($sessionId = 0)
1050
    {
1051
        if ($this->course->has_resources(RESOURCE_FORUM)) {
1052
            $sessionId = intval($sessionId);
1053
            $table_forum = Database::get_course_table(TABLE_FORUM);
1054
            $resources = $this->course->resources;
1055
            foreach ($resources[RESOURCE_FORUM] as $id => $forum) {
1056
                $params = (array) $forum->obj;
1057
                $cat_id = '';
1058
                if (isset($this->course->resources[RESOURCE_FORUMCATEGORY]) &&
1059
                    isset($this->course->resources[RESOURCE_FORUMCATEGORY][$params['forum_category']])) {
1060
                    if ($this->course->resources[RESOURCE_FORUMCATEGORY][$params['forum_category']]->destination_id == -1) {
1061
                        $cat_id = $this->restore_forum_category(
1062
                            $params['forum_category'],
1063
                            $sessionId
1064
                        );
1065
                    } else {
1066
                        $cat_id = $this->course->resources[RESOURCE_FORUMCATEGORY][$params['forum_category']]->destination_id;
1067
                    }
1068
                }
1069
1070
                $params = self::DBUTF8_array($params);
0 ignored issues
show
Bug Best Practice introduced by
The method Chamilo\CourseBundle\Com...estorer::DBUTF8_array() is not static, but was called statically. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

1070
                /** @scrutinizer ignore-call */ 
1071
                $params = self::DBUTF8_array($params);
Loading history...
1071
                $params['c_id'] = $this->destination_course_id;
1072
                $params['forum_category'] = $cat_id;
1073
                $params['session_id'] = $sessionId;
1074
                $params['start_time'] = isset($params['start_time']) && $params['start_time'] === '0000-00-00 00:00:00' ? null : $params['start_time'];
1075
                $params['end_time'] = isset($params['end_time']) && $params['end_time'] === '0000-00-00 00:00:00' ? null : $params['end_time'];
1076
                $params['forum_id'] = 0;
1077
                unset($params['iid']);
1078
1079
                $params['forum_comment'] = DocumentManager::replaceUrlWithNewCourseCode(
1080
                    $params['forum_comment'],
0 ignored issues
show
Bug introduced by
It seems like $params['forum_comment'] can also be of type false; however, parameter $content_html of DocumentManager::replaceUrlWithNewCourseCode() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1080
                    /** @scrutinizer ignore-type */ $params['forum_comment'],
Loading history...
1081
                    $this->course->code,
1082
                    $this->course->destination_path,
1083
                    $this->course->backup_path,
1084
                    $this->course->info['path']
0 ignored issues
show
Bug introduced by
The property info does not seem to exist on Chamilo\CourseBundle\Component\CourseCopy\Course.
Loading history...
1085
                );
1086
1087
                if (!empty($params['forum_image'])) {
1088
                    $original_forum_image = $this->course->path.'upload/forum/images/'.$params['forum_image'];
1089
                    if (file_exists($original_forum_image)) {
1090
                        $new_forum_image = api_get_path(SYS_COURSE_PATH).$this->destination_course_info['path'].'/upload/forum/images/'.$params['forum_image'];
1091
                        @copy($original_forum_image, $new_forum_image);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for copy(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unhandled  annotation

1091
                        /** @scrutinizer ignore-unhandled */ @copy($original_forum_image, $new_forum_image);

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
1092
                    }
1093
                }
1094
1095
                $new_id = Database::insert($table_forum, $params);
1096
1097
                if ($new_id) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $new_id of type integer|false is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
1098
                    $sql = "UPDATE $table_forum SET forum_id = iid WHERE iid = $new_id";
1099
                    Database::query($sql);
1100
                }
1101
1102
                $this->course->resources[RESOURCE_FORUM][$id]->destination_id = $new_id;
1103
1104
                $forum_topics = 0;
1105
                if (is_array($this->course->resources[RESOURCE_FORUMTOPIC])) {
1106
                    foreach ($this->course->resources[RESOURCE_FORUMTOPIC] as $topic_id => $topic) {
1107
                        if ($topic->obj->forum_id == $id) {
1108
                            $this->restore_topic($topic_id, $new_id, $sessionId);
1109
                            $forum_topics++;
1110
                        }
1111
                    }
1112
                }
1113
                if ($forum_topics > 0) {
1114
                    $sql = "UPDATE ".$table_forum." SET forum_threads = ".$forum_topics."
1115
                            WHERE c_id = {$this->destination_course_id} AND forum_id = ".(int) $new_id;
1116
                    Database::query($sql);
1117
                }
1118
            }
1119
        }
1120
    }
1121
1122
    /**
1123
     * Restore forum-categories
1124
     */
1125
    public function restore_forum_category($my_id = null, $sessionId = 0)
1126
    {
1127
        $forum_cat_table = Database::get_course_table(TABLE_FORUM_CATEGORY);
1128
        $resources = $this->course->resources;
1129
        if (!empty($resources[RESOURCE_FORUMCATEGORY])) {
1130
            foreach ($resources[RESOURCE_FORUMCATEGORY] as $id => $forum_cat) {
1131
                if (!empty($my_id)) {
1132
                    if ($my_id != $id) {
1133
                        continue;
1134
                    }
1135
                }
1136
                if ($forum_cat && !$forum_cat->is_restored()) {
1137
                    $params = (array) $forum_cat->obj;
1138
                    $params['c_id'] = $this->destination_course_id;
1139
                    $params['cat_comment'] = DocumentManager::replaceUrlWithNewCourseCode(
1140
                        $params['cat_comment'],
1141
                        $this->course->code,
1142
                        $this->course->destination_path,
1143
                        $this->course->backup_path,
1144
                        $this->course->info['path']
0 ignored issues
show
Bug introduced by
The property info does not seem to exist on Chamilo\CourseBundle\Component\CourseCopy\Course.
Loading history...
1145
                    );
1146
                    $params['session_id'] = intval($sessionId);
1147
                    $params['cat_id'] = 0;
1148
                    unset($params['iid']);
1149
1150
                    $params = self::DBUTF8_array($params);
0 ignored issues
show
Bug Best Practice introduced by
The method Chamilo\CourseBundle\Com...estorer::DBUTF8_array() is not static, but was called statically. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

1150
                    /** @scrutinizer ignore-call */ 
1151
                    $params = self::DBUTF8_array($params);
Loading history...
1151
                    $new_id = Database::insert($forum_cat_table, $params);
1152
1153
                    if ($new_id) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $new_id of type integer|false is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
1154
                        $sql = "UPDATE $forum_cat_table SET cat_id = iid WHERE iid = $new_id";
1155
                        Database::query($sql);
1156
                    }
1157
1158
                    $this->course->resources[RESOURCE_FORUMCATEGORY][$id]->destination_id = $new_id;
1159
                    if (!empty($my_id)) {
1160
                        return $new_id;
1161
                    }
1162
                }
1163
            }
1164
        }
1165
    }
1166
1167
    /**
1168
     * Restore a forum-topic
1169
     * @param false|string $forum_id
1170
     * @return int
1171
     */
1172
    public function restore_topic($thread_id, $forum_id, $sessionId = 0)
1173
    {
1174
        $table = Database::get_course_table(TABLE_FORUM_THREAD);
1175
        $topic = $this->course->resources[RESOURCE_FORUMTOPIC][$thread_id];
1176
1177
        $params = (array) $topic->obj;
1178
        $params = self::DBUTF8_array($params);
0 ignored issues
show
Bug Best Practice introduced by
The method Chamilo\CourseBundle\Com...estorer::DBUTF8_array() is not static, but was called statically. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

1178
        /** @scrutinizer ignore-call */ 
1179
        $params = self::DBUTF8_array($params);
Loading history...
1179
        $params['c_id'] = $this->destination_course_id;
1180
        $params['forum_id'] = $forum_id;
1181
        $params['thread_poster_id'] = $this->first_teacher_id;
1182
        $params['thread_date'] = api_get_utc_datetime();
1183
        $params['thread_close_date'] = null;
1184
        $params['thread_last_post'] = 0;
1185
        $params['thread_replies'] = 0;
1186
        $params['thread_views'] = 0;
1187
        $params['session_id'] = intval($sessionId);
1188
        $params['thread_id'] = 0;
1189
1190
        unset($params['iid']);
1191
1192
        $new_id = Database::insert($table, $params);
1193
1194
        if ($new_id) {
1195
            $sql = "UPDATE $table SET thread_id = iid WHERE iid = $new_id";
1196
            Database::query($sql);
1197
        }
1198
1199
        api_item_property_update(
1200
            $this->destination_course_info,
1201
            TOOL_FORUM_THREAD,
1202
            $new_id,
1203
            'ThreadAdded',
1204
            api_get_user_id(),
1205
            0,
1206
            0,
1207
            null,
1208
            null,
1209
            $sessionId
1210
        );
1211
1212
        $this->course->resources[RESOURCE_FORUMTOPIC][$thread_id]->destination_id = $new_id;
1213
        $topic_replies = -1;
1214
1215
        foreach ($this->course->resources[RESOURCE_FORUMPOST] as $post_id => $post) {
1216
            if ($post->obj->thread_id == $thread_id) {
1217
                $topic_replies++;
1218
                $this->restore_post($post_id, $new_id, $forum_id, $sessionId);
1219
            }
1220
        }
1221
        return $new_id;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $new_id returns the type false which is incompatible with the documented return type integer.
Loading history...
1222
    }
1223
1224
    /**
1225
     * Restore a forum-post
1226
     * @TODO Restore tree-structure of posts. For example: attachments to posts.
1227
     * @param false|string $topic_id
1228
     * @return int
1229
     */
1230
    public function restore_post($id, $topic_id, $forum_id, $sessionId = 0)
1231
    {
1232
        $table_post = Database::get_course_table(TABLE_FORUM_POST);
1233
        $post = $this->course->resources[RESOURCE_FORUMPOST][$id];
1234
        $params = (array) $post->obj;
1235
        $params['c_id'] = $this->destination_course_id;
1236
        $params['forum_id'] = $forum_id;
1237
        $params['thread_id'] = $topic_id;
1238
        $params['poster_id'] = $this->first_teacher_id;
1239
        $params['post_date'] = api_get_utc_datetime();
1240
        $params['post_id'] = 0;
1241
        unset($params['iid']);
1242
1243
        $params['post_text'] = DocumentManager::replaceUrlWithNewCourseCode(
1244
            $params['post_text'],
0 ignored issues
show
Bug introduced by
It seems like $params['post_text'] can also be of type false; however, parameter $content_html of DocumentManager::replaceUrlWithNewCourseCode() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1244
            /** @scrutinizer ignore-type */ $params['post_text'],
Loading history...
1245
            $this->course->code,
1246
            $this->course->destination_path,
1247
            $this->course->backup_path,
1248
            $this->course->info['path']
0 ignored issues
show
Bug introduced by
The property info does not seem to exist on Chamilo\CourseBundle\Component\CourseCopy\Course.
Loading history...
1249
        );
1250
        $new_id = Database::insert($table_post, $params);
1251
1252
        if ($new_id) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $new_id of type integer|false is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
1253
            $sql = "UPDATE $table_post SET post_id = iid WHERE iid = $new_id";
1254
            Database::query($sql);
1255
        }
1256
1257
        api_item_property_update(
1258
            $this->destination_course_info,
1259
            TOOL_FORUM_POST,
1260
            $new_id,
0 ignored issues
show
Bug introduced by
It seems like $new_id can also be of type false; however, parameter $item_id of api_item_property_update() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1260
            /** @scrutinizer ignore-type */ $new_id,
Loading history...
1261
            'PostAdded',
1262
            api_get_user_id(),
1263
            0,
1264
            0,
1265
            null,
1266
            null,
1267
            $sessionId
1268
        );
1269
        $this->course->resources[RESOURCE_FORUMPOST][$id]->destination_id = $new_id;
1270
1271
        return $new_id;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $new_id could also return false which is incompatible with the documented return type integer. Did you maybe forget to handle an error condition?

If the returned type also contains false, it is an indicator that maybe an error condition leading to the specific return statement remains unhandled.

Loading history...
1272
    }
1273
1274
    /**
1275
     * Restore links
1276
     */
1277
    public function restore_links($session_id = 0)
1278
    {
1279
        if ($this->course->has_resources(RESOURCE_LINK)) {
1280
            $link_table = Database::get_course_table(TABLE_LINK);
1281
            $resources = $this->course->resources;
1282
1283
            foreach ($resources[RESOURCE_LINK] as $oldLinkId => $link) {
1284
                $cat_id = $this->restore_link_category(
1285
                    $link->category_id,
1286
                    $session_id
1287
                );
1288
                $sql = "SELECT MAX(display_order)
1289
                        FROM $link_table
1290
                        WHERE
1291
                            c_id = ".$this->destination_course_id." AND
1292
                            category_id='".intval($cat_id)."'";
1293
                $result = Database::query($sql);
1294
                list($max_order) = Database::fetch_array($result);
1295
1296
                $params = [];
1297
                if (!empty($session_id)) {
1298
                    $params['session_id'] = $session_id;
1299
                }
1300
1301
                $params['c_id'] = $this->destination_course_id;
1302
                $params['url'] = self::DBUTF8($link->url);
0 ignored issues
show
Bug Best Practice introduced by
The method Chamilo\CourseBundle\Com...ourseRestorer::DBUTF8() is not static, but was called statically. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

1302
                /** @scrutinizer ignore-call */ 
1303
                $params['url'] = self::DBUTF8($link->url);
Loading history...
1303
                $params['title'] = self::DBUTF8($link->title);
1304
                $params['description'] = self::DBUTF8($link->description);
1305
                $params['category_id'] = $cat_id;
1306
                $params['on_homepage'] = $link->on_homepage;
1307
                $params['display_order'] = $max_order + 1;
1308
                $params['target'] = $link->target;
1309
1310
                $id = Database::insert($link_table, $params);
1311
1312
                if ($id) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $id of type integer|false is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
1313
                    $sql = "UPDATE $link_table SET id = iid WHERE iid = $id";
1314
                    Database::query($sql);
1315
1316
                    api_item_property_update(
1317
                        $this->destination_course_info,
1318
                        TOOL_LINK,
1319
                        $id,
1320
                        'LinkAdded',
1321
                        api_get_user_id()
1322
                    );
1323
1324
                    if (!isset($this->course->resources[RESOURCE_LINK][$oldLinkId])) {
1325
                        $this->course->resources[RESOURCE_LINK][$oldLinkId] = new stdClass();
1326
                    }
1327
                    $this->course->resources[RESOURCE_LINK][$oldLinkId]->destination_id = $id;
1328
                }
1329
            }
1330
        }
1331
    }
1332
1333
    /**
1334
     * Restore a link-category
1335
     * @param int
1336
     * @param int
1337
     */
1338
    public function restore_link_category($id, $session_id = 0)
1339
    {
1340
        $params = [];
1341
        if (!empty($session_id)) {
1342
            $params['session_id'] = $session_id;
1343
        }
1344
1345
        if ($id == 0) {
1346
            return 0;
1347
        }
1348
        $link_cat_table = Database::get_course_table(TABLE_LINK_CATEGORY);
1349
        $resources = $this->course->resources;
1350
        $link_cat = $resources[RESOURCE_LINKCATEGORY][$id];
1351
        if (is_object($link_cat) && !$link_cat->is_restored()) {
1352
            $sql = "SELECT MAX(display_order) FROM  $link_cat_table
1353
                    WHERE c_id = ".$this->destination_course_id;
1354
            $result = Database::query($sql);
1355
            list($orderMax) = Database::fetch_array($result, 'NUM');
1356
            $display_order = $orderMax + 1;
1357
1358
            $params['c_id'] = $this->destination_course_id;
1359
            $params['category_title'] = self::DBUTF8($link_cat->title);
0 ignored issues
show
Bug Best Practice introduced by
The method Chamilo\CourseBundle\Com...ourseRestorer::DBUTF8() is not static, but was called statically. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

1359
            /** @scrutinizer ignore-call */ 
1360
            $params['category_title'] = self::DBUTF8($link_cat->title);
Loading history...
1360
            $params['description'] = self::DBUTF8($link_cat->description);
1361
            $params['display_order'] = $display_order;
1362
            $new_id = Database::insert($link_cat_table, $params);
1363
1364
            if ($new_id) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $new_id of type integer|false is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
1365
                $sql = "UPDATE $link_cat_table 
1366
                        SET id = iid 
1367
                        WHERE iid = $new_id";
1368
                Database::query($sql);
1369
1370
                $courseInfo = api_get_course_info_by_id($this->destination_course_id);
1371
                api_item_property_update(
1372
                    $courseInfo,
1373
                    TOOL_LINK_CATEGORY,
1374
                    $new_id,
1375
                    'LinkCategoryAdded',
1376
                    api_get_user_id()
1377
                );
1378
                api_set_default_visibility(
1379
                    $new_id,
1380
                    TOOL_LINK_CATEGORY,
1381
                    0,
1382
                    $courseInfo
1383
                );
1384
            }
1385
1386
            $this->course->resources[RESOURCE_LINKCATEGORY][$id]->destination_id = $new_id;
1387
            return $new_id;
1388
        }
1389
1390
        return $this->course->resources[RESOURCE_LINKCATEGORY][$id]->destination_id;
1391
    }
1392
1393
    /**
1394
     * Restore tool intro
1395
     * @param int
1396
     */
1397
    public function restore_tool_intro($sessionId = 0)
1398
    {
1399
        if ($this->course->has_resources(RESOURCE_TOOL_INTRO)) {
1400
            $sessionId = intval($sessionId);
1401
            $tool_intro_table = Database::get_course_table(TABLE_TOOL_INTRO);
1402
            $resources = $this->course->resources;
1403
            foreach ($resources[RESOURCE_TOOL_INTRO] as $id => $tool_intro) {
1404
                $sql = "DELETE FROM $tool_intro_table
1405
                        WHERE
1406
                            c_id = ".$this->destination_course_id." AND
1407
                            id='".self::DBUTF8escapestring($tool_intro->id)."'";
0 ignored issues
show
Bug Best Practice introduced by
The method Chamilo\CourseBundle\Com...r::DBUTF8escapestring() is not static, but was called statically. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

1407
                            id='".self::/** @scrutinizer ignore-call */ DBUTF8escapestring($tool_intro->id)."'";
Loading history...
1408
                Database::query($sql);
1409
1410
                $tool_intro->intro_text = DocumentManager::replaceUrlWithNewCourseCode(
1411
                    $tool_intro->intro_text,
1412
                    $this->course->code,
1413
                    $this->course->destination_path,
1414
                    $this->course->backup_path,
1415
                    $this->course->info['path']
0 ignored issues
show
Bug introduced by
The property info does not seem to exist on Chamilo\CourseBundle\Component\CourseCopy\Course.
Loading history...
1416
                );
1417
1418
                $params = [
1419
                    'c_id' => $this->destination_course_id,
1420
                    'id' => ($tool_intro->id === false ? '' : self::DBUTF8($tool_intro->id)),
0 ignored issues
show
Bug Best Practice introduced by
The method Chamilo\CourseBundle\Com...ourseRestorer::DBUTF8() is not static, but was called statically. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

1420
                    'id' => ($tool_intro->id === false ? '' : self::/** @scrutinizer ignore-call */ DBUTF8($tool_intro->id)),
Loading history...
1421
                    'intro_text' => self::DBUTF8($tool_intro->intro_text),
1422
                    'session_id' => $sessionId,
1423
                ];
1424
1425
                $id = Database::insert($tool_intro_table, $params);
1426
                if ($id) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $id of type integer|false is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
1427
                    if (!isset($this->course->resources[RESOURCE_TOOL_INTRO][$id])) {
1428
                        $this->course->resources[RESOURCE_TOOL_INTRO][$id] = new stdClass();
1429
                    }
1430
1431
                    $this->course->resources[RESOURCE_TOOL_INTRO][$id]->destination_id = $id;
1432
                }
1433
            }
1434
        }
1435
    }
1436
1437
    /**
1438
     * Restore events
1439
     * @param int
1440
     */
1441
    public function restore_events($sessionId = 0)
1442
    {
1443
        if ($this->course->has_resources(RESOURCE_EVENT)) {
1444
            $sessionId = intval($sessionId);
1445
            $table = Database::get_course_table(TABLE_AGENDA);
1446
            $resources = $this->course->resources;
1447
            foreach ($resources[RESOURCE_EVENT] as $id => $event) {
1448
                // check resources inside html from ckeditor tool and copy correct urls into recipient course
1449
                $event->content = DocumentManager::replaceUrlWithNewCourseCode(
1450
                    $event->content,
1451
                    $this->course->code,
1452
                    $this->course->destination_path,
1453
                    $this->course->backup_path,
1454
                    $this->course->info['path']
0 ignored issues
show
Bug introduced by
The property info does not seem to exist on Chamilo\CourseBundle\Component\CourseCopy\Course.
Loading history...
1455
                );
1456
1457
                $params = [
1458
                    'c_id' => $this->destination_course_id,
1459
                    'title' => self::DBUTF8($event->title),
0 ignored issues
show
Bug Best Practice introduced by
The method Chamilo\CourseBundle\Com...ourseRestorer::DBUTF8() is not static, but was called statically. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

1459
                    'title' => self::/** @scrutinizer ignore-call */ DBUTF8($event->title),
Loading history...
1460
                    'content' => ($event->content === false ? '' : self::DBUTF8($event->content)),
1461
                    'all_day' => $event->all_day,
1462
                    'start_date' => $event->start_date,
1463
                    'end_date' => $event->end_date,
1464
                    'session_id' => $sessionId,
1465
                ];
1466
                $new_event_id = Database::insert($table, $params);
1467
1468
                if ($new_event_id) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $new_event_id of type integer|false is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
1469
                    $sql = "UPDATE $table SET id = iid WHERE iid = $new_event_id";
1470
                    Database::query($sql);
1471
1472
                    if (!isset($this->course->resources[RESOURCE_EVENT][$id])) {
1473
                        $this->course->resources[RESOURCE_EVENT][$id] = new stdClass();
1474
                    }
1475
                    $this->course->resources[RESOURCE_EVENT][$id]->destination_id = $new_event_id;
1476
                }
1477
1478
                // Copy event attachment
1479
                $origin_path = $this->course->backup_path.'/upload/calendar/';
1480
                $destination_path = api_get_path(SYS_COURSE_PATH).$this->course->destination_path.'/upload/calendar/';
1481
1482
                if (!empty($this->course->orig)) {
1483
                    $table_attachment = Database::get_course_table(TABLE_AGENDA_ATTACHMENT);
1484
                    $sql = 'SELECT path, comment, size, filename
1485
                            FROM '.$table_attachment.'
1486
                            WHERE c_id = '.$this->destination_course_id.' AND agenda_id = '.$id;
1487
                    $attachment_event = Database::query($sql);
1488
                    $attachment_event = Database::fetch_object($attachment_event);
1489
1490
                    if (file_exists($origin_path.$attachment_event->path) &&
1491
                        !is_dir($origin_path.$attachment_event->path)
1492
                    ) {
1493
                        $new_filename = uniqid(''); //ass seen in the add_agenda_attachment_file() function in agenda.inc.php
1494
                        $copy_result = copy(
1495
                            $origin_path.$attachment_event->path,
1496
                            $destination_path.$new_filename
1497
                        );
1498
                        //$copy_result = true;
1499
                        if ($copy_result) {
1500
                            $table_attachment = Database::get_course_table(TABLE_AGENDA_ATTACHMENT);
1501
1502
                            $params = [
1503
                                'c_id' => $this->destination_course_id,
1504
                                'path' => self::DBUTF8($new_filename),
1505
                                'comment' => self::DBUTF8($attachment_event->comment),
1506
                                'size' => isset($attachment_event->size) ? $attachment_event->size : '',
1507
                                'filename' => isset($attachment_event->filename) ? $attachment_event->filename : '',
1508
                                'agenda_id' => $new_event_id,
1509
                            ];
1510
                            $id = Database::insert($table_attachment, $params);
1511
                            if ($id) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $id of type integer|false is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
1512
                                $sql = "UPDATE $table_attachment SET id = iid WHERE iid = $id";
1513
                                Database::query($sql);
1514
                            }
1515
                        }
1516
                    }
1517
                } else {
1518
                    // get the info of the file
1519
                    if (!empty($event->attachment_path) &&
1520
                        is_file($origin_path.$event->attachment_path) &&
1521
                        is_readable($origin_path.$event->attachment_path)
1522
                    ) {
1523
                        $new_filename = uniqid(''); //ass seen in the add_agenda_attachment_file() function in agenda.inc.php
1524
                        $copy_result = copy(
1525
                            $origin_path.$event->attachment_path,
1526
                            $destination_path.$new_filename
1527
                        );
1528
                        if ($copy_result) {
1529
                            $table_attachment = Database::get_course_table(TABLE_AGENDA_ATTACHMENT);
1530
1531
                            $params = [
1532
                                'c_id' => $this->destination_course_id,
1533
                                'path' => self::DBUTF8($new_filename),
1534
                                'comment' => self::DBUTF8($event->attachment_comment),
1535
                                'size' => isset($event->size) ? $event->size : '',
1536
                                'filename' => isset($event->filename) ? $event->filename : '',
1537
                                'agenda_id' => $new_event_id,
1538
                            ];
1539
                            $id = Database::insert($table_attachment, $params);
1540
1541
                            if ($id) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $id of type integer|false is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
1542
                                $sql = "UPDATE $table_attachment SET id = iid WHERE iid = $id";
1543
                                Database::query($sql);
1544
                            }
1545
                        }
1546
                    }
1547
                }
1548
            }
1549
        }
1550
    }
1551
1552
    /**
1553
     * Restore course-description
1554
     * @param int
1555
     */
1556
    public function restore_course_descriptions($session_id = 0)
1557
    {
1558
        if ($this->course->has_resources(RESOURCE_COURSEDESCRIPTION)) {
1559
            $table = Database::get_course_table(TABLE_COURSE_DESCRIPTION);
1560
            $resources = $this->course->resources;
1561
            foreach ($resources[RESOURCE_COURSEDESCRIPTION] as $id => $cd) {
1562
                $courseDescription = (array) $cd;
1563
1564
                $content = isset($courseDescription['content']) ? $courseDescription['content'] : '';
1565
                $descriptionType = isset($courseDescription['description_type']) ? $courseDescription['description_type'] : '';
1566
                $title = isset($courseDescription['title']) ? $courseDescription['title'] : '';
1567
1568
                // check resources inside html from ckeditor tool and copy correct urls into recipient course
1569
                $description_content = DocumentManager::replaceUrlWithNewCourseCode(
1570
                    $content,
1571
                    $this->course->code,
1572
                    $this->course->destination_path,
1573
                    $this->course->backup_path,
1574
                    $this->course->info['path']
0 ignored issues
show
Bug introduced by
The property info does not seem to exist on Chamilo\CourseBundle\Component\CourseCopy\Course.
Loading history...
1575
                );
1576
1577
                $params = [];
1578
1579
                $session_id = intval($session_id);
1580
                $params['session_id'] = $session_id;
1581
                $params['c_id'] = $this->destination_course_id;
1582
                $params['description_type'] = self::DBUTF8($descriptionType);
0 ignored issues
show
Bug Best Practice introduced by
The method Chamilo\CourseBundle\Com...ourseRestorer::DBUTF8() is not static, but was called statically. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

1582
                /** @scrutinizer ignore-call */ 
1583
                $params['description_type'] = self::DBUTF8($descriptionType);
Loading history...
1583
                $params['title'] = self::DBUTF8($title);
1584
                $params['content'] = ($description_content === false ? '' : self::DBUTF8($description_content));
1585
                $params['progress'] = 0;
1586
1587
                $id = Database::insert($table, $params);
1588
                if ($id) {
1589
                    $sql = "UPDATE $table SET id = iid WHERE iid = $id";
1590
                    Database::query($sql);
1591
1592
                    if (!isset($this->course->resources[RESOURCE_COURSEDESCRIPTION][$id])) {
1593
                        $this->course->resources[RESOURCE_COURSEDESCRIPTION][$id] = new stdClass();
1594
                    }
1595
                    $this->course->resources[RESOURCE_COURSEDESCRIPTION][$id]->destination_id = $id;
1596
                }
1597
            }
1598
        }
1599
    }
1600
1601
    /**
1602
     * Restore announcements
1603
     * @param int
1604
     */
1605
    public function restore_announcements($sessionId = 0)
1606
    {
1607
        if ($this->course->has_resources(RESOURCE_ANNOUNCEMENT)) {
1608
            $sessionId = intval($sessionId);
1609
            $table = Database::get_course_table(TABLE_ANNOUNCEMENT);
1610
            $resources = $this->course->resources;
1611
            foreach ($resources[RESOURCE_ANNOUNCEMENT] as $id => $announcement) {
1612
                // check resources inside html from ckeditor tool and copy correct urls into recipient course
1613
                $announcement->content = DocumentManager::replaceUrlWithNewCourseCode(
1614
                    $announcement->content,
1615
                    $this->course->code,
1616
                    $this->course->destination_path,
1617
                    $this->course->backup_path,
1618
                    $this->course->info['path']
0 ignored issues
show
Bug introduced by
The property info does not seem to exist on Chamilo\CourseBundle\Component\CourseCopy\Course.
Loading history...
1619
                );
1620
1621
                $params = [
1622
                    'c_id' => $this->destination_course_id,
1623
                    'title' =>  self::DBUTF8($announcement->title),
0 ignored issues
show
Bug Best Practice introduced by
The method Chamilo\CourseBundle\Com...ourseRestorer::DBUTF8() is not static, but was called statically. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

1623
                    'title' =>  self::/** @scrutinizer ignore-call */ DBUTF8($announcement->title),
Loading history...
1624
                    'content' => ($announcement->content === false ? '' : self::DBUTF8($announcement->content)),
1625
                    'end_date' => $announcement->date,
1626
                    'display_order' => $announcement->display_order,
1627
                    'email_sent' => $announcement->email_sent,
1628
                    'session_id' => $sessionId,
1629
                ];
1630
1631
                $new_announcement_id = Database::insert($table, $params);
1632
1633
                if ($new_announcement_id) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $new_announcement_id of type integer|false is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
1634
                    $sql = "UPDATE $table SET id = iid WHERE iid = $new_announcement_id";
1635
                    Database::query($sql);
1636
1637
                    if (!isset($this->course->resources[RESOURCE_ANNOUNCEMENT][$id])) {
1638
                        $this->course->resources[RESOURCE_ANNOUNCEMENT][$id] = new stdClass();
1639
                    }
1640
                    $this->course->resources[RESOURCE_ANNOUNCEMENT][$id]->destination_id = $new_announcement_id;
1641
                }
1642
1643
                $origin_path = $this->course->backup_path.'/upload/announcements/';
1644
                $destination_path = api_get_path(SYS_COURSE_PATH).$this->course->destination_path.'/upload/announcements/';
1645
1646
                // Copy announcement attachment file
1647
                if (!empty($this->course->orig)) {
1648
                    $table_attachment = Database::get_course_table(TABLE_ANNOUNCEMENT_ATTACHMENT);
1649
                    $sql = 'SELECT path, comment, size, filename
1650
                            FROM '.$table_attachment.'
1651
                            WHERE
1652
                                c_id = '.$this->destination_course_id.' AND
1653
                                announcement_id = '.$id;
1654
                    $attachment_event = Database::query($sql);
1655
                    $attachment_event = Database::fetch_object($attachment_event);
1656
1657
                    if (file_exists($origin_path.$attachment_event->path) &&
1658
                        !is_dir($origin_path.$attachment_event->path)
1659
                    ) {
1660
                        $new_filename = uniqid(''); //ass seen in the add_agenda_attachment_file() function in agenda.inc.php
1661
                        $copy_result = copy(
1662
                            $origin_path.$attachment_event->path,
1663
                            $destination_path.$new_filename
1664
                        );
1665
1666
                        if ($copy_result) {
1667
                            $table_attachment = Database::get_course_table(TABLE_ANNOUNCEMENT_ATTACHMENT);
1668
1669
                            $params = [
1670
                                'c_id' => $this->destination_course_id,
1671
                                'path' => self::DBUTF8($new_filename),
1672
                                'comment' => self::DBUTF8($attachment_event->comment),
1673
                                'size' => $attachment_event->size,
1674
                                'filename' => $attachment_event->filename,
1675
                                'announcement_id' => $new_announcement_id,
1676
                            ];
1677
1678
                            $attachmentId = Database::insert($table_attachment, $params);
1679
1680
                            if ($attachmentId) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $attachmentId of type integer|false is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
1681
                                $sql = "UPDATE $table_attachment SET id = iid WHERE iid = $attachmentId";
1682
                                Database::query($sql);
1683
                            }
1684
                        }
1685
                    }
1686
                } else {
1687
                    // get the info of the file
1688
                    if (!empty($announcement->attachment_path) &&
1689
                        is_file($origin_path.$announcement->attachment_path) &&
1690
                        is_readable($origin_path.$announcement->attachment_path)
1691
                    ) {
1692
                        $new_filename = uniqid(''); //ass seen in the add_agenda_attachment_file() function in agenda.inc.php
1693
                        $copy_result = copy($origin_path.$announcement->attachment_path, $destination_path.$new_filename);
1694
1695
                        if ($copy_result) {
1696
                            $table_attachment = Database::get_course_table(TABLE_ANNOUNCEMENT_ATTACHMENT);
1697
1698
                            $params = [
1699
                                'c_id' => $this->destination_course_id,
1700
                                'path' => self::DBUTF8($new_filename),
1701
                                'comment' => self::DBUTF8($announcement->attachment_comment),
1702
                                'size' => $announcement->attachment_size,
1703
                                'filename' => $announcement->attachment_filename,
1704
                                'announcement_id' => $new_announcement_id,
1705
                            ];
1706
1707
                            $attachmentId = Database::insert($table_attachment, $params);
1708
1709
                            if ($attachmentId) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $attachmentId of type integer|false is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
1710
                                $sql = "UPDATE $table_attachment SET id = iid WHERE iid = $attachmentId";
1711
                                Database::query($sql);
1712
                            }
1713
                        }
1714
                    }
1715
                }
1716
            }
1717
        }
1718
    }
1719
1720
    /**
1721
     * Restore Quiz
1722
     * @param int $session_id
1723
     * @param bool $respect_base_content
1724
     */
1725
    public function restore_quizzes(
1726
        $session_id = 0,
1727
        $respect_base_content = false
1728
    ) {
1729
        if ($this->course->has_resources(RESOURCE_QUIZ)) {
1730
            $table_qui = Database::get_course_table(TABLE_QUIZ_TEST);
1731
            $table_rel = Database::get_course_table(TABLE_QUIZ_TEST_QUESTION);
1732
            $table_doc = Database::get_course_table(TABLE_DOCUMENT);
1733
            $resources = $this->course->resources;
1734
1735
            foreach ($resources[RESOURCE_QUIZ] as $id => $quiz) {
1736
                if (isset($quiz->obj)) {
1737
                    // For new imports
1738
                    $quiz = $quiz->obj;
1739
                } else {
1740
                    // For backward compatibility
1741
                    $quiz->obj = $quiz;
1742
                }
1743
1744
                $doc = '';
1745
                if (!empty($quiz->sound)) {
1746
                    if (isset($this->course->resources[RESOURCE_DOCUMENT][$quiz->sound]) &&
1747
                        $this->course->resources[RESOURCE_DOCUMENT][$quiz->sound]->is_restored()) {
1748
                        $sql = "SELECT path FROM $table_doc
1749
                                WHERE
1750
                                    c_id = ".$this->destination_course_id."  AND
1751
                                    id = " . $resources[RESOURCE_DOCUMENT][$quiz->sound]->destination_id;
1752
                        $doc = Database::query($sql);
1753
                        $doc = Database::fetch_object($doc);
1754
                        $doc = str_replace('/audio/', '', $doc->path);
1755
                    }
1756
                }
1757
1758
                if ($id != -1) {
1759
                    // check resources inside html from ckeditor tool and copy correct urls into recipient course
1760
                    $quiz->description = DocumentManager::replaceUrlWithNewCourseCode(
1761
                        $quiz->description,
1762
                        $this->course->code,
1763
                        $this->course->destination_path,
1764
                        $this->course->backup_path,
1765
                        $this->course->info['path']
0 ignored issues
show
Bug introduced by
The property info does not seem to exist on Chamilo\CourseBundle\Component\CourseCopy\Course.
Loading history...
1766
                    );
1767
1768
                    $quiz->start_time = $quiz->start_time == '0000-00-00 00:00:00' ? null : $quiz->start_time;
1769
                    $quiz->end_time = $quiz->end_time == '0000-00-00 00:00:00' ? null : $quiz->end_time;
1770
1771
                    global $_custom;
1772
                    if (isset($_custom['exercises_clean_dates_when_restoring']) &&
1773
                        $_custom['exercises_clean_dates_when_restoring']
1774
                    ) {
1775
                        $quiz->start_time = null;
1776
                        $quiz->end_time   = null;
1777
                    }
1778
1779
                    $params = [
1780
                        'c_id' => $this->destination_course_id,
1781
                        'title' => self::DBUTF8($quiz->title),
0 ignored issues
show
Bug Best Practice introduced by
The method Chamilo\CourseBundle\Com...ourseRestorer::DBUTF8() is not static, but was called statically. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

1781
                        'title' => self::/** @scrutinizer ignore-call */ DBUTF8($quiz->title),
Loading history...
1782
                        'description' => ($quiz->description === false ? '' : self::DBUTF8($quiz->description)),
1783
                        'type' => isset($quiz->quiz_type) ? (int) $quiz->quiz_type : $quiz->type,
1784
                        'random' => (int) $quiz->random,
1785
                        'active' => $quiz->active,
1786
                        'sound' => self::DBUTF8($doc),
1787
                        'max_attempt' => (int) $quiz->max_attempt,
1788
                        'results_disabled' => (int) $quiz->results_disabled,
1789
                        'access_condition' => $quiz->access_condition,
1790
                        'pass_percentage' => $quiz->pass_percentage,
1791
                        'feedback_type' => (int) $quiz->feedback_type,
1792
                        'random_answers' => (int) $quiz->random_answers,
1793
                        'random_by_category' => (int) $quiz->random_by_category,
1794
                        'review_answers' => (int) $quiz->review_answers,
1795
                        'propagate_neg' => (int) $quiz->propagate_neg,
1796
                        'text_when_finished' => (string) $quiz->text_when_finished,
1797
                        'expired_time' => (int) $quiz->expired_time,
1798
                        'start_time' => $quiz->start_time,
1799
                        'end_time' => $quiz->end_time,
1800
                        'save_correct_answers' => 0,
1801
                        'display_category_name' => 0,
1802
                        'save_correct_answers' => $quiz->save_correct_answers,
1803
                        'hide_question_title' => isset($quiz->hide_question_title) ? $quiz->hide_question_title : 0,
1804
                    ];
1805
1806
                    $allow = api_get_configuration_value('allow_notification_setting_per_exercise');
1807
                    if ($allow) {
1808
                        $params['notifications'] = $quiz->notifications;
1809
                    }
1810
1811
                    if ($respect_base_content) {
1812
                        $my_session_id = $quiz->session_id;
1813
                        if (!empty($quiz->session_id)) {
1814
                            $my_session_id = $session_id;
1815
                        }
1816
                        $params['session_id'] = $my_session_id;
1817
                    } else {
1818
                        if (!empty($session_id)) {
1819
                            $session_id = intval($session_id);
1820
                            $params['session_id'] = $session_id;
1821
                        }
1822
                    }
1823
                    $new_id = Database::insert($table_qui, $params);
1824
1825
                    if ($new_id) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $new_id of type integer|false is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
1826
                        $sql = "UPDATE $table_qui SET id = iid WHERE iid = $new_id";
1827
                        Database::query($sql);
1828
                    }
1829
                } else {
1830
                    // $id = -1 identifies the fictionary test for collecting
1831
                    // orphan questions. We do not store it in the database.
1832
                    $new_id = -1;
1833
                }
1834
1835
                $this->course->resources[RESOURCE_QUIZ][$id]->destination_id = $new_id;
1836
1837
                $order = 0;
1838
                if (!empty($quiz->question_ids)) {
1839
                    foreach ($quiz->question_ids as $index => $question_id) {
1840
                        $qid = $this->restore_quiz_question($question_id);
1841
                        $question_order = $quiz->question_orders[$index] ? $quiz->question_orders[$index] : ++$order;
1842
                        $sql = "INSERT IGNORE INTO $table_rel SET
1843
                                c_id = ".$this->destination_course_id.",
1844
                                question_id = $qid ,
1845
                                exercice_id = $new_id ,
1846
                                question_order = ".$question_order;
1847
                        Database::query($sql);
1848
                    }
1849
                }
1850
            }
1851
        }
1852
    }
1853
1854
    /**
1855
     * Restore quiz-questions
1856
     * @params int $id question id
1857
     */
1858
    public function restore_quiz_question($id)
1859
    {
1860
        $em = Database::getManager();
1861
        $resources = $this->course->resources;
1862
        /** @var QuizQuestion $question */
1863
        $question = isset($resources[RESOURCE_QUIZQUESTION][$id]) ? $resources[RESOURCE_QUIZQUESTION][$id] : null;
1864
        $new_id = 0;
1865
1866
        if (is_object($question)) {
1867
            if ($question->is_restored()) {
1868
                return $question->destination_id;
1869
            }
1870
            $table_que = Database::get_course_table(TABLE_QUIZ_QUESTION);
1871
            $table_ans = Database::get_course_table(TABLE_QUIZ_ANSWER);
1872
            $table_options = Database::get_course_table(TABLE_QUIZ_QUESTION_OPTION);
1873
1874
            // check resources inside html from ckeditor tool and copy correct urls into recipient course
1875
            $question->description = DocumentManager::replaceUrlWithNewCourseCode(
1876
                $question->description,
1877
                $this->course->code,
1878
                $this->course->destination_path,
1879
                $this->course->backup_path,
1880
                $this->course->info['path']
0 ignored issues
show
Bug introduced by
The property info does not seem to exist on Chamilo\CourseBundle\Component\CourseCopy\Course.
Loading history...
1881
            );
1882
1883
            $imageNewId = '';
1884
            if (preg_match('/^quiz-.*$/', $question->picture) &&
1885
                isset($resources[RESOURCE_DOCUMENT]['image_quiz'][$question->picture])
1886
            ) {
1887
                $imageNewId = $resources[RESOURCE_DOCUMENT]['image_quiz'][$question->picture]['destination_id'];
1888
            } else {
1889
                if (isset($resources[RESOURCE_DOCUMENT][$question->picture])) {
1890
                    $documentsToRestore = $resources[RESOURCE_DOCUMENT][$question->picture];
1891
                    $imageNewId = $documentsToRestore->destination_id;
1892
                }
1893
            }
1894
1895
            $params = [
1896
                'c_id' => $this->destination_course_id,
1897
                'question' => self::DBUTF8($question->question),
0 ignored issues
show
Bug Best Practice introduced by
The method Chamilo\CourseBundle\Com...ourseRestorer::DBUTF8() is not static, but was called statically. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

1897
                'question' => self::/** @scrutinizer ignore-call */ DBUTF8($question->question),
Loading history...
1898
                'description' => ($question->description === false ? '' : self::DBUTF8($question->description)),
1899
                'ponderation' => self::DBUTF8($question->ponderation),
1900
                'position' => self::DBUTF8($question->position),
1901
                'type' => self::DBUTF8($question->quiz_type),
1902
                'picture' => self::DBUTF8($imageNewId),
1903
                'level' => self::DBUTF8($question->level),
1904
                'extra' => self::DBUTF8($question->extra),
1905
            ];
1906
1907
            $new_id = Database::insert($table_que, $params);
1908
1909
            if ($new_id) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $new_id of type integer|false is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
1910
                $sql = "UPDATE $table_que SET id = iid WHERE iid = $new_id";
1911
                Database::query($sql);
1912
            }
1913
1914
            $correctAnswers = [];
1915
            $allAnswers = [];
1916
            $onlyAnswers = [];
1917
1918
            if (in_array($question->quiz_type, [DRAGGABLE, MATCHING, MATCHING_DRAGGABLE])) {
1919
                $allAnswers = array_column($question->answers, 'answer', 'id');
1920
            }
1921
1922
            if (in_array($question->quiz_type, [MATCHING, MATCHING_DRAGGABLE])) {
1923
                $temp = [];
1924
                foreach ($question->answers as $index => $answer) {
1925
                    $temp[$answer['position']] = $answer;
1926
                }
1927
1928
                foreach ($temp as $index => $answer) {
1929
                    // check resources inside html from ckeditor tool and copy correct urls into recipient course
1930
                    $answer['answer'] = DocumentManager::replaceUrlWithNewCourseCode(
1931
                        $answer['answer'],
1932
                        $this->course->code,
1933
                        $this->course->destination_path,
1934
                        $this->course->backup_path,
1935
                        $this->course->info['path']
1936
                    );
1937
1938
                    $answer['comment'] = DocumentManager::replaceUrlWithNewCourseCode(
1939
                        $answer['comment'],
1940
                        $this->course->code,
1941
                        $this->course->destination_path,
1942
                        $this->course->backup_path,
1943
                        $this->course->info['path']
1944
                    );
1945
1946
                    $quizAnswer = new CQuizAnswer();
1947
                    $quizAnswer
1948
                        ->setCId($this->destination_course_id)
1949
                        ->setQuestionId($new_id)
0 ignored issues
show
Bug introduced by
It seems like $new_id can also be of type false; however, parameter $questionId of Chamilo\CourseBundle\Ent...Answer::setQuestionId() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1949
                        ->setQuestionId(/** @scrutinizer ignore-type */ $new_id)
Loading history...
1950
                        ->setAnswer(self::DBUTF8($answer['answer']))
1951
                        ->setCorrect($answer['correct'])
1952
                        ->setComment($answer['comment'] === false ? '' : self::DBUTF8($answer['comment']))
1953
                        ->setPonderation($answer['ponderation'])
1954
                        ->setPosition($answer['position'])
1955
                        ->setHotspotCoordinates($answer['hotspot_coordinates'])
1956
                        ->setHotspotType($answer['hotspot_type'])
1957
                        ->setIdAuto(0);
1958
1959
                    $em->persist($quizAnswer);
1960
                    $em->flush();
1961
1962
                    $answerId = $quizAnswer->getIid();
1963
1964
                    if ($answerId) {
1965
                        $quizAnswer
1966
                            ->setId($answerId)
1967
                            ->setIdAuto($answerId);
1968
1969
                        $em->merge($quizAnswer);
1970
                        $em->flush();
1971
1972
                        $correctAnswers[$answerId] = $answer['correct'];
1973
                        $onlyAnswers[$answerId] = $answer['answer'];
1974
                    }
1975
                }
1976
            } else {
1977
                foreach ($question->answers as $index => $answer) {
1978
                    // check resources inside html from ckeditor tool and copy correct urls into recipient course
1979
                    $answer['answer'] = DocumentManager::replaceUrlWithNewCourseCode(
1980
                        $answer['answer'],
1981
                        $this->course->code,
1982
                        $this->course->destination_path,
1983
                        $this->course->backup_path,
1984
                        $this->course->info['path']
1985
                    );
1986
1987
                    $answer['comment'] = DocumentManager::replaceUrlWithNewCourseCode(
1988
                        $answer['comment'],
1989
                        $this->course->code,
1990
                        $this->course->destination_path,
1991
                        $this->course->backup_path,
1992
                        $this->course->info['path']
1993
                    );
1994
1995
                    $params = [
1996
                        'c_id' => $this->destination_course_id,
1997
                        'question_id' => $new_id,
1998
                        'answer' => self::DBUTF8($answer['answer']),
1999
                        'correct' => $answer['correct'],
2000
                        'comment' => ($answer['comment'] === false ? '' : self::DBUTF8($answer['comment'])),
2001
                        'ponderation' => $answer['ponderation'],
2002
                        'position' => $answer['position'],
2003
                        'hotspot_coordinates' => $answer['hotspot_coordinates'],
2004
                        'hotspot_type' => $answer['hotspot_type'],
2005
                        'id_auto' => 0,
2006
                        'destination' => '',
2007
                    ];
2008
2009
                    $answerId = Database::insert($table_ans, $params);
2010
2011
                    if ($answerId) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $answerId of type integer|false is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
2012
                        $sql = "UPDATE $table_ans SET id = iid, id_auto = iid WHERE iid = $answerId";
2013
                        Database::query($sql);
2014
                    }
2015
2016
                    $correctAnswers[$answerId] = $answer['correct'];
2017
                    $onlyAnswers[$answerId] = $answer['answer'];
2018
                }
2019
            }
2020
2021
            // Current course id
2022
            $course_id = api_get_course_int_id();
2023
2024
            // Moving quiz_question_options
2025
            if ($question->quiz_type == MULTIPLE_ANSWER_TRUE_FALSE) {
2026
                $question_option_list = Question::readQuestionOption($id, $course_id);
2027
2028
                // Question copied from the current platform
2029
                if ($question_option_list) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $question_option_list of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
2030
                    $old_option_ids = [];
2031
                    foreach ($question_option_list as $item) {
2032
                        $old_id = $item['id'];
2033
                        unset($item['id']);
2034
                        if (isset($item['iid'])) {
2035
                            unset($item['iid']);
2036
                        }
2037
                        $item['question_id'] = $new_id;
2038
                        $item['c_id'] = $this->destination_course_id;
2039
                        $question_option_id = Database::insert($table_options, $item);
2040
                        if ($question_option_id) {
2041
                            $old_option_ids[$old_id] = $question_option_id;
2042
                            $sql = "UPDATE $table_options SET id = iid WHERE iid = $question_option_id";
2043
                            Database::query($sql);
2044
                        }
2045
                    }
2046
                    if ($old_option_ids) {
2047
                        $new_answers = Database::select(
2048
                            'iid, correct',
2049
                            $table_ans,
2050
                            [
2051
                                'WHERE' => [
2052
                                    'question_id = ? AND c_id = ? ' => [
2053
                                        $new_id,
2054
                                        $this->destination_course_id,
2055
                                    ],
2056
                                ],
2057
                            ]
2058
                        );
2059
2060
                        foreach ($new_answers as $answer_item) {
2061
                            $params = [];
2062
                            $params['correct'] = $old_option_ids[$answer_item['correct']];
2063
                            Database::update(
2064
                                $table_ans,
2065
                                $params,
2066
                                [
2067
                                    'iid = ? AND c_id = ? AND question_id = ? ' => [
2068
                                        $answer_item['iid'],
2069
                                        $this->destination_course_id,
2070
                                        $new_id,
2071
                                    ],
2072
                                ],
2073
                                false
2074
                            );
2075
                        }
2076
                    }
2077
                } else {
2078
                    $new_options = [];
2079
                    if (isset($question->question_options)) {
2080
                        foreach ($question->question_options as $obj) {
2081
                            $item = [];
2082
                            $item['question_id'] = $new_id;
2083
                            $item['c_id'] = $this->destination_course_id;
2084
                            $item['name'] = $obj->obj->name;
2085
                            $item['position'] = $obj->obj->position;
2086
                            $question_option_id = Database::insert($table_options, $item);
2087
2088
                            if ($question_option_id) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $question_option_id of type integer|false is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
2089
                                $new_options[$obj->obj->id] = $question_option_id;
2090
                                $sql = "UPDATE $table_options SET id = iid WHERE iid = $question_option_id";
2091
                                Database::query($sql);
2092
                            }
2093
                        }
2094
2095
                        foreach ($correctAnswers as $answer_id => $correct_answer) {
2096
                            $params = [];
2097
                            $params['correct'] = $new_options[$correct_answer];
2098
                            Database::update(
2099
                                $table_ans,
2100
                                $params,
2101
                                [
2102
                                    'id = ? AND c_id = ? AND question_id = ? ' => [
2103
                                        $answer_id,
2104
                                        $this->destination_course_id,
2105
                                        $new_id,
2106
                                    ],
2107
                                ],
2108
                                false
2109
                            );
2110
                        }
2111
                    }
2112
                }
2113
            }
2114
2115
            // Fix correct answers
2116
            if (in_array($question->quiz_type, [DRAGGABLE, MATCHING, MATCHING_DRAGGABLE])) {
2117
                $onlyAnswersFlip = array_flip($onlyAnswers);
2118
                foreach ($correctAnswers as $answer_id => $correct_answer) {
2119
                    $params = [];
2120
                    if (isset($allAnswers[$correct_answer]) &&
2121
                        isset($onlyAnswersFlip[$allAnswers[$correct_answer]])
2122
                    ) {
2123
                        $params['correct'] = $onlyAnswersFlip[$allAnswers[$correct_answer]];
2124
                        Database::update(
2125
                            $table_ans,
2126
                            $params,
2127
                            [
2128
                                'id = ? AND c_id = ? AND question_id = ? ' => [
2129
                                    $answer_id,
2130
                                    $this->destination_course_id,
2131
                                    $new_id,
2132
                                ],
2133
                            ]
2134
                        );
2135
                    }
2136
                }
2137
            }
2138
2139
            $this->course->resources[RESOURCE_QUIZQUESTION][$id]->destination_id = $new_id;
2140
        }
2141
2142
        return $new_id;
2143
    }
2144
2145
    /**
2146
     * @todo : add session id when used for session
2147
     */
2148
    public function restore_test_category($session_id, $respect_base_content, $destination_course_code)
2149
    {
2150
        $destinationCourseId = $this->destination_course_info['real_id'];
2151
        // Let's restore the categories
2152
        $categoryOldVsNewList = []; // used to build the quiz_question_rel_category table
2153
        if ($this->course->has_resources(RESOURCE_TEST_CATEGORY)) {
2154
            $resources = $this->course->resources;
2155
            foreach ($resources[RESOURCE_TEST_CATEGORY] as $id => $courseCopyTestCategory) {
2156
                $categoryOldVsNewList[$courseCopyTestCategory->source_id] = $id;
2157
                // check if this test_category already exist in the destination BDD
2158
                // do not Database::escape_string $title and $description, it will be done later
2159
                $title = $courseCopyTestCategory->title;
2160
                $description = $courseCopyTestCategory->description;
2161
                if (TestCategory::categoryTitleExists($title, $destinationCourseId)) {
2162
                    switch ($this->file_option) {
2163
                        case FILE_SKIP:
2164
                            //Do nothing
2165
                            break;
2166
                        case FILE_RENAME:
2167
                            $new_title = $title.'_';
2168
                            while (TestCategory::categoryTitleExists($new_title, $destinationCourseId)) {
2169
                                $new_title .= '_';
2170
                            }
2171
                            $test_category = new TestCategory();
2172
                            $test_category->name = $new_title;
2173
                            $test_category->description = $description;
2174
                            $new_id = $test_category->save($destinationCourseId);
2175
                            $categoryOldVsNewList[$courseCopyTestCategory->source_id] = $new_id;
2176
                            break;
2177
                        case FILE_OVERWRITE:
2178
                            // get category from source
2179
                            $destinationCategoryId = TestCategory::get_category_id_for_title(
2180
                                $title,
2181
                                $destinationCourseId
2182
                            );
2183
                            if ($destinationCategoryId) {
2184
                                $my_cat = new TestCategory();
2185
                                $my_cat = $my_cat->getCategory($destinationCategoryId, $destinationCourseId);
2186
                                $my_cat->name = $title;
2187
                                $my_cat->description = $description;
2188
                                $my_cat->modifyCategory($destinationCourseId);
2189
                                $categoryOldVsNewList[$courseCopyTestCategory->source_id] = $destinationCategoryId;
2190
                            }
2191
                            break;
2192
                    }
2193
                } else {
2194
                    // create a new test_category
2195
                    $test_category = new TestCategory();
2196
                    $test_category->name = $title;
2197
                    $test_category->description = $description;
2198
                    $new_id = $test_category->save($destinationCourseId);
2199
                    $categoryOldVsNewList[$courseCopyTestCategory->source_id] = $new_id;
2200
                }
2201
                $this->course->resources[RESOURCE_TEST_CATEGORY][$id]->destination_id = $categoryOldVsNewList[$courseCopyTestCategory->source_id];
2202
            }
2203
        }
2204
2205
        // lets check if quizzes-question are restored too,
2206
        // to redo the link between test_category and quizzes question for questions restored
2207
        // we can use the source_id field
2208
        // question source_id => category source_id
2209
        if ($this->course->has_resources(RESOURCE_QUIZQUESTION)) {
2210
            // check the category number of each question restored
2211
            if (!empty($resources[RESOURCE_QUIZQUESTION])) {
2212
                foreach ($resources[RESOURCE_QUIZQUESTION] as $id => $courseCopyQuestion) {
2213
                    $newQuestionId = $resources[RESOURCE_QUIZQUESTION][$id]->destination_id;
2214
                    $questionCategoryId = $courseCopyQuestion->question_category;
2215
                    if ($newQuestionId > 0 &&
2216
                        $questionCategoryId > 0 &&
2217
                        isset($categoryOldVsNewList[$questionCategoryId])
2218
                    ) {
2219
                        TestCategory::addCategoryToQuestion(
2220
                            $categoryOldVsNewList[$questionCategoryId],
2221
                            $newQuestionId,
2222
                            $destinationCourseId
2223
                        );
2224
                    }
2225
                }
2226
            }
2227
        }
2228
    }
2229
2230
    /**
2231
     * Restore surveys
2232
     * @param int $sessionId Optional. The session id
2233
     */
2234
    public function restore_surveys($sessionId = 0)
2235
    {
2236
        $sessionId = intval($sessionId);
2237
        if ($this->course->has_resources(RESOURCE_SURVEY)) {
2238
            $table_sur = Database::get_course_table(TABLE_SURVEY);
2239
            $table_que = Database::get_course_table(TABLE_SURVEY_QUESTION);
2240
            $table_ans = Database::get_course_table(TABLE_SURVEY_QUESTION_OPTION);
2241
            $resources = $this->course->resources;
2242
            foreach ($resources[RESOURCE_SURVEY] as $id => $survey) {
2243
                $sql = 'SELECT survey_id FROM '.$table_sur.'
2244
                        WHERE
2245
                            c_id = '.$this->destination_course_id.' AND
2246
                            code = "'.self::DBUTF8escapestring($survey->code).'" AND
0 ignored issues
show
Bug Best Practice introduced by
The method Chamilo\CourseBundle\Com...r::DBUTF8escapestring() is not static, but was called statically. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

2246
                            code = "'.self::/** @scrutinizer ignore-call */ DBUTF8escapestring($survey->code).'" AND
Loading history...
2247
                            lang = "'.self::DBUTF8escapestring($survey->lang).'" ';
2248
2249
                $result_check = Database::query($sql);
2250
2251
                // check resources inside html from ckeditor tool and copy correct urls into recipient course
2252
                $survey->title = DocumentManager::replaceUrlWithNewCourseCode(
2253
                    $survey->title,
2254
                    $this->course->code,
2255
                    $this->course->destination_path,
2256
                    $this->course->backup_path,
2257
                    $this->course->info['path']
0 ignored issues
show
Bug introduced by
The property info does not seem to exist on Chamilo\CourseBundle\Component\CourseCopy\Course.
Loading history...
2258
                );
2259
2260
                $survey->subtitle = DocumentManager::replaceUrlWithNewCourseCode(
2261
                    $survey->subtitle,
2262
                    $this->course->code,
2263
                    $this->course->destination_path,
2264
                    $this->course->backup_path,
2265
                    $this->course->info['path']
2266
                );
2267
2268
                $survey->intro = DocumentManager::replaceUrlWithNewCourseCode(
2269
                    $survey->intro,
2270
                    $this->course->code,
2271
                    $this->course->destination_path,
2272
                    $this->course->backup_path,
2273
                    $this->course->info['path']
2274
                );
2275
2276
                $survey->surveythanks = DocumentManager::replaceUrlWithNewCourseCode(
2277
                    $survey->surveythanks,
2278
                    $this->course->code,
2279
                    $this->course->destination_path,
2280
                    $this->course->backup_path,
2281
                    $this->course->info['path']
2282
                );
2283
2284
                $params = [
2285
                    'c_id' => $this->destination_course_id,
2286
                    'code' => self::DBUTF8($survey->code),
0 ignored issues
show
Bug Best Practice introduced by
The method Chamilo\CourseBundle\Com...ourseRestorer::DBUTF8() is not static, but was called statically. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

2286
                    'code' => self::/** @scrutinizer ignore-call */ DBUTF8($survey->code),
Loading history...
2287
                    'title' => ($survey->title === false ? '' : self::DBUTF8($survey->title)),
2288
                    'subtitle' => ($survey->subtitle === false ? '' : self::DBUTF8($survey->subtitle)),
2289
                    'author' => self::DBUTF8($survey->author),
2290
                    'lang' => self::DBUTF8($survey->lang),
2291
                    'avail_from' => self::DBUTF8($survey->avail_from),
2292
                    'avail_till' => self::DBUTF8($survey->avail_till),
2293
                    'is_shared' => self::DBUTF8($survey->is_shared),
2294
                    'template' => self::DBUTF8($survey->template),
2295
                    'intro' => ($survey->intro === false ? '' : self::DBUTF8($survey->intro)),
2296
                    'surveythanks' => ($survey->surveythanks === false ? '' : self::DBUTF8($survey->surveythanks)),
2297
                    'creation_date' => self::DBUTF8($survey->creation_date),
2298
                    'invited' => '0',
2299
                    'answered' => '0',
2300
                    'invite_mail' => self::DBUTF8($survey->invite_mail),
2301
                    'reminder_mail' => self::DBUTF8($survey->reminder_mail),
2302
                    'session_id' => $sessionId,
2303
                ];
2304
2305
                //An existing survey exists with the same code and the same language
2306
                if (Database::num_rows($result_check) == 1) {
2307
                    switch ($this->file_option) {
2308
                        case FILE_SKIP:
2309
                            //Do nothing
2310
                            break;
2311
                        case FILE_RENAME:
2312
                            $survey_code = $survey->code.'_';
2313
                            $i = 1;
2314
                            $temp_survey_code = $survey_code.$i;
2315
                            while (!$this->is_survey_code_available($temp_survey_code)) {
2316
                                $temp_survey_code = $survey_code.++$i;
2317
                            }
2318
                            $survey_code = $temp_survey_code;
2319
2320
                            $params['code'] = $survey_code;
2321
                            $new_id = Database::insert($table_sur, $params);
2322
                            if ($new_id) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $new_id of type integer|false is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
2323
                                $sql = "UPDATE $table_sur SET survey_id = iid WHERE iid = $new_id";
2324
                                Database::query($sql);
2325
2326
                                $this->course->resources[RESOURCE_SURVEY][$id]->destination_id = $new_id;
2327
                                foreach ($survey->question_ids as $index => $question_id) {
2328
                                    $qid = $this->restore_survey_question($question_id, $new_id);
2329
                                    $sql = "UPDATE $table_que SET survey_id = $new_id
2330
                                            WHERE c_id = ".$this->destination_course_id." AND question_id = $qid";
2331
                                    Database::query($sql);
2332
                                    $sql = "UPDATE $table_ans SET survey_id = $new_id
2333
                                            WHERE  c_id = ".$this->destination_course_id." AND  question_id = $qid";
2334
                                    Database::query($sql);
2335
                                }
2336
                            }
2337
                            break;
2338
                        case FILE_OVERWRITE:
2339
                            // Delete the existing survey with the same code and language and
2340
                            // import the one of the source course
2341
                            // getting the information of the survey (used for when the survey is shared)
2342
2343
                            $sql = "SELECT * FROM $table_sur
2344
                                    WHERE
2345
                                        c_id = ".$this->destination_course_id." AND
2346
                                        survey_id='".self::DBUTF8escapestring(Database::result($result_check, 0, 0))."'";
2347
                            $result = Database::query($sql);
2348
                            $survey_data = Database::fetch_array($result, 'ASSOC');
2349
2350
                            // if the survey is shared => also delete the shared content
2351
                            if (isset($survey_data['survey_share']) && is_numeric($survey_data['survey_share'])) {
2352
                                SurveyManager::delete_survey(
2353
                                    $survey_data['survey_share'],
2354
                                    true,
2355
                                    $this->destination_course_id
2356
                                );
2357
                            }
2358
                            SurveyManager::delete_survey(
2359
                                $survey_data['survey_id'],
2360
                                false,
2361
                                $this->destination_course_id
2362
                            );
2363
2364
                            // Insert the new source survey
2365
                            $new_id = Database::insert($table_sur, $params);
2366
2367
                            if ($new_id) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $new_id of type integer|false is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
2368
                                $sql = "UPDATE $table_sur SET survey_id = iid WHERE iid = $new_id";
2369
                                Database::query($sql);
2370
2371
                                $this->course->resources[RESOURCE_SURVEY][$id]->destination_id = $new_id;
2372
                                foreach ($survey->question_ids as $index => $question_id) {
2373
                                    $qid = $this->restore_survey_question(
2374
                                        $question_id,
2375
                                        $new_id
2376
                                    );
2377
                                    $sql = "UPDATE $table_que SET survey_id = $new_id
2378
                                            WHERE c_id = ".$this->destination_course_id." AND question_id = $qid";
2379
                                    Database::query($sql);
2380
                                    $sql = "UPDATE $table_ans SET survey_id = $new_id
2381
                                            WHERE c_id = ".$this->destination_course_id." AND question_id = $qid";
2382
                                    Database::query($sql);
2383
                                }
2384
                            }
2385
                            break;
2386
                        default:
2387
                            break;
2388
                    }
2389
                } else {
2390
                    // No existing survey with the same language and the same code, we just copy the survey
2391
                    $new_id = Database::insert($table_sur, $params);
2392
2393
                    if ($new_id) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $new_id of type integer|false is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
2394
                        $sql = "UPDATE $table_sur SET survey_id = iid WHERE iid = $new_id";
2395
                        Database::query($sql);
2396
2397
                        $this->course->resources[RESOURCE_SURVEY][$id]->destination_id = $new_id;
2398
                        foreach ($survey->question_ids as $index => $question_id) {
2399
                            $qid = $this->restore_survey_question(
2400
                                $question_id,
2401
                                $new_id
2402
                            );
2403
                            $sql = "UPDATE $table_que SET survey_id = $new_id
2404
                                    WHERE c_id = ".$this->destination_course_id." AND question_id = $qid";
2405
                            Database::query($sql);
2406
                            $sql = "UPDATE $table_ans SET survey_id = $new_id
2407
                                    WHERE c_id = ".$this->destination_course_id." AND question_id = $qid";
2408
                            Database::query($sql);
2409
                        }
2410
                    }
2411
                }
2412
            }
2413
        }
2414
    }
2415
2416
    /**
2417
     * Check availability of a survey code
2418
     * @param string $survey_code
2419
     * @return bool
2420
     */
2421
    public function is_survey_code_available($survey_code)
2422
    {
2423
        $table_sur = Database::get_course_table(TABLE_SURVEY);
2424
        $sql = "SELECT * FROM $table_sur
2425
                WHERE
2426
                    c_id = ".$this->destination_course_id." AND
2427
                    code = '".self::DBUTF8escapestring($survey_code)."'";
0 ignored issues
show
Bug Best Practice introduced by
The method Chamilo\CourseBundle\Com...r::DBUTF8escapestring() is not static, but was called statically. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

2427
                    code = '".self::/** @scrutinizer ignore-call */ DBUTF8escapestring($survey_code)."'";
Loading history...
2428
        $result = Database::query($sql);
2429
        if (Database::num_rows($result) > 0) {
2430
            return false;
2431
        } else {
2432
            return true;
2433
        }
2434
    }
2435
2436
    /**
2437
     * Restore survey-questions
2438
     * @param int $id
2439
     * @param string $survey_id
2440
     */
2441
    public function restore_survey_question($id, $survey_id)
2442
    {
2443
        $resources = $this->course->resources;
2444
        $question = $resources[RESOURCE_SURVEYQUESTION][$id];
2445
        $new_id = 0;
2446
2447
        if (is_object($question)) {
2448
            if ($question->is_restored()) {
2449
                return $question->destination_id;
2450
            }
2451
            $table_que = Database::get_course_table(TABLE_SURVEY_QUESTION);
2452
            $table_ans = Database::get_course_table(TABLE_SURVEY_QUESTION_OPTION);
2453
2454
            // check resources inside html from ckeditor tool and copy correct urls into recipient course
2455
            $question->survey_question = DocumentManager::replaceUrlWithNewCourseCode(
2456
                $question->survey_question,
2457
                $this->course->code,
2458
                $this->course->destination_path,
2459
                $this->course->backup_path,
2460
                $this->course->info['path']
0 ignored issues
show
Bug introduced by
The property info does not seem to exist on Chamilo\CourseBundle\Component\CourseCopy\Course.
Loading history...
2461
            );
2462
2463
            $params = [
2464
                'c_id' => $this->destination_course_id,
2465
                'survey_id' => self::DBUTF8($survey_id),
0 ignored issues
show
Bug Best Practice introduced by
The method Chamilo\CourseBundle\Com...ourseRestorer::DBUTF8() is not static, but was called statically. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

2465
                'survey_id' => self::/** @scrutinizer ignore-call */ DBUTF8($survey_id),
Loading history...
2466
                'survey_question' => ($question->survey_question === false ? '' : self::DBUTF8($question->survey_question)),
2467
                'survey_question_comment' => self::DBUTF8($question->survey_question_comment),
2468
                'type' => self::DBUTF8($question->survey_question_type),
2469
                'display' => self::DBUTF8($question->display),
2470
                'sort' => self::DBUTF8($question->sort),
2471
                'shared_question_id' => self::DBUTF8($question->shared_question_id),
2472
                'max_value' => self::DBUTF8($question->max_value),
2473
            ];
2474
            if (api_get_configuration_value('allow_required_survey_questions')) {
2475
                if (isset($question->is_required)) {
2476
                    $params['is_required'] = $question->is_required;
2477
                }
2478
            }
2479
2480
2481
            $new_id = Database::insert($table_que, $params);
2482
            if ($new_id) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $new_id of type integer|false is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
2483
                $sql = "UPDATE $table_que SET question_id = iid WHERE iid = $new_id";
2484
                Database::query($sql);
2485
2486
                foreach ($question->answers as $index => $answer) {
2487
2488
                    // check resources inside html from ckeditor tool and copy correct urls into recipient course
2489
                    $answer['option_text'] = DocumentManager::replaceUrlWithNewCourseCode(
2490
                        $answer['option_text'],
2491
                        $this->course->code,
2492
                        $this->course->destination_path,
2493
                        $this->course->backup_path,
2494
                        $this->course->info['path']
2495
                    );
2496
2497
                    $params = [
2498
                        'c_id' => $this->destination_course_id,
2499
                        'question_id' => $new_id,
2500
                        'option_text' => ($answer['option_text'] === false ? '' : self::DBUTF8($answer['option_text'])),
2501
                        'sort' => $answer['sort'],
2502
                        'survey_id' => self::DBUTF8($survey_id),
2503
                    ];
2504
                    $answerId = Database::insert($table_ans, $params);
2505
                    if ($answerId) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $answerId of type integer|false is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
2506
                        $sql = "UPDATE $table_ans SET question_option_id = iid
2507
                                WHERE iid = $answerId";
2508
                        Database::query($sql);
2509
                    }
2510
                }
2511
                $this->course->resources[RESOURCE_SURVEYQUESTION][$id]->destination_id = $new_id;
2512
            }
2513
        }
2514
2515
        return $new_id;
2516
    }
2517
2518
    /**
2519
     * Restoring learning paths
2520
     * @param int $session_id
2521
     * @param bool|false $respect_base_content
2522
     */
2523
    public function restore_learnpaths($session_id = 0, $respect_base_content = false)
2524
    {
2525
        $session_id = intval($session_id);
2526
2527
        if ($this->course->has_resources(RESOURCE_LEARNPATH)) {
2528
            $table_main = Database::get_course_table(TABLE_LP_MAIN);
2529
            $table_item = Database::get_course_table(TABLE_LP_ITEM);
2530
            $table_tool = Database::get_course_table(TABLE_TOOL_LIST);
2531
2532
            $resources = $this->course->resources;
2533
2534
            $origin_path = $this->course->backup_path.'/upload/learning_path/images/';
2535
            $destination_path = api_get_path(SYS_COURSE_PATH).$this->course->destination_path.'/upload/learning_path/images/';
2536
2537
            foreach ($resources[RESOURCE_LEARNPATH] as $id => $lp) {
2538
                $condition_session = '';
2539
                if (!empty($session_id)) {
2540
                    if ($respect_base_content) {
2541
                        $my_session_id = $lp->session_id;
2542
                        if (!empty($lp->session_id)) {
2543
                            $my_session_id = $session_id;
2544
                        }
2545
                        $condition_session = $my_session_id;
2546
                    } else {
2547
                        $session_id = intval($session_id);
2548
                        $condition_session = $session_id;
2549
                    }
2550
                }
2551
2552
                // Adding the author's image
2553
                if (!empty($lp->preview_image)) {
2554
                    $new_filename = uniqid('').substr(
2555
                        $lp->preview_image,
2556
                        strlen($lp->preview_image) - 7,
2557
                        strlen($lp->preview_image)
2558
                    );
2559
                    if (file_exists($origin_path.$lp->preview_image) &&
2560
                        !is_dir($origin_path.$lp->preview_image)
2561
                    ) {
2562
                        $copy_result = copy(
2563
                            $origin_path.$lp->preview_image,
2564
                            $destination_path.$new_filename
2565
                        );
2566
                        if ($copy_result) {
2567
                            $lp->preview_image = $new_filename;
2568
                        } else {
2569
                            $lp->preview_image = '';
2570
                        }
2571
                    }
2572
                }
2573
2574
                if ($this->add_text_in_items) {
2575
                    $lp->name = $lp->name.' '.get_lang('CopyLabelSuffix');
2576
                }
2577
2578
                if (isset($this->tool_copy_settings['learnpaths'])) {
2579
                    if (isset($this->tool_copy_settings['learnpaths']['reset_dates']) &&
2580
                        $this->tool_copy_settings['learnpaths']['reset_dates']
2581
                    ) {
2582
                        $lp->created_on = api_get_utc_datetime();
2583
                        $lp->modified_on = api_get_utc_datetime();
2584
                        $lp->publicated_on = null;
2585
                    }
2586
                }
2587
2588
                $lp->expired_on = isset($lp->expired_on) && $lp->expired_on === '0000-00-00 00:00:00' ? null : $lp->expired_on;
2589
                $lp->publicated_on = isset($lp->publicated_on) && $lp->publicated_on === '0000-00-00 00:00:00' ? null : $lp->publicated_on;
2590
2591
                $params = [
2592
                    'c_id' => $this->destination_course_id,
2593
                    'lp_type' => $lp->lp_type,
2594
                    'name' => self::DBUTF8($lp->name),
0 ignored issues
show
Bug Best Practice introduced by
The method Chamilo\CourseBundle\Com...ourseRestorer::DBUTF8() is not static, but was called statically. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

2594
                    'name' => self::/** @scrutinizer ignore-call */ DBUTF8($lp->name),
Loading history...
2595
                    'path' => self::DBUTF8($lp->path),
2596
                    'ref' => $lp->ref,
2597
                    'description' => self::DBUTF8($lp->description),
2598
                    'content_local' => self::DBUTF8($lp->content_local),
2599
                    'default_encoding' => self::DBUTF8($lp->default_encoding),
2600
                    'default_view_mod' => self::DBUTF8($lp->default_view_mod),
2601
                    'prevent_reinit' => self::DBUTF8($lp->prevent_reinit),
2602
                    'force_commit' => self::DBUTF8($lp->force_commit),
2603
                    'content_maker' => self::DBUTF8($lp->content_maker),
2604
                    'display_order' => self::DBUTF8($lp->display_order),
2605
                    'js_lib' => self::DBUTF8($lp->js_lib),
2606
                    'content_license' => self::DBUTF8($lp->content_license),
2607
                    'author' => self::DBUTF8($lp->author),
2608
                    'preview_image' => self::DBUTF8($lp->preview_image),
2609
                    'use_max_score' => self::DBUTF8($lp->use_max_score),
2610
                    'autolaunch' => self::DBUTF8(isset($lp->autolaunch) ? $lp->autolaunch : ''),
2611
                    'created_on' => self::DBUTF8($lp->created_on),
2612
                    'modified_on' => self::DBUTF8($lp->modified_on),
2613
                    'publicated_on' => empty($lp->publicated_on) ? api_get_utc_datetime() : self::DBUTF8($lp->publicated_on),
2614
                    'expired_on' => self::DBUTF8($lp->expired_on),
2615
                    'debug' => self::DBUTF8($lp->debug),
2616
                    'theme' => '',
2617
                    'session_id' => $session_id,
2618
                    'prerequisite' => 0,
2619
                    'hide_toc_frame' => 0,
2620
                    'seriousgame_mode' => 0,
2621
                    'category_id' => 0,
2622
                    'max_attempts' => 0,
2623
                    'subscribe_users' => 0,
2624
                ];
2625
2626
                if (!empty($condition_session)) {
2627
                    $params['session_id'] = $condition_session;
2628
                }
2629
2630
                $new_lp_id = Database::insert($table_main, $params);
2631
2632
                if ($new_lp_id) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $new_lp_id of type integer|false is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
2633
                    // The following only makes sense if a new LP was
2634
                    // created in the destination course
2635
                    $sql = "UPDATE $table_main SET id = iid WHERE iid = $new_lp_id";
2636
                    Database::query($sql);
2637
2638
                    if ($lp->visibility) {
2639
                        $params = [
2640
                            'c_id' => $this->destination_course_id,
2641
                            'name' => self::DBUTF8($lp->name),
2642
                            'link' => "lp/lp_controller.php?action=view&lp_id=$new_lp_id&id_session=$session_id",
2643
                            'image' => 'scormbuilder.gif',
2644
                            'visibility' => '0',
2645
                            'admin' => '0',
2646
                            'address' => 'squaregrey.gif',
2647
                            'session_id' => $session_id,
2648
                        ];
2649
                        $insertId = Database::insert($table_tool, $params);
2650
                        if ($insertId) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $insertId of type integer|false is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
2651
                            $sql = "UPDATE $table_tool SET id = iid WHERE iid = $insertId";
2652
                            Database::query($sql);
2653
                        }
2654
                    }
2655
2656
                    api_item_property_update(
2657
                        $this->destination_course_info,
2658
                        TOOL_LEARNPATH,
2659
                        $new_lp_id,
2660
                        'LearnpathAdded',
2661
                        api_get_user_id(),
2662
                        0,
2663
                        0,
2664
                        0,
2665
                        0,
2666
                        $session_id
2667
                    );
2668
2669
                    // Set the new LP to visible
2670
                    api_item_property_update(
2671
                        $this->destination_course_info,
2672
                        TOOL_LEARNPATH,
2673
                        $new_lp_id,
2674
                        'invisible',
2675
                        api_get_user_id(),
2676
                        0,
2677
                        0,
2678
                        0,
2679
                        0,
2680
                        $session_id
2681
                    );
2682
2683
                    $new_item_ids = [];
2684
                    $parent_item_ids = [];
2685
                    $previous_item_ids = [];
2686
                    $next_item_ids = [];
2687
                    $old_prerequisite = [];
2688
                    $old_refs = [];
2689
                    $prerequisite_ids = [];
2690
2691
                    foreach ($lp->get_items() as $index => $item) {
2692
                        // we set the ref code here and then we update in a for loop
2693
                        $ref = $item['ref'];
2694
2695
                        // Dealing with path the same way as ref as some data has
2696
                        // been put into path when it's a local resource
2697
                        // Only fix the path for no scos
2698
                        if ($item['item_type'] == 'sco') {
2699
                            $path = $item['path'];
2700
                        } else {
2701
                            $path = $item['path'];
2702
                            $path = $this->get_new_id($item['item_type'], $path);
2703
                        }
2704
2705
                        $item['item_type'] = $item['item_type'] == 'dokeos_chapter' ? 'dir' : $item['item_type'];
2706
2707
                        $params = [
2708
                            'c_id' => $this->destination_course_id,
2709
                            'lp_id' => self::DBUTF8($new_lp_id),
2710
                            'item_type' => self::DBUTF8($item['item_type']),
2711
                            'ref' => self::DBUTF8($ref),
2712
                            'path' => self::DBUTF8($path),
2713
                            'title' => self::DBUTF8($item['title']),
2714
                            'description' => self::DBUTF8($item['description']),
2715
                            'min_score' => self::DBUTF8($item['min_score']),
2716
                            'max_score' => self::DBUTF8($item['max_score']),
2717
                            'mastery_score' => self::DBUTF8($item['mastery_score']),
2718
                            'parent_item_id' => self::DBUTF8($item['parent_item_id']),
2719
                            'previous_item_id' => self::DBUTF8($item['previous_item_id']),
2720
                            'next_item_id' => self::DBUTF8($item['next_item_id']),
2721
                            'display_order' => self::DBUTF8($item['display_order']),
2722
                            'prerequisite' => self::DBUTF8($item['prerequisite']),
2723
                            'parameters' => self::DBUTF8($item['parameters']),
2724
                            'audio' => self::DBUTF8($item['audio']),
2725
                            'launch_data' => self::DBUTF8($item['launch_data']),
2726
                        ];
2727
2728
                        $new_item_id = Database::insert($table_item, $params);
2729
2730
                        $sql = "UPDATE $table_item SET id = iid WHERE iid = $new_item_id";
2731
                        Database::query($sql);
2732
2733
                        //save a link between old and new item IDs
2734
                        $new_item_ids[$item['id']] = $new_item_id;
2735
                        //save a reference of items that need a parent_item_id refresh
2736
                        $parent_item_ids[$new_item_id] = $item['parent_item_id'];
2737
                        //save a reference of items that need a previous_item_id refresh
2738
                        $previous_item_ids[$new_item_id] = $item['previous_item_id'];
2739
                        //save a reference of items that need a next_item_id refresh
2740
                        $next_item_ids[$new_item_id] = $item['next_item_id'];
2741
2742
                        if (!empty($item['prerequisite'])) {
2743
                            if ($lp->lp_type == '2') {
2744
                                // if is an sco
2745
                                $old_prerequisite[$new_item_id] = $item['prerequisite'];
2746
                            } else {
2747
                                $old_prerequisite[$new_item_id] = $new_item_ids[$item['prerequisite']];
2748
                            }
2749
                        }
2750
2751
                        if (!empty($ref)) {
2752
                            if ($lp->lp_type == '2') {
2753
                                // if is an sco
2754
                                $old_refs[$new_item_id] = $ref;
2755
                            } elseif (isset($new_item_ids[$ref])) {
2756
                                $old_refs[$new_item_id] = $new_item_ids[$ref];
2757
                            }
2758
                        }
2759
2760
                        $prerequisite_ids[$new_item_id] = $item['prerequisite'];
2761
                    }
2762
2763
                    // Updating prerequisites
2764
                    foreach ($old_prerequisite as $key => $my_old_prerequisite) {
2765
                        if ($my_old_prerequisite != '') {
2766
                            $sql = "UPDATE ".$table_item." SET prerequisite = '".$my_old_prerequisite."'
2767
                                    WHERE c_id = " . $this->destination_course_id." AND id = '".$key."'  ";
2768
                            Database::query($sql);
2769
                        }
2770
                    }
2771
2772
                    // Updating refs
2773
                    foreach ($old_refs as $key => $my_old_ref) {
2774
                        if ($my_old_ref != '') {
2775
                            $sql = "UPDATE ".$table_item." SET ref = '".$my_old_ref."'
2776
                                    WHERE c_id = " . $this->destination_course_id." AND id = '".$key."'  ";
2777
                            Database::query($sql);
2778
                        }
2779
                    }
2780
2781
                    foreach ($parent_item_ids as $new_item_id => $parent_item_old_id) {
2782
                        $parent_new_id = 0;
2783
                        if ($parent_item_old_id != 0) {
2784
                            $parent_new_id = $new_item_ids[$parent_item_old_id];
2785
                        }
2786
                        $sql = "UPDATE ".$table_item." SET parent_item_id = '".$parent_new_id."'
2787
                                WHERE c_id = " . $this->destination_course_id." AND id = '".$new_item_id."'";
2788
                        Database::query($sql);
2789
                    }
2790
                    foreach ($previous_item_ids as $new_item_id => $previous_item_old_id) {
2791
                        $previous_new_id = 0;
2792
                        if ($previous_item_old_id != 0) {
2793
                            $previous_new_id = $new_item_ids[$previous_item_old_id];
2794
                        }
2795
                        $sql = "UPDATE ".$table_item." SET previous_item_id = '".$previous_new_id."'
2796
                                WHERE  c_id = " . $this->destination_course_id." AND id = '".$new_item_id."'";
2797
                        Database::query($sql);
2798
                    }
2799
2800
                    foreach ($next_item_ids as $new_item_id => $next_item_old_id) {
2801
                        $next_new_id = 0;
2802
                        if ($next_item_old_id != 0) {
2803
                            $next_new_id = $new_item_ids[$next_item_old_id];
2804
                        }
2805
                        $sql = "UPDATE ".$table_item." SET next_item_id = '".$next_new_id."'
2806
                                WHERE c_id = ".$this->destination_course_id." AND id = '".$new_item_id."'";
2807
                        Database::query($sql);
2808
                    }
2809
2810
                    foreach ($prerequisite_ids as $new_item_id => $prerequisite_old_id) {
2811
                        $prerequisite_new_id = 0;
2812
                        if ($prerequisite_old_id != 0) {
2813
                            $prerequisite_new_id = $new_item_ids[$prerequisite_old_id];
2814
                        }
2815
                        $sql = "UPDATE ".$table_item." SET prerequisite = '".$prerequisite_new_id."'
2816
                                WHERE c_id = ".$this->destination_course_id." AND id = '".$new_item_id."'";
2817
                        Database::query($sql);
2818
                    }
2819
                    $this->course->resources[RESOURCE_LEARNPATH][$id]->destination_id = $new_lp_id;
2820
                }
2821
            }
2822
        }
2823
    }
2824
2825
    /**
2826
    * Copy all directory and sub directory
2827
    * @param string $source The path origin
2828
    * @param string $dest The path destination
2829
    * @param boolean Option Overwrite
2830
    * @return void
2831
    * @deprecated
2832
    */
2833
    public function allow_create_all_directory($source, $dest, $overwrite = false)
2834
    {
2835
        if (!is_dir($dest)) {
2836
            mkdir($dest, api_get_permissions_for_new_directories());
2837
        }
2838
        if ($handle = opendir($source)) {
2839
            // if the folder exploration is sucsessful, continue
2840
            while (false !== ($file = readdir($handle))) {
2841
                // as long as storing the next file to $file is successful, continue
2842
                if ($file != '.' && $file != '..') {
2843
                    $path = $source.'/'.$file;
2844
                    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...
2845
                        /* if (!is_file($dest . '/' . $file) || $overwrite)
2846
                         if (!@copy($path, $dest . '/' . $file)) {
2847
                             echo '<font color="red">File ('.$path.') '.get_lang('NotHavePermission').'</font>';
2848
                         }*/
2849
                    } elseif (is_dir($path)) {
2850
                        if (!is_dir($dest.'/'.$file)) {
2851
                            mkdir($dest.'/'.$file);
2852
                        }
2853
                        self:: allow_create_all_directory($path, $dest.'/'.$file, $overwrite);
0 ignored issues
show
Deprecated Code introduced by
The function Chamilo\CourseBundle\Com..._create_all_directory() has been deprecated. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

2853
                        /** @scrutinizer ignore-deprecated */ self:: allow_create_all_directory($path, $dest.'/'.$file, $overwrite);
Loading history...
Bug Best Practice introduced by
The method Chamilo\CourseBundle\Com..._create_all_directory() is not static, but was called statically. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

2853
                        self:: /** @scrutinizer ignore-call */ 
2854
                               allow_create_all_directory($path, $dest.'/'.$file, $overwrite);
Loading history...
2854
                    }
2855
                }
2856
            }
2857
            closedir($handle);
2858
        }
2859
    }
2860
2861
    /**
2862
     * Gets the new ID of one specific tool item from the tool name and the old ID
2863
     * @param	string	Tool name
2864
     * @param	integer	Old ID
2865
     * @return	integer	New ID
2866
     */
2867
    public function get_new_id($tool, $ref)
2868
    {
2869
        // Check if the value exist in the current array.
2870
        if ($tool === 'hotpotatoes') {
2871
            $tool = 'document';
2872
        }
2873
2874
        if (isset($this->course->resources[$tool][$ref]) &&
2875
            isset($this->course->resources[$tool][$ref]->destination_id) &&
2876
            !empty($this->course->resources[$tool][$ref]->destination_id)
2877
        ) {
2878
            return $this->course->resources[$tool][$ref]->destination_id;
2879
        }
2880
2881
        // Check if the course is the same (last hope).
2882
        if ($this->course_origin_id == $this->destination_course_id) {
2883
            return $ref;
2884
        }
2885
2886
        return '';
0 ignored issues
show
Bug Best Practice introduced by
The expression return '' returns the type string which is incompatible with the documented return type integer.
Loading history...
2887
    }
2888
2889
    /**
2890
     * Restore glossary
2891
     */
2892
    public function restore_glossary($session_id = 0)
2893
    {
2894
        if ($this->course->has_resources(RESOURCE_GLOSSARY)) {
2895
            $table_glossary = Database::get_course_table(TABLE_GLOSSARY);
2896
            $resources = $this->course->resources;
2897
            foreach ($resources[RESOURCE_GLOSSARY] as $id => $glossary) {
2898
                $params = [];
2899
                if (!empty($session_id)) {
2900
                    $session_id = intval($session_id);
2901
                    $params['session_id'] = $session_id;
2902
                }
2903
2904
                // check resources inside html from ckeditor tool and copy correct urls into recipient course
2905
                $glossary->description = DocumentManager::replaceUrlWithNewCourseCode(
2906
                    $glossary->description,
2907
                    $this->course->code,
2908
                    $this->course->destination_path,
2909
                    $this->course->backup_path,
2910
                    $this->course->info['path']
0 ignored issues
show
Bug introduced by
The property info does not seem to exist on Chamilo\CourseBundle\Component\CourseCopy\Course.
Loading history...
2911
                );
2912
2913
                $params['c_id'] = $this->destination_course_id;
2914
                $params['description'] = ($glossary->description === false ? '' : self::DBUTF8($glossary->description));
0 ignored issues
show
Bug Best Practice introduced by
The method Chamilo\CourseBundle\Com...ourseRestorer::DBUTF8() is not static, but was called statically. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

2914
                $params['description'] = ($glossary->description === false ? '' : self::/** @scrutinizer ignore-call */ DBUTF8($glossary->description));
Loading history...
2915
                $params['display_order'] = $glossary->display_order;
2916
                $params['name'] = self::DBUTF8($glossary->name);
2917
                $params['glossary_id'] = 0;
2918
                $my_id = Database::insert($table_glossary, $params);
2919
                if ($my_id) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $my_id of type integer|false is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
2920
                    $sql = "UPDATE $table_glossary SET glossary_id = iid WHERE iid = $my_id";
2921
                    Database::query($sql);
2922
2923
                    api_item_property_update(
2924
                        $this->destination_course_info,
2925
                        TOOL_GLOSSARY,
2926
                        $my_id,
2927
                        'GlossaryAdded',
2928
                        api_get_user_id()
2929
                    );
2930
2931
                    if (!isset($this->course->resources[RESOURCE_GLOSSARY][$id])) {
2932
                        $this->course->resources[RESOURCE_GLOSSARY][$id] = new stdClass();
2933
                    }
2934
2935
                    $this->course->resources[RESOURCE_GLOSSARY][$id]->destination_id = $my_id;
2936
                }
2937
            }
2938
        }
2939
    }
2940
2941
    /**
2942
     * @param int $session_id
2943
     */
2944
    public function restore_wiki($session_id = 0)
2945
    {
2946
        if ($this->course->has_resources(RESOURCE_WIKI)) {
2947
            // wiki table of the target course
2948
            $table_wiki = Database::get_course_table(TABLE_WIKI);
2949
            $table_wiki_conf = Database::get_course_table(TABLE_WIKI_CONF);
2950
2951
            // storing all the resources that have to be copied in an array
2952
            $resources = $this->course->resources;
2953
2954
            foreach ($resources[RESOURCE_WIKI] as $id => $wiki) {
2955
                // the sql statement to insert the groups from the old course to the new course
2956
                // check resources inside html from ckeditor tool and copy correct urls into recipient course
2957
                $wiki->content = DocumentManager::replaceUrlWithNewCourseCode(
2958
                    $wiki->content,
2959
                    $this->course->code,
2960
                    $this->course->destination_path,
2961
                    $this->course->backup_path,
2962
                    $this->course->info['path']
0 ignored issues
show
Bug introduced by
The property info does not seem to exist on Chamilo\CourseBundle\Component\CourseCopy\Course.
Loading history...
2963
                );
2964
2965
                $params = [
2966
                    'c_id' => $this->destination_course_id,
2967
                    'page_id' => self::DBUTF8($wiki->page_id),
0 ignored issues
show
Bug Best Practice introduced by
The method Chamilo\CourseBundle\Com...ourseRestorer::DBUTF8() is not static, but was called statically. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

2967
                    'page_id' => self::/** @scrutinizer ignore-call */ DBUTF8($wiki->page_id),
Loading history...
2968
                    'reflink' => self::DBUTF8($wiki->reflink),
2969
                    'title' => self::DBUTF8($wiki->title),
2970
                    'content' => ($wiki->content === false ? '' : self::DBUTF8($wiki->content)),
2971
                    'user_id' => intval($wiki->user_id),
2972
                    'group_id' => intval($wiki->group_id),
2973
                    'dtime' => self::DBUTF8($wiki->dtime),
2974
                    'progress' => self::DBUTF8($wiki->progress),
2975
                    'version' => intval($wiki->version),
2976
                    'session_id' => !empty($session_id) ? intval($session_id) : 0,
2977
                    'addlock' => 0,
2978
                    'editlock' => 0,
2979
                    'visibility' => 0,
2980
                    'addlock_disc' => 0,
2981
                    'visibility_disc' => 0,
2982
                    'ratinglock_disc' => 0,
2983
                    'assignment' => 0,
2984
                    'comment' => '',
2985
                    'is_editing' => 0,
2986
                    'linksto' => 0,
2987
                    'tag' => '',
2988
                    'user_ip' => '',
2989
                ];
2990
2991
                $new_id = Database::insert($table_wiki, $params);
2992
2993
                if ($new_id) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $new_id of type integer|false is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
2994
                    $sql = "UPDATE $table_wiki SET page_id = '$new_id', id = iid
2995
                            WHERE c_id = ".$this->destination_course_id." AND iid = '$new_id'";
2996
                    Database::query($sql);
2997
2998
                    $this->course->resources[RESOURCE_WIKI][$id]->destination_id = $new_id;
2999
3000
                    // we also add an entry in wiki_conf
3001
                    $params = [
3002
                        'c_id' => $this->destination_course_id,
3003
                        'page_id' => $new_id,
3004
                        'task' => '',
3005
                        'feedback1' => '',
3006
                        'feedback2' => '',
3007
                        'feedback3' => '',
3008
                        'fprogress1' => '',
3009
                        'fprogress2' => '',
3010
                        'fprogress3' => '',
3011
                        'max_size' => 0,
3012
                        'max_text' => 0,
3013
                        'max_version' => 0,
3014
                        'startdate_assig' => null,
3015
                        'enddate_assig' => null,
3016
                        'delayedsubmit' => 0,
3017
                    ];
3018
3019
                    Database::insert($table_wiki_conf, $params);
3020
                }
3021
            }
3022
        }
3023
    }
3024
3025
    /**
3026
     * Restore Thematics
3027
     * @param int $session_id
3028
     */
3029
    public function restore_thematic($session_id = 0)
3030
    {
3031
        if ($this->course->has_resources(RESOURCE_THEMATIC)) {
3032
            $table_thematic = Database::get_course_table(TABLE_THEMATIC);
3033
            $table_thematic_advance = Database::get_course_table(TABLE_THEMATIC_ADVANCE);
3034
            $table_thematic_plan = Database::get_course_table(TABLE_THEMATIC_PLAN);
3035
3036
            $resources = $this->course->resources;
3037
            foreach ($resources[RESOURCE_THEMATIC] as $id => $thematic) {
3038
3039
                // check resources inside html from ckeditor tool and copy correct urls into recipient course
3040
                $thematic->params['content'] = DocumentManager::replaceUrlWithNewCourseCode(
3041
                    $thematic->params['content'],
3042
                    $this->course->code,
3043
                    $this->course->destination_path,
3044
                    $this->course->backup_path,
3045
                    $this->course->info['path']
0 ignored issues
show
Bug introduced by
The property info does not seem to exist on Chamilo\CourseBundle\Component\CourseCopy\Course.
Loading history...
3046
                );
3047
                $thematic->params['c_id'] = $this->destination_course_id;
3048
                unset($thematic->params['id']);
3049
                unset($thematic->params['iid']);
3050
3051
                $last_id = Database::insert($table_thematic, $thematic->params, false);
3052
3053
                if ($last_id) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $last_id of type integer|false is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
3054
                    $sql = "UPDATE $table_thematic SET id = iid WHERE iid = $last_id";
3055
                    Database::query($sql);
3056
3057
                    api_item_property_update(
3058
                        $this->destination_course_info,
3059
                        'thematic',
3060
                        $last_id,
3061
                        "ThematicAdded",
3062
                        api_get_user_id()
3063
                    );
3064
3065
                    foreach ($thematic->thematic_advance_list as $thematic_advance) {
3066
                        unset($thematic_advance['id']);
3067
                        unset($thematic_advance['iid']);
3068
                        $thematic_advance['attendance_id'] = 0;
3069
                        $thematic_advance['thematic_id'] = $last_id;
3070
                        $thematic_advance['c_id'] = $this->destination_course_id;
3071
3072
                        $my_id = Database::insert(
3073
                            $table_thematic_advance,
3074
                            $thematic_advance,
3075
                            false
3076
                        );
3077
3078
                        if ($my_id) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $my_id of type integer|false is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
3079
                            $sql = "UPDATE $table_thematic_advance SET id = iid WHERE iid = $my_id";
3080
                            Database::query($sql);
3081
3082
                            api_item_property_update(
3083
                                $this->destination_course_info,
3084
                                'thematic_advance',
3085
                                $my_id,
3086
                                'ThematicAdvanceAdded',
3087
                                api_get_user_id()
3088
                            );
3089
                        }
3090
                    }
3091
3092
                    foreach ($thematic->thematic_plan_list as $thematic_plan) {
3093
                        unset($thematic_plan['id']);
3094
                        unset($thematic_plan['iid']);
3095
                        $thematic_plan['thematic_id'] = $last_id;
3096
                        $thematic_plan['c_id'] = $this->destination_course_id;
3097
                        $my_id = Database::insert($table_thematic_plan, $thematic_plan, false);
3098
3099
                        if ($my_id) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $my_id of type integer|false is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
3100
                            $sql = "UPDATE $table_thematic_plan SET id = iid WHERE iid = $my_id";
3101
                            Database::query($sql);
3102
3103
                            api_item_property_update(
3104
                                $this->destination_course_info,
3105
                                'thematic_plan',
3106
                                $my_id,
3107
                                'ThematicPlanAdded',
3108
                                api_get_user_id()
3109
                            );
3110
                        }
3111
                    }
3112
                }
3113
            }
3114
        }
3115
    }
3116
3117
    /**
3118
     * Restore Attendance
3119
     * @param int $session_id
3120
     */
3121
    public function restore_attendance($session_id = 0)
3122
    {
3123
        if ($this->course->has_resources(RESOURCE_ATTENDANCE)) {
3124
            $table_attendance = Database::get_course_table(TABLE_ATTENDANCE);
3125
            $table_attendance_calendar = Database::get_course_table(TABLE_ATTENDANCE_CALENDAR);
3126
3127
            $resources = $this->course->resources;
3128
            foreach ($resources[RESOURCE_ATTENDANCE] as $id => $obj) {
3129
                // check resources inside html from ckeditor tool and copy correct urls into recipient course
3130
                $obj->params['description'] = DocumentManager::replaceUrlWithNewCourseCode(
3131
                    $obj->params['description'],
3132
                    $this->course->code,
3133
                    $this->course->destination_path,
3134
                    $this->course->backup_path,
3135
                    $this->course->info['path']
0 ignored issues
show
Bug introduced by
The property info does not seem to exist on Chamilo\CourseBundle\Component\CourseCopy\Course.
Loading history...
3136
                );
3137
3138
                unset($obj->params['id']);
3139
                unset($obj->params['iid']);
3140
                $obj->params['c_id'] = $this->destination_course_id;
3141
                $last_id = Database::insert($table_attendance, $obj->params);
3142
3143
                if (is_numeric($last_id)) {
3144
                    $sql = "UPDATE $table_attendance SET id = iid WHERE iid = $last_id";
3145
                    Database::query($sql);
3146
3147
                    $this->course->resources[RESOURCE_ATTENDANCE][$id]->destination_id = $last_id;
3148
3149
                    api_item_property_update(
3150
                        $this->destination_course_info,
3151
                        TOOL_ATTENDANCE,
3152
                        $last_id,
3153
                        "AttendanceAdded",
3154
                        api_get_user_id()
3155
                    );
3156
3157
                    foreach ($obj->attendance_calendar as $attendance_calendar) {
3158
                        unset($attendance_calendar['id']);
3159
                        unset($attendance_calendar['iid']);
3160
3161
                        $attendance_calendar['attendance_id'] = $last_id;
3162
                        $attendance_calendar['c_id'] = $this->destination_course_id;
3163
                        $attendanceCalendarId = Database::insert(
3164
                            $table_attendance_calendar,
3165
                            $attendance_calendar
3166
                        );
3167
3168
                        $sql = "UPDATE $table_attendance_calendar SET id = iid WHERE iid = $attendanceCalendarId";
3169
                        Database::query($sql);
3170
                    }
3171
                }
3172
            }
3173
        }
3174
    }
3175
3176
    /**
3177
     * Restore Works
3178
     * @param int $sessionId
3179
     */
3180
    public function restore_works($sessionId = 0)
3181
    {
3182
        require_once api_get_path(SYS_CODE_PATH).'work/work.lib.php';
3183
        if ($this->course->has_resources(RESOURCE_WORK)) {
3184
            $table_work_assignment = Database::get_course_table(TABLE_STUDENT_PUBLICATION_ASSIGNMENT);
3185
3186
            $resources = $this->course->resources;
3187
            foreach ($resources[RESOURCE_WORK] as $obj) {
3188
3189
                // check resources inside html from ckeditor tool and copy correct urls into recipient course
3190
                $obj->params['description'] = DocumentManager::replaceUrlWithNewCourseCode(
3191
                    $obj->params['description'],
3192
                    $this->course->code,
3193
                    $this->course->destination_path,
3194
                    $this->course->backup_path,
3195
                    $this->course->info['path']
0 ignored issues
show
Bug introduced by
The property info does not seem to exist on Chamilo\CourseBundle\Component\CourseCopy\Course.
Loading history...
3196
                );
3197
3198
                $id_work = $obj->params['id'];
3199
                $obj->params['id'] = null;
3200
                $obj->params['c_id'] = $this->destination_course_info['real_id'];
3201
3202
                // re-create dir
3203
                // @todo check security against injection of dir in crafted course backup here!
3204
                $path = $obj->params['url'];
3205
                $path = '/'.str_replace('/', '', substr($path, 1));
3206
3207
                $workData = [];
3208
                switch ($this->file_option) {
3209
                    case FILE_SKIP:
3210
                        $workData = get_work_data_by_path(
3211
                            $path,
3212
                            $this->destination_course_info['real_id']
3213
                        );
3214
                        if (!empty($workData)) {
3215
                            continue;
3216
                        }
3217
                        break;
3218
                    case FILE_OVERWRITE:
3219
                        if (!empty($this->course_origin_id)) {
3220
                            $sql = 'SELECT * FROM '.$table_work_assignment.'
3221
                                    WHERE
3222
                                        c_id = ' . $this->course_origin_id.' AND
3223
                                        publication_id = ' . $id_work;
3224
3225
                            $result = Database::query($sql);
3226
                            $cant = Database::num_rows($result);
3227
                            if ($cant > 0) {
3228
                                $row = Database::fetch_assoc($result);
3229
                            }
3230
3231
                            $obj->params['enableExpiryDate'] = empty($row['expires_on']) ? false : true;
3232
                            $obj->params['enableEndDate'] = empty($row['ends_on']) ? false : true;
3233
                            $obj->params['expires_on'] = $row['expires_on'];
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $row does not seem to be defined for all execution paths leading up to this point.
Loading history...
3234
                            $obj->params['ends_on'] = $row['ends_on'];
3235
                            $obj->params['enable_qualification'] = $row['enable_qualification'];
3236
                            $obj->params['add_to_calendar'] = !empty($row['add_to_calendar']) ? 1 : 0;
3237
                        }
3238
                        //no break
3239
                    case FILE_RENAME:
3240
                        $workData = get_work_data_by_path(
3241
                            $path,
3242
                            $this->destination_course_info['real_id']
3243
                        );
3244
                        break;
3245
                }
3246
3247
                $obj->params['work_title'] = $obj->params['title'];
3248
                $obj->params['new_dir'] = $obj->params['title'];
3249
3250
                if (empty($workData)) {
3251
                    addDir(
3252
                        $obj->params,
3253
                        api_get_user_id(),
3254
                        $this->destination_course_info,
3255
                        0,
3256
                        $sessionId
3257
                    );
3258
                } else {
3259
                    $workId = $workData['iid'];
3260
                    updateWork(
3261
                        $workId,
3262
                        $obj->params,
3263
                        $this->destination_course_info,
3264
                        $sessionId
3265
                    );
3266
                    updatePublicationAssignment(
3267
                        $workId,
3268
                        $obj->params,
3269
                        $this->destination_course_info,
3270
                        0
3271
                    );
3272
                }
3273
            }
3274
        }
3275
    }
3276
3277
    /**
3278
     * Restore gradebook
3279
     * @param int $sessionId
3280
     * @return  bool
3281
     */
3282
    public function restore_gradebook($sessionId = 0)
3283
    {
3284
        if (in_array($this->file_option, [FILE_SKIP, FILE_RENAME])) {
3285
            return false;
3286
        }
3287
        // if overwrite
3288
        if ($this->course->has_resources(RESOURCE_GRADEBOOK)) {
3289
            $resources = $this->course->resources;
3290
            $destinationCourseCode = $this->destination_course_info['code'];
3291
            // Delete destination gradebook
3292
            $cats = \Category:: load(
3293
                null,
3294
                null,
3295
                $destinationCourseCode,
3296
                null,
3297
                null,
3298
                $sessionId
3299
            );
3300
3301
            if (!empty($cats)) {
3302
                /** @var \Category $cat */
3303
                foreach ($cats as $cat) {
3304
                    $cat->delete_all();
3305
                }
3306
            }
3307
3308
            /** @var GradeBookBackup $obj */
3309
            foreach ($resources[RESOURCE_GRADEBOOK] as $id => $obj) {
3310
                if (!empty($obj->categories)) {
3311
                    $categoryIdList = [];
3312
                    /** @var \Category $cat */
3313
                    foreach ($obj->categories as $cat) {
3314
                        $cat->set_course_code($destinationCourseCode);
3315
                        $cat->set_session_id($sessionId);
3316
3317
                        $parentId = $cat->get_parent_id();
3318
                        if (!empty($parentId)) {
3319
                            if (isset($categoryIdList[$parentId])) {
3320
                                $cat->set_parent_id($categoryIdList[$parentId]);
3321
                            }
3322
                        }
3323
                        $oldId = $cat->get_id();
3324
                        $categoryId = $cat->add();
3325
                        $categoryIdList[$oldId] = $categoryId;
3326
                        if (!empty($cat->evaluations)) {
3327
                            /** @var \Evaluation $evaluation */
3328
                            foreach ($cat->evaluations as $evaluation) {
3329
                                $evaluation->set_category_id($categoryId);
3330
                                $evaluation->set_course_code($destinationCourseCode);
3331
                                $evaluation->setSessionId($sessionId);
3332
                                $evaluation->add();
3333
                            }
3334
                        }
3335
3336
                        if (!empty($cat->links)) {
3337
                            /** @var \AbstractLink $link */
3338
                            foreach ($cat->links as $link) {
3339
                                $link->set_category_id($categoryId);
3340
                                $link->set_course_code($destinationCourseCode);
3341
                                $link->set_session_id($sessionId);
3342
                                $import = false;
3343
                                $itemId = $link->get_ref_id();
3344
                                switch ($link->get_type()) {
3345
                                    case LINK_EXERCISE:
3346
                                        $type = RESOURCE_QUIZ;
3347
                                        break;
3348
                                    /*case LINK_DROPBOX:
3349
                                        break;*/
3350
                                    case LINK_STUDENTPUBLICATION:
3351
                                        $type = RESOURCE_WORK;
3352
                                        break;
3353
                                    case LINK_LEARNPATH:
3354
                                        $type = RESOURCE_LEARNPATH;
3355
                                        break;
3356
                                    case LINK_FORUM_THREAD:
3357
                                        $type = RESOURCE_FORUMTOPIC;
3358
                                        break;
3359
                                    case LINK_ATTENDANCE:
3360
                                        $type = RESOURCE_ATTENDANCE;
3361
                                        break;
3362
                                    case LINK_SURVEY:
3363
                                        $type = RESOURCE_ATTENDANCE;
3364
                                        break;
3365
                                    case LINK_HOTPOTATOES:
3366
                                        $type = RESOURCE_QUIZ;
3367
                                        break;
3368
                                }
3369
3370
                                if ($this->course->has_resources($type) &&
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $type does not seem to be defined for all execution paths leading up to this point.
Loading history...
3371
                                    isset($this->course->resources[$type][$itemId])
3372
                                ) {
3373
                                    $item = $this->course->resources[$type][$itemId];
3374
                                    if ($item && $item->is_restored()) {
3375
                                        $link->set_ref_id($item->destination_id);
3376
                                        $import = true;
3377
                                    }
3378
                                }
3379
3380
                                if ($import) {
3381
                                    $link->add();
3382
                                }
3383
                            }
3384
                        }
3385
                    }
3386
                }
3387
            }
3388
        }
3389
    }
3390
3391
    /**
3392
     * Restore course assets (not included in documents)
3393
     */
3394
    public function restore_assets()
3395
    {
3396
        if ($this->course->has_resources(RESOURCE_ASSET)) {
3397
            $resources = $this->course->resources;
3398
            $path = api_get_path(SYS_COURSE_PATH).$this->course->destination_path.'/';
3399
3400
            foreach ($resources[RESOURCE_ASSET] as $id => $asset) {
3401
                if (is_file($this->course->backup_path.'/'.$asset->path) &&
3402
                    is_readable($this->course->backup_path.'/'.$asset->path) &&
3403
                    is_dir(dirname($path.$asset->path)) &&
3404
                    is_writeable(dirname($path.$asset->path))
3405
                ) {
3406
                    switch ($this->file_option) {
3407
                        case FILE_SKIP:
3408
                            continue;
3409
                        case FILE_OVERWRITE:
3410
                            copy(
3411
                                $this->course->backup_path.'/'.$asset->path,
3412
                                $path.$asset->path
3413
                            );
3414
                            break;
3415
                    }
3416
                }
3417
            }
3418
        }
3419
    }
3420
3421
3422
    /**
3423
     * @param string $str
3424
     * @return string
3425
     */
3426
    public function DBUTF8($str)
3427
    {
3428
        if (UTF8_CONVERT) {
3429
            $str = utf8_encode($str);
3430
        }
3431
        return $str;
3432
    }
3433
3434
    /**
3435
     * @param string $str
3436
     * @return string
3437
     */
3438
    public function DBUTF8escapestring($str)
3439
    {
3440
        if (UTF8_CONVERT) {
3441
            $str = utf8_encode($str);
3442
        }
3443
        return Database::escape_string($str);
3444
    }
3445
3446
    /**
3447
     * @param array $array
3448
     * @return mixed
3449
     */
3450
    public function DBUTF8_array($array)
3451
    {
3452
        if (UTF8_CONVERT) {
3453
            foreach ($array as &$item) {
3454
                $item = utf8_encode($item);
3455
            }
3456
            return $array;
3457
        } else {
3458
            return $array;
3459
        }
3460
    }
3461
3462
    /**
3463
     * @param int $groupId
3464
     * @return array
3465
     */
3466
    public function checkGroupId($groupId)
3467
    {
3468
        return \GroupManager::get_group_properties($groupId);
3469
    }
3470
3471
    /**
3472
     * Check if user exist otherwise use current user
3473
     * @param int $userId
3474
     * @param bool $returnNull
3475
     *
3476
     * @return int
3477
     */
3478
    private function checkUserId($userId, $returnNull = false)
3479
    {
3480
        if (!empty($userId)) {
3481
            $userInfo = api_get_user_info($userId);
3482
            if (empty($userInfo)) {
3483
                return api_get_user_id();
3484
            }
3485
        }
3486
3487
        if ($returnNull) {
3488
            return null;
3489
        }
3490
3491
        if (empty($userId)) {
3492
            return api_get_user_id();
3493
        }
3494
3495
        return $userId;
3496
    }
3497
}
3498