ImportCsv::importCalendarStatic()   F
last analyzed

Complexity

Conditions 79
Paths 6

Size

Total Lines 664
Code Lines 439

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 439
dl 0
loc 664
rs 3.3333
c 0
b 0
f 0
cc 79
nc 6
nop 2

How to fix   Long Method    Complexity   

Long Method

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

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

Commonly applied refactorings include:

1
<?php
2
3
/* For licensing terms, see /license.txt */
4
5
use Chamilo\CourseBundle\Entity\CCalendarEvent;
6
use Chamilo\CourseBundle\Entity\CItemProperty;
7
use Chamilo\PluginBundle\Entity\StudentFollowUp\CarePost;
8
use Fhaculty\Graph\Graph;
9
use Monolog\Handler\BufferHandler;
10
use Monolog\Handler\ErrorLogHandler;
11
use Monolog\Handler\RotatingFileHandler;
12
use Monolog\Handler\StreamHandler;
13
use Monolog\Logger;
14
15
if (PHP_SAPI != 'cli') {
16
    exit('Run this script through the command line or comment this line in the code');
17
}
18
19
if (file_exists('multiple_url_fix.php')) {
20
    require 'multiple_url_fix.php';
21
}
22
23
require_once __DIR__.'/../inc/global.inc.php';
24
25
ini_set('memory_limit', -1);
26
ini_set('max_execution_time', 0);
27
ini_set('log_errors', '1');
28
ini_set('display_errors', '1');
29
30
/**
31
 * Class ImportCsv.
32
 */
33
class ImportCsv
34
{
35
    public $test;
36
    public $defaultLanguage = 'dutch';
37
    public $extraFieldIdNameList = [
38
        'session' => 'external_session_id',
39
        'session_career' => 'external_career_id',
40
        'course' => 'external_course_id',
41
        'user' => 'external_user_id',
42
        'calendar_event' => 'external_calendar_event_id',
43
        'career' => 'external_career_id',
44
        'career_urls' => 'career_urls',
45
        'career_diagram' => 'career_diagram',
46
    ];
47
    public $defaultAdminId = 1;
48
    public $defaultSessionVisibility = 1;
49
50
    /**
51
     * When creating a user the expiration date is set to registration date + this value.
52
     *
53
     * @var int number of years
54
     */
55
    public $expirationDateInUserCreation = 1;
56
57
    public $batchSize = 20;
58
59
    /**
60
     * When updating a user the expiration date is set to update date + this value.
61
     *
62
     * @var int number of years
63
     */
64
    public $expirationDateInUserUpdate = 1;
65
    public $daysCoachAccessBeforeBeginning = 14;
66
    public $daysCoachAccessAfterBeginning = 14;
67
    public $conditions;
68
    private $logger;
69
    private $dumpValues;
70
    private $updateEmailToDummy;
71
72
    /**
73
     * @param Monolog\Logger $logger
74
     * @param array
75
     */
76
    public function __construct($logger, $conditions)
77
    {
78
        $this->logger = $logger;
79
        $this->conditions = $conditions;
80
        $this->updateEmailToDummy = false;
81
    }
82
83
    /**
84
     * @param bool $dump
85
     */
86
    public function setDumpValues($dump)
87
    {
88
        $this->dumpValues = $dump;
89
    }
90
91
    /**
92
     * @return bool
93
     */
94
    public function getDumpValues()
95
    {
96
        return $this->dumpValues;
97
    }
98
99
    /**
100
     * Runs the import process.
101
     */
102
    public function run()
103
    {
104
        global $_configuration;
105
106
        $value = api_get_configuration_value('import_csv_custom_url_id');
107
        if (!empty($value)) {
108
            $_configuration['access_url'] = $value;
109
        }
110
111
        $path = api_get_path(SYS_CODE_PATH).'cron/incoming/';
112
        if (!is_dir($path)) {
113
            echo "The folder! $path does not exits";
114
115
            return 0;
116
        }
117
118
        if ($this->getDumpValues()) {
119
            $this->dumpDatabaseTables();
120
        }
121
122
        echo 'Reading files: '.PHP_EOL.PHP_EOL;
123
124
        $files = scandir($path);
125
        $fileToProcess = [];
126
        $fileToProcessStatic = [];
127
        $teacherBackup = [];
128
        $groupBackup = [];
129
130
        $this->prepareImport();
131
132
        if (!empty($files)) {
133
            foreach ($files as $file) {
134
                $fileInfo = pathinfo($file);
135
                if (isset($fileInfo['extension']) && $fileInfo['extension'] === 'csv') {
136
                    // Checking teachers_yyyymmdd.csv,
137
                    // courses_yyyymmdd.csv, students_yyyymmdd.csv and sessions_yyyymmdd.csv
138
                    $parts = explode('_', $fileInfo['filename']);
139
                    $preMethod = ucwords($parts[1]);
140
                    $preMethod = str_replace('-static', 'Static', $preMethod);
141
                    $method = 'import'.$preMethod;
142
                    $isStatic = strpos($method, 'Static');
143
144
                    if ($method == 'importSessionsextidStatic') {
145
                        $method = 'importSessionsExtIdStatic';
146
                    }
147
148
                    if ($method == 'importCourseinsertStatic') {
149
                        $method = 'importSubscribeUserToCourse';
150
                    }
151
152
                    if ($method == 'importUnsubsessionsextidStatic') {
153
                        $method = 'importUnsubsessionsExtidStatic';
154
                    }
155
156
                    if ($method == 'importCareersdiagram') {
157
                        $method = 'importCareersDiagram';
158
                    }
159
160
                    if ($method == 'importCareersresults') {
161
                        $method = 'importCareersResults';
162
                    }
163
164
                    if ($method == 'importCareersresultsremoveStatic') {
165
                        $method = 'importCareersResultsRemoveStatic';
166
                    }
167
168
                    if ($method == 'importOpensessions') {
169
                        $method = 'importOpenSessions';
170
                    }
171
172
                    if ($method == 'importOpensessions') {
173
                        $method = 'importOpenSessions';
174
                    }
175
176
                    if ($method === 'importSessionsall') {
177
                        $method = 'importSessionsUsersCareers';
178
                    }
179
180
                    if ($method === 'importSubsessionsextidStatic') {
181
                        $method = 'importSubscribeUserToCourseSessionExtStatic';
182
                    }
183
184
                    if (method_exists($this, $method)) {
185
                        if ((
186
                                $method == 'importSubscribeStatic' ||
187
                                $method == 'importSubscribeUserToCourse'
188
                            ) ||
189
                            empty($isStatic)
190
                        ) {
191
                            $fileToProcess[$parts[1]][] = [
192
                                'method' => $method,
193
                                'file' => $path.$fileInfo['basename'],
194
                            ];
195
                        } else {
196
                            $fileToProcessStatic[$parts[1]][] = [
197
                                'method' => $method,
198
                                'file' => $path.$fileInfo['basename'],
199
                            ];
200
                        }
201
                    } else {
202
                        echo "Error - This file '$file' can't be processed.".PHP_EOL;
203
                        echo "Trying to call $method".PHP_EOL;
204
                        echo "The file have to has this format:".PHP_EOL;
205
                        echo "prefix_students_ddmmyyyy.csv, prefix_teachers_ddmmyyyy.csv,
206
                        prefix_courses_ddmmyyyy.csv, prefix_sessions_ddmmyyyy.csv ".PHP_EOL;
207
                        exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
208
                    }
209
                }
210
            }
211
212
            if (empty($fileToProcess) && empty($fileToProcessStatic)) {
213
                echo 'Error - no files to process.';
214
215
                return 0;
216
            }
217
218
            $sections = [
219
                'students',
220
                'teachers',
221
                'courses',
222
                'sessions',
223
                'sessionsall',
224
                'opensessions',
225
                'subscribe-static',
226
                'courseinsert-static',
227
                'unsubscribe-static',
228
                'care',
229
                'skillset',
230
                //'careers',
231
                //'careersdiagram',
232
                //'careersresults',
233
            ];
234
235
            foreach ($sections as $section) {
236
                if (isset($fileToProcess[$section]) && !empty($fileToProcess[$section])) {
237
                    $this->logger->addInfo("-- Import $section --");
238
                    $files = $fileToProcess[$section];
239
                    foreach ($files as $fileInfo) {
240
                        $method = $fileInfo['method'];
241
                        $file = $fileInfo['file'];
242
                        echo 'File: '.$file.PHP_EOL;
243
                        echo 'Method : '.$method.PHP_EOL;
244
                        echo PHP_EOL;
245
246
                        $this->logger->addInfo('====================================================');
247
                        $this->logger->addInfo("Reading file: $file");
248
                        $this->logger->addInfo("Loading method $method ");
249
                        if ($method == 'importSessions' || $method == 'importOpenSessions') {
250
                            $this->$method(
251
                                $file,
252
                                true,
253
                                $teacherBackup,
254
                                $groupBackup
255
                            );
256
                        } else {
257
                            $this->$method($file, true);
258
                        }
259
                        $this->logger->addInfo('--Finish reading file--');
260
                    }
261
                }
262
            }
263
264
            $sections = [
265
                'students-static',
266
                'teachers-static',
267
                'courses-static',
268
                'sessions-static',
269
                'sessionsextid-static',
270
                'unsubscribe-static',
271
                'unsubsessionsextid-static',
272
                'subsessionsextid-static',
273
                'calendar-static',
274
                //'careersresultsremove-static',
275
            ];
276
277
            foreach ($sections as $section) {
278
                if (isset($fileToProcessStatic[$section]) &&
279
                    !empty($fileToProcessStatic[$section])
280
                ) {
281
                    $this->logger->addInfo("-- Import static files $section --");
282
                    $files = $fileToProcessStatic[$section];
283
                    foreach ($files as $fileInfo) {
284
                        $method = $fileInfo['method'];
285
286
                        $file = $fileInfo['file'];
287
                        echo 'Static file: '.$file.PHP_EOL;
288
                        echo 'Method : '.$method.PHP_EOL;
289
                        echo PHP_EOL;
290
                        $this->logger->addInfo("Reading static file: $file");
291
                        $this->logger->addInfo("Loading method $method ");
292
                        $this->$method(
293
                            $file,
294
                            true,
295
                            $teacherBackup,
296
                            $groupBackup
297
                        );
298
                        $this->logger->addInfo('--Finish reading file--');
299
                    }
300
                }
301
            }
302
303
            $this->logger->addInfo('teacher backup');
304
            $this->logger->addInfo(print_r($teacherBackup, 1));
305
306
            // Careers at the end:
307
            $sections = [
308
                'careers',
309
                'careersdiagram',
310
                'careersresults',
311
            ];
312
313
            foreach ($sections as $section) {
314
                if (isset($fileToProcess[$section]) && !empty($fileToProcess[$section])) {
315
                    $this->logger->addInfo("-- Import $section --");
316
                    $files = $fileToProcess[$section];
317
                    foreach ($files as $fileInfo) {
318
                        $method = $fileInfo['method'];
319
                        $file = $fileInfo['file'];
320
                        echo 'File: '.$file.PHP_EOL;
321
                        echo 'Method : '.$method.PHP_EOL;
322
                        echo PHP_EOL;
323
324
                        $this->logger->addInfo('====================================================');
325
                        $this->logger->addInfo("Reading file: $file");
326
                        $this->logger->addInfo("Loading method $method ");
327
                        $this->$method($file, true);
328
                        $this->logger->addInfo('--Finish reading file--');
329
                    }
330
                }
331
            }
332
333
            $removeResults = 'careersresultsremove-static';
334
            if (isset($fileToProcessStatic[$removeResults]) &&
335
                !empty($fileToProcessStatic[$removeResults])
336
            ) {
337
                $files = $fileToProcessStatic[$removeResults];
338
                foreach ($files as $fileInfo) {
339
                    $method = $fileInfo['method'];
340
                    $file = $fileInfo['file'];
341
                    echo 'Static file: '.$file.PHP_EOL;
342
                    echo 'Method : '.$method.PHP_EOL;
343
                    echo PHP_EOL;
344
                    $this->logger->addInfo("Reading static file: $file");
345
                    $this->logger->addInfo("Loading method $method ");
346
                    $this->$method(
347
                        $file,
348
                        true
349
                    );
350
                    $this->logger->addInfo('--Finish reading file--');
351
                }
352
            }
353
        }
354
    }
355
356
    /**
357
     * @param $file
358
     * @param bool $moveFile
359
     */
360
    public function importCare($file, $moveFile = false)
361
    {
362
        $data = Import::csv_reader($file);
363
        $counter = 1;
364
        $batchSize = $this->batchSize;
365
        $em = Database::getManager();
366
367
        if (!empty($data)) {
368
            $this->logger->addInfo(count($data)." records found.");
369
            $items = [];
370
            foreach ($data as $list) {
371
                $post = [];
372
                foreach ($list as $key => $value) {
373
                    $key = (string) trim($key);
374
                    // Remove utf8 bom
375
                    $key = preg_replace('/[\x00-\x1F\x80-\xFF]/', '', $key);
376
                    $post[$key] = $value;
377
                }
378
379
                if (empty($post)) {
380
                    continue;
381
                }
382
383
                $externalId = $post['External_care_id'];
384
                $items[$externalId] = $post;
385
            }
386
            ksort($items);
387
388
            foreach ($items as $row) {
389
                // Insert user
390
                //$insertUserInfo = api_get_user_info_from_username($row['Added_by']);
391
392
                // User about the post
393
                $userId = UserManager::get_user_id_from_original_id(
394
                    $row['Added_by'],
395
                    $this->extraFieldIdNameList['user']
396
                );
397
398
                $insertUserInfo = api_get_user_info($userId);
399
400
                if (empty($insertUserInfo)) {
401
                    $this->logger->addInfo("User: '".$row['Added_by']."' doesn't exists. Skip this entry.");
402
                    continue;
403
                }
404
                $insertUserInfo = api_get_user_entity($insertUserInfo['user_id']);
405
406
                // User about the post
407
                $userId = UserManager::get_user_id_from_original_id(
408
                    $row['External_user_id'],
409
                    $this->extraFieldIdNameList['user']
410
                );
411
412
                if (empty($userId)) {
413
                    $this->logger->addInfo("User does '".$row['External_user_id']."' not exists skip this entry.");
414
                    continue;
415
                }
416
417
                $userInfo = api_get_user_entity($userId);
418
419
                if (empty($userInfo)) {
420
                    $this->logger->addInfo("Chamilo user does not found: #".$userId."' ");
421
                    continue;
422
                }
423
424
                // Dates
425
                $createdAt = $this->createDateTime($row['Added_On']);
426
                $updatedAt = $this->createDateTime($row['Edited_on']);
427
428
                // Parent
429
                $parent = null;
430
                if (!empty($row['Parent_id'])) {
431
                    $parentId = $items[$row['Parent_id']];
432
                    $criteria = [
433
                        'externalCareId' => $parentId,
434
                    ];
435
                    $parent = $em->getRepository('ChamiloPluginBundle:StudentFollowUp\CarePost')->findOneBy($criteria);
436
                }
437
438
                // Tags
439
                $tags = explode(',', $row['Tags']);
440
441
                // Check if post already was added:
442
                $criteria = [
443
                    'externalCareId' => $row['External_care_id'],
444
                ];
445
                $post = $em->getRepository('ChamiloPluginBundle:StudentFollowUp\CarePost')->findOneBy($criteria);
446
447
                if (empty($post)) {
448
                    $post = new CarePost();
449
                    $this->logger->addInfo("New post will be created no match for externalCareId = ".$row['External_care_id']);
450
                }
451
452
                $contentDecoded = utf8_encode(base64_decode($row['Article']));
453
454
                $post
455
                    ->setTitle($row['Title'])
456
                    ->setContent($contentDecoded)
457
                    ->setExternalCareId($row['External_care_id'])
458
                    ->setCreatedAt($createdAt)
459
                    ->setUpdatedAt($updatedAt)
460
                    ->setPrivate((int) $row['Private'])
461
                    ->setInsertUser($insertUserInfo)
462
                    ->setExternalSource((int) $row['Source_is_external'])
463
                    ->setParent($parent)
464
                    ->setTags($tags)
465
                    ->setUser($userInfo)
466
                    ->setAttachment($row['Attachement'])
467
                ;
468
                $em->persist($post);
469
                $em->flush();
470
471
                $this->logger->addInfo("Post id saved #".$post->getId());
472
473
                if (($counter % $batchSize) === 0) {
474
                    $em->flush();
475
                    $em->clear(); // Detaches all objects from Doctrine!
476
                }
477
                $counter++;
478
            }
479
480
            $em->clear(); // Detaches all objects from Doctrine!
481
        }
482
    }
483
484
    /**
485
     * @return mixed
486
     */
487
    public function getUpdateEmailToDummy()
488
    {
489
        return $this->updateEmailToDummy;
490
    }
491
492
    /**
493
     * @param mixed $updateEmailToDummy
494
     */
495
    public function setUpdateEmailToDummy($updateEmailToDummy)
496
    {
497
        $this->updateEmailToDummy = $updateEmailToDummy;
498
    }
499
500
    /**
501
     * Change emails of all users except admins.
502
     */
503
    public function updateUsersEmails()
504
    {
505
        if ($this->getUpdateEmailToDummy() === true) {
506
            $sql = "UPDATE user SET email = CONCAT(username,'@example.com') WHERE id NOT IN (SELECT user_id FROM admin)";
507
            Database::query($sql);
508
        }
509
    }
510
511
    /**
512
     * Prepares extra fields before the import.
513
     */
514
    private function prepareImport()
515
    {
516
        // Create user extra field: extra_external_user_id
517
        UserManager::create_extra_field(
518
            $this->extraFieldIdNameList['user'],
519
            1,
520
            'External user id',
521
            null
522
        );
523
524
        // Create course extra field: extra_external_course_id
525
        CourseManager::create_course_extra_field(
526
            $this->extraFieldIdNameList['course'],
527
            1,
528
            'External course id',
529
            ''
530
        );
531
532
        // Course skill set.
533
        CourseManager::create_course_extra_field(
534
            'skillset',
535
            1,
536
            'Skill set',
537
            ''
538
        );
539
540
        CourseManager::create_course_extra_field(
541
            'disable_import_calendar',
542
            13,
543
            'Disable import calendar',
544
            ''
545
        );
546
547
        // Create session extra field extra_external_session_id
548
        SessionManager::create_session_extra_field(
549
            $this->extraFieldIdNameList['session'],
550
            1,
551
            'External session id'
552
        );
553
554
        SessionManager::create_session_extra_field(
555
            $this->extraFieldIdNameList['session_career'],
556
            1,
557
            'Career id'
558
        );
559
560
        // Create calendar_event extra field extra_external_session_id
561
        $extraField = new ExtraField('calendar_event');
562
        $extraField->save(
563
            [
564
                'field_type' => ExtraField::FIELD_TYPE_TEXT,
565
                'variable' => $this->extraFieldIdNameList['calendar_event'],
566
                'display_text' => 'External calendar event id',
567
            ]
568
        );
569
570
        $extraField = new ExtraField('career');
571
        $extraField->save(
572
            [
573
                'visible_to_self' => 1,
574
                'field_type' => ExtraField::FIELD_TYPE_TEXT,
575
                'variable' => $this->extraFieldIdNameList['career'],
576
                'display_text' => 'External career id',
577
            ]
578
        );
579
580
        $extraField->save(
581
            [
582
                'visible_to_self' => 1,
583
                'field_type' => ExtraField::FIELD_TYPE_TEXTAREA,
584
                'variable' => $this->extraFieldIdNameList['career_diagram'],
585
                'display_text' => 'Career diagram',
586
            ]
587
        );
588
589
        $extraField->save(
590
            [
591
                'visible_to_self' => 1,
592
                'field_type' => ExtraField::FIELD_TYPE_TEXTAREA,
593
                'variable' => $this->extraFieldIdNameList['career_urls'],
594
                'display_text' => 'Career urls',
595
            ]
596
        );
597
    }
598
599
    /**
600
     * @param string $file
601
     */
602
    private function moveFile($file)
603
    {
604
        $moved = str_replace('incoming', 'treated', $file);
605
606
        if ($this->test) {
607
            $result = 1;
608
        } else {
609
            $result = rename($file, $moved);
610
        }
611
612
        if ($result) {
613
            $this->logger->addInfo("Moving file to the treated folder: $file");
614
        } else {
615
            $this->logger->addError(
616
                "Error - Cant move file to the treated folder: $file"
617
            );
618
        }
619
    }
620
621
    /**
622
     * @param array $row
623
     *
624
     * @return array
625
     */
626
    private function cleanUserRow($row)
627
    {
628
        $row['lastname'] = $row['LastName'];
629
        $row['firstname'] = $row['FirstName'];
630
        $row['email'] = $row['Email'];
631
        $row['username'] = $row['UserName'];
632
        $row['password'] = $row['Password'];
633
        $row['auth_source'] = isset($row['AuthSource']) ? $row['AuthSource'] : PLATFORM_AUTH_SOURCE;
634
        $row['official_code'] = $row['OfficialCode'];
635
        $row['phone'] = isset($row['PhoneNumber']) ? $row['PhoneNumber'] : '';
636
637
        if (isset($row['StudentID'])) {
638
            $row['extra_'.$this->extraFieldIdNameList['user']] = $row['StudentID'];
639
        }
640
641
        if (isset($row['TeacherID'])) {
642
            $row['extra_'.$this->extraFieldIdNameList['user']] = $row['TeacherID'];
643
        }
644
645
        return $row;
646
    }
647
648
    /**
649
     * @param array $row
650
     *
651
     * @return array
652
     */
653
    private function cleanCourseRow($row)
654
    {
655
        $row['title'] = $row['Title'];
656
        $row['course_code'] = $row['Code'];
657
        $row['course_category'] = $row['CourseCategory'];
658
        $row['email'] = $row['Teacher'];
659
        $row['language'] = $row['Language'];
660
        $row['visibility'] = isset($row['Visibility']) ? $row['Visibility'] : COURSE_VISIBILITY_REGISTERED;
661
662
        $row['teachers'] = [];
663
        if (isset($row['Teacher']) && !empty($row['Teacher'])) {
664
            $this->logger->addInfo("Teacher list found: ".$row['Teacher']);
665
            $teachers = explode(',', $row['Teacher']);
666
            if (!empty($teachers)) {
667
                foreach ($teachers as $teacherUserName) {
668
                    $teacherUserName = trim($teacherUserName);
669
                    $userInfo = api_get_user_info_from_username($teacherUserName);
670
                    if (!empty($userInfo)) {
671
                        $this->logger->addInfo("Username found: $teacherUserName");
672
                        $row['teachers'][] = $userInfo['user_id'];
673
                    }
674
                }
675
            }
676
        }
677
678
        if (isset($row['CourseID'])) {
679
            $row['extra_'.$this->extraFieldIdNameList['course']] = $row['CourseID'];
680
        }
681
682
        return $row;
683
    }
684
685
    /**
686
     * File to import.
687
     *
688
     * @param string $file
689
     */
690
    private function importTeachersStatic($file)
691
    {
692
        $this->importTeachers($file, true);
693
    }
694
695
    /**
696
     * File to import.
697
     *
698
     * @param string $file
699
     * @param bool   $moveFile
700
     */
701
    private function importTeachers($file, $moveFile = true)
702
    {
703
        $this->fixCSVFile($file);
704
        $data = Import::csvToArray($file);
705
706
        /* Unique identifier: official-code username.
707
        Email address and password should never get updated. *ok
708
        The only fields that I can think of that should update if the data changes in the csv file are FirstName and LastName. *ok
709
        A slight edit of these fields should be taken into account. ???
710
        Adding teachers is no problem, but deleting them shouldn’t be automated, but we should get a log of “to delete teachers”.
711
        We’ll handle that manually if applicable.
712
        No delete!
713
        */
714
        $language = $this->defaultLanguage;
715
716
        if (!empty($data)) {
717
            $this->logger->addInfo(count($data)." records found.");
718
719
            $batchSize = $this->batchSize;
720
            $em = Database::getManager();
721
            $counter = 1;
722
            foreach ($data as $row) {
723
                $row = $this->cleanUserRow($row);
724
                $externalUserId = $row['official_code'];
725
                $row['extra_'.$this->extraFieldIdNameList['user']] = $externalUserId;
726
727
                $user_id = UserManager::get_user_id_from_original_id(
728
                    $row['extra_'.$this->extraFieldIdNameList['user']],
729
                    $this->extraFieldIdNameList['user']
730
                );
731
                $userInfo = [];
732
                $userInfoByOfficialCode = null;
733
734
                if (!empty($user_id)) {
735
                    $userInfo = api_get_user_info($user_id);
736
                    $userInfoByOfficialCode = api_get_user_info_from_official_code($row['official_code']);
737
                }
738
739
                if (empty($userInfo) && empty($userInfoByOfficialCode)) {
740
                    // Create user
741
                    $userId = UserManager::create_user(
742
                        $row['firstname'],
743
                        $row['lastname'],
744
                        COURSEMANAGER,
745
                        $row['email'],
746
                        $row['username'],
747
                        $row['password'],
748
                        $row['official_code'],
749
                        $language, //$row['language'],
750
                        $row['phone'],
751
                        null, //$row['picture'], //picture
752
                        $row['auth_source'], // ?
753
                        null,
754
                        1, //active
755
                        0,
756
                        null, // extra
757
                        null, //$encrypt_method = '',
758
                        false //$send_mail = false
759
                    );
760
761
                    $row['extra_mail_notify_invitation'] = 1;
762
                    $row['extra_mail_notify_message'] = 1;
763
                    $row['extra_mail_notify_group_message'] = 1;
764
765
                    if ($userId) {
766
                        foreach ($row as $key => $value) {
767
                            if (substr($key, 0, 6) == 'extra_') {
768
                                //an extra field
769
                                UserManager::update_extra_field_value(
770
                                    $userId,
771
                                    substr($key, 6),
772
                                    $value
773
                                );
774
                            }
775
                        }
776
                        $this->logger->addInfo("Teachers - User created: ".$row['username']);
777
                    } else {
778
                        $this->logger->addError("Teachers - User NOT created: ".$row['username']." ".$row['firstname']." ".$row['lastname']);
779
                        $this->logger->addError(strip_tags(Display::getFlashToString()));
780
                        Display::cleanFlashMessages();
781
                    }
782
                } else {
783
                    if (empty($userInfo)) {
784
                        $this->logger->addError("Teachers - Can't update user :".$row['username']);
785
                        continue;
786
                    }
787
788
                    // Update user
789
                    $result = UserManager::update_user(
790
                        $userInfo['user_id'],
791
                        $row['firstname'], // <<-- changed
792
                        $row['lastname'], // <<-- changed
793
                        $userInfo['username'],
794
                        null, //$password = null,
795
                        $row['auth_source'],
796
                        $userInfo['email'],
797
                        COURSEMANAGER,
798
                        $userInfo['official_code'],
799
                        $userInfo['phone'],
800
                        $userInfo['picture_uri'],
801
                        null,
802
                        $userInfo['active'],
803
                        null, //$creator_id = null,
804
                        0, //$hr_dept_id = 0,
805
                        null, // $extra = null,
806
                        null, //$language = 'english',
807
                        null, //$encrypt_method = '',
808
                        false, //$send_email = false,
809
                        0 //$reset_password = 0
810
                    );
811
812
                    $table = Database::get_main_table(TABLE_MAIN_USER);
813
                    $authSource = Database::escape_string($row['auth_source']);
814
                    $sql = "UPDATE $table SET auth_source = '$authSource' WHERE id = ".$userInfo['user_id'];
815
                    Database::query($sql);
816
817
                    $this->logger->addInfo(
818
                        'Teachers - #'.$userInfo['user_id']." auth_source was changed from '".$userInfo['auth_source']."' to '".$row['auth_source']."' "
819
                    );
820
821
                    if ($result) {
822
                        foreach ($row as $key => $value) {
823
                            if (substr($key, 0, 6) == 'extra_') {
824
                                //an extra field
825
                                UserManager::update_extra_field_value(
826
                                    $userInfo['user_id'],
827
                                    substr($key, 6),
828
                                    $value
829
                                );
830
                            }
831
                        }
832
                        $this->logger->addInfo("Teachers - User updated: ".$row['username']);
833
                    } else {
834
                        $this->logger->addError("Teachers - User not updated: ".$row['username']);
835
                    }
836
                }
837
838
                if (($counter % $batchSize) === 0) {
839
                    $em->flush();
840
                    $em->clear(); // Detaches all objects from Doctrine!
841
                }
842
                $counter++;
843
            }
844
845
            $em->clear(); // Detaches all objects from Doctrine!
846
        }
847
848
        if ($moveFile) {
849
            $this->moveFile($file);
850
        }
851
852
        $this->updateUsersEmails();
853
    }
854
855
    /**
856
     * @param string $file
857
     */
858
    private function importStudentsStatic($file)
859
    {
860
        $this->importStudents($file, true);
861
    }
862
863
    /**
864
     * @param string $file
865
     * @param bool   $moveFile
866
     */
867
    private function importStudents($file, $moveFile = true)
868
    {
869
        $this->fixCSVFile($file);
870
        $data = Import::csvToArray($file);
871
872
        /*
873
         * Another users import.
874
        Unique identifier: official code and username . ok
875
        Password should never get updated. ok
876
        If an update should need to occur (because it changed in the .csv),
877
        we’ll want that logged. We will handle this manually in that case.
878
        All other fields should be updateable, though passwords should of course not get updated. ok
879
        If a user gets deleted (not there anymore),
880
        He should be set inactive one year after the current date.
881
        So I presume you’ll just update the expiration date.
882
        We want to grant access to courses up to a year after deletion.
883
         */
884
        $timeStart = microtime(true);
885
886
        $batchSize = $this->batchSize;
887
        $em = Database::getManager();
888
889
        if (!empty($data)) {
890
            $language = $this->defaultLanguage;
891
            $this->logger->addInfo(count($data)." records found.");
892
893
            $counter = 1;
894
            $secondsInYear = 365 * 24 * 60 * 60;
895
896
            foreach ($data as $row) {
897
                $row = $this->cleanUserRow($row);
898
                $externalUserId = $row['official_code'];
899
                $row['extra_'.$this->extraFieldIdNameList['user']] = $externalUserId;
900
901
                $user_id = UserManager::get_user_id_from_original_id(
902
                    $row['extra_'.$this->extraFieldIdNameList['user']],
903
                    $this->extraFieldIdNameList['user']
904
                );
905
906
                $userInfo = [];
907
                $userInfoByOfficialCode = null;
908
                if (!empty($user_id)) {
909
                    $userInfo = api_get_user_info($user_id, false, true);
910
                    $userInfoByOfficialCode = api_get_user_info_from_official_code($row['official_code']);
911
                }
912
913
                $userInfoFromUsername = api_get_user_info_from_username($row['username']);
914
                if (!empty($userInfoFromUsername)) {
915
                    $extraFieldValue = new ExtraFieldValue('user');
916
                    $extraFieldValues = $extraFieldValue->get_values_by_handler_and_field_variable(
917
                        $userInfoFromUsername['user_id'],
918
                        $this->extraFieldIdNameList['user']
919
                    );
920
921
                    if (!empty($extraFieldValues)) {
922
                        $value = 0;
923
                        foreach ($extraFieldValues as $extraFieldValue) {
924
                            if (isset($extraFieldValue['value'])) {
925
                                $value = $extraFieldValue['value'];
926
                            }
927
                        }
928
                        if (!empty($user_id) && $value != $user_id) {
929
                            $emails = api_get_configuration_value('cron_notification_help_desk');
930
                            if (!empty($emails)) {
931
                                $this->logger->addInfo('Preparing email to users in configuration: "cron_notification_help_desk"');
932
                                $subject = 'User not added due to same username';
933
                                $body = 'Cannot add username: "'.$row['username'].'"
934
                                    with external_user_id: '.$row['extra_'.$this->extraFieldIdNameList['user']].'
935
                                    because '.$userInfoFromUsername['username'].' with external_user_id '.$value.' exists on the portal';
936
                                $this->logger->addInfo($body);
937
                                foreach ($emails as $email) {
938
                                    api_mail_html('', $email, $subject, $body);
939
                                }
940
                            }
941
                        }
942
                    }
943
                }
944
945
                if (empty($userInfo) && empty($userInfoByOfficialCode)) {
946
                    // Create user
947
                    $result = UserManager::create_user(
948
                        $row['firstname'],
949
                        $row['lastname'],
950
                        STUDENT,
951
                        $row['email'],
952
                        $row['username'],
953
                        $row['password'],
954
                        $row['official_code'],
955
                        $language, //$row['language'],
956
                        $row['phone'],
957
                        null, //$row['picture'], //picture
958
                        $row['auth_source'], // ?
959
                        null,
960
                        1, //active
961
                        0,
962
                        null, // extra
963
                        null, //$encrypt_method = '',
964
                        false //$send_mail = false
965
                    );
966
967
                    $row['extra_mail_notify_invitation'] = 1;
968
                    $row['extra_mail_notify_message'] = 1;
969
                    $row['extra_mail_notify_group_message'] = 1;
970
971
                    if ($result) {
972
                        foreach ($row as $key => $value) {
973
                            if (substr($key, 0, 6) === 'extra_') {
974
                                //an extra field
975
                                UserManager::update_extra_field_value(
976
                                    $result,
977
                                    substr($key, 6),
978
                                    $value
979
                                );
980
                            }
981
                        }
982
                        $this->logger->addInfo("Students - User created: ".$row['username']);
983
                    } else {
984
                        $this->logger->addError("Students - User NOT created: ".$row['username']." ".$row['firstname']." ".$row['lastname']);
985
                        $this->logger->addError(strip_tags(Display::getFlashToString()));
986
                        Display::cleanFlashMessages();
987
                    }
988
                } else {
989
                    if (empty($userInfo)) {
990
                        $this->logger->addError("Students - Can't update user :".$row['username']);
991
                        continue;
992
                    }
993
994
                    $password = $row['password']; // change password
995
                    $email = $row['email']; // change email
996
                    $resetPassword = 2; // allow password change
997
998
                    // Conditions that disables the update of password and email:
999
                    if (isset($this->conditions['importStudents'])) {
1000
                        if (isset($this->conditions['importStudents']['update']) &&
1001
                            isset($this->conditions['importStudents']['update']['avoid'])
1002
                        ) {
1003
                            // Blocking email update -
1004
                            // 1. Condition
1005
                            $avoidUsersWithEmail = $this->conditions['importStudents']['update']['avoid']['email'];
1006
                            if ($userInfo['email'] != $row['email'] && in_array($row['email'], $avoidUsersWithEmail)) {
1007
                                $this->logger->addInfo("Students - User email is not updated : ".$row['username']." because the avoid conditions (email).");
1008
                                // Do not change email keep the old email.
1009
                                $email = $userInfo['email'];
1010
                            }
1011
1012
                            // 2. Condition
1013
                            if (!in_array($userInfo['email'], $avoidUsersWithEmail) && !in_array($row['email'], $avoidUsersWithEmail)) {
1014
                                $this->logger->addInfo("Students - User email is not updated from ".$userInfo['email']." to ".$row['email']." because the avoid conditions (email).");
1015
                                $email = $userInfo['email'];
1016
                            }
1017
1018
                            // 3. Condition
1019
                            if (in_array($userInfo['email'], $avoidUsersWithEmail) && !in_array($row['email'], $avoidUsersWithEmail)) {
1020
                                $this->logger->addInfo('Email to be updated from:'.$userInfo['email'].' to '.$row['email']);
1021
                                $email = $row['email'];
1022
                            }
1023
1024
                            // Blocking password update
1025
                            //$avoidUsersWithPassword = $this->conditions['importStudents']['update']['avoid']['password'];
1026
1027
                            /*if (isset($row['password'])) {
1028
                                $user = api_get_user_entity($userInfo['id']);
1029
                                $encoded = UserManager::encryptPassword(
1030
                                    $row['password'],
1031
                                    $user
1032
                                );
1033
1034
                                if ($userInfo['password'] != $encoded &&
1035
                                    in_array($row['password'], $avoidUsersWithPassword)
1036
                                ) {
1037
                                    $this->logger->addInfo(
1038
                                        "Students - User password is not updated: ".$row['username']." because the avoid conditions (password)."
1039
                                    );
1040
                                    $password = null;
1041
                                    $resetPassword = 0; // disallow password change
1042
                                }
1043
                            }*/
1044
                        }
1045
                    }
1046
1047
                    // Always disallow password change during update
1048
                    $password = null;
1049
                    $resetPassword = 0; // disallow password change
1050
1051
                    // Update user
1052
                    $result = UserManager::update_user(
1053
                        $userInfo['user_id'],
1054
                        $row['firstname'], // <<-- changed
1055
                        $row['lastname'], // <<-- changed
1056
                        $row['username'], // <<-- changed
1057
                        $password, //$password = null,
1058
                        $row['auth_source'],
1059
                        $email,
1060
                        STUDENT,
1061
                        $userInfo['official_code'],
1062
                        $userInfo['phone'],
1063
                        $userInfo['picture_uri'],
1064
                        null,
1065
                        $userInfo['active'],
1066
                        null, //$creator_id = null,
1067
                        0, //$hr_dept_id = 0,
1068
                        null, // $extra = null,
1069
                        null, //$language = 'english',
1070
                        null, //$encrypt_method = '',
1071
                        false, //$send_email = false,
1072
                        $resetPassword //$reset_password = 0
1073
                    );
1074
1075
                    $table = Database::get_main_table(TABLE_MAIN_USER);
1076
                    $authSource = Database::escape_string($row['auth_source']);
1077
                    $sql = "UPDATE $table SET auth_source = '$authSource' WHERE id = ".$userInfo['user_id'];
1078
                    Database::query($sql);
1079
1080
                    $this->logger->addInfo(
1081
                        "Students - #".$userInfo['user_id']." auth_source was changed from '".$userInfo['auth_source']."' to '".$row['auth_source']."' "
1082
                    );
1083
1084
                    if ($result) {
1085
                        if ($row['username'] != $userInfo['username']) {
1086
                            $this->logger->addInfo("Students - Username was changes from '".$userInfo['username']."' to '".$row['username']."' ");
1087
                        }
1088
                        foreach ($row as $key => $value) {
1089
                            if (substr($key, 0, 6) === 'extra_') {
1090
                                //an extra field
1091
                                UserManager::update_extra_field_value(
1092
                                    $userInfo['user_id'],
1093
                                    substr($key, 6),
1094
                                    $value
1095
                                );
1096
                            }
1097
                        }
1098
                        $this->logger->addInfo(
1099
                            'Students - User updated: username:'.$row['username'].' firstname:'.$row['firstname'].' lastname:'.$row['lastname'].' email:'.$email
1100
                        );
1101
                    } else {
1102
                        $this->logger->addError("Students - User NOT updated: ".$row['username']." ".$row['firstname']." ".$row['lastname']);
1103
                    }
1104
                }
1105
1106
                if (($counter % $batchSize) === 0) {
1107
                    $em->flush();
1108
                    $em->clear(); // Detaches all objects from Doctrine!
1109
                    $this->logger->addInfo("Detaches all objects");
1110
                }
1111
                $counter++;
1112
            }
1113
            $em->clear(); // Detaches all objects from Doctrine!
1114
        }
1115
1116
        $timeEnd = microtime(true);
1117
        $executionTime = round(($timeEnd - $timeStart) / 60, 2);
1118
        $this->logger->addInfo("Execution Time for process students: $executionTime Min");
1119
1120
        if ($moveFile) {
1121
            $this->moveFile($file);
1122
        }
1123
1124
        $this->updateUsersEmails();
1125
    }
1126
1127
    /**
1128
     * @param string $file
1129
     */
1130
    private function importCoursesStatic($file, $moveFile, &$teacherBackup = [], &$groupBackup = [])
1131
    {
1132
        $this->importCourses($file, true, $teacherBackup, $groupBackup);
1133
    }
1134
1135
    /**
1136
     * @param string $file
1137
     * @param bool   $moveFile
1138
     *
1139
     * @return int
1140
     */
1141
    private function importCalendarStatic($file, $moveFile = true)
1142
    {
1143
        $this->fixCSVFile($file);
1144
1145
        $this->updateUsersEmails();
1146
        $data = Import::csvToArray($file);
1147
1148
        if (!empty($data)) {
1149
            $this->logger->addInfo(count($data).' records found.');
1150
            $eventsToCreate = [];
1151
            $errorFound = false;
1152
1153
            $courseExtraFieldValue = new ExtraFieldValue('course');
1154
1155
            foreach ($data as $row) {
1156
                $sessionId = null;
1157
                $externalSessionId = null;
1158
                if (isset($row['external_sessionID'])) {
1159
                    $externalSessionId = $row['external_sessionID'];
1160
                    $sessionId = SessionManager::getSessionIdFromOriginalId(
1161
                        $externalSessionId,
1162
                        $this->extraFieldIdNameList['session']
1163
                    );
1164
                }
1165
1166
                $courseCode = null;
1167
                if (isset($row['coursecode'])) {
1168
                    $courseCode = $row['coursecode'];
1169
                }
1170
                $courseInfo = api_get_course_info($courseCode);
1171
                $courseId = $courseInfo['real_id'] ?? 0;
1172
1173
                $item = $courseExtraFieldValue->get_values_by_handler_and_field_variable(
1174
                    $courseId,
1175
                    'disable_import_calendar'
1176
                );
1177
1178
                if (!empty($item) && isset($item['value']) && $item['value'] == 1) {
1179
                    $this->logger->addInfo(
1180
                        "Course '".$courseInfo['code']."' has 'disable_import_calendar' turn on. Skip"
1181
                    );
1182
                    $errorFound = true;
1183
                }
1184
1185
                if (empty($courseInfo)) {
1186
                    $this->logger->addInfo("Course '$courseCode' does not exists");
1187
                } else {
1188
                    if ($courseInfo['visibility'] == COURSE_VISIBILITY_HIDDEN) {
1189
                        $this->logger->addInfo("Course '".$courseInfo['code']."' has hidden visibility. Skip");
1190
                        $errorFound = true;
1191
                    }
1192
                }
1193
1194
                if (empty($sessionId)) {
1195
                    $this->logger->addInfo("external_sessionID: $externalSessionId does not exists.");
1196
                }
1197
                $teacherId = null;
1198
                $sessionInfo = [];
1199
                if (!empty($sessionId) && !empty($courseInfo)) {
1200
                    $sessionInfo = api_get_session_info($sessionId);
1201
                    $courseIncluded = SessionManager::relation_session_course_exist($sessionId, $courseId);
1202
1203
                    if ($courseIncluded == false) {
1204
                        $this->logger->addInfo(
1205
                            "Course '$courseCode' is not included in session: $sessionId"
1206
                        );
1207
                        $errorFound = true;
1208
                    } else {
1209
                        $teachers = CourseManager::get_coach_list_from_course_code($courseInfo['code'], $sessionId);
1210
1211
                        // Getting first teacher.
1212
                        if (!empty($teachers)) {
1213
                            $teacher = current($teachers);
1214
                            $teacherId = $teacher['user_id'];
1215
                        } else {
1216
                            $teacherId = $sessionInfo['id_coach'];
1217
                        }
1218
                    }
1219
                } else {
1220
                    $errorFound = true;
1221
                }
1222
1223
                if (empty($teacherId)) {
1224
                    $errorFound = true;
1225
                    $this->logger->addInfo(
1226
                        "No teacher found in course code : '$courseCode' and session: '$sessionId'"
1227
                    );
1228
                }
1229
1230
                $date = $row['date'];
1231
                $startTime = $row['time_start'];
1232
                $endTime = $row['time_end'];
1233
                $title = $row['title'];
1234
                $comment = $row['comment'] ?? '';
1235
                $color = $row['color'] ?? '';
1236
1237
                $startDateYear = substr($date, 0, 4);
1238
                $startDateMonth = substr($date, 4, 2);
1239
                $startDateDay = substr($date, 6, 8);
1240
1241
                $startDate = $startDateYear.'-'.$startDateMonth.'-'.$startDateDay.' '.$startTime.':00';
1242
                $endDate = $startDateYear.'-'.$startDateMonth.'-'.$startDateDay.' '.$endTime.':00';
1243
1244
                if (!api_is_valid_date($startDate) || !api_is_valid_date($endDate)) {
1245
                    $this->logger->addInfo("Verify your dates: '$startDate' : '$endDate' ");
1246
                    $errorFound = true;
1247
                }
1248
1249
                // Check session dates.
1250
                if ($sessionInfo && !empty($sessionInfo['access_start_date'])) {
1251
                    $date = new \DateTime($sessionInfo['access_start_date']);
1252
                    $intervalInput = '7';
1253
                    if (!empty($row['dateinterval'])) {
1254
                        if ((int) $row['dateinterval'] >= 0) {
1255
                            $intervalInput = (int) $row['dateinterval'];
1256
                        }
1257
                    }
1258
                    $interval = new \DateInterval('P'.$intervalInput.'D');
1259
                    $date->sub($interval);
1260
                    if ($date->getTimestamp() > time()) {
1261
                        $this->logger->addInfo(
1262
                            "Calendar event # ".$row['external_calendar_itemID']."
1263
                            in session [$externalSessionId] was not added
1264
                            because the startdate is more than $intervalInput days in the future: ".$sessionInfo['access_start_date']
1265
                        );
1266
                        $errorFound = true;
1267
                    }
1268
                }
1269
1270
                $sendAnnouncement = false;
1271
                if (isset($row['sendmail']) && 1 === (int) $row['sendmail']) {
1272
                    $sendAnnouncement = true;
1273
                }
1274
1275
                // New condition.
1276
                if ($errorFound == false) {
1277
                    $eventsToCreate[] = [
1278
                        'start' => $startDate,
1279
                        'end' => $endDate,
1280
                        'title' => $title,
1281
                        'sender_id' => $teacherId,
1282
                        'course_id' => $courseInfo['real_id'],
1283
                        'session_id' => $sessionId,
1284
                        'comment' => $comment,
1285
                        'color' => $color,
1286
                        'send_announcement' => $sendAnnouncement,
1287
                        $this->extraFieldIdNameList['calendar_event'] => $row['external_calendar_itemID'],
1288
                    ];
1289
                }
1290
                $errorFound = false;
1291
            }
1292
1293
            if (empty($eventsToCreate)) {
1294
                $this->logger->addInfo('No events to add');
1295
1296
                return 0;
1297
            }
1298
1299
            $extraFieldValue = new ExtraFieldValue('calendar_event');
1300
            $extraFieldName = $this->extraFieldIdNameList['calendar_event'];
1301
            $externalEventId = null;
1302
1303
            $extraField = new ExtraField('calendar_event');
1304
            $extraFieldInfo = $extraField->get_handler_field_info_by_field_variable($extraFieldName);
1305
1306
            if (empty($extraFieldInfo)) {
1307
                $this->logger->addInfo(
1308
                    "No calendar event extra field created: $extraFieldName"
1309
                );
1310
1311
                return 0;
1312
            }
1313
1314
            $this->logger->addInfo('Ready to insert # '.count($eventsToCreate).' events');
1315
            $batchSize = $this->batchSize;
1316
            $counter = 1;
1317
            $em = Database::getManager();
1318
            $eventStartDateList = [];
1319
            $eventEndDateList = [];
1320
            $report = [
1321
                'mail_sent' => 0,
1322
                'mail_not_sent_announcement_exists' => 0,
1323
                'mail_not_sent_because_date' => 0,
1324
                'mail_not_sent_because_setting' => 0,
1325
            ];
1326
1327
            $eventsToCreateFinal = [];
1328
            foreach ($eventsToCreate as $event) {
1329
                $update = false;
1330
                $item = null;
1331
                if (!isset($event[$extraFieldName])) {
1332
                    $this->logger->addInfo('No external_calendar_itemID found. Skipping ...');
1333
                    continue;
1334
                } else {
1335
                    $externalEventId = $event[$extraFieldName];
1336
                    if (empty($externalEventId)) {
1337
                        $this->logger->addInfo('external_calendar_itemID was set but empty. Skipping ...');
1338
                        continue;
1339
                    }
1340
1341
                    $item = $extraFieldValue->get_item_id_from_field_variable_and_field_value(
1342
                        $extraFieldName,
1343
                        $externalEventId,
1344
                        false,
1345
                        false,
1346
                        false
1347
                    );
1348
1349
                    if (!empty($item)) {
1350
                        $update = true;
1351
                    }
1352
                }
1353
1354
                $courseInfo = api_get_course_info_by_id($event['course_id']);
1355
                $event['course_info'] = $courseInfo;
1356
                $event['update'] = $update;
1357
                $event['item'] = $item;
1358
1359
                $calendarEvent = null;
1360
                /* Check if event changed of course code */
1361
                if (!empty($item) && isset($item['item_id']) && !empty($item['item_id'])) {
1362
                    /** @var CCalendarEvent $calendarEvent */
1363
                    $calendarEvent = $em->getRepository('ChamiloCourseBundle:CCalendarEvent')->find($item['item_id']);
1364
                }
1365
1366
                if ($calendarEvent) {
1367
                    $this->logger->addInfo('Calendar event found '.$item['item_id']);
1368
                    if ($calendarEvent->getCId() != $courseInfo['real_id']) {
1369
                        $this->logger->addInfo('Move from course #'.$calendarEvent->getCId().' to #'.$courseInfo['real_id']);
1370
                        // Seems that the course id changed in the csv
1371
                        $calendarEvent->setCId($courseInfo['real_id']);
1372
                        $em->persist($calendarEvent);
1373
                        $em->flush();
1374
1375
                        $criteria = [
1376
                            'tool' => 'calendar_event',
1377
                            'ref' => $item['item_id'],
1378
                        ];
1379
                        /** @var CItemProperty $itemProperty */
1380
                        $itemProperty = $em->getRepository('ChamiloCourseBundle:CItemProperty')->findOneBy($criteria);
1381
                        $courseEntity = $em->getRepository('ChamiloCoreBundle:Course')->find($courseInfo['real_id']);
1382
                        if ($itemProperty && $courseEntity) {
1383
                            $itemProperty->setCourse($courseEntity);
1384
                            $em->persist($itemProperty);
1385
                            $em->flush();
1386
                        }
1387
                    }
1388
1389
                    // Checking if session still exists
1390
                    $calendarSessionId = (int) $calendarEvent->getSessionId();
1391
                    if (!empty($calendarSessionId)) {
1392
                        $calendarSessionInfo = api_get_session_info($calendarSessionId);
1393
                        if (empty($calendarSessionInfo)) {
1394
                            $calendarId = (int) $calendarEvent->getIid();
1395
1396
                            // Delete calendar events because the session was deleted!
1397
                            $this->logger->addInfo(
1398
                                "Delete event # $calendarId because session # $calendarSessionId doesn't exist"
1399
                            );
1400
1401
                            $sql = "DELETE FROM c_calendar_event
1402
                                    WHERE iid = $calendarId AND session_id = $calendarSessionId";
1403
                            Database::query($sql);
1404
                            $this->logger->addInfo($sql);
1405
1406
                            $sql = "DELETE FROM c_item_property
1407
                                    WHERE
1408
                                        tool = 'calendar_event' AND
1409
                                        ref = $calendarSessionId AND
1410
                                        session_id = $calendarSessionId";
1411
                            Database::query($sql);
1412
                            $this->logger->addInfo($sql);
1413
                        }
1414
                    }
1415
                } else {
1416
                    $this->logger->addInfo('Calendar event not found '.$item['item_id']);
1417
                }
1418
1419
                $event['external_event_id'] = $externalEventId;
1420
                if (isset($eventStartDateList[$courseInfo['real_id']]) &&
1421
                    isset($eventStartDateList[$courseInfo['real_id']][$event['session_id']])
1422
                ) {
1423
                    $currentItemDate = api_strtotime($event['start']);
1424
                    $firstDate = $eventStartDateList[$courseInfo['real_id']][$event['session_id']];
1425
                    if ($currentItemDate < api_strtotime($firstDate)) {
1426
                        $eventStartDateList[$courseInfo['real_id']][$event['session_id']] = $event['start'];
1427
                        $eventEndDateList[$courseInfo['real_id']][$event['session_id']] = $event['end'];
1428
                    }
1429
                } else {
1430
                    // First time
1431
                    $eventStartDateList[$courseInfo['real_id']][$event['session_id']] = $event['start'];
1432
                    $eventEndDateList[$courseInfo['real_id']][$event['session_id']] = $event['end'];
1433
                }
1434
                $eventsToCreateFinal[] = $event;
1435
            }
1436
1437
            $eventAlreadySent = [];
1438
1439
            $tpl = new Template(null, false, false, false, false, false, false);
1440
1441
            foreach ($eventsToCreateFinal as $event) {
1442
                $courseInfo = $event['course_info'];
1443
                $item = $event['item'];
1444
                $update = $event['update'];
1445
                $externalEventId = $event['external_event_id'];
1446
                $info = 'Course: '.$courseInfo['real_id'].' ('.$courseInfo['code'].') - Session: '.$event['session_id'].' external event id: '.$externalEventId;
1447
1448
                $agenda = new Agenda(
1449
                    'course',
1450
                    $event['sender_id'],
1451
                    $courseInfo['real_id'],
1452
                    $event['session_id']
1453
                );
1454
                $agenda->set_course($courseInfo);
1455
                $agenda->setSessionId($event['session_id']);
1456
                $agenda->setSenderId($event['sender_id']);
1457
                $agenda->setIsAllowedToEdit(true);
1458
                $eventComment = $event['comment'];
1459
                $color = $event['color'];
1460
1461
                // To use the event comment you need
1462
                // ALTER TABLE c_calendar_event ADD COLUMN comment TEXT;
1463
                // add in configuration.php allow_agenda_event_comment = true
1464
                if (empty($courseInfo)) {
1465
                    $this->logger->addInfo(
1466
                        "No course found for event #$externalEventId Course #".$event['course_id']." Skipping ..."
1467
                    );
1468
                    continue;
1469
                }
1470
1471
                if (empty($event['sender_id'])) {
1472
                    $this->logger->addInfo(
1473
                        "No sender found for event #$externalEventId Send #".$event['sender_id']." Skipping ..."
1474
                    );
1475
                    continue;
1476
                }
1477
1478
                // Taking first element of course-session event
1479
                $alreadyAdded = false;
1480
                $firstDate = $eventStartDateList[$courseInfo['real_id']][$event['session_id']];
1481
                $firstEndDate = $eventEndDateList[$courseInfo['real_id']][$event['session_id']];
1482
1483
                if (isset($eventAlreadySent[$courseInfo['real_id']]) &&
1484
                    isset($eventAlreadySent[$courseInfo['real_id']][$event['session_id']])
1485
                ) {
1486
                    $alreadyAdded = true;
1487
                } else {
1488
                    $eventAlreadySent[$courseInfo['real_id']][$event['session_id']] = true;
1489
                }
1490
1491
                // Working days (Mon-Fri) see BT#12156#note-16
1492
                $days = 3;
1493
                $startDatePlusDays = api_strtotime("$days weekdays");
1494
1495
                /*
1496
                $timePart = date('H:i:s', api_strtotime('now'));
1497
                $datePart = date('Y-m-d', api_strtotime("$days weekdays"));
1498
                $startDatePlusDays = "$timePart $datePart";
1499
                */
1500
                $this->logger->addInfo(
1501
                    'startDatePlusDays: '.api_get_utc_datetime($startDatePlusDays).' - First date: '.$firstDate
1502
                );
1503
1504
                // Send.
1505
                $sendMail = false;
1506
                if ($startDatePlusDays > api_strtotime($firstDate)) {
1507
                    $sendMail = true;
1508
                }
1509
1510
                $allowAnnouncementSendEmail = false;
1511
                if ($event['send_announcement']) {
1512
                    $allowAnnouncementSendEmail = true;
1513
                }
1514
1515
                // Send announcement to users
1516
                if ($allowAnnouncementSendEmail) {
1517
                    if ($sendMail && $alreadyAdded == false) {
1518
                        $start = $firstDate;
1519
                        $end = $firstEndDate;
1520
1521
                        if (!empty($end) &&
1522
                            api_format_date($start, DATE_FORMAT_LONG) ==
1523
                            api_format_date($end, DATE_FORMAT_LONG)
1524
                        ) {
1525
                            $date = api_format_date($start, DATE_FORMAT_LONG).' ('.
1526
                                api_format_date($start, TIME_NO_SEC_FORMAT).' '.
1527
                                api_format_date($end, TIME_NO_SEC_FORMAT).')';
1528
                        } else {
1529
                            $date = api_format_date($start, DATE_TIME_FORMAT_LONG_24H).' - '.
1530
                                api_format_date($end, DATE_TIME_FORMAT_LONG_24H);
1531
                        }
1532
1533
                        $sessionName = '';
1534
                        $sessionId = isset($event['session_id']) && !empty($event['session_id']) ? $event['session_id'] : 0;
1535
                        if (!empty($sessionId)) {
1536
                            $sessionName = api_get_session_name($sessionId);
1537
                        }
1538
1539
                        $courseTitle = $courseInfo['title'];
1540
1541
                        // Get the value of the "careerid" extra field of this
1542
                        // session
1543
                        $sessionExtraFieldValue = new ExtraFieldValue('session');
1544
                        $externalCareerIdList = $sessionExtraFieldValue->get_values_by_handler_and_field_variable(
1545
                            $event['session_id'],
1546
                            'careerid'
1547
                        );
1548
                        $externalCareerIdList = $externalCareerIdList['value'];
1549
                        if (substr($externalCareerIdList, 0, 1) === '[') {
1550
                            $externalCareerIdList = substr($externalCareerIdList, 1, -1);
1551
                            $externalCareerIds = preg_split('/,/', $externalCareerIdList);
1552
                        } else {
1553
                            $externalCareerIds = [$externalCareerIdList];
1554
                        }
1555
1556
                        $careerExtraFieldValue = new ExtraFieldValue('career');
1557
                        $career = new Career();
1558
                        $careerName = '';
1559
1560
                        // Concat the names of each career linked to this session
1561
                        foreach ($externalCareerIds as $externalCareerId) {
1562
                            // Using the external_career_id field (from above),
1563
                            // find the career ID
1564
                            $careerValue = $careerExtraFieldValue->get_item_id_from_field_variable_and_field_value(
1565
                                'external_career_id',
1566
                                $externalCareerId
1567
                            );
1568
                            $career = $career->find($careerValue['item_id']);
1569
                            $careerName .= $career['name'].', ';
1570
                        }
1571
                        // Remove trailing comma
1572
                        $careerName = substr($careerName, 0, -2);
1573
                        $subject = sprintf(
1574
                            get_lang('WelcomeToPortalXInCourseSessionX'),
1575
                            api_get_setting('Institution'),
1576
                            $courseInfo['title']
1577
                        );
1578
1579
                        $tpl->assign('course_title', $courseTitle);
1580
                        $tpl->assign('career_name', $careerName);
1581
                        $tpl->assign('first_lesson', $date);
1582
                        $tpl->assign('location', $eventComment);
1583
                        $tpl->assign('session_name', $sessionName);
1584
1585
                        if (empty($sessionId)) {
1586
                            $teachersToString = CourseManager::getTeacherListFromCourseCodeToString(
1587
                                $courseInfo['code'],
1588
                                ','
1589
                            );
1590
                        } else {
1591
                            $teachersToString = SessionManager::getCoachesByCourseSessionToString(
1592
                                $sessionId,
1593
                                $courseInfo['real_id'],
1594
                                ','
1595
                            );
1596
                        }
1597
1598
                        $tpl->assign('teachers', $teachersToString);
1599
1600
                        $templateName = $this->getCustomMailTemplate();
1601
                        $emailBody = $tpl->fetch($templateName);
1602
1603
                        $coaches = SessionManager::getCoachesByCourseSession(
1604
                            $event['session_id'],
1605
                            $courseInfo['real_id']
1606
                        );
1607
1608
                        // Search if an announcement exists:
1609
                        $announcementsWithTitleList = AnnouncementManager::getAnnouncementsByTitle(
1610
                            $subject,
1611
                            $courseInfo['real_id'],
1612
                            $event['session_id'],
1613
                            1
1614
                        );
1615
1616
                        if (count($announcementsWithTitleList) === 0) {
1617
                            $this->logger->addInfo(
1618
                                'Mail to be sent because start date: '.$event['start'].' and no announcement found.'
1619
                            );
1620
1621
                            $senderId = $this->defaultAdminId;
1622
                            if (!empty($coaches) && isset($coaches[0]) && !empty($coaches[0])) {
1623
                                $senderId = $coaches[0];
1624
                            }
1625
1626
                            $announcementId = AnnouncementManager::add_announcement(
1627
                                $courseInfo,
1628
                                $event['session_id'],
1629
                                $subject,
1630
                                $emailBody,
1631
                                [
1632
                                    'everyone',
1633
                                    'users' => $coaches,
1634
                                ],
1635
                                [],
1636
                                null,
1637
                                null,
1638
                                false,
1639
                                $senderId
1640
                            );
1641
1642
                            if ($announcementId) {
1643
                                $this->logger->addInfo("Announcement added: $announcementId in $info");
1644
                                $this->logger->addInfo("<<--SENDING MAIL Sender id: $senderId-->>");
1645
                                $report['mail_sent']++;
1646
                                AnnouncementManager::sendEmail(
1647
                                    $courseInfo,
1648
                                    $event['session_id'],
1649
                                    $announcementId,
1650
                                    false,
1651
                                    false,
1652
                                    $this->logger,
1653
                                    $senderId,
1654
                                    true
1655
                                );
1656
                            } else {
1657
                                $this->logger->addError(
1658
                                    "Error when trying to add announcement with title $subject here: $info and SenderId = $senderId"
1659
                                );
1660
                            }
1661
                        } else {
1662
                            $report['mail_not_sent_announcement_exists']++;
1663
                            $this->logger->addInfo(
1664
                                "Mail NOT sent. An announcement seems to be already saved in '$info'"
1665
                            );
1666
                        }
1667
                    } else {
1668
                        $this->logger->addInfo(
1669
                            "Send Mail: ".intval($sendMail).' - Already added: '.intval($alreadyAdded)
1670
                        );
1671
                        if ($sendMail == false) {
1672
                            $report['mail_not_sent_because_date']++;
1673
                        }
1674
                    }
1675
                } else {
1676
                    $this->logger->addInfo("Announcement not sent because config 'sendmail' in CSV");
1677
                    $report['mail_not_sent_because_setting']++;
1678
                }
1679
1680
                $content = '';
1681
                if ($update && isset($item['item_id'])) {
1682
                    $eventInfo = $agenda->get_event($item['item_id']);
1683
                    if (empty($eventInfo)) {
1684
                        // Means that agenda external id exists but the event doesn't exist
1685
                        $this->logger->addInfo("external event id exists: $externalEventId");
1686
                        $this->logger->addInfo("but Chamilo event doesn't exists: ".$item['item_id']);
1687
1688
                        $eventId = $agenda->addEvent(
1689
                            $event['start'],
1690
                            $event['end'],
1691
                            false,
1692
                            $event['title'],
1693
                            $content,
1694
                            ['everyone'], // $usersToSend
1695
                            false, //$addAsAnnouncement = false
1696
                            null, //  $parentEventId
1697
                            [], //$attachmentArray = array(),
1698
                            [], //$attachmentCommentList
1699
                            $eventComment,
1700
                            $color
1701
                        );
1702
1703
                        if (!empty($eventId)) {
1704
                            $this->logger->addInfo("Chamilo event created: ".$eventId);
1705
                            $extraFieldValueItem = $extraFieldValue->get_values_by_handler_and_field_id(
1706
                                $item['item_id'],
1707
                                $extraFieldInfo['id']
1708
                            );
1709
1710
                            if (!empty($extraFieldValueItem) && isset($extraFieldValueItem['id'])) {
1711
                                $params = [
1712
                                    'id' => $extraFieldValueItem['id'],
1713
                                    'item_id' => $eventId,
1714
                                ];
1715
                                $extraFieldValue->update($params);
1716
                                $this->logger->addInfo(
1717
                                    'Updating calendar extra field #'.$extraFieldValueItem['id'].'
1718
                                    new item_id: '.$eventId.' old item_id: '.$item['item_id']
1719
                                );
1720
                            }
1721
                        } else {
1722
                            $this->logger->addInfo("Error while creating event external id: $externalEventId");
1723
                        }
1724
                    } else {
1725
                        // The event already exists, just update
1726
                        $eventResult = $agenda->editEvent(
1727
                            $item['item_id'],
1728
                            $event['start'],
1729
                            $event['end'],
1730
                            false,
1731
                            $event['title'],
1732
                            $content,
1733
                            ['everyone'], // $usersToSend
1734
                            [], //$attachmentArray = array(),
1735
                            [], //$attachmentCommentList
1736
                            $eventComment,
1737
                            $color,
1738
                            false,
1739
                            false,
1740
                            $this->defaultAdminId
1741
                        );
1742
1743
                        if ($eventResult !== false) {
1744
                            $this->logger->addInfo(
1745
                                "Event updated #".$item['item_id']." External cal Id: (".$externalEventId.") $info"
1746
                            );
1747
                        } else {
1748
                            $this->logger->addInfo(
1749
                                "Error while updating event with external id: $externalEventId"
1750
                            );
1751
                        }
1752
                    }
1753
                } else {
1754
                    // New event. Create it.
1755
                    $eventId = $agenda->addEvent(
1756
                        $event['start'],
1757
                        $event['end'],
1758
                        false,
1759
                        $event['title'],
1760
                        $content,
1761
                        ['everyone'], // $usersToSend
1762
                        false, //$addAsAnnouncement = false
1763
                        null, //  $parentEventId
1764
                        [], //$attachmentArray = array(),
1765
                        [], //$attachmentCommentList
1766
                        $eventComment,
1767
                        $color
1768
                    );
1769
1770
                    if (!empty($eventId)) {
1771
                        $extraFieldValue->save(
1772
                            [
1773
                                'value' => $externalEventId,
1774
                                'field_id' => $extraFieldInfo['id'],
1775
                                'item_id' => $eventId,
1776
                            ]
1777
                        );
1778
                        $this->logger->addInfo(
1779
                            "Event added: #$eventId External cal id: (".$externalEventId.") $info"
1780
                        );
1781
                    } else {
1782
                        $this->logger->addInfo(
1783
                            "Error while creating event external id: $externalEventId"
1784
                        );
1785
                    }
1786
                }
1787
1788
                if (($counter % $batchSize) === 0) {
1789
                    $em->flush();
1790
                    $em->clear(); // Detaches all objects from Doctrine!
1791
                }
1792
                $counter++;
1793
            }
1794
1795
            $em->clear(); // Detaches all objects from Doctrine!
1796
            $this->logger->addInfo('------Summary------');
1797
            foreach ($report as $title => $count) {
1798
                $this->logger->addInfo("$title: $count");
1799
            }
1800
            $this->logger->addInfo('------End Summary------');
1801
        }
1802
1803
        if ($moveFile) {
1804
            $this->moveFile($file);
1805
        }
1806
    }
1807
1808
    private function importSkillset(
1809
        $file,
1810
        $moveFile = true
1811
    ) {
1812
        $this->fixCSVFile($file);
1813
        $data = Import::csvToArray($file);
1814
        if (!empty($data)) {
1815
            $this->logger->addInfo(count($data).' records found.');
1816
            $extraFieldValues = new ExtraFieldValue('skill');
1817
            $em = Database::getManager();
1818
            $repo = $em->getRepository(\Chamilo\CoreBundle\Entity\Skill::class);
1819
            $skillSetList = [];
1820
            $urlId = api_get_current_access_url_id();
1821
1822
            foreach ($data as $row) {
1823
                $skill = $repo->findOneBy(['shortCode' => $row['Code']]);
1824
                $new = false;
1825
                if ($skill === null) {
1826
                    $new = true;
1827
                    $skill = new \Chamilo\CoreBundle\Entity\Skill();
1828
                    $skill
1829
                        ->setShortCode($row['Code'])
1830
                        ->setDescription('')
1831
                        ->setAccessUrlId($urlId)
1832
                        ->setIcon('')
1833
                        ->setStatus(1)
1834
                    ;
1835
                }
1836
1837
                $skill
1838
                    ->setName($row['Tekst'])
1839
                    ->setUpdatedAt(new DateTime())
1840
                ;
1841
                $em->persist($skill);
1842
                $em->flush();
1843
1844
                if ($new) {
1845
                    $skillRelSkill = (new \Chamilo\CoreBundle\Entity\SkillRelSkill())
1846
                        ->setRelationType(0)
1847
                        ->setParentId(0)
1848
                        ->setLevel(0)
1849
                        ->setSkillId($skill->getId())
1850
                    ;
1851
                    $em->persist($skillRelSkill);
1852
                    $em->flush();
1853
                }
1854
1855
                /*
1856
                $params = [
1857
                    'item_id' => $skill->getId(),
1858
                    'variable' => 'skillset',
1859
                    'value' => $row['SkillsetID'],
1860
                ];
1861
                $extraFieldValues->save($params);*/
1862
                $skillSetList[$row['SkillsetID']][] = $skill->getId();
1863
            }
1864
1865
            //$courseRelSkills = [];
1866
            foreach ($skillSetList as $skillSetId => $skillList) {
1867
                $skillList = array_unique($skillList);
1868
                if (empty($skillList)) {
1869
                    continue;
1870
                }
1871
1872
                $sql = "SELECT id FROM course WHERE code LIKE '%$skillSetId' ";
1873
                $result = Database::query($sql);
1874
                while ($row = Database::fetch_array($result, 'ASSOC')) {
1875
                    $courseId = $row['id'];
1876
                    //$courseRelSkills[$courseId] = $skillList;
1877
                    Skill::saveSkillsToCourse($skillList, $courseId, null);
1878
                }
1879
            }
1880
        }
1881
    }
1882
1883
    /**
1884
     * @param string $file
1885
     * @param bool   $moveFile
1886
     * @param array  $teacherBackup
1887
     * @param array  $groupBackup
1888
     */
1889
    private function importCourses(
1890
        $file,
1891
        $moveFile = true,
1892
        &$teacherBackup = [],
1893
        &$groupBackup = []
1894
    ) {
1895
        $this->fixCSVFile($file);
1896
        $data = Import::csvToArray($file);
1897
1898
        if (!empty($data)) {
1899
            $this->logger->addInfo(count($data)." records found.");
1900
1901
            foreach ($data as $row) {
1902
                $row = $this->cleanCourseRow($row);
1903
                $courseId = CourseManager::get_course_id_from_original_id(
1904
                    $row['extra_'.$this->extraFieldIdNameList['course']],
1905
                    $this->extraFieldIdNameList['course']
1906
                );
1907
1908
                $courseInfo = api_get_course_info_by_id($courseId);
1909
1910
                if (empty($courseInfo)) {
1911
                    // Create
1912
                    $params = [];
1913
                    $params['title'] = $row['title'];
1914
                    $params['exemplary_content'] = false;
1915
                    $params['wanted_code'] = $row['course_code'];
1916
                    $params['course_category'] = $row['course_category'];
1917
                    $params['course_language'] = $row['language'];
1918
                    $params['teachers'] = $row['teachers'];
1919
                    $params['visibility'] = $row['visibility'];
1920
1921
                    $courseInfo = CourseManager::create_course(
1922
                        $params,
1923
                        $this->defaultAdminId
1924
                    );
1925
1926
                    if (!empty($courseInfo)) {
1927
                        CourseManager::update_course_extra_field_value(
1928
                            $courseInfo['code'],
1929
                            'external_course_id',
1930
                            $row['extra_'.$this->extraFieldIdNameList['course']]
1931
                        );
1932
1933
                        CourseManager::update_course_extra_field_value(
1934
                            $courseInfo['code'],
1935
                            'skillset',
1936
                            $row['extra_courseskillset']
1937
                        );
1938
1939
                        $this->logger->addInfo("Courses - Course created ".$courseInfo['code']);
1940
                    } else {
1941
                        $this->logger->addError("Courses - Can't create course:".$row['title']);
1942
                    }
1943
                } else {
1944
                    // Update
1945
                    $params = [
1946
                        'title' => $row['title'],
1947
                        'category_code' => $row['course_category'],
1948
                        'visibility' => $row['visibility'],
1949
                    ];
1950
1951
                    $result = CourseManager::update_attributes(
1952
                        $courseInfo['real_id'],
1953
                        $params
1954
                    );
1955
1956
                    $addTeacherToSession = isset($courseInfo['add_teachers_to_sessions_courses']) && !empty($courseInfo['add_teachers_to_sessions_courses']) ? true : false;
1957
1958
                    $teachers = $row['teachers'];
1959
                    if (!is_array($teachers)) {
1960
                        $teachers = [$teachers];
1961
                    }
1962
1963
                    if ($addTeacherToSession) {
1964
                        $this->logger->addInfo("Add teacher to all course sessions");
1965
                        CourseManager::updateTeachers(
1966
                            $courseInfo,
1967
                            $row['teachers'],
1968
                            false,
1969
                            true,
1970
                            false,
1971
                            $teacherBackup,
1972
                            $this->logger
1973
                        );
1974
                    } else {
1975
                        CourseManager::updateTeachers(
1976
                            $courseInfo,
1977
                            $row['teachers'],
1978
                            true,
1979
                            false,
1980
                            false,
1981
                            $teacherBackup,
1982
                            $this->logger
1983
                        );
1984
                    }
1985
1986
                    CourseManager::update_course_extra_field_value(
1987
                        $courseInfo['code'],
1988
                        'skillset',
1989
                        $row['extra_courseskillset']
1990
                    );
1991
1992
                    foreach ($teachers as $teacherId) {
1993
                        if (isset($groupBackup['tutor'][$teacherId]) &&
1994
                            isset($groupBackup['tutor'][$teacherId][$courseInfo['code']])
1995
                        ) {
1996
                            foreach ($groupBackup['tutor'][$teacherId][$courseInfo['code']] as $data) {
1997
                                $groupInfo = GroupManager::get_group_properties($data['group_id']);
1998
                                GroupManager::subscribe_tutors(
1999
                                    [$teacherId],
2000
                                    $groupInfo,
2001
                                    $data['c_id']
2002
                                );
2003
                            }
2004
                        }
2005
2006
                        if (isset($groupBackup['user'][$teacherId]) &&
2007
                            isset($groupBackup['user'][$teacherId][$courseInfo['code']]) &&
2008
                            !empty($groupBackup['user'][$teacherId][$courseInfo['code']])
2009
                        ) {
2010
                            foreach ($groupBackup['user'][$teacherId][$courseInfo['code']] as $data) {
2011
                                $groupInfo = GroupManager::get_group_properties($data['group_id']);
2012
                                GroupManager::subscribe_users(
2013
                                    [$teacherId],
2014
                                    $groupInfo,
2015
                                    $data['c_id']
2016
                                );
2017
                            }
2018
                        }
2019
                    }
2020
2021
                    if ($result) {
2022
                        $this->logger->addInfo("Courses - Course updated ".$courseInfo['code']);
2023
                    } else {
2024
                        $this->logger->addError("Courses - Course NOT updated ".$courseInfo['code']);
2025
                    }
2026
                }
2027
            }
2028
        }
2029
2030
        if ($moveFile) {
2031
            $this->moveFile($file);
2032
        }
2033
    }
2034
2035
    /**
2036
     * Parse filename: encora_subsessionsextid-static_31082016.csv.
2037
     *
2038
     * @param string $file
2039
     */
2040
    private function importSubscribeUserToCourseSessionExtStatic($file, $moveFile = true)
2041
    {
2042
        $data = Import::csv_reader($file);
2043
        if (!empty($data)) {
2044
            $this->logger->addInfo(count($data)." records found.");
2045
            $userIdList = [];
2046
            foreach ($data as $row) {
2047
                $chamiloUserName = $row['UserName'];
2048
                $chamiloCourseCode = $row['CourseCode'];
2049
                $externalSessionId = $row['ExtSessionID'];
2050
                $status = $row['Status'];
2051
2052
                $chamiloSessionId = null;
2053
                if (!empty($externalSessionId)) {
2054
                    $chamiloSessionId = SessionManager::getSessionIdFromOriginalId(
2055
                        $externalSessionId,
2056
                        $this->extraFieldIdNameList['session']
2057
                    );
2058
                }
2059
2060
                $sessionInfo = api_get_session_info($chamiloSessionId);
2061
2062
                if (empty($sessionInfo)) {
2063
                    $this->logger->addError('Session does not exists: '.$chamiloSessionId);
2064
                    continue;
2065
                }
2066
2067
                $courseInfo = api_get_course_info($chamiloCourseCode);
2068
                if (empty($courseInfo)) {
2069
                    $this->logger->addError('Course does not exists: '.$courseInfo);
2070
                    continue;
2071
                }
2072
2073
                $userId = UserManager::get_user_id_from_username($chamiloUserName);
2074
2075
                if (empty($userId)) {
2076
                    $this->logger->addError('User does not exists: '.$chamiloUserName);
2077
                    continue;
2078
                }
2079
2080
                switch ($status) {
2081
                    case 'student':
2082
                        SessionManager::subscribe_users_to_session_course(
2083
                            [$userId],
2084
                            $chamiloSessionId,
2085
                            $courseInfo['code']
2086
                        );
2087
                        break;
2088
                    case 'teacher':
2089
                        SessionManager::set_coach_to_course_session(
2090
                            $userId,
2091
                            $chamiloSessionId,
2092
                            $courseInfo['code']
2093
                        );
2094
                        break;
2095
                    case 'drh':
2096
                        $removeAllSessionsFromUser = true;
2097
                        if (in_array($userId, $userIdList)) {
2098
                            $removeAllSessionsFromUser = false;
2099
                        } else {
2100
                            $userIdList[] = $userId;
2101
                        }
2102
2103
                        $userInfo = api_get_user_info($userId);
2104
                        SessionManager::subscribeSessionsToDrh(
2105
                            $userInfo,
2106
                            [$chamiloSessionId],
2107
                            false,
2108
                            $removeAllSessionsFromUser
2109
                        );
2110
                        break;
2111
                }
2112
2113
                $this->logger->addError(
2114
                    "User '$chamiloUserName' was added as '$status' to Session: #$chamiloSessionId - Course: ".$courseInfo['code']
2115
                );
2116
            }
2117
        }
2118
2119
        if ($moveFile) {
2120
            $this->moveFile($file);
2121
        }
2122
    }
2123
2124
    /**
2125
     * @param $file
2126
     * @param bool $moveFile
2127
     */
2128
    private function importUnsubSessionsExtIdStatic($file, $moveFile = true)
2129
    {
2130
        $data = Import::csv_reader($file);
2131
2132
        if (!empty($data)) {
2133
            $this->logger->addInfo(count($data)." records found.");
2134
            foreach ($data as $row) {
2135
                $chamiloUserName = $row['UserName'];
2136
                $chamiloCourseCode = $row['CourseCode'];
2137
                $externalSessionId = $row['ExtSessionID'];
2138
                $dateStop = $row['DateStop'];
2139
2140
                $chamiloSessionId = null;
2141
                if (!empty($externalSessionId)) {
2142
                    $chamiloSessionId = SessionManager::getSessionIdFromOriginalId(
2143
                        $externalSessionId,
2144
                        $this->extraFieldIdNameList['session']
2145
                    );
2146
                }
2147
2148
                $sessionInfo = api_get_session_info($chamiloSessionId);
2149
2150
                if (empty($sessionInfo)) {
2151
                    $this->logger->addError('Session does not exists: '.$chamiloSessionId);
2152
                    continue;
2153
                }
2154
2155
                $courseInfo = api_get_course_info($chamiloCourseCode);
2156
                if (empty($courseInfo)) {
2157
                    $this->logger->addError('Course does not exists: '.$courseInfo);
2158
                    continue;
2159
                }
2160
2161
                $userId = UserManager::get_user_id_from_username($chamiloUserName);
2162
2163
                if (empty($userId)) {
2164
                    $this->logger->addError('User does not exists: '.$chamiloUserName);
2165
                    continue;
2166
                }
2167
2168
                SessionManager::removeUsersFromCourseSession(
2169
                    [$userId],
2170
                    $chamiloSessionId,
2171
                    $courseInfo
2172
                );
2173
2174
                $this->logger->addError(
2175
                    "User '$chamiloUserName' was remove from Session: #$chamiloSessionId - Course: ".$courseInfo['code']
2176
                );
2177
            }
2178
        }
2179
2180
        if ($moveFile) {
2181
            $this->moveFile($file);
2182
        }
2183
    }
2184
2185
    /**
2186
     * @param string $file
2187
     */
2188
    private function importSessionsExtIdStatic($file, $moveFile = true)
2189
    {
2190
        $data = Import::csv_reader($file);
2191
2192
        if (!empty($data)) {
2193
            $this->logger->addInfo(count($data)." records found.");
2194
            foreach ($data as $row) {
2195
                $chamiloUserName = $row['UserName'];
2196
                $chamiloCourseCode = $row['CourseCode'];
2197
                $externalSessionId = $row['ExtSessionID'];
2198
                $type = $row['Type'];
2199
2200
                $chamiloSessionId = null;
2201
                if (!empty($externalSessionId)) {
2202
                    $chamiloSessionId = SessionManager::getSessionIdFromOriginalId(
2203
                        $externalSessionId,
2204
                        $this->extraFieldIdNameList['session']
2205
                    );
2206
                }
2207
2208
                $sessionInfo = api_get_session_info($chamiloSessionId);
2209
2210
                if (empty($sessionInfo)) {
2211
                    $this->logger->addError('Session does not exists: '.$chamiloSessionId);
2212
                    continue;
2213
                }
2214
2215
                $courseInfo = api_get_course_info($chamiloCourseCode);
2216
                if (empty($courseInfo)) {
2217
                    $this->logger->addError('Course does not exists: '.$courseInfo);
2218
                    continue;
2219
                }
2220
2221
                $userId = UserManager::get_user_id_from_username($chamiloUserName);
2222
2223
                if (empty($userId)) {
2224
                    $this->logger->addError('User does not exists: '.$chamiloUserName);
2225
                    continue;
2226
                }
2227
                switch ($type) {
2228
                    case 'student':
2229
                        SessionManager::subscribe_users_to_session_course(
2230
                            [$userId],
2231
                            $chamiloSessionId,
2232
                            $courseInfo['code'],
2233
                            null,
2234
                            false
2235
                        );
2236
                        break;
2237
                    case 'teacher':
2238
                        SessionManager::set_coach_to_course_session(
2239
                            $userId,
2240
                            $chamiloSessionId,
2241
                            $courseInfo['code']
2242
                        );
2243
                        break;
2244
                }
2245
2246
                $this->logger->addError(
2247
                    "User '$chamiloUserName' with status $type was added to session: #$chamiloSessionId - Course: ".$courseInfo['code']
2248
                );
2249
            }
2250
        }
2251
2252
        if ($moveFile) {
2253
            $this->moveFile($file);
2254
        }
2255
    }
2256
2257
    /**
2258
     * Updates the session synchronize with the csv file.
2259
     *
2260
     * @param bool   $moveFile
2261
     * @param string $file
2262
     */
2263
    private function importSessionsStatic($file, $moveFile = true)
2264
    {
2265
        $content = file($file);
2266
        $sessions = [];
2267
        $tag_names = [];
2268
2269
        foreach ($content as $key => $enreg) {
2270
            $enreg = explode(';', trim($enreg));
2271
            if ($key) {
2272
                foreach ($tag_names as $tag_key => $tag_name) {
2273
                    if (isset($enreg[$tag_key])) {
2274
                        $sessions[$key - 1][$tag_name] = $enreg[$tag_key];
2275
                    }
2276
                }
2277
            } else {
2278
                foreach ($enreg as $tag_name) {
2279
                    $tag_names[] = api_preg_replace(
2280
                        '/[^a-zA-Z0-9_\-]/',
2281
                        '',
2282
                        $tag_name
2283
                    );
2284
                }
2285
                if (!in_array('SessionName', $tag_names) ||
2286
                    !in_array('DateStart', $tag_names) || !in_array('DateEnd', $tag_names)
2287
                ) {
2288
                    $error_message = get_lang('NoNeededData');
2289
                    break;
2290
                }
2291
            }
2292
        }
2293
2294
        if (!empty($sessions)) {
2295
            // Looping the sessions.
2296
            foreach ($sessions as $session) {
2297
                if (!empty($session['SessionID'])) {
2298
                    $sessionId = SessionManager::getSessionIdFromOriginalId(
2299
                        $session['SessionID'],
2300
                        $this->extraFieldIdNameList['session']
2301
                    );
2302
2303
                    $coachUserName = isset($session['Coach']) ? $session['Coach'] : null;
2304
                    $categoryId = isset($session['category_id']) ? $session['category_id'] : null;
2305
2306
                    // 2014-06-30
2307
                    $dateStart = explode('/', $session['DateStart']);
2308
                    $dateEnd = explode('/', $session['DateEnd']);
2309
                    $visibility = $this->defaultSessionVisibility;
2310
2311
                    $coachId = null;
2312
                    if (!empty($coachUserName)) {
2313
                        $coachInfo = api_get_user_info_from_username($coachUserName);
2314
                        $coachId = $coachInfo['user_id'];
2315
                    }
2316
2317
                    $dateStart = $dateStart[0].'-'.$dateStart[1].'-'.$dateStart[2].' 00:00:00';
2318
                    $dateEnd = $dateEnd[0].'-'.$dateEnd[1].'-'.$dateEnd[2].' 23:59:59';
2319
2320
                    $date = new \DateTime($dateStart);
2321
                    $interval = new DateInterval('P'.$this->daysCoachAccessBeforeBeginning.'D');
2322
                    $date->sub($interval);
2323
                    $coachBefore = $date->format('Y-m-d h:i');
2324
2325
                    $date = new \DateTime($dateEnd);
2326
                    $interval = new DateInterval('P'.$this->daysCoachAccessAfterBeginning.'D');
2327
                    $date->add($interval);
2328
                    $coachAfter = $date->format('Y-m-d h:i');
2329
2330
                    /*$dateStart = api_get_utc_datetime($dateStart);
2331
                    $dateEnd = api_get_utc_datetime($dateEnd);
2332
                    $coachBefore = api_get_utc_datetime($coachBefore);
2333
                    $coachAfter = api_get_utc_datetime($coachAfter);*/
2334
2335
                    if (empty($sessionId)) {
2336
                        $result = SessionManager::create_session(
2337
                            $session['SessionName'],
2338
                            $dateStart,
2339
                            $dateEnd,
2340
                            $dateStart,
2341
                            $dateEnd,
2342
                            $coachBefore,
2343
                            $coachAfter,
2344
                            $coachId,
2345
                            $categoryId,
2346
                            $visibility
2347
                        );
2348
2349
                        if (is_numeric($result)) {
2350
                            $sessionId = $result;
2351
                            $this->logger->addInfo("Session #$sessionId created: ".$session['SessionName']);
2352
                            SessionManager::update_session_extra_field_value(
2353
                                $sessionId,
2354
                                $this->extraFieldIdNameList['session'],
2355
                                $session['SessionID']
2356
                            );
2357
                        } else {
2358
                            $this->logger->addInfo("Failed creating session: ".$session['SessionName']);
2359
                        }
2360
                    } else {
2361
                        $sessionInfo = api_get_session_info($sessionId);
2362
                        $accessBefore = null;
2363
                        $accessAfter = null;
2364
2365
                        if (empty($sessionInfo['nb_days_access_before_beginning']) ||
2366
                            (!empty($sessionInfo['nb_days_access_before_beginning']) &&
2367
                                $sessionInfo['nb_days_access_before_beginning'] < $this->daysCoachAccessBeforeBeginning)
2368
                        ) {
2369
                            $accessBefore = $coachBefore;
2370
                        }
2371
2372
                        $accessAfter = null;
2373
                        if (empty($sessionInfo['nb_days_access_after_end']) ||
2374
                            (!empty($sessionInfo['nb_days_access_after_end']) &&
2375
                                $sessionInfo['nb_days_access_after_end'] < $this->daysCoachAccessAfterBeginning)
2376
                        ) {
2377
                            $accessAfter = $coachAfter;
2378
                        }
2379
2380
                        $showDescription = isset($sessionInfo['show_description']) ? $sessionInfo['show_description'] : 1;
2381
2382
                        $result = SessionManager::edit_session(
2383
                            $sessionId,
2384
                            $session['SessionName'],
2385
                            $dateStart,
2386
                            $dateEnd,
2387
                            $dateStart,
2388
                            $dateEnd,
2389
                            $accessBefore,
2390
                            $accessAfter,
2391
                            $coachId,
2392
                            $categoryId,
2393
                            $visibility,
2394
                            null, //$description = null,
2395
                            $showDescription
2396
                        );
2397
2398
                        if (is_numeric($result)) {
2399
                            $this->logger->addInfo("Session #$sessionId updated: ".$session['SessionName']);
2400
                            $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
2401
                            $params = [
2402
                                'description' => $session['SessionDescription'],
2403
                            ];
2404
                            Database::update(
2405
                                $tbl_session,
2406
                                $params,
2407
                                ['id = ?' => $sessionId]
2408
                            );
2409
                        }
2410
                    }
2411
2412
                    if (!empty($sessionId)) {
2413
                        // Courses
2414
                        $courses = explode('|', $session['Courses']);
2415
                        $courseList = [];
2416
                        $courseListWithCoach = [];
2417
                        foreach ($courses as $course) {
2418
                            $courseArray = bracketsToArray($course);
2419
                            $courseCode = $courseArray[0];
2420
                            if (CourseManager::course_exists($courseCode)) {
2421
                                $courseInfo = api_get_course_info($courseCode);
2422
                                $courseList[] = $courseInfo['real_id'];
2423
                                // Extracting course coaches
2424
                                $courseCoaches = isset($courseArray[1]) ? $courseArray[1] : null;
2425
                                $courseCoaches = explode(',', $courseCoaches);
2426
2427
                                // Extracting students
2428
                                $courseUsers = isset($courseArray[2]) ? $courseArray[2] : null;
2429
                                $courseUsers = explode(',', $courseUsers);
2430
2431
                                $courseListWithCoach[] = [
2432
                                    'course_info' => $courseInfo,
2433
                                    'coaches' => $courseCoaches,
2434
                                    'course_users' => $courseUsers,
2435
                                ];
2436
                            }
2437
                        }
2438
2439
                        SessionManager::add_courses_to_session(
2440
                            $sessionId,
2441
                            $courseList,
2442
                            true
2443
                        );
2444
2445
                        $this->logger->addInfo("Session #$sessionId: Courses added: '".implode(', ', $courseList)."'");
2446
2447
                        if (empty($courseListWithCoach)) {
2448
                            $this->logger->addInfo("No users/coaches to update");
2449
                            continue;
2450
                        }
2451
2452
                        foreach ($courseListWithCoach as $courseData) {
2453
                            $courseInfo = $courseData['course_info'];
2454
                            $courseCode = $courseInfo['code'];
2455
                            $courseId = $courseInfo['real_id'];
2456
                            $courseCoaches = $courseData['coaches'];
2457
                            $courseUsers = $courseData['course_users'];
2458
2459
                            // Coaches
2460
                            if (!empty($courseCoaches)) {
2461
                                $coachList = [];
2462
                                foreach ($courseCoaches as $courseCoach) {
2463
                                    $courseCoachId = UserManager::get_user_id_from_username(
2464
                                        $courseCoach
2465
                                    );
2466
                                    if ($courseCoachId !== false) {
2467
                                        // Just insert new coaches
2468
                                        $coachList[] = $courseCoachId;
2469
                                    }
2470
                                }
2471
2472
                                $this->logger->addInfo("Session #$sessionId: course '$courseCode' coaches added: '".implode(', ', $coachList)."'");
2473
2474
                                SessionManager::updateCoaches(
2475
                                    $sessionId,
2476
                                    $courseId,
2477
                                    $coachList,
2478
                                    true
2479
                                );
2480
                            } else {
2481
                                $this->logger->addInfo("No coaches added");
2482
                            }
2483
2484
                            // Students
2485
                            if (!empty($courseUsers)) {
2486
                                $userList = [];
2487
                                foreach ($courseUsers as $username) {
2488
                                    $userInfo = api_get_user_info_from_username(trim($username));
2489
                                    if (!empty($userInfo)) {
2490
                                        $userList[] = $userInfo['user_id'];
2491
                                    }
2492
                                }
2493
2494
                                $this->logger->addInfo("Session #$sessionId: course '$courseCode': Students added '".implode(', ', $userList)."'");
2495
                                SessionManager::subscribe_users_to_session_course(
2496
                                    $userList,
2497
                                    $sessionId,
2498
                                    $courseCode,
2499
                                    SESSION_VISIBLE_READ_ONLY,
2500
                                    true
2501
                                );
2502
                            } else {
2503
                                $this->logger->addInfo("No users to register.");
2504
                            }
2505
                        }
2506
                    } else {
2507
                        $this->logger->addInfo(
2508
                            'SessionID not found in system.'
2509
                        );
2510
                    }
2511
                } else {
2512
                    $this->logger->addInfo('SessionID does not exists');
2513
                }
2514
            }
2515
        } else {
2516
            $this->logger->addInfo($error_message);
2517
        }
2518
2519
        if ($moveFile) {
2520
            $this->moveFile($file);
2521
        }
2522
    }
2523
2524
    /**
2525
     * @param $file
2526
     * @param bool  $moveFile
2527
     * @param array $teacherBackup
2528
     * @param array $groupBackup
2529
     */
2530
    private function importOpenSessions(
2531
        $file,
2532
        $moveFile = true,
2533
        &$teacherBackup = [],
2534
        &$groupBackup = []
2535
    ) {
2536
        $this->importSessions($file, $moveFile, $teacherBackup, $groupBackup);
2537
    }
2538
2539
    private function importSessionsUsersCareers(
2540
        $file,
2541
        $moveFile = false,
2542
        &$teacherBackup = [],
2543
        &$groupBackup = []
2544
    ) {
2545
        $data = Import::csvToArray($file);
2546
        if (!empty($data)) {
2547
            $extraFieldValueCareer = new ExtraFieldValue('career');
2548
            $sessionExtraFieldValue = new ExtraFieldValue('session');
2549
            $career = new Career();
2550
2551
            $this->logger->addInfo(count($data)." records found.");
2552
            foreach ($data as $row) {
2553
                $users = $row['Users'];
2554
                if (empty($users)) {
2555
                    $this->logger->addError('No users found');
2556
                    continue;
2557
                }
2558
2559
                $users = explode('|', $users);
2560
                $careerList = str_replace(['[', ']'], '', $row['extra_careerid']);
2561
                $careerList = explode(',', $careerList);
2562
2563
                $finalCareerIdList = [];
2564
                $careerListValidated = [];
2565
                foreach ($careerList as $careerId) {
2566
                    $realCareerIdList = $extraFieldValueCareer->get_item_id_from_field_variable_and_field_value(
2567
                        'external_career_id',
2568
                        $careerId
2569
                    );
2570
                    if (isset($realCareerIdList['item_id'])) {
2571
                        $careerListValidated[] = $careerId;
2572
                        $finalCareerIdList[] = $realCareerIdList['item_id'];
2573
                    }
2574
                }
2575
2576
                if (empty($finalCareerIdList)) {
2577
                    $this->logger->addError('Careers not found: '.print_r($finalCareerIdList, 1));
2578
                    continue;
2579
                }
2580
2581
                //$chamiloSessionId = $row['SessionID'];
2582
2583
                $chamiloSessionId = SessionManager::getSessionIdFromOriginalId(
2584
                    $row['SessionID'],
2585
                    $this->extraFieldIdNameList['session']
2586
                );
2587
2588
                $sessionInfo = api_get_session_info($chamiloSessionId);
2589
2590
                if (empty($sessionInfo)) {
2591
                    $this->logger->addError('Session does not exists: '.$chamiloSessionId);
2592
                    continue;
2593
                } else {
2594
                    $this->logger->addInfo("Session id: ".$sessionInfo['id']);
2595
                }
2596
2597
                $sessionId = $sessionInfo['id'];
2598
2599
                // Add career to session.
2600
                $externalCareerIdList = $sessionExtraFieldValue->get_values_by_handler_and_field_variable(
2601
                    $sessionId,
2602
                    'careerid'
2603
                );
2604
2605
                if (empty($externalCareerIdList) ||
2606
                    (isset($externalCareerIdList['value']) && empty($externalCareerIdList['value']))
2607
                ) {
2608
                    $careerItem = '['.implode(',', $careerListValidated).']';
2609
                    $params = ['item_id' => $sessionId, 'extra_careerid' => $careerItem];
2610
                    $this->logger->addInfo("Saving career: $careerItem to session: $sessionId");
2611
                    $sessionExtraFieldValue->saveFieldValues($params, true);
2612
                } else {
2613
                    /*foreach ($finalCareerIdList as $careerId) {
2614
                        if (empty($externalCareerIdList)) {
2615
                            $params = ['item_id' => $sessionId, 'extra_careerid' => $careerId];
2616
                            $sessionExtraFieldValue->saveFieldValues($params, true);
2617
                        }
2618
                    }*/
2619
                }
2620
2621
                // Add career to users.
2622
                foreach ($users as $username) {
2623
                    $userInfo = api_get_user_info_from_username($username);
2624
                    if (empty($userInfo)) {
2625
                        $this->logger->addError('username not found: '.$username);
2626
                        continue;
2627
                    }
2628
2629
                    foreach ($finalCareerIdList as $careerId) {
2630
                        $this->logger->addInfo("Adding Career $careerId: To user $username");
2631
                        UserManager::addUserCareer($userInfo['id'], $careerId);
2632
                    }
2633
                }
2634
            }
2635
        }
2636
    }
2637
2638
    /**
2639
     * @param string $file
2640
     * @param bool   $moveFile
2641
     * @param array  $teacherBackup
2642
     * @param array  $groupBackup
2643
     */
2644
    private function importSessions(
2645
        $file,
2646
        $moveFile = true,
2647
        &$teacherBackup = [],
2648
        &$groupBackup = []
2649
    ) {
2650
        $avoid = null;
2651
        if (isset($this->conditions['importSessions']) &&
2652
            isset($this->conditions['importSessions']['update'])
2653
        ) {
2654
            $avoid = $this->conditions['importSessions']['update'];
2655
        }
2656
        $result = SessionManager::importCSV(
2657
            $file,
2658
            true,
2659
            $this->defaultAdminId,
2660
            $this->logger,
2661
            [
2662
                'SessionID' => 'extra_'.$this->extraFieldIdNameList['session'],
2663
                'CareerId' => 'extra_'.$this->extraFieldIdNameList['session_career'],
2664
            ],
2665
            $this->extraFieldIdNameList['session'],
2666
            $this->daysCoachAccessBeforeBeginning,
2667
            $this->daysCoachAccessAfterBeginning,
2668
            $this->defaultSessionVisibility,
2669
            $avoid,
2670
            false, // deleteUsersNotInList
2671
            false, // updateCourseCoaches
2672
            true, // sessionWithCoursesModifier
2673
            true, //$addOriginalCourseTeachersAsCourseSessionCoaches
2674
            false, //$removeAllTeachersFromCourse
2675
            1, // $showDescription,
2676
            $teacherBackup,
2677
            $groupBackup
2678
        );
2679
2680
        if (!empty($result['error_message'])) {
2681
            $this->logger->addError($result['error_message']);
2682
        }
2683
        $this->logger->addInfo("Sessions - Sessions parsed: ".$result['session_counter']);
2684
2685
        if ($moveFile) {
2686
            $this->moveFile($file);
2687
        }
2688
    }
2689
2690
    /**
2691
     * @param string $file
2692
     * @param bool   $moveFile
2693
     */
2694
    private function importSubscribeStatic($file, $moveFile = true)
2695
    {
2696
        $data = Import::csv_reader($file);
2697
2698
        if (!empty($data)) {
2699
            $this->logger->addInfo(count($data)." records found.");
2700
            foreach ($data as $row) {
2701
                $chamiloUserName = $row['UserName'];
2702
                $chamiloCourseCode = $row['CourseCode'];
2703
                $chamiloSessionId = $row['SessionID'];
2704
                $type = $row['Type'];
2705
2706
                $sessionInfo = api_get_session_info($chamiloSessionId);
2707
2708
                if (empty($sessionInfo)) {
2709
                    $this->logger->addError('Session does not exists: '.$chamiloSessionId);
2710
                    continue;
2711
                }
2712
2713
                $courseInfo = api_get_course_info($chamiloCourseCode);
2714
                if (empty($courseInfo)) {
2715
                    $this->logger->addError('Course does not exists: '.$courseInfo);
2716
                    continue;
2717
                }
2718
2719
                $userId = UserManager::get_user_id_from_username($chamiloUserName);
2720
2721
                if (empty($userId)) {
2722
                    $this->logger->addError('User does not exists: '.$chamiloUserName);
2723
                    continue;
2724
                }
2725
2726
                switch ($type) {
2727
                    case 'student':
2728
                        SessionManager::subscribe_users_to_session_course(
2729
                            [$userId],
2730
                            $chamiloSessionId,
2731
                            $courseInfo['code'],
2732
                            null,
2733
                            false
2734
                        );
2735
                        break;
2736
                    case 'teacher':
2737
                        SessionManager::set_coach_to_course_session(
2738
                            $userId,
2739
                            $chamiloSessionId,
2740
                            $courseInfo['real_id']
2741
                        );
2742
                        break;
2743
                }
2744
2745
                $this->logger->addError(
2746
                    "User '$chamiloUserName' with status $type was added to session: #$chamiloSessionId - Course: ".$courseInfo['code']
2747
                );
2748
            }
2749
        }
2750
2751
        if ($moveFile) {
2752
            $this->moveFile($file);
2753
        }
2754
    }
2755
2756
    /**
2757
     * @param $file
2758
     * @param bool $moveFile
2759
     */
2760
    private function importSubscribeUserToCourse($file, $moveFile = false, &$teacherBackup = [])
2761
    {
2762
        $data = Import::csv_reader($file);
2763
2764
        if (!empty($data)) {
2765
            $this->logger->addInfo(count($data)." records found.");
2766
            foreach ($data as $row) {
2767
                $chamiloUserName = $row['UserName'];
2768
                $chamiloCourseCode = $row['CourseCode'];
2769
                $status = $row['Status'];
2770
2771
                $courseInfo = api_get_course_info($chamiloCourseCode);
2772
2773
                if (empty($courseInfo)) {
2774
                    $this->logger->addError(
2775
                        'Course does not exists: '.$chamiloCourseCode
2776
                    );
2777
                    continue;
2778
                }
2779
2780
                $userId = UserManager::get_user_id_from_username(
2781
                    $chamiloUserName
2782
                );
2783
2784
                if (empty($userId)) {
2785
                    $this->logger->addError(
2786
                        'User does not exists: '.$chamiloUserName
2787
                    );
2788
                    continue;
2789
                }
2790
2791
                $userCourseCategory = '';
2792
                if (isset($teacherBackup[$userId]) &&
2793
                    isset($teacherBackup[$userId][$courseInfo['code']])
2794
                ) {
2795
                    $courseUserData = $teacherBackup[$userId][$courseInfo['code']];
2796
                    $userCourseCategory = $courseUserData['user_course_cat'];
2797
                }
2798
2799
                $result = CourseManager::subscribeUser(
2800
                    $userId,
2801
                    $courseInfo['code'],
2802
                    $status,
2803
                    0,
2804
                    $userCourseCategory
2805
                );
2806
2807
                if ($result) {
2808
                    $this->logger->addInfo(
2809
                        "User $userId added to course ".$courseInfo['code']." with status '$status' with course category: '$userCourseCategory'"
2810
                    );
2811
                } else {
2812
                    $this->logger->addInfo(
2813
                        "User $userId was NOT ADDED to course ".$courseInfo['code']." with status '$status' with course category: '$userCourseCategory'"
2814
                    );
2815
                }
2816
            }
2817
        }
2818
2819
        if ($moveFile) {
2820
            $this->moveFile($file);
2821
        }
2822
    }
2823
2824
    /**
2825
     * 23/4/2017 to datetime.
2826
     *
2827
     * @param $string
2828
     *
2829
     * @return mixed
2830
     */
2831
    private function createDateTime($string)
2832
    {
2833
        if (empty($string)) {
2834
            return null;
2835
        }
2836
2837
        $date = DateTime::createFromFormat('j/m/Y', $string);
2838
        if ($date) {
2839
            return $date;
2840
        }
2841
2842
        return null;
2843
    }
2844
2845
    /**
2846
     * @param $file
2847
     * @param bool  $moveFile
2848
     * @param array $teacherBackup
2849
     * @param array $groupBackup
2850
     *
2851
     * @return bool
2852
     */
2853
    private function importCareers(
2854
        $file,
2855
        $moveFile = false,
2856
        &$teacherBackup = [],
2857
        &$groupBackup = []
2858
    ) {
2859
        $data = Import::csv_reader($file);
2860
2861
        if (!empty($data)) {
2862
            $this->logger->addInfo(count($data).' records found.');
2863
            $extraFieldValue = new ExtraFieldValue('career');
2864
            $extraFieldName = $this->extraFieldIdNameList['career'];
2865
            $externalEventId = null;
2866
2867
            $extraField = new ExtraField('career');
2868
            $extraFieldInfo = $extraField->get_handler_field_info_by_field_variable($extraFieldName);
2869
2870
            if (empty($extraFieldInfo)) {
2871
                $this->logger->addInfo("Extra field doesn't exists: $extraFieldName");
2872
2873
                return false;
2874
            }
2875
2876
            foreach ($data as $row) {
2877
                foreach ($row as $key => $value) {
2878
                    $key = (string) trim($key);
2879
                    // Remove utf8 bom
2880
                    $key = preg_replace('/[\x00-\x1F\x80-\xFF]/', '', $key);
2881
                    $row[$key] = $value;
2882
                }
2883
2884
                $itemId = $row['CareerId'];
2885
                $item = $extraFieldValue->get_item_id_from_field_variable_and_field_value(
2886
                    $extraFieldName,
2887
                    $itemId,
2888
                    false,
2889
                    false,
2890
                    false
2891
                );
2892
2893
                $career = new Career();
2894
                if (empty($item)) {
2895
                    $params = [
2896
                        'status' => 1,
2897
                        'name' => $row['CareerName'],
2898
                    ];
2899
                    $careerId = $career->save($params);
2900
                    if ($careerId) {
2901
                        $this->logger->addInfo('Career saved: '.print_r($params, 1));
2902
                        $params = [
2903
                            'item_id' => $careerId,
2904
                            'extra_'.$extraFieldName => $itemId,
2905
                        ];
2906
                        $links = isset($row['HLinks']) ? $row['HLinks'] : [];
2907
                        if (!empty($links)) {
2908
                            $extraFieldUrlName = $this->extraFieldIdNameList['career_urls'];
2909
                            $extraFieldInfo = $extraField->get_handler_field_info_by_field_variable(
2910
                                $extraFieldUrlName
2911
                            );
2912
                            if (!empty($extraFieldInfo)) {
2913
                                $params['extra_'.$extraFieldUrlName] = $links;
2914
                            }
2915
                        }
2916
                        $extraFieldValue->saveFieldValues($params);
2917
                    }
2918
                } else {
2919
                    if (isset($item['item_id'])) {
2920
                        $params = [
2921
                            'id' => $item['item_id'],
2922
                            'name' => $row['CareerName'],
2923
                        ];
2924
                        $career->update($params);
2925
                        $this->logger->addInfo('Career updated: '.print_r($params, 1));
2926
                        $links = isset($row['HLinks']) ? $row['HLinks'] : [];
2927
2928
                        if (!empty($links)) {
2929
                            $extraFieldUrlName = $this->extraFieldIdNameList['career_urls'];
2930
                            $extraFieldInfo = $extraField->get_handler_field_info_by_field_variable(
2931
                                $extraFieldUrlName
2932
                            );
2933
                            if (!empty($extraFieldInfo)) {
2934
                                $params = [
2935
                                    'item_id' => $item['item_id'],
2936
                                    'extra_'.$extraFieldName => $itemId,
2937
                                    'extra_'.$extraFieldUrlName => $links,
2938
                                ];
2939
                                $extraFieldValue->saveFieldValues($params);
2940
                            }
2941
                        }
2942
                    }
2943
                }
2944
            }
2945
        }
2946
2947
        if ($moveFile) {
2948
            $this->moveFile($file);
2949
        }
2950
    }
2951
2952
    /**
2953
     * @param $file
2954
     * @param bool  $moveFile
2955
     * @param array $teacherBackup
2956
     * @param array $groupBackup
2957
     */
2958
    private function importCareersResultsRemoveStatic(
2959
        $file,
2960
        $moveFile = false
2961
    ) {
2962
        $data = Import::csv_reader($file);
2963
2964
        $careerIdList = [];
2965
        $userIdList = [];
2966
2967
        if (!empty($data)) {
2968
            $totalCount = count($data);
2969
            $this->logger->addInfo($totalCount.' records found.');
2970
2971
            $extraFieldValue = new ExtraFieldValue('career');
2972
            $extraFieldName = $this->extraFieldIdNameList['career'];
2973
            $rowCounter = 0;
2974
            foreach ($data as $row) {
2975
                $this->logger->addInfo("---------- Row: # $rowCounter");
2976
                $rowCounter++;
2977
                if (empty($row)) {
2978
                    continue;
2979
                }
2980
2981
                foreach ($row as $key => $value) {
2982
                    $key = (string) trim($key);
2983
                    // Remove utf8 bom
2984
                    $key = preg_replace('/[\x00-\x1F\x80-\xFF]/', '', $key);
2985
                    $row[$key] = $value;
2986
                }
2987
2988
                $rowStudentId = $row['StudentId'];
2989
2990
                if (isset($userIdList[$rowStudentId])) {
2991
                    $studentId = $userIdList[$rowStudentId];
2992
                } else {
2993
                    $studentId = UserManager::get_user_id_from_original_id(
2994
                        $rowStudentId,
2995
                        $this->extraFieldIdNameList['user']
2996
                    );
2997
                    $userIdList[$rowStudentId] = $studentId;
2998
                }
2999
3000
                $careerId = $row['CareerId'];
3001
                if (isset($careerIdList[$careerId])) {
3002
                    $careerChamiloId = $careerIdList[$careerId];
3003
                } else {
3004
                    $item = $extraFieldValue->get_item_id_from_field_variable_and_field_value(
3005
                        $extraFieldName,
3006
                        $careerId
3007
                    );
3008
3009
                    if (empty($item)) {
3010
                        $careerIdList[$careerId] = 0;
3011
                        continue;
3012
                    } else {
3013
                        if (isset($item['item_id'])) {
3014
                            $careerChamiloId = $item['item_id'];
3015
                            $careerIdList[$careerId] = $careerChamiloId;
3016
                        } else {
3017
                            $careerIdList[$careerId] = 0;
3018
                            continue;
3019
                        }
3020
                    }
3021
                }
3022
3023
                if (empty($careerChamiloId)) {
3024
                    $this->logger->addInfo("Career not found: $careerId ");
3025
                    continue;
3026
                }
3027
3028
                $userCareerData = UserManager::getUserCareer($studentId, $careerChamiloId);
3029
3030
                if (empty($userCareerData)) {
3031
                    $this->logger->addInfo(
3032
                        "User chamilo id # $studentId (".$row['StudentId'].") has no career #$careerChamiloId (ext #$careerId)"
3033
                    );
3034
                    continue;
3035
                }
3036
3037
                $extraData = isset($userCareerData['extra_data']) && !empty($userCareerData['extra_data']) ? unserialize($userCareerData['extra_data']) : [];
3038
                unset($extraData[$row['CourseId']][$row['ResultId']]);
3039
                $serializedValue = serialize($extraData);
3040
3041
                UserManager::updateUserCareer($userCareerData['id'], $serializedValue);
3042
3043
                $this->logger->addInfo('Deleting: result id'.$row['ResultId']);
3044
                $this->logger->addInfo(
3045
                    "Saving graph for user chamilo # $studentId (".$row['StudentId'].") with career #$careerChamiloId (ext #$careerId)"
3046
                );
3047
            }
3048
        }
3049
3050
        if ($moveFile) {
3051
            $this->moveFile($file);
3052
        }
3053
    }
3054
3055
    /**
3056
     * @param $file
3057
     * @param bool  $moveFile
3058
     * @param array $teacherBackup
3059
     * @param array $groupBackup
3060
     */
3061
    private function importCareersResults(
3062
        $file,
3063
        $moveFile = false,
3064
        &$teacherBackup = [],
3065
        &$groupBackup = []
3066
    ) {
3067
        $data = Import::csv_reader($file);
3068
3069
        $userTable = Database::get_main_table(TABLE_MAIN_USER);
3070
        $careerIdList = [];
3071
        $userIdList = [];
3072
        if (!empty($data)) {
3073
            $totalCount = count($data);
3074
            $this->logger->addInfo($totalCount.' records found.');
3075
3076
            $extraFieldValue = new ExtraFieldValue('career');
3077
            $extraFieldName = $this->extraFieldIdNameList['career'];
3078
            $rowCounter = 0;
3079
            foreach ($data as $row) {
3080
                $this->logger->addInfo("---------- Row: # $rowCounter");
3081
                $rowCounter++;
3082
                if (empty($row)) {
3083
                    continue;
3084
                }
3085
3086
                foreach ($row as $key => $value) {
3087
                    $key = (string) trim($key);
3088
                    // Remove utf8 bom
3089
                    $key = preg_replace('/[\x00-\x1F\x80-\xFF]/', '', $key);
3090
                    $row[$key] = $value;
3091
                }
3092
3093
                $rowStudentId = $row['StudentId'];
3094
3095
                if (isset($userIdList[$rowStudentId])) {
3096
                    $studentId = $userIdList[$rowStudentId];
3097
                } else {
3098
                    $studentId = UserManager::get_user_id_from_original_id(
3099
                        $rowStudentId,
3100
                        $this->extraFieldIdNameList['user']
3101
                    );
3102
3103
                    $userIdList[$rowStudentId] = $studentId;
3104
                }
3105
3106
                $careerId = $row['CareerId'];
3107
                if (isset($careerIdList[$careerId])) {
3108
                    $careerChamiloId = $careerIdList[$careerId];
3109
                } else {
3110
                    $item = $extraFieldValue->get_item_id_from_field_variable_and_field_value(
3111
                        $extraFieldName,
3112
                        $careerId
3113
                    );
3114
3115
                    if (empty($item)) {
3116
                        //$this->logger->addInfo("Career not found: $careerId case 1");
3117
                        $careerIdList[$careerId] = 0;
3118
                        continue;
3119
                    } else {
3120
                        if (isset($item['item_id'])) {
3121
                            $careerChamiloId = $item['item_id'];
3122
                            $careerIdList[$careerId] = $careerChamiloId;
3123
                        } else {
3124
                            $careerIdList[$careerId] = 0;
3125
                            //$this->logger->addInfo("Career not found: $careerId case 2");
3126
                            continue;
3127
                        }
3128
                    }
3129
                }
3130
3131
                if (empty($careerChamiloId)) {
3132
                    $this->logger->addInfo("Career not found: $careerId ");
3133
                    continue;
3134
                }
3135
3136
                $userCareerData = UserManager::getUserCareer($studentId, $careerChamiloId);
3137
3138
                if (empty($userCareerData)) {
3139
                    $this->logger->addInfo(
3140
                        "User chamilo id # $studentId (".$row['StudentId'].") has no career #$careerChamiloId (ext #$careerId)"
3141
                    );
3142
                    continue;
3143
                }
3144
3145
                $extraData = isset($userCareerData['extra_data']) && !empty($userCareerData['extra_data']) ? unserialize($userCareerData['extra_data']) : [];
3146
3147
                $sql = "SELECT firstname, lastname FROM $userTable
3148
                        WHERE username='".Database::escape_string($row['TeacherUsername'])."'";
3149
                $result = Database::query($sql);
3150
3151
                $teacherName = $row['TeacherUsername'];
3152
                if (Database::num_rows($result)) {
3153
                    $teacherInfo = Database::fetch_array($result);
3154
                    $teacherName = $teacherInfo['firstname'].' '.$teacherInfo['lastname'];
3155
                }
3156
3157
                $extraData[$row['CourseId']][$row['ResultId']] = [
3158
                    'Description' => $row['Description'],
3159
                    'Period' => $row['Period'],
3160
                    'TeacherText' => $row['TeacherText'],
3161
                    'TeacherUsername' => $teacherName,
3162
                    'ScoreText' => $row['ScoreText'],
3163
                    'ScoreValue' => $row['ScoreValue'],
3164
                    'Info' => $row['Info'],
3165
                    'BgColor' => $row['BgColor'],
3166
                    'Color' => $row['Color'],
3167
                    'BorderColor' => $row['BorderColor'],
3168
                    'Icon' => $row['Icon'],
3169
                    'IconColor' => $row['IconColor'],
3170
                    'SortDate' => $row['SortDate'] ?? '',
3171
                ];
3172
                $serializedValue = serialize($extraData);
3173
3174
                UserManager::updateUserCareer($userCareerData['id'], $serializedValue);
3175
3176
                $this->logger->addInfo(
3177
                    "Saving graph for user chamilo # $studentId (".$row['StudentId'].") with career #$careerChamiloId (ext #$careerId)"
3178
                );
3179
            }
3180
        }
3181
3182
        if ($moveFile) {
3183
            $this->moveFile($file);
3184
        }
3185
    }
3186
3187
    /**
3188
     * @param $file
3189
     * @param bool  $moveFile
3190
     * @param array $teacherBackup
3191
     * @param array $groupBackup
3192
     */
3193
    private function importCareersDiagram(
3194
        $file,
3195
        $moveFile = false,
3196
        &$teacherBackup = [],
3197
        &$groupBackup = []
3198
    ) {
3199
        $data = Import::csv_reader($file);
3200
3201
        $extraFieldValue = new ExtraFieldValue('career');
3202
        $extraFieldName = $this->extraFieldIdNameList['career'];
3203
3204
        $extraField = new ExtraField('career');
3205
        $extraFieldInfo = $extraField->get_handler_field_info_by_field_variable($extraFieldName);
3206
3207
        $careerDiagramExtraFieldName = $this->extraFieldIdNameList['career_diagram'];
3208
        $extraFieldDiagramInfo = $extraField->get_handler_field_info_by_field_variable(
3209
            $careerDiagramExtraFieldName
3210
        );
3211
3212
        if (empty($extraFieldInfo) || empty($extraFieldDiagramInfo)) {
3213
            return false;
3214
        }
3215
3216
        if (!empty($data)) {
3217
            $this->logger->addInfo(count($data).' records found.');
3218
            $values = [];
3219
            foreach ($data as $row) {
3220
                if (empty($row)) {
3221
                    continue;
3222
                }
3223
                foreach ($row as $key => $value) {
3224
                    $key = (string) trim($key);
3225
                    // Remove utf8 bom
3226
                    $key = preg_replace('/[\x00-\x1F\x80-\xFF]/', '', $key);
3227
                    $row[$key] = $value;
3228
                }
3229
                $values[$row['Column']][] = $row;
3230
            }
3231
3232
            $careerList = [];
3233
            $careerNameList = [];
3234
            ksort($values);
3235
            $careerChamiloIdList = [];
3236
            // 1. First create all items
3237
            foreach ($values as $column => $rowList) {
3238
                foreach ($rowList as $row) {
3239
                    $careerId = $row['CareerId'];
3240
                    $item = $extraFieldValue->get_item_id_from_field_variable_and_field_value(
3241
                        $extraFieldName,
3242
                        $careerId,
3243
                        false,
3244
                        false,
3245
                        false
3246
                    );
3247
3248
                    if (empty($item)) {
3249
                        $this->logger->addInfo("Career not found: $careerId");
3250
                        continue;
3251
                    } else {
3252
                        if (isset($item['item_id'])) {
3253
                            $careerChamiloId = $item['item_id'];
3254
                            $career = new Career();
3255
                            $career = $career->find($careerChamiloId);
3256
                            $chamiloCareerName = $career['name'];
3257
                            $careerNameList[$careerId] = $chamiloCareerName;
3258
                            $careerChamiloIdList[$careerId] = $careerChamiloId;
3259
                        } else {
3260
                            continue;
3261
                        }
3262
                    }
3263
3264
                    if (empty($chamiloCareerName)) {
3265
                        $this->logger->addInfo("Career not found: $careerId");
3266
                        continue;
3267
                    }
3268
3269
                    if (isset($careerList[$careerId])) {
3270
                        $graph = $careerList[$careerId];
3271
                    } else {
3272
                        $graph = new Graph($careerId);
3273
                        $graph->setAttribute('graphviz.graph.rankdir', 'LR');
3274
                        $careerList[$careerId] = $graph;
3275
                    }
3276
3277
                    $currentCourseId = $row['CourseId'];
3278
                    $name = $row['CourseName'];
3279
                    $notes = $row['Notes'];
3280
                    $groupValue = $row['Group'];
3281
                    $boxColumn = $row['Column'];
3282
                    $rowValue = $row['Row'];
3283
                    $color = isset($row['DefinedColor']) ? $row['DefinedColor'] : '';
3284
                    $arrow = isset($row['DrawArrowFrom']) ? $row['DrawArrowFrom'] : '';
3285
                    $subGroup = isset($row['SubGroup']) ? $row['SubGroup'] : '';
3286
                    $connections = isset($row['Connections']) ? $row['Connections'] : '';
3287
                    $linkedElement = isset($row['LinkedElement']) ? $row['LinkedElement'] : '';
3288
3289
                    if ($graph->hasVertex($currentCourseId)) {
3290
                        // Avoid double insertion
3291
                        continue;
3292
                    } else {
3293
                        $current = $graph->createVertex($currentCourseId);
3294
                        $current->setAttribute('graphviz.label', $name);
3295
                        $current->setAttribute('DefinedColor', $color);
3296
                        $current->setAttribute('Notes', $notes);
3297
                        $current->setAttribute('Row', $rowValue);
3298
                        $current->setAttribute('Group', $groupValue);
3299
                        $current->setAttribute('Column', $boxColumn);
3300
                        $current->setAttribute('DrawArrowFrom', $arrow);
3301
                        $current->setAttribute('SubGroup', $subGroup);
3302
                        $current->setAttribute('Connections', $connections);
3303
                        $current->setAttribute('LinkedElement', $linkedElement);
3304
                        $current->setAttribute('graphviz.shape', 'box');
3305
                        $current->setGroup($column);
3306
                    }
3307
                }
3308
            }
3309
3310
            // 2. Create connections
3311
            // $column start with 1 (depending in Column row)
3312
            foreach ($values as $column => $rowList) {
3313
                foreach ($rowList as $row) {
3314
                    $careerId = $row['CareerId'];
3315
                    if (isset($careerList[$careerId])) {
3316
                        $graph = $careerList[$careerId];
3317
                    } else {
3318
                        continue;
3319
                    }
3320
3321
                    $currentCourseId = $row['CourseId'];
3322
                    if ($graph->hasVertex($currentCourseId)) {
3323
                        $current = $graph->getVertex($currentCourseId);
3324
                    } else {
3325
                        continue;
3326
                    }
3327
3328
                    if (isset($row['DependedOn']) && !empty($row['DependedOn'])) {
3329
                        $parentList = explode(',', $row['DependedOn']);
3330
                        foreach ($parentList as $parentId) {
3331
                            $parentId = (int) $parentId;
3332
                            if ($graph->hasVertex($parentId)) {
3333
                                /** @var Vertex $parent */
3334
                                $parent = $graph->getVertex($parentId);
3335
                                /*$parent->setAttribute('graphviz.color', 'red');
3336
                                $parent->setAttribute('graphviz.label', $name);
3337
                                $parent->setAttribute('graphviz.shape', 'square');*/
3338
                                $parent->createEdgeTo($current);
3339
                            }
3340
                        }
3341
                    }
3342
                }
3343
            }
3344
3345
            /** @var Graph $graph */
3346
            foreach ($careerList as $id => $graph) {
3347
                if (isset($careerChamiloIdList[$id])) {
3348
                    $params = [
3349
                        'item_id' => $careerChamiloIdList[$id],
3350
                        'extra_'.$careerDiagramExtraFieldName => serialize($graph),
3351
                        'extra_'.$extraFieldName => $id,
3352
                    ];
3353
                    $extraFieldValue->saveFieldValues($params, true);
3354
                }
3355
            }
3356
        }
3357
3358
        if ($moveFile) {
3359
            $this->moveFile($file);
3360
        }
3361
    }
3362
3363
    /**
3364
     * @param string $file
3365
     * @param bool   $moveFile
3366
     * @param array  $teacherBackup
3367
     * @param array  $groupBackup
3368
     */
3369
    private function importUnsubscribeStatic(
3370
        $file,
3371
        $moveFile = false,
3372
        &$teacherBackup = [],
3373
        &$groupBackup = []
3374
    ) {
3375
        $data = Import::csv_reader($file);
3376
3377
        if (!empty($data)) {
3378
            $this->logger->addInfo(count($data)." records found.");
3379
            foreach ($data as $row) {
3380
                $chamiloUserName = $row['UserName'];
3381
                $chamiloCourseCode = $row['CourseCode'];
3382
                $chamiloSessionId = $row['SessionID'];
3383
3384
                $sessionInfo = api_get_session_info($chamiloSessionId);
3385
3386
                if (empty($sessionInfo)) {
3387
                    $this->logger->addError('Session does not exists: '.$chamiloSessionId);
3388
                    continue;
3389
                }
3390
3391
                $courseInfo = api_get_course_info($chamiloCourseCode);
3392
                if (empty($courseInfo)) {
3393
                    $this->logger->addError('Course does not exists: '.$courseInfo);
3394
                    continue;
3395
                }
3396
3397
                $userId = UserManager::get_user_id_from_username($chamiloUserName);
3398
3399
                if (empty($userId)) {
3400
                    $this->logger->addError('User does not exists: '.$chamiloUserName);
3401
                    continue;
3402
                }
3403
3404
                $sql = "SELECT * FROM ".Database::get_main_table(TABLE_MAIN_COURSE_USER)."
3405
                        WHERE
3406
                            user_id = ".$userId." AND
3407
                            c_id = '".$courseInfo['real_id']."'
3408
                        ";
3409
                $result = Database::query($sql);
3410
                $rows = Database::num_rows($result);
3411
                if ($rows > 0) {
3412
                    $userCourseData = Database::fetch_array($result, 'ASSOC');
3413
                    if (!empty($userCourseData)) {
3414
                        $teacherBackup[$userId][$courseInfo['code']] = $userCourseData;
3415
                    }
3416
                }
3417
3418
                $sql = "SELECT * FROM ".Database::get_course_table(TABLE_GROUP_USER)."
3419
                        WHERE
3420
                            user_id = ".$userId." AND
3421
                            c_id = '".$courseInfo['real_id']."'
3422
                        ";
3423
3424
                $result = Database::query($sql);
3425
                while ($groupData = Database::fetch_array($result, 'ASSOC')) {
3426
                    $groupBackup['user'][$userId][$courseInfo['code']][$groupData['group_id']] = $groupData;
3427
                }
3428
3429
                $sql = "SELECT * FROM ".Database::get_course_table(TABLE_GROUP_TUTOR)."
3430
                        WHERE
3431
                            user_id = ".$userId." AND
3432
                            c_id = '".$courseInfo['real_id']."'
3433
                        ";
3434
3435
                $result = Database::query($sql);
3436
                while ($groupData = Database::fetch_array($result, 'ASSOC')) {
3437
                    $groupBackup['tutor'][$userId][$courseInfo['code']][$groupData['group_id']] = $groupData;
3438
                }
3439
3440
                CourseManager::unsubscribe_user(
3441
                    $userId,
3442
                    $courseInfo['code'],
3443
                    $chamiloSessionId
3444
                );
3445
3446
                $this->logger->addError(
3447
                    "User '$chamiloUserName' was removed from session: #$chamiloSessionId, Course: ".$courseInfo['code']
3448
                );
3449
            }
3450
        }
3451
3452
        if ($moveFile) {
3453
            $this->moveFile($file);
3454
        }
3455
    }
3456
3457
    /**
3458
     *  Dump database tables.
3459
     */
3460
    private function dumpDatabaseTables()
3461
    {
3462
        echo 'Dumping tables'.PHP_EOL;
3463
3464
        // User
3465
        $table = Database::get_main_table(TABLE_MAIN_USER);
3466
        $tableAdmin = Database::get_main_table(TABLE_MAIN_ADMIN);
3467
        $sql = "DELETE FROM $table
3468
                WHERE user_id not in (select user_id from $tableAdmin) and status <> ".ANONYMOUS;
3469
        Database::query($sql);
3470
        echo $sql.PHP_EOL;
3471
3472
        // Truncate tables
3473
        $truncateTables = [
3474
            Database::get_main_table(TABLE_MAIN_COURSE),
3475
            Database::get_main_table(TABLE_MAIN_COURSE_USER),
3476
            Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE),
3477
            Database::get_main_table(TABLE_MAIN_CATEGORY),
3478
            Database::get_main_table(TABLE_MAIN_COURSE_MODULE),
3479
            Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER),
3480
            Database::get_main_table(TABLE_MAIN_SESSION),
3481
            Database::get_main_table(TABLE_MAIN_SESSION_CATEGORY),
3482
            Database::get_main_table(TABLE_MAIN_SESSION_COURSE),
3483
            Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER),
3484
            Database::get_main_table(TABLE_MAIN_SESSION_USER),
3485
            Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_SESSION),
3486
            Database::get_main_table(TABLE_MAIN_SESSION_FIELD_VALUES),
3487
            Database::get_main_table(TABLE_MAIN_COURSE_FIELD_VALUES),
3488
            Database::get_main_table(TABLE_MAIN_USER_FIELD_VALUES),
3489
            Database::get_main_table(TABLE_MAIN_USER_FIELD),
3490
            Database::get_main_table(TABLE_MAIN_USER_FIELD_OPTIONS),
3491
            Database::get_main_table(TABLE_MAIN_COURSE_FIELD),
3492
            Database::get_main_table(TABLE_MAIN_COURSE_FIELD_VALUES),
3493
            Database::get_main_table(TABLE_MAIN_SESSION_FIELD),
3494
            Database::get_main_table(TABLE_MAIN_SESSION_FIELD_VALUES),
3495
            Database::get_course_table(TABLE_AGENDA),
3496
            Database::get_course_table(TABLE_AGENDA_ATTACHMENT),
3497
            Database::get_course_table(TABLE_AGENDA_REPEAT),
3498
            Database::get_course_table(TABLE_AGENDA_REPEAT_NOT),
3499
            Database::get_main_table(TABLE_PERSONAL_AGENDA),
3500
            Database::get_main_table(TABLE_PERSONAL_AGENDA_REPEAT_NOT),
3501
            Database::get_main_table(TABLE_PERSONAL_AGENDA_REPEAT),
3502
            Database::get_main_table(TABLE_MAIN_CALENDAR_EVENT_VALUES),
3503
            Database::get_main_table(TABLE_STATISTIC_TRACK_E_LASTACCESS),
3504
            Database::get_main_table(TABLE_STATISTIC_TRACK_E_ACCESS),
3505
            Database::get_main_table(TABLE_STATISTIC_TRACK_E_LOGIN),
3506
            Database::get_main_table(TABLE_STATISTIC_TRACK_E_DOWNLOADS),
3507
            Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCICES),
3508
            Database::get_main_table(TABLE_STATISTIC_TRACK_E_ATTEMPT),
3509
            Database::get_main_table(TABLE_STATISTIC_TRACK_E_ATTEMPT_RECORDING),
3510
            Database::get_main_table(TABLE_STATISTIC_TRACK_E_DEFAULT),
3511
            Database::get_main_table(TABLE_STATISTIC_TRACK_E_UPLOADS),
3512
            Database::get_main_table(TABLE_STATISTIC_TRACK_E_HOTSPOT),
3513
            Database::get_main_table(TABLE_STATISTIC_TRACK_E_ITEM_PROPERTY),
3514
            Database::get_main_table(TABLE_MAIN_GRADEBOOK_CATEGORY),
3515
            Database::get_main_table(TABLE_MAIN_GRADEBOOK_EVALUATION),
3516
            Database::get_main_table(TABLE_MAIN_GRADEBOOK_LINKEVAL_LOG),
3517
            Database::get_main_table(TABLE_MAIN_GRADEBOOK_RESULT),
3518
            Database::get_main_table(TABLE_MAIN_GRADEBOOK_RESULT_LOG),
3519
            Database::get_main_table(TABLE_MAIN_GRADEBOOK_LINK),
3520
            Database::get_main_table(TABLE_MAIN_GRADEBOOK_SCORE_DISPLAY),
3521
            Database::get_main_table(TABLE_MAIN_GRADEBOOK_CERTIFICATE),
3522
            Database::get_course_table(TABLE_STUDENT_PUBLICATION),
3523
            Database::get_course_table(TABLE_QUIZ_QUESTION),
3524
            Database::get_course_table(TABLE_QUIZ_TEST),
3525
            Database::get_course_table(TABLE_QUIZ_ORDER),
3526
            Database::get_course_table(TABLE_QUIZ_ANSWER),
3527
            Database::get_course_table(TABLE_QUIZ_TEST_QUESTION),
3528
            Database::get_course_table(TABLE_QUIZ_QUESTION_OPTION),
3529
            Database::get_course_table(TABLE_QUIZ_QUESTION_CATEGORY),
3530
            Database::get_course_table(TABLE_QUIZ_QUESTION_REL_CATEGORY),
3531
            Database::get_course_table(TABLE_LP_MAIN),
3532
            Database::get_course_table(TABLE_LP_ITEM),
3533
            Database::get_course_table(TABLE_LP_VIEW),
3534
            Database::get_course_table(TABLE_LP_ITEM_VIEW),
3535
            Database::get_course_table(TABLE_DOCUMENT),
3536
            Database::get_course_table(TABLE_ITEM_PROPERTY),
3537
            Database::get_course_table(TABLE_TOOL_LIST),
3538
            Database::get_course_table(TABLE_TOOL_INTRO),
3539
            Database::get_course_table(TABLE_COURSE_SETTING),
3540
            Database::get_course_table(TABLE_SURVEY),
3541
            Database::get_course_table(TABLE_SURVEY_QUESTION),
3542
            Database::get_course_table(TABLE_SURVEY_QUESTION_OPTION),
3543
            Database::get_course_table(TABLE_SURVEY_INVITATION),
3544
            Database::get_course_table(TABLE_SURVEY_ANSWER),
3545
            Database::get_course_table(TABLE_SURVEY_QUESTION_GROUP),
3546
            Database::get_course_table(TABLE_SURVEY_REPORT),
3547
            Database::get_course_table(TABLE_GLOSSARY),
3548
            Database::get_course_table(TABLE_LINK),
3549
            Database::get_course_table(TABLE_LINK_CATEGORY),
3550
            Database::get_course_table(TABLE_GROUP),
3551
            Database::get_course_table(TABLE_GROUP_USER),
3552
            Database::get_course_table(TABLE_GROUP_TUTOR),
3553
            Database::get_course_table(TABLE_GROUP_CATEGORY),
3554
            Database::get_course_table(TABLE_DROPBOX_CATEGORY),
3555
            Database::get_course_table(TABLE_DROPBOX_FEEDBACK),
3556
            Database::get_course_table(TABLE_DROPBOX_POST),
3557
            Database::get_course_table(TABLE_DROPBOX_FILE),
3558
            Database::get_course_table(TABLE_DROPBOX_PERSON),
3559
        ];
3560
3561
        foreach ($truncateTables as $table) {
3562
            $sql = "TRUNCATE $table";
3563
            Database::query($sql);
3564
            echo $sql.PHP_EOL;
3565
        }
3566
3567
        $table = Database::get_course_table(TABLE_ITEM_PROPERTY);
3568
        $sql = "DELETE FROM $table WHERE tool = 'calendar_event'";
3569
        Database::query($sql);
3570
        echo $sql.PHP_EOL;
3571
    }
3572
3573
    /**
3574
     * If csv file ends with '"' character then a '";' is added.
3575
     *
3576
     * @param string $file
3577
     */
3578
    private function fixCSVFile($file)
3579
    {
3580
        /*$f = fopen($file, 'r+');
3581
        $cursor = -1;
3582
3583
        fseek($f, $cursor, SEEK_END);
3584
        $char = fgetc($f);
3585
        while ($char === "\n" || $char === "\r") {
3586
            fseek($f, $cursor--, SEEK_END);
3587
            $char = fgetc($f);
3588
        }
3589
3590
        if ($char === "\"") {
3591
            fseek($f, -1, SEEK_CUR);
3592
            fwrite($f, '";');
3593
        }*/
3594
    }
3595
3596
    /**
3597
     * Get custom tpl for mail welcome.
3598
     */
3599
    private function getCustomMailTemplate(): string
3600
    {
3601
        $name = 'mail/custom_calendar_welcome.tpl';
3602
        $sysTemplatePath = api_get_path(SYS_TEMPLATE_PATH);
3603
        if (is_readable($sysTemplatePath.'overrides/'.$name)) {
3604
            return 'overrides/'.$name;
3605
        }
3606
        $customThemeFolder = api_get_configuration_value('default_template');
3607
        if (is_readable($sysTemplatePath.$customThemeFolder.'/'.$name)) {
3608
            return $customThemeFolder.'/'.$name;
3609
        }
3610
        if (is_readable($sysTemplatePath.'default/'.$name)) {
3611
            return 'default/'.$name;
3612
        }
3613
        // If none has been found, it means we don't have a custom mail
3614
        // welcome message, so use the .dist version
3615
        $alternateName = 'mail/custom_calendar_welcome.dist.tpl';
3616
3617
        return 'default/'.$alternateName;
3618
    }
3619
}
3620
3621
$logger = new Logger('cron');
3622
$emails = isset($_configuration['cron_notification_mails']) ? $_configuration['cron_notification_mails'] : null;
3623
3624
$minLevel = Logger::DEBUG;
3625
3626
if (!is_array($emails)) {
3627
    $emails = [$emails];
3628
}
3629
$subject = "Cron main/cron/import_csv.php ".date('Y-m-d h:i:s');
3630
$from = api_get_setting('emailAdministrator');
3631
/*
3632
if (!empty($emails)) {
3633
    foreach ($emails as $email) {
3634
        $stream = new NativeMailerHandler($email, $subject, $from, $minLevel);
3635
        $logger->pushHandler(new BufferHandler($stream, 0, $minLevel));
3636
    }
3637
}*/
3638
3639
$stream = new StreamHandler(
3640
    api_get_path(SYS_ARCHIVE_PATH).'import_csv.log',
3641
    $minLevel
3642
);
3643
$logger->pushHandler(new BufferHandler($stream, 0, $minLevel));
3644
$logger->pushHandler(new RotatingFileHandler('import_csv', 5, $minLevel));
3645
3646
$verbose = false;
3647
if (isset($argv[1]) && $argv[1] === '--verbose') {
3648
    $verbose = true;
3649
}
3650
if ($verbose) {
3651
    $logger->pushHandler(new ErrorLogHandler());
3652
}
3653
3654
$cronImportCSVConditions = isset($_configuration['cron_import_csv_conditions']) ? $_configuration['cron_import_csv_conditions'] : null;
3655
3656
echo 'See the error log here: '.api_get_path(SYS_ARCHIVE_PATH).'import_csv.log'."\n";
3657
3658
$import = new ImportCsv($logger, $cronImportCSVConditions);
3659
3660
if (isset($_configuration['default_admin_user_id_for_cron'])) {
3661
    $import->defaultAdminId = $_configuration['default_admin_user_id_for_cron'];
3662
}
3663
// @todo in production disable the dump option
3664
$dump = false;
3665
if (isset($argv[1]) && $argv[1] === '--dump') {
3666
    $dump = true;
3667
}
3668
3669
if (isset($_configuration['import_csv_disable_dump']) &&
3670
    $_configuration['import_csv_disable_dump'] == true
3671
) {
3672
    $import->setDumpValues(false);
3673
} else {
3674
    $import->setDumpValues($dump);
3675
}
3676
3677
$import->setUpdateEmailToDummy(api_get_configuration_value('update_users_email_to_dummy_except_admins'));
3678
3679
// Do not moves the files to treated
3680
if (isset($_configuration['import_csv_test'])) {
3681
    $import->test = $_configuration['import_csv_test'];
3682
} else {
3683
    $import->test = true;
3684
}
3685
3686
$languageFilesToLoad = api_get_language_files_to_load($import->defaultLanguage);
3687
3688
foreach ($languageFilesToLoad as $languageFile) {
3689
    include $languageFile;
3690
}
3691
3692
// Set default language to be loaded
3693
$language = $import->defaultLanguage;
3694
global $language_interface;
3695
$language_interface = $language;
3696
global $language_interface_initial_value;
3697
$language_interface_initial_value = $language;
3698
3699
$timeStart = microtime(true);
3700
$import->run();
3701
$timeEnd = microtime(true);
3702
$executionTime = round(($timeEnd - $timeStart) / 60, 2);
3703
$logger->addInfo("Total execution Time $executionTime Min");
3704
3705
if (isset($_configuration['import_csv_fix_permissions']) &&
3706
    $_configuration['import_csv_fix_permissions'] == true
3707
) {
3708
    $command = "sudo find ".api_get_path(SYS_COURSE_PATH)." -type d -exec chmod 777 {} \; ";
3709
    echo "Executing: ".$command.PHP_EOL;
3710
    system($command);
3711
3712
    $command = "sudo find ".api_get_path(SYS_CODE_PATH)."upload/users  -type d -exec chmod 777 {} \;";
3713
    echo "Executing: ".$command.PHP_EOL;
3714
    system($command);
3715
}
3716