Test Setup Failed
Push — master ( 4e700f...c7183e )
by Julito
63:12
created

ImportCsv::getDumpValues()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 0
dl 0
loc 4
rs 10
c 0
b 0
f 0
1
<?php
2
/* For licensing terms, see /license.txt */
3
4
use Chamilo\CourseBundle\Entity\CCalendarEvent;
5
use Chamilo\CourseBundle\Entity\CItemProperty;
6
use Chamilo\PluginBundle\Entity\StudentFollowUp\CarePost;
7
use Fhaculty\Graph\Graph;
8
use Graphp\GraphViz\GraphViz;
9
use Monolog\Logger;
10
use Monolog\Handler\StreamHandler;
11
use Monolog\Handler\NativeMailerHandler;
12
use Monolog\Handler\RotatingFileHandler;
13
use Monolog\Handler\BufferHandler;
14
15
if (PHP_SAPI != 'cli') {
16
    die('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
29
/**
30
 * Class ImportCsv
31
 */
32
class ImportCsv
33
{
34
    private $logger;
35
    private $dumpValues;
36
    public $test;
37
    public $defaultLanguage = 'dutch';
38
    public $extraFieldIdNameList = array(
39
        'session' => 'external_session_id',
40
        'session_career' => 'external_career_id',
41
        'course' => 'external_course_id',
42
        'user' => 'external_user_id',
43
        'calendar_event' => 'external_calendar_event_id',
44
        'career' => 'external_career_id',
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
     * @var int number of years
53
     */
54
    public $expirationDateInUserCreation = 1;
55
56
    public $batchSize = 20;
57
58
    /**
59
     * When updating a user the expiration date is set to update date + this value
60
     * @var int number of years
61
     */
62
    public $expirationDateInUserUpdate = 1;
63
    public $daysCoachAccessBeforeBeginning = 14;
64
    public $daysCoachAccessAfterBeginning = 14;
65
    public $conditions;
66
    private $updateEmailToDummy;
67
68
    /**
69
     * @param Monolog\Logger $logger
70
     * @param array
71
     */
72
    public function __construct($logger, $conditions)
73
    {
74
        $this->logger = $logger;
75
        $this->conditions = $conditions;
76
        $this->updateEmailToDummy = false;
77
    }
78
79
    /**
80
     * @param bool $dump
81
     */
82
    public function setDumpValues($dump)
83
    {
84
        $this->dumpValues = $dump;
85
    }
86
87
    /**
88
     * @return boolean
89
     */
90
    public function getDumpValues()
91
    {
92
        return $this->dumpValues;
93
    }
94
95
    /**
96
     * Runs the import process
97
     */
98
    public function run()
99
    {
100
        global $_configuration;
101
102
        $value = api_get_configuration_value('import_csv_custom_url_id');
103
        if (!empty($value)) {
104
            $_configuration['access_url'] = $value;
105
        }
106
107
        $path = api_get_path(SYS_CODE_PATH).'cron/incoming/';
108
        if (!is_dir($path)) {
109
            echo "The folder! $path does not exits";
110
111
            return 0;
112
        }
113
114
        if ($this->getDumpValues()) {
115
            $this->dumpDatabaseTables();
116
        }
117
118
        echo "Reading files: ".PHP_EOL.PHP_EOL;
119
120
        $files = scandir($path);
121
        $fileToProcess = array();
122
        $fileToProcessStatic = array();
123
        $teacherBackup = array();
124
        $groupBackup = array();
125
126
        if (!empty($files)) {
127
            foreach ($files as $file) {
128
                $fileInfo = pathinfo($file);
129
                if (isset($fileInfo['extension']) && $fileInfo['extension'] === 'csv') {
130
                    // Checking teachers_yyyymmdd.csv, courses_yyyymmdd.csv, students_yyyymmdd.csv and sessions_yyyymmdd.csv
131
                    $parts = explode('_', $fileInfo['filename']);
132
                    $preMethod = ucwords($parts[1]);
133
                    $preMethod = str_replace('-static', 'Static', $preMethod);
134
                    $method = 'import'.$preMethod;
135
136
                    $isStatic = strpos($method, 'Static');
137
138
                    if ($method == 'importSessionsextidStatic') {
139
                        $method = 'importSessionsExtIdStatic';
140
                    }
141
142
                    if ($method == 'importCourseinsertStatic') {
143
                        $method = 'importSubscribeUserToCourse';
144
                    }
145
146
                    if ($method == 'importUnsubsessionsextidStatic') {
147
                        $method = 'importUnsubsessionsExtidStatic';
148
                    }
149
150
                    if ($method == 'importCareersdiagram') {
151
                        $method = 'importCareersDiagram';
152
                    }
153
154
                    if ($method == 'importSubsessionsextidStatic') {
155
                        $method = 'importSubscribeUserToCourseSessionExtStatic';
156
                    }
157
                    if (method_exists($this, $method)) {
158
                        if ((
159
                                $method == 'importSubscribeStatic' ||
160
                                $method == 'importSubscribeUserToCourse'
161
                            ) ||
162
                            empty($isStatic)
163
                        ) {
164
                            $fileToProcess[$parts[1]][] = array(
165
                                'method' => $method,
166
                                'file' => $path.$fileInfo['basename']
167
                            );
168
                        } else {
169
                            $fileToProcessStatic[$parts[1]][] = array(
170
                                'method' => $method,
171
                                'file' => $path.$fileInfo['basename']
172
                            );
173
                        }
174
                    } else {
175
                        echo "Error - This file '$file' can't be processed.".PHP_EOL;
176
                        echo "Trying to call $method".PHP_EOL;
177
178
                        echo "The file have to has this format:".PHP_EOL;
179
                        echo "prefix_students_ddmmyyyy.csv, prefix_teachers_ddmmyyyy.csv, prefix_courses_ddmmyyyy.csv, prefix_sessions_ddmmyyyy.csv ".PHP_EOL;
180
                        exit;
181
                    }
182
                }
183
            }
184
185
            if (empty($fileToProcess) && empty($fileToProcessStatic)) {
186
                echo 'Error - no files to process.';
187
188
                return 0;
189
            }
190
191
            $this->prepareImport();
192
193
            $sections = array(
194
                'students',
195
                'teachers',
196
                'courses',
197
                'sessions',
198
                'subscribe-static',
199
                'courseinsert-static',
200
                'unsubscribe-static',
201
                'care',
202
                'careers',
203
                'careersdiagram'
204
            );
205
206
            foreach ($sections as $section) {
207
                $this->logger->addInfo("-- Import $section --");
208
209
                if (isset($fileToProcess[$section]) && !empty($fileToProcess[$section])) {
210
                    $files = $fileToProcess[$section];
211
                    foreach ($files as $fileInfo) {
212
                        $method = $fileInfo['method'];
213
                        $file = $fileInfo['file'];
214
215
                        echo 'File: '.$file.PHP_EOL;
216
                        echo 'Method : '.$method.PHP_EOL;
217
                        echo PHP_EOL;
218
                        $this->logger->addInfo("Reading file: $file");
219
                        $this->logger->addInfo("Loading method $method ");
220
                        if ($method == 'importSessions') {
221
                            $this->$method(
222
                                $file,
223
                                true,
224
                                $teacherBackup,
225
                                $groupBackup
226
                            );
227
                        } else {
228
                            $this->$method($file, true);
229
                        }
230
                        $this->logger->addInfo("--Finish reading file--");
231
                    }
232
                }
233
            }
234
235
            $sections = array(
236
                'students-static',
237
                'teachers-static',
238
                'courses-static',
239
                'sessions-static',
240
                'calendar-static',
241
                'sessionsextid-static',
242
                'unsubscribe-static',
243
                'unsubsessionsextid-static',
244
                'subsessionsextid-static'
245
            );
246
247
            foreach ($sections as $section) {
248
                $this->logger->addInfo("-- Import static files $section --");
249
250
                if (isset($fileToProcessStatic[$section]) &&
251
                    !empty($fileToProcessStatic[$section])
252
                ) {
253
                    $files = $fileToProcessStatic[$section];
254
                    foreach ($files as $fileInfo) {
255
                        $method = $fileInfo['method'];
256
257
                        $file = $fileInfo['file'];
258
                        echo 'Static file: '.$file.PHP_EOL;
259
                        echo 'Method : '.$method.PHP_EOL;
260
                        echo PHP_EOL;
261
                        $this->logger->addInfo("Reading static file: $file");
262
                        $this->logger->addInfo("Loading method $method ");
263
                        $this->$method(
264
                            $file,
265
                            true,
266
                            $teacherBackup,
267
                            $groupBackup
268
                        );
269
                        $this->logger->addInfo("--Finish reading file--");
270
                    }
271
                }
272
            }
273
            $this->logger->addInfo("teacher backup");
274
            $this->logger->addInfo(print_r($teacherBackup, 1));
275
        }
276
    }
277
278
    /**
279
     * Prepares extra fields before the import
280
     */
281
    private function prepareImport()
282
    {
283
        // Create user extra field: extra_external_user_id
284
        UserManager::create_extra_field(
285
            $this->extraFieldIdNameList['user'],
286
            1,
287
            'External user id',
288
            null
289
        );
290
291
        // Create course extra field: extra_external_course_id
292
        CourseManager::create_course_extra_field(
293
            $this->extraFieldIdNameList['course'],
294
            1,
295
            'External course id',
296
            ''
297
        );
298
299
        // Create session extra field extra_external_session_id
300
        SessionManager::create_session_extra_field(
301
            $this->extraFieldIdNameList['session'],
302
            1,
303
            'External session id'
304
        );
305
306
        SessionManager::create_session_extra_field(
307
            $this->extraFieldIdNameList['session_career'],
308
            1,
309
            'Career id'
310
        );
311
312
        // Create calendar_event extra field extra_external_session_id
313
        $extraField = new ExtraField('calendar_event');
314
        $extraField->save(
315
            array(
316
                'field_type' => ExtraField::FIELD_TYPE_TEXT,
317
                'variable' => $this->extraFieldIdNameList['calendar_event'],
318
                'display_text' => 'External calendar event id',
319
            )
320
        );
321
322
        $extraField = new ExtraField('career');
323
        $extraField->save(
324
            array(
325
                'visible_to_self' => 1,
326
                'field_type' => ExtraField::FIELD_TYPE_TEXT,
327
                'variable' => $this->extraFieldIdNameList['career'],
328
                'display_text' => 'External career id',
329
            )
330
        );
331
332
        $extraField->save(
333
            array(
334
                'visible_to_self' => 1,
335
                'field_type' => ExtraField::FIELD_TYPE_TEXTAREA,
336
                'variable' => $this->extraFieldIdNameList['career_diagram'],
337
                'display_text' => 'Career diagram',
338
            )
339
        );
340
    }
341
342
    /**
343
     * @param string $file
344
     */
345
    private function moveFile($file)
346
    {
347
        $moved = str_replace('incoming', 'treated', $file);
348
349
        if ($this->test) {
350
            $result = 1;
351
        } else {
352
            $result = rename($file, $moved);
353
        }
354
355
        if ($result) {
356
            $this->logger->addInfo("Moving file to the treated folder: $file");
357
        } else {
358
            $this->logger->addError(
359
                "Error - Cant move file to the treated folder: $file"
360
            );
361
        }
362
    }
363
364
    /**
365
     * @param array $row
366
     *
367
     * @return array
368
     */
369
    private function cleanUserRow($row)
370
    {
371
        $row['lastname'] = $row['LastName'];
372
        $row['firstname'] = $row['FirstName'];
373
        $row['email'] = $row['Email'];
374
        $row['username'] = $row['UserName'];
375
        $row['password'] = $row['Password'];
376
        $row['auth_source'] = isset($row['AuthSource']) ? $row['AuthSource'] : PLATFORM_AUTH_SOURCE;
377
        $row['official_code'] = $row['OfficialCode'];
378
        $row['phone'] = isset($row['PhoneNumber']) ? $row['PhoneNumber'] : '';
379
380
        if (isset($row['StudentID'])) {
381
            $row['extra_'.$this->extraFieldIdNameList['user']] = $row['StudentID'];
382
        }
383
384
        if (isset($row['TeacherID'])) {
385
            $row['extra_'.$this->extraFieldIdNameList['user']] = $row['TeacherID'];
386
        }
387
388
        return $row;
389
    }
390
391
    /**
392
     * @param array $row
393
     *
394
     * @return array
395
     */
396
    private function cleanCourseRow($row)
397
    {
398
        $row['title'] = $row['Title'];
399
        $row['course_code'] = $row['Code'];
400
        $row['course_category'] = $row['CourseCategory'];
401
        $row['email'] = $row['Teacher'];
402
        $row['language'] = $row['Language'];
403
        $row['visibility'] = isset($row['Visibility']) ? $row['Visibility'] : COURSE_VISIBILITY_REGISTERED;
404
405
        $row['teachers'] = array();
406
        if (isset($row['Teacher']) && !empty($row['Teacher'])) {
407
            $this->logger->addInfo("Teacher list found: ".$row['Teacher']);
408
            $teachers = explode(',', $row['Teacher']);
409
            if (!empty($teachers)) {
410
                foreach ($teachers as $teacherUserName) {
411
                    $teacherUserName = trim($teacherUserName);
412
                    $userInfo = api_get_user_info_from_username($teacherUserName);
413
                    if (!empty($userInfo)) {
414
                        $this->logger->addInfo("Username found: $teacherUserName");
415
                        $row['teachers'][] = $userInfo['user_id'];
416
                    }
417
                }
418
            }
419
        }
420
421
        if (isset($row['CourseID'])) {
422
            $row['extra_'.$this->extraFieldIdNameList['course']] = $row['CourseID'];
423
        }
424
425
        return $row;
426
    }
427
428
    /**
429
     * File to import
430
     * @param string $file
431
     */
432
    private function importTeachersStatic($file)
433
    {
434
        $this->importTeachers($file, true);
435
    }
436
437
    /**
438
     * File to import
439
     * @param string $file
440
     * @param bool $moveFile
441
     */
442
    private function importTeachers($file, $moveFile = true)
443
    {
444
        $this->fixCSVFile($file);
0 ignored issues
show
Unused Code introduced by
The call to the method ImportCsv::fixCSVFile() seems un-needed as the method has no side-effects.

PHP Analyzer performs a side-effects analysis of your code. A side-effect is basically anything that might be visible after the scope of the method is left.

Let’s take a look at an example:

class User
{
    private $email;

    public function getEmail()
    {
        return $this->email;
    }

    public function setEmail($email)
    {
        $this->email = $email;
    }
}

If we look at the getEmail() method, we can see that it has no side-effect. Whether you call this method or not, no future calls to other methods are affected by this. As such code as the following is useless:

$user = new User();
$user->getEmail(); // This line could safely be removed as it has no effect.

On the hand, if we look at the setEmail(), this method _has_ side-effects. In the following case, we could not remove the method call:

$user = new User();
$user->setEmail('email@domain'); // This line has a side-effect (it changes an
                                 // instance variable).
Loading history...
445
        $data = Import::csvToArray($file);
0 ignored issues
show
Deprecated Code introduced by
The method Import::csvToArray() has been deprecated with message: use cvs_reader instead

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
446
447
        /* Unique identifier: official-code username.
448
        Email address and password should never get updated. *ok
449
        The only fields that I can think of that should update if the data changes in the csv file are FirstName and LastName. *ok
450
        A slight edit of these fields should be taken into account. ???
451
        Adding teachers is no problem, but deleting them shouldn’t be automated, but we should get a log of “to delete teachers”.
452
        We’ll handle that manually if applicable.
453
        No delete!
454
        */
455
        $language = $this->defaultLanguage;
456
457
        if (!empty($data)) {
458
            $this->logger->addInfo(count($data)." records found.");
459
            $expirationDateOnCreation = api_get_utc_datetime(strtotime("+".intval($this->expirationDateInUserCreation)."years"));
460
            $expirationDateOnUpdate = api_get_utc_datetime(strtotime("+".intval($this->expirationDateInUserUpdate)."years"));
461
462
            $batchSize = $this->batchSize;
463
            $em = Database::getManager();
464
            $counter = 1;
465
            foreach ($data as $row) {
466
                $row = $this->cleanUserRow($row);
467
468
                $user_id = UserManager::get_user_id_from_original_id(
469
                    $row['extra_'.$this->extraFieldIdNameList['user']],
470
                    $this->extraFieldIdNameList['user']
471
                );
472
                $userInfo = array();
473
                $userInfoByOfficialCode = null;
474
475 View Code Duplication
                if (!empty($user_id)) {
476
                    $userInfo = api_get_user_info($user_id);
477
                    $userInfoByOfficialCode = api_get_user_info_from_official_code($row['official_code']);
478
                }
479
480
                if (empty($userInfo) && empty($userInfoByOfficialCode)) {
481
                    // Create user
482
                    $userId = UserManager::create_user(
483
                        $row['firstname'],
484
                        $row['lastname'],
485
                        COURSEMANAGER,
486
                        $row['email'],
487
                        $row['username'],
488
                        $row['password'],
489
                        $row['official_code'],
490
                        $language, //$row['language'],
491
                        $row['phone'],
492
                        null, //$row['picture'], //picture
493
                        $row['auth_source'], // ?
494
                        $expirationDateOnCreation, //'0000-00-00 00:00:00', //$row['expiration_date'], //$expiration_date = '0000-00-00 00:00:00',
0 ignored issues
show
Bug introduced by
It seems like $expirationDateOnCreation defined by api_get_utc_datetime(str...erCreation) . 'years')) on line 459 can also be of type object<DateTime>; however, UserManager::create_user() does only seem to accept string|null, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
495
                        1, //active
496
                        0,
497
                        null, // extra
498
                        null, //$encrypt_method = '',
499
                        false //$send_mail = false
500
                    );
501
502 View Code Duplication
                    if ($userId) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $userId of type false|integer is loosely compared to true; this is ambiguous if the integer can be zero. You might want to explicitly use !== null instead.

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

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

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

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
503
                        foreach ($row as $key => $value) {
504
                            if (substr($key, 0, 6) == 'extra_') {
505
                                //an extra field
506
                                UserManager::update_extra_field_value(
507
                                    $userId,
508
                                    substr($key, 6),
509
                                    $value
510
                                );
511
                            }
512
                        }
513
                        $this->logger->addInfo("Teachers - User created: ".$row['username']);
514
                    } else {
515
                        $this->logger->addError("Teachers - User NOT created: ".$row['username']." ".$row['firstname']." ".$row['lastname']);
516
                        $this->logger->addError(strip_tags(Display::getFlashToString()));
0 ignored issues
show
Deprecated Code introduced by
The method Display::getFlashToString() has been deprecated.

This method has been deprecated.

Loading history...
517
                        Display::cleanFlashMessages();
0 ignored issues
show
Deprecated Code introduced by
The method Display::cleanFlashMessages() has been deprecated.

This method has been deprecated.

Loading history...
518
                    }
519
                } else {
520
                    if (empty($userInfo)) {
521
                        $this->logger->addError("Teachers - Can't update user :".$row['username']);
522
                        continue;
523
                    }
524
525
                    // Update user
526
                    $result = UserManager::update_user(
527
                        $userInfo['user_id'],
528
                        $row['firstname'], // <<-- changed
529
                        $row['lastname'], // <<-- changed
530
                        $userInfo['username'],
531
                        null, //$password = null,
532
                        $row['auth_source'],
533
                        $userInfo['email'],
534
                        COURSEMANAGER,
535
                        $userInfo['official_code'],
536
                        $userInfo['phone'],
537
                        $userInfo['picture_uri'],
538
                        $expirationDateOnUpdate,
539
                        $userInfo['active'],
540
                        null, //$creator_id = null,
541
                        0, //$hr_dept_id = 0,
542
                        null, // $extra = null,
543
                        null, //$language = 'english',
544
                        null, //$encrypt_method = '',
545
                        false, //$send_email = false,
546
                        0 //$reset_password = 0
547
                    );
548
549
                    if ($result) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $result of type false|integer is loosely compared to true; this is ambiguous if the integer can be zero. You might want to explicitly use !== null instead.

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

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

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

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
550 View Code Duplication
                        foreach ($row as $key => $value) {
551
                            if (substr($key, 0, 6) == 'extra_') {
552
                                //an extra field
553
                                UserManager::update_extra_field_value(
554
                                    $userInfo['user_id'],
555
                                    substr($key, 6),
556
                                    $value
557
                                );
558
                            }
559
                        }
560
                        $this->logger->addInfo("Teachers - User updated: ".$row['username']);
561
                    } else {
562
                        $this->logger->addError("Teachers - User not updated: ".$row['username']);
563
                    }
564
                }
565
566
                if (($counter % $batchSize) === 0) {
567
                    $em->flush();
568
                    $em->clear(); // Detaches all objects from Doctrine!
569
                }
570
                $counter++;
571
            }
572
573
            $em->clear(); // Detaches all objects from Doctrine!
574
        }
575
576
        if ($moveFile) {
577
            $this->moveFile($file);
578
        }
579
580
        $this->updateUsersEmails();
581
    }
582
583
    /**
584
     * @param string $file
585
     */
586
    private function importStudentsStatic($file)
587
    {
588
        $this->importStudents($file, true);
589
    }
590
591
    /**
592
     * @param string $file
593
     * @param bool $moveFile
594
     */
595
    private function importStudents($file, $moveFile = true)
596
    {
597
        $this->fixCSVFile($file);
0 ignored issues
show
Unused Code introduced by
The call to the method ImportCsv::fixCSVFile() seems un-needed as the method has no side-effects.

PHP Analyzer performs a side-effects analysis of your code. A side-effect is basically anything that might be visible after the scope of the method is left.

Let’s take a look at an example:

class User
{
    private $email;

    public function getEmail()
    {
        return $this->email;
    }

    public function setEmail($email)
    {
        $this->email = $email;
    }
}

If we look at the getEmail() method, we can see that it has no side-effect. Whether you call this method or not, no future calls to other methods are affected by this. As such code as the following is useless:

$user = new User();
$user->getEmail(); // This line could safely be removed as it has no effect.

On the hand, if we look at the setEmail(), this method _has_ side-effects. In the following case, we could not remove the method call:

$user = new User();
$user->setEmail('email@domain'); // This line has a side-effect (it changes an
                                 // instance variable).
Loading history...
598
        $data = Import::csvToArray($file);
0 ignored issues
show
Deprecated Code introduced by
The method Import::csvToArray() has been deprecated with message: use cvs_reader instead

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
599
600
        /*
601
         * Another users import.
602
        Unique identifier: official code and username . ok
603
        Password should never get updated. ok
604
        If an update should need to occur (because it changed in the .csv),
605
        we’ll want that logged. We will handle this manually in that case.
606
        All other fields should be updateable, though passwords should of course not get updated. ok
607
        If a user gets deleted (not there anymore),
608
        He should be set inactive one year after the current date.
609
        So I presume you’ll just update the expiration date.
610
        We want to grant access to courses up to a year after deletion.
611
         */
612
        $timeStart = microtime(true);
613
614
        $batchSize = $this->batchSize;
615
        $em = Database::getManager();
616
617
        if (!empty($data)) {
618
            $language = $this->defaultLanguage;
619
            $this->logger->addInfo(count($data)." records found.");
620
621
            $expirationDateOnCreate = api_get_utc_datetime(strtotime("+".intval($this->expirationDateInUserCreation)."years"));
622
            $expirationDateOnUpdate = api_get_utc_datetime(strtotime("+".intval($this->expirationDateInUserUpdate)."years"));
623
624
            $counter = 1;
625
            $secondsInYear = 365 * 24 * 60 * 60;
626
627
            foreach ($data as $row) {
628
                $row = $this->cleanUserRow($row);
629
                $user_id = UserManager::get_user_id_from_original_id(
630
                    $row['extra_'.$this->extraFieldIdNameList['user']],
631
                    $this->extraFieldIdNameList['user']
632
                );
633
634
                $userInfo = array();
635
                $userInfoByOfficialCode = null;
636 View Code Duplication
                if (!empty($user_id)) {
637
                    $userInfo = api_get_user_info($user_id, false, true);
638
                    $userInfoByOfficialCode = api_get_user_info_from_official_code($row['official_code']);
639
                }
640
641
                if (empty($userInfo) && empty($userInfoByOfficialCode)) {
642
                    // Create user
643
                    $result = UserManager::create_user(
644
                        $row['firstname'],
645
                        $row['lastname'],
646
                        STUDENT,
647
                        $row['email'],
648
                        $row['username'],
649
                        $row['password'],
650
                        $row['official_code'],
651
                        $language, //$row['language'],
652
                        $row['phone'],
653
                        null, //$row['picture'], //picture
654
                        $row['auth_source'], // ?
655
                        $expirationDateOnCreate, //'0000-00-00 00:00:00', //$row['expiration_date'], //$expiration_date = '0000-00-00 00:00:00',
0 ignored issues
show
Bug introduced by
It seems like $expirationDateOnCreate defined by api_get_utc_datetime(str...erCreation) . 'years')) on line 621 can also be of type object<DateTime>; however, UserManager::create_user() does only seem to accept string|null, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
656
                        1, //active
657
                        0,
658
                        null, // extra
659
                        null, //$encrypt_method = '',
660
                        false //$send_mail = false
661
                    );
662
663 View Code Duplication
                    if ($result) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $result of type false|integer is loosely compared to true; this is ambiguous if the integer can be zero. You might want to explicitly use !== null instead.

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

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

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

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
664
                        foreach ($row as $key => $value) {
665
                            if (substr($key, 0, 6) === 'extra_') {
666
                                //an extra field
667
                                UserManager::update_extra_field_value(
668
                                    $result,
669
                                    substr($key, 6),
670
                                    $value
671
                                );
672
                            }
673
                        }
674
                        $this->logger->addInfo("Students - User created: ".$row['username']);
675
                    } else {
676
                        $this->logger->addError("Students - User NOT created: ".$row['username']." ".$row['firstname']." ".$row['lastname']);
677
                        $this->logger->addError(strip_tags(Display::getFlashToString()));
0 ignored issues
show
Deprecated Code introduced by
The method Display::getFlashToString() has been deprecated.

This method has been deprecated.

Loading history...
678
                        Display::cleanFlashMessages();
0 ignored issues
show
Deprecated Code introduced by
The method Display::cleanFlashMessages() has been deprecated.

This method has been deprecated.

Loading history...
679
                    }
680
                } else {
681
                    if (empty($userInfo)) {
682
                        $this->logger->addError("Students - Can't update user :".$row['username']);
683
                        continue;
684
                    }
685
686
                    if (isset($row['action']) && $row['action'] === 'delete') {
687
                        // Inactive one year later
688
                        $userInfo['expiration_date'] = api_get_utc_datetime(api_strtotime(time() + $secondsInYear));
689
                    }
690
691
                    $password = $row['password']; // change password
692
                    $email = $row['email']; // change email
693
                    $resetPassword = 2; // allow password change
694
695
                    // Conditions that disables the update of password and email:
696
                    if (isset($this->conditions['importStudents'])) {
697
                        if (isset($this->conditions['importStudents']['update']) &&
698
                            isset($this->conditions['importStudents']['update']['avoid'])
699
                        ) {
700
                            // Blocking email update -
701
                            // 1. Condition
702
                            $avoidUsersWithEmail = $this->conditions['importStudents']['update']['avoid']['email'];
703
                            if ($userInfo['email'] != $row['email'] && in_array($row['email'], $avoidUsersWithEmail)) {
704
                                $this->logger->addInfo("Students - User email is not updated : ".$row['username']." because the avoid conditions (email).");
705
                                // Do not change email keep the old email.
706
                                $email = $userInfo['email'];
707
                            }
708
709
                            // 2. Condition
710 View Code Duplication
                            if (!in_array($userInfo['email'], $avoidUsersWithEmail) && !in_array($row['email'], $avoidUsersWithEmail)) {
711
                                $email = $userInfo['email'];
712
                            }
713
714
                            // 3. Condition
715 View Code Duplication
                            if (in_array($userInfo['email'], $avoidUsersWithEmail) && !in_array($row['email'], $avoidUsersWithEmail)) {
716
                                $email = $row['email'];
717
                            }
718
719
                            // Blocking password update
720
                            //$avoidUsersWithPassword = $this->conditions['importStudents']['update']['avoid']['password'];
721
722
                            /*if (isset($row['password'])) {
723
                                $user = api_get_user_entity($userInfo['id']);
724
                                $encoded = UserManager::encryptPassword(
725
                                    $row['password'],
726
                                    $user
727
                                );
728
729
                                if ($userInfo['password'] != $encoded &&
730
                                    in_array($row['password'], $avoidUsersWithPassword)
731
                                ) {
732
                                    $this->logger->addInfo(
733
                                        "Students - User password is not updated: ".$row['username']." because the avoid conditions (password)."
734
                                    );
735
                                    $password = null;
736
                                    $resetPassword = 0; // disallow password change
737
                                }
738
                            }*/
739
                        }
740
                    }
741
742
                    // Always disallow password change during update
743
                    $password = null;
744
                    $resetPassword = 0; // disallow password change
745
746
                    // Update user
747
                    $result = UserManager::update_user(
748
                        $userInfo['user_id'],
749
                        $row['firstname'], // <<-- changed
750
                        $row['lastname'], // <<-- changed
751
                        $row['username'], // <<-- changed
752
                        $password, //$password = null,
753
                        $row['auth_source'],
754
                        $email,
755
                        STUDENT,
756
                        $userInfo['official_code'],
757
                        $userInfo['phone'],
758
                        $userInfo['picture_uri'],
759
                        $expirationDateOnUpdate,
760
                        $userInfo['active'],
761
                        null, //$creator_id = null,
762
                        0, //$hr_dept_id = 0,
763
                        null, // $extra = null,
764
                        null, //$language = 'english',
765
                        null, //$encrypt_method = '',
766
                        false, //$send_email = false,
767
                        $resetPassword //$reset_password = 0
768
                    );
769
770
                    if ($result) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $result of type false|integer is loosely compared to true; this is ambiguous if the integer can be zero. You might want to explicitly use !== null instead.

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

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

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

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
771
                        if ($row['username'] != $userInfo['username']) {
772
                            $this->logger->addInfo("Students - Username was changes from '".$userInfo['username']."' to '".$row['username']."' ");
773
                        }
774 View Code Duplication
                        foreach ($row as $key => $value) {
775
                            if (substr($key, 0, 6) === 'extra_') {
776
                                //an extra field
777
                                UserManager::update_extra_field_value(
778
                                    $userInfo['user_id'],
779
                                    substr($key, 6),
780
                                    $value
781
                                );
782
                            }
783
                        }
784
785
                        $this->logger->addInfo("Students - User updated: ".$row['username']);
786
                    } else {
787
                        $this->logger->addError("Students - User NOT updated: ".$row['username']." ".$row['firstname']." ".$row['lastname']);
788
                    }
789
                }
790
791
                if (($counter % $batchSize) === 0) {
792
                    $em->flush();
793
                    $em->clear(); // Detaches all objects from Doctrine!
794
                    $this->logger->addInfo("Detaches all objects");
795
                }
796
                $counter++;
797
            }
798
            $em->clear(); // Detaches all objects from Doctrine!
799
        }
800
801
        $timeEnd = microtime(true);
802
        $executionTime = round(($timeEnd - $timeStart) / 60, 2);
803
        $this->logger->addInfo("Execution Time for process students: $executionTime Min");
804
805
        if ($moveFile) {
806
            $this->moveFile($file);
807
        }
808
809
        $this->updateUsersEmails();
810
    }
811
812
    /**
813
     * @param string $file
814
     */
815
    private function importCoursesStatic($file, $moveFile, &$teacherBackup = array(), &$groupBackup = array())
816
    {
817
        $this->importCourses($file, true, $teacherBackup, $groupBackup);
818
    }
819
820
    /**
821
     * @param string $file
822
     * @param bool $moveFile
823
     *
824
     * @return int
825
     */
826
    private function importCalendarStatic($file, $moveFile = true)
827
    {
828
        $this->fixCSVFile($file);
0 ignored issues
show
Unused Code introduced by
The call to the method ImportCsv::fixCSVFile() seems un-needed as the method has no side-effects.

PHP Analyzer performs a side-effects analysis of your code. A side-effect is basically anything that might be visible after the scope of the method is left.

Let’s take a look at an example:

class User
{
    private $email;

    public function getEmail()
    {
        return $this->email;
    }

    public function setEmail($email)
    {
        $this->email = $email;
    }
}

If we look at the getEmail() method, we can see that it has no side-effect. Whether you call this method or not, no future calls to other methods are affected by this. As such code as the following is useless:

$user = new User();
$user->getEmail(); // This line could safely be removed as it has no effect.

On the hand, if we look at the setEmail(), this method _has_ side-effects. In the following case, we could not remove the method call:

$user = new User();
$user->setEmail('email@domain'); // This line has a side-effect (it changes an
                                 // instance variable).
Loading history...
829
830
        $this->updateUsersEmails();
831
        $data = Import::csvToArray($file);
0 ignored issues
show
Deprecated Code introduced by
The method Import::csvToArray() has been deprecated with message: use cvs_reader instead

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
832
833
        if (!empty($data)) {
834
            $this->logger->addInfo(count($data)." records found.");
835
            $eventsToCreate = array();
836
            $errorFound = false;
837
838
            foreach ($data as $row) {
839
                $sessionId = null;
840
                $externalSessionId = null;
841
                if (isset($row['external_sessionID'])) {
842
                    $externalSessionId = $row['external_sessionID'];
843
                    $sessionId = SessionManager::getSessionIdFromOriginalId(
844
                        $externalSessionId,
845
                        $this->extraFieldIdNameList['session']
846
                    );
847
                }
848
849
                $courseCode = null;
850
                if (isset($row['coursecode'])) {
851
                    $courseCode = $row['coursecode'];
852
                }
853
                $courseInfo = api_get_course_info($courseCode);
854
855
                if (empty($courseInfo)) {
856
                    $this->logger->addInfo("Course '$courseCode' does not exists");
857
                }
858
859
                if (empty($sessionId)) {
860
                    $this->logger->addInfo("external_sessionID: ".$externalSessionId." does not exists.");
861
                }
862
                $teacherId = null;
863
864
                if (!empty($sessionId) && !empty($courseInfo)) {
865
                    $courseIncluded = SessionManager::relation_session_course_exist(
866
                        $sessionId,
867
                        $courseInfo['real_id']
868
                    );
869
870
                    if ($courseIncluded == false) {
871
                        $this->logger->addInfo(
872
                            "Course '$courseCode' is not included in session: $sessionId"
873
                        );
874
                        $errorFound = true;
875 View Code Duplication
                    } else {
876
                        $teachers = CourseManager::get_coach_list_from_course_code(
877
                            $courseInfo['code'],
878
                            $sessionId
879
                        );
880
881
                        // Getting first teacher.
882
                        if (!empty($teachers)) {
883
                            $teacher = current($teachers);
884
                            $teacherId = $teacher['user_id'];
885
                        } else {
886
                            $sessionInfo = api_get_session_info($sessionId);
887
                            $teacherId = $sessionInfo['id_coach'];
888
                        }
889
                    }
890
                } else {
891
                    $errorFound = true;
892
                }
893
894
                if (empty($teacherId)) {
895
                    $errorFound = true;
896
                    $this->logger->addInfo(
897
                        "No teacher found in course code : '$courseCode' and session: '$sessionId'"
898
                    );
899
                }
900
901
                $date = $row['date'];
902
                $startTime = $row['time_start'];
903
                $endTime = $row['time_end'];
904
                $title = $row['title'];
905
                $comment = $row['comment'];
906
                $color = isset($row['color']) ? $row['color'] : '';
907
908
                $startDateYear = substr($date, 0, 4);
909
                $startDateMonth = substr($date, 4, 2);
910
                $startDateDay = substr($date, 6, 8);
911
912
                $startDate = $startDateYear.'-'.$startDateMonth.'-'.$startDateDay.' '.$startTime.":00";
913
                $endDate = $startDateYear.'-'.$startDateMonth.'-'.$startDateDay.' '.$endTime.":00";
914
915
                if (!api_is_valid_date($startDate) || !api_is_valid_date($endDate)) {
916
                    $this->logger->addInfo(
917
                        "Verify your dates:  '$startDate' : '$endDate' "
918
                    );
919
                    $errorFound = true;
920
                }
921
922
                if ($errorFound == false) {
923
                    $eventsToCreate[] = array(
924
                        'start' => $startDate,
925
                        'end' => $endDate,
926
                        'title' => $title,
927
                        'sender_id' => $teacherId,
928
                        'course_id' => $courseInfo['real_id'],
929
                        'session_id' => $sessionId,
930
                        'comment' => $comment,
931
                        'color' => $color,
932
                        $this->extraFieldIdNameList['calendar_event'] => $row['external_calendar_itemID'],
933
                    );
934
                }
935
                $errorFound = false;
936
            }
937
938
            if (empty($eventsToCreate)) {
939
                $this->logger->addInfo(
940
                    "No events to add"
941
                );
942
943
                return 0;
944
            }
945
946
            $extraFieldValue = new ExtraFieldValue('calendar_event');
947
            $extraFieldName = $this->extraFieldIdNameList['calendar_event'];
948
            $externalEventId = null;
949
950
            $extraField = new ExtraField('calendar_event');
951
            $extraFieldInfo = $extraField->get_handler_field_info_by_field_variable(
952
                $extraFieldName
953
            );
954
955
            if (empty($extraFieldInfo)) {
956
                $this->logger->addInfo(
957
                    "No calendar event extra field created: $extraFieldName"
958
                );
959
960
                return 0;
961
            }
962
963
            $this->logger->addInfo('Ready to insert # '.count($eventsToCreate).' events');
964
            $batchSize = $this->batchSize;
965
            $counter = 1;
966
            $em = Database::getManager();
967
            $eventStartDateList = [];
968
            $eventEndDateList = [];
969
            $report = [
970
                'mail_sent' => 0,
971
                'mail_not_sent_announcement_exists' => 0,
972
                'mail_not_sent_because_date' => 0
973
            ];
974
975
            $eventsToCreateFinal = [];
976
            foreach ($eventsToCreate as $event) {
977
                $update = false;
978
                $item = null;
979
                if (!isset($event[$extraFieldName])) {
980
                    $this->logger->addInfo(
981
                        "No external_calendar_itemID found. Skipping ..."
982
                    );
983
                    continue;
984
                } else {
985
                    $externalEventId = $event[$extraFieldName];
986
                    if (empty($externalEventId)) {
987
                        $this->logger->addInfo(
988
                            "external_calendar_itemID was set but empty. Skipping ..."
989
                        );
990
                        continue;
991
                    }
992
993
                    $item = $extraFieldValue->get_item_id_from_field_variable_and_field_value(
994
                        $extraFieldName,
995
                        $externalEventId,
996
                        false,
997
                        false,
998
                        false
999
                    );
1000
1001
                    if (!empty($item)) {
1002
                        $update = true;
1003
                    }
1004
                }
1005
1006
                $courseInfo = api_get_course_info_by_id($event['course_id']);
1007
                $event['course_info'] = $courseInfo;
1008
                $event['update'] = $update;
1009
                $event['item'] = $item;
1010
1011
                $calendarEvent = null;
1012
                /* Check if event changed of course code */
1013
                if (!empty($item) && isset($item['item_id']) && !empty($item['item_id'])) {
1014
                    /** @var CCalendarEvent $calendarEvent */
1015
                    $calendarEvent = $em->getRepository('ChamiloCourseBundle:CCalendarEvent')->find($item['item_id']);
1016
                }
1017
1018
                if ($calendarEvent) {
1019
                    $this->logger->addInfo('Calendar event found '.$item['item_id']);
1020
                    if ($calendarEvent->getCId() != $courseInfo['real_id']) {
1021
                        $this->logger->addInfo('Move from course #'.$calendarEvent->getCId().' to #'.$courseInfo['real_id']);
1022
                        // Seems that the course id changed in the csv
1023
                        $calendarEvent->setCId($courseInfo['real_id']);
1024
                        $em->persist($calendarEvent);
1025
                        $em->flush();
1026
1027
                        $criteria = [
1028
                            'tool' => 'calendar_event',
1029
                            'ref' => $item['item_id']
1030
                        ];
1031
                        /** @var CItemProperty $itemProperty */
1032
                        $itemProperty = $em->getRepository('ChamiloCourseBundle:CItemProperty')->findOneBy($criteria);
1033
                        $courseEntity = $em->getRepository('ChamiloCoreBundle:Course')->find($courseInfo['real_id']);
1034
                        if ($itemProperty && $courseEntity) {
1035
                            $itemProperty->setCourse($courseEntity);
1036
                            $em->persist($itemProperty);
1037
                            $em->flush();
1038
                        }
1039
                    }
1040
                } else {
1041
                    $this->logger->addInfo('Calendar event not found '.$item['item_id']);
1042
                }
1043
1044
                $event['external_event_id'] = $externalEventId;
1045
                if (isset($eventStartDateList[$courseInfo['real_id']]) &&
1046
                    isset($eventStartDateList[$courseInfo['real_id']][$event['session_id']])
1047
                ) {
1048
                    $currentItemDate = api_strtotime($event['start']);
1049
                    $firstDate = $eventStartDateList[$courseInfo['real_id']][$event['session_id']];
1050 View Code Duplication
                    if ($currentItemDate < api_strtotime($firstDate)) {
1051
                        $eventStartDateList[$courseInfo['real_id']][$event['session_id']] = $event['start'];
1052
                        $eventEndDateList[$courseInfo['real_id']][$event['session_id']] = $event['end'];
1053
                    }
1054 View Code Duplication
                } else {
1055
                    // First time
1056
                    $eventStartDateList[$courseInfo['real_id']][$event['session_id']] = $event['start'];
1057
                    $eventEndDateList[$courseInfo['real_id']][$event['session_id']] = $event['end'];
1058
                }
1059
                $eventsToCreateFinal[] = $event;
1060
            }
1061
1062
            $eventAlreadySent = [];
1063
            foreach ($eventsToCreateFinal as $event) {
1064
                $courseInfo = $event['course_info'];
1065
                $item = $event['item'];
1066
                $update = $event['update'];
1067
                $externalEventId = $event['external_event_id'];
1068
                $info = 'Course: '.$courseInfo['real_id'].' ('.$courseInfo['code'].') - Session: '.$event['session_id'];
1069
1070
                $agenda = new Agenda(
1071
                    'course',
1072
                    $event['sender_id'],
1073
                    $courseInfo['real_id'],
1074
                    $event['session_id']
1075
                );
1076
                $agenda->set_course($courseInfo);
1077
                $agenda->setSessionId($event['session_id']);
1078
                $agenda->setSenderId($event['sender_id']);
1079
                $agenda->setIsAllowedToEdit(true);
1080
                $eventComment = $event['comment'];
1081
                $color = $event['color'];
1082
1083
                // To use the event comment you need
1084
                // ALTER TABLE c_calendar_event ADD COLUMN comment TEXT;
1085
                // add in configuration.php allow_agenda_event_comment = true
1086
                if (empty($courseInfo)) {
1087
                    $this->logger->addInfo(
1088
                        "No course found for event #$externalEventId Course #".$event['course_id']." Skipping ..."
1089
                    );
1090
                    continue;
1091
                }
1092
1093
                if (empty($event['sender_id'])) {
1094
                    $this->logger->addInfo(
1095
                        "No sender found for event #$externalEventId Send #".$event['sender_id']." Skipping ..."
1096
                    );
1097
                    continue;
1098
                }
1099
1100
                // Taking first element of course-session event
1101
                $alreadyAdded = false;
1102
                $firstDate = $eventStartDateList[$courseInfo['real_id']][$event['session_id']];
1103
                $firstEndDate = $eventEndDateList[$courseInfo['real_id']][$event['session_id']];
1104
1105
                if (isset($eventAlreadySent[$courseInfo['real_id']]) &&
1106
                    isset($eventAlreadySent[$courseInfo['real_id']][$event['session_id']])
1107
                ) {
1108
                    $alreadyAdded = true;
1109
                } else {
1110
                    $eventAlreadySent[$courseInfo['real_id']][$event['session_id']] = true;
1111
                }
1112
1113
                // Working days (Mon-Fri)see BT#12156#note-16
1114
                $days = 5;
1115
                $startDatePlusDays = api_strtotime("$days weekdays");
1116
1117
                $this->logger->addInfo(
1118
                    "startDatePlusDays: ".api_get_utc_datetime($startDatePlusDays).' - First date: '.$firstDate
1119
                );
1120
1121
                // Send
1122
                if ($startDatePlusDays > api_strtotime($firstDate)) {
1123
                    $sendMail = true;
1124
                } else {
1125
                    $sendMail = false;
1126
                }
1127
1128
                // Send announcement to users
1129
                if ($sendMail && $alreadyAdded == false) {
1130
                    $start = $firstDate;
1131
                    $end = $firstEndDate;
1132
1133
                    if (!empty($end) &&
1134
                        api_format_date($start, DATE_FORMAT_LONG) == api_format_date($end, DATE_FORMAT_LONG)
1135
                    ) {
1136
                        $date = api_format_date($start, DATE_FORMAT_LONG).' ('.
1137
                            api_format_date($start, TIME_NO_SEC_FORMAT).' '.
1138
                            api_format_date($end, TIME_NO_SEC_FORMAT).')';
1139
                    } else {
1140
                        $date = api_format_date($start, DATE_TIME_FORMAT_LONG_24H).' - '.
1141
                                api_format_date($end, DATE_TIME_FORMAT_LONG_24H);
1142
                    }
1143
1144
                    $sessionName = '';
1145
                    if (!empty($event['session_id'])) {
1146
                        $sessionName = ' ('.api_get_session_name($event['session_id']).')';
1147
                    }
1148
1149
                    $courseTitle = $courseInfo['title'].$sessionName;
1150
1151
                    $emailBody = get_lang('Dear').' ((user_firstname)) <br />'.
1152
                        sprintf(
1153
                        get_lang('YouHaveBeenSubscribedToCourseXTheStartDateXAndCommentX'),
1154
                        $courseTitle,
1155
                        $date,
1156
                        $event['comment']
1157
                    );
1158
1159
                    $subject = sprintf(
1160
                        get_lang('AgendaAvailableInCourseX'),
1161
                        $courseInfo['title']
1162
                    );
1163
1164
                    $coaches = SessionManager::getCoachesByCourseSession(
1165
                        $courseInfo['real_id'],
1166
                        $event['session_id']
1167
                    );
1168
1169
                    // Search if an announcement exists:
1170
                    $announcementsWithTitleList = AnnouncementManager::getAnnouncementsByTitle(
1171
                        $subject,
1172
                        $courseInfo['real_id'],
1173
                        $event['session_id'],
1174
                        1
1175
                    );
1176
1177
                    if (count($announcementsWithTitleList) === 0) {
1178
                        $this->logger->addInfo(
1179
                            "Mail to be sent because start date: ".$event['start']." and no announcement found."
1180
                        );
1181
                        $announcementId = AnnouncementManager::add_announcement(
1182
                            $courseInfo,
1183
                            $event['session_id'],
1184
                            $subject,
1185
                            $emailBody,
1186
                            [
1187
                                'everyone',
1188
                                'users' => $coaches
1189
                            ],
1190
                            [],
1191
                            null,
1192
                            null,
1193
                            false,
1194
                            $this->defaultAdminId
1195
                        );
1196
1197
                        if ($announcementId) {
1198
                            $this->logger->addInfo(
1199
                                "Announcement added: ".(int) ($announcementId)." in $info"
1200
                            );
1201
                            $this->logger->addInfo(
1202
                                "<<--SENDING MAIL-->>"
1203
                            );
1204
1205
                            $report['mail_sent']++;
1206
                            AnnouncementManager::sendEmail(
1207
                                $courseInfo,
1208
                                $event['session_id'],
1209
                                $announcementId,
1210
                                false
1211
                            );
1212
                        }
1213
                    } else {
1214
                        $report['mail_not_sent_announcement_exists']++;
1215
                        $this->logger->addInfo(
1216
                            "Mail NOT sent. An announcement seems to be already saved in '$info'"
1217
                        );
1218
                    }
1219
                } else {
1220
                    if ($sendMail == false) {
1221
                        $report['mail_not_sent_because_date']++;
1222
                    }
1223
                }
1224
                $content = '';
1225
                if ($update && isset($item['item_id'])) {
1226
                    //the event already exists, just update
1227
                    $eventResult = $agenda->editEvent(
1228
                        $item['item_id'],
1229
                        $event['start'],
1230
                        $event['end'],
1231
                        false,
1232
                        $event['title'],
1233
                        $content,
1234
                        array('everyone'), // $usersToSend
1235
                        array(), //$attachmentArray = array(),
1236
                        [], //$attachmentCommentList
1237
                        $eventComment,
1238
                        $color,
1239
                        false,
1240
                        false,
1241
                        $this->defaultAdminId
1242
                    );
1243
1244
                    if ($eventResult !== false) {
1245
                        $this->logger->addInfo(
1246
                            "Event updated #".$item['item_id']." External cal Id: (".$externalEventId.") $info"
1247
                        );
1248
                    } else {
1249
                        $this->logger->addInfo(
1250
                            "Error while updating event with external id: $externalEventId"
1251
                        );
1252
                    }
1253
                } else {
1254
                    // New event. Create it.
1255
                    $eventId = $agenda->addEvent(
1256
                        $event['start'],
1257
                        $event['end'],
1258
                        false,
1259
                        $event['title'],
1260
                        $content,
1261
                        array('everyone'), // $usersToSend
1262
                        false, //$addAsAnnouncement = false
1263
                        null, //  $parentEventId
1264
                        array(), //$attachmentArray = array(),
1265
                        [], //$attachmentCommentList
1266
                        $eventComment,
1267
                        $color
1268
                    );
1269
1270
                    if (!empty($eventId)) {
1271
                        $extraFieldValue->save(
1272
                            array(
1273
                                'value' => $externalEventId,
1274
                                'field_id' => $extraFieldInfo['id'],
1275
                                'item_id' => $eventId
1276
                            )
1277
                        );
1278
                        $this->logger->addInfo(
1279
                            "Event added: #$eventId External cal id: (".$externalEventId.") $info"
1280
                        );
1281
                    } else {
1282
                        $this->logger->addInfo(
1283
                            "Error while creating event external id: $externalEventId"
1284
                        );
1285
                    }
1286
                }
1287
1288
                if (($counter % $batchSize) === 0) {
1289
                    $em->flush();
1290
                    $em->clear(); // Detaches all objects from Doctrine!
1291
                }
1292
                $counter++;
1293
            }
1294
1295
            $em->clear(); // Detaches all objects from Doctrine!
1296
            $this->logger->addInfo('------Summary------');
1297
            foreach ($report as $title => $count) {
1298
                $this->logger->addInfo("$title: $count");
1299
            }
1300
            $this->logger->addInfo('------End Summary------');
1301
        }
1302
1303
        if ($moveFile) {
1304
            $this->moveFile($file);
1305
        }
1306
    }
1307
1308
    /**
1309
     * @param string $file
1310
     * @param bool $moveFile
1311
     * @param array $teacherBackup
1312
     * @param array $groupBackup
1313
     */
1314
    private function importCourses(
1315
        $file,
1316
        $moveFile = true,
1317
        &$teacherBackup = array(),
1318
        &$groupBackup = array()
1319
    ) {
1320
        $this->fixCSVFile($file);
0 ignored issues
show
Unused Code introduced by
The call to the method ImportCsv::fixCSVFile() seems un-needed as the method has no side-effects.

PHP Analyzer performs a side-effects analysis of your code. A side-effect is basically anything that might be visible after the scope of the method is left.

Let’s take a look at an example:

class User
{
    private $email;

    public function getEmail()
    {
        return $this->email;
    }

    public function setEmail($email)
    {
        $this->email = $email;
    }
}

If we look at the getEmail() method, we can see that it has no side-effect. Whether you call this method or not, no future calls to other methods are affected by this. As such code as the following is useless:

$user = new User();
$user->getEmail(); // This line could safely be removed as it has no effect.

On the hand, if we look at the setEmail(), this method _has_ side-effects. In the following case, we could not remove the method call:

$user = new User();
$user->setEmail('email@domain'); // This line has a side-effect (it changes an
                                 // instance variable).
Loading history...
1321
        $data = Import::csvToArray($file);
0 ignored issues
show
Deprecated Code introduced by
The method Import::csvToArray() has been deprecated with message: use cvs_reader instead

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
1322
1323
        if (!empty($data)) {
1324
            $this->logger->addInfo(count($data)." records found.");
1325
1326
            foreach ($data as $row) {
1327
                $row = $this->cleanCourseRow($row);
1328
1329
                $courseId = CourseManager::get_course_id_from_original_id(
1330
                    $row['extra_'.$this->extraFieldIdNameList['course']],
1331
                    $this->extraFieldIdNameList['course']
1332
                );
1333
1334
                $courseInfo = api_get_course_info_by_id($courseId);
1335
1336
                if (empty($courseInfo)) {
1337
                    // Create
1338
                    $params = array();
1339
                    $params['title'] = $row['title'];
1340
                    $params['exemplary_content'] = false;
1341
                    $params['wanted_code'] = $row['course_code'];
1342
                    $params['course_category'] = $row['course_category'];
1343
                    $params['course_language'] = $row['language'];
1344
                    $params['teachers'] = $row['teachers'];
1345
                    $params['visibility'] = $row['visibility'];
1346
1347
                    $courseInfo = CourseManager::create_course(
1348
                        $params,
1349
                        $this->defaultAdminId
1350
                    );
1351
1352
                    if (!empty($courseInfo)) {
1353
                        CourseManager::update_course_extra_field_value(
1354
                            $courseInfo['code'],
1355
                            'external_course_id',
1356
                            $row['extra_'.$this->extraFieldIdNameList['course']]
1357
                        );
1358
1359
                        $this->logger->addInfo("Courses - Course created ".$courseInfo['code']);
1360
                    } else {
1361
                        $this->logger->addError("Courses - Can't create course:".$row['title']);
1362
                    }
1363
                } else {
1364
                    // Update
1365
                    $params = array(
1366
                        'title' => $row['title'],
1367
                        'category_code' => $row['course_category'],
1368
                        'visibility' => $row['visibility']
1369
                    );
1370
1371
                    $result = CourseManager::update_attributes(
1372
                        $courseInfo['real_id'],
1373
                        $params
1374
                    );
1375
1376
                    $addTeacherToSession = isset($courseInfo['add_teachers_to_sessions_courses']) && !empty($courseInfo['add_teachers_to_sessions_courses']) ? true : false;
1377
1378
                    $teachers = $row['teachers'];
1379
                    if (!is_array($teachers)) {
1380
                        $teachers = array($teachers);
1381
                    }
1382
1383
                    if ($addTeacherToSession) {
1384
                        $this->logger->addInfo("Add teacher to all course sessions");
1385
                        CourseManager::updateTeachers(
1386
                            $courseInfo,
1387
                            $row['teachers'],
1388
                            false,
1389
                            true,
1390
                            false,
1391
                            $teacherBackup,
1392
                            $this->logger
1393
                        );
1394
                    } else {
1395
                        CourseManager::updateTeachers(
1396
                            $courseInfo,
1397
                            $row['teachers'],
1398
                            true,
1399
                            false,
1400
                            false,
1401
                            $teacherBackup,
1402
                            $this->logger
1403
                        );
1404
                    }
1405
1406
                    foreach ($teachers as $teacherId) {
1407
                        if (isset($groupBackup['tutor'][$teacherId]) &&
1408
                            isset($groupBackup['tutor'][$teacherId][$courseInfo['code']])
1409
                        ) {
1410
                            foreach ($groupBackup['tutor'][$teacherId][$courseInfo['code']] as $data) {
1411
                                $groupInfo = GroupManager::get_group_properties($data['group_id']);
1412
                                GroupManager::subscribe_tutors(
1413
                                    array($teacherId),
1414
                                    $groupInfo,
1415
                                    $data['c_id']
1416
                                );
1417
                            }
1418
                        }
1419
1420
                        if (isset($groupBackup['user'][$teacherId]) &&
1421
                            isset($groupBackup['user'][$teacherId][$courseInfo['code']]) &&
1422
                            !empty($groupBackup['user'][$teacherId][$courseInfo['code']])
1423
                        ) {
1424
                            foreach ($groupBackup['user'][$teacherId][$courseInfo['code']] as $data) {
1425
                                $groupInfo = GroupManager::get_group_properties($data['group_id']);
1426
                                GroupManager::subscribe_users(
1427
                                    array($teacherId),
1428
                                    $groupInfo,
0 ignored issues
show
Bug introduced by
It seems like $groupInfo defined by \GroupManager::get_group...ties($data['group_id']) on line 1425 can also be of type null; however, GroupManager::subscribe_users() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
1429
                                    $data['c_id']
1430
                                );
1431
                            }
1432
                        }
1433
                    }
1434
1435
                    if ($result) {
1436
                        $this->logger->addInfo("Courses - Course updated ".$courseInfo['code']);
1437
                    } else {
1438
                        $this->logger->addError("Courses - Course NOT updated ".$courseInfo['code']);
1439
                    }
1440
                }
1441
            }
1442
        }
1443
1444
        if ($moveFile) {
1445
            $this->moveFile($file);
1446
        }
1447
    }
1448
1449
    /**
1450
     * Parse filename: encora_subsessionsextid-static_31082016.csv
1451
     * @param string $file
1452
     */
1453
    private function importSubscribeUserToCourseSessionExtStatic($file, $moveFile = true)
1454
    {
1455
        $data = Import::csv_reader($file);
1456
        if (!empty($data)) {
1457
            $this->logger->addInfo(count($data)." records found.");
1458
            $userIdList = [];
1459
            foreach ($data as $row) {
1460
                $chamiloUserName = $row['UserName'];
1461
                $chamiloCourseCode = $row['CourseCode'];
1462
                $externalSessionId = $row['ExtSessionID'];
1463
                $status = $row['Status'];
1464
1465
                $chamiloSessionId = null;
1466
                if (!empty($externalSessionId)) {
1467
                    $chamiloSessionId = SessionManager::getSessionIdFromOriginalId(
1468
                        $externalSessionId,
1469
                        $this->extraFieldIdNameList['session']
1470
                    );
1471
                }
1472
1473
                $sessionInfo = api_get_session_info($chamiloSessionId);
1474
1475
                if (empty($sessionInfo)) {
1476
                    $this->logger->addError('Session does not exists: '.$chamiloSessionId);
1477
                    continue;
1478
                }
1479
1480
                $courseInfo = api_get_course_info($chamiloCourseCode);
1481
                if (empty($courseInfo)) {
1482
                    $this->logger->addError('Course does not exists: '.$courseInfo);
1483
                    continue;
1484
                }
1485
1486
                $userId = UserManager::get_user_id_from_username($chamiloUserName);
1487
1488
                if (empty($userId)) {
1489
                    $this->logger->addError('User does not exists: '.$chamiloUserName);
1490
                    continue;
1491
                }
1492
1493
                switch ($status) {
1494
                    case 'student':
1495
                        SessionManager::subscribe_users_to_session_course(
1496
                            array($userId),
1497
                            $chamiloSessionId,
1498
                            $courseInfo['code']
1499
                        );
1500
                        break;
1501
                    case 'teacher':
1502
                        SessionManager::set_coach_to_course_session(
1503
                            $userId,
1504
                            $chamiloSessionId,
1505
                            $courseInfo['code']
1506
                        );
1507
                        break;
1508
                    case 'drh':
1509
                        $removeAllSessionsFromUser = true;
1510
                        if (in_array($userId, $userIdList)) {
1511
                            $removeAllSessionsFromUser = false;
1512
                        } else {
1513
                            $userIdList[] = $userId;
1514
                        }
1515
1516
                        $userInfo = api_get_user_info($userId);
1517
                        SessionManager::subscribeSessionsToDrh(
1518
                            $userInfo,
0 ignored issues
show
Security Bug introduced by
It seems like $userInfo defined by api_get_user_info($userId) on line 1516 can also be of type false; however, SessionManager::subscribeSessionsToDrh() does only seem to accept array, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
1519
                            [$chamiloSessionId],
1520
                            false,
1521
                            $removeAllSessionsFromUser
1522
                        );
1523
                        break;
1524
                }
1525
1526
                $this->logger->addError(
1527
                    "User '$chamiloUserName' was added as '$status' to Session: #$chamiloSessionId - Course: ".$courseInfo['code']
1528
                );
1529
1530
            }
1531
        }
1532
1533
        if ($moveFile) {
1534
            $this->moveFile($file);
1535
        }
1536
    }
1537
1538
    /**
1539
     * @param $file
1540
     * @param bool $moveFile
1541
     */
1542
    private function importUnsubSessionsExtIdStatic($file, $moveFile = true)
1543
    {
1544
        $data = Import::csv_reader($file);
1545
1546
        if (!empty($data)) {
1547
            $this->logger->addInfo(count($data)." records found.");
1548
            foreach ($data as $row) {
1549
                $chamiloUserName = $row['UserName'];
1550
                $chamiloCourseCode = $row['CourseCode'];
1551
                $externalSessionId = $row['ExtSessionID'];
1552
                $dateStop = $row['DateStop'];
1553
1554
                $chamiloSessionId = null;
1555
                if (!empty($externalSessionId)) {
1556
                    $chamiloSessionId = SessionManager::getSessionIdFromOriginalId(
1557
                        $externalSessionId,
1558
                        $this->extraFieldIdNameList['session']
1559
                    );
1560
                }
1561
1562
                $sessionInfo = api_get_session_info($chamiloSessionId);
1563
1564
                if (empty($sessionInfo)) {
1565
                    $this->logger->addError('Session does not exists: '.$chamiloSessionId);
1566
                    continue;
1567
                }
1568
1569
                $courseInfo = api_get_course_info($chamiloCourseCode);
1570
                if (empty($courseInfo)) {
1571
                    $this->logger->addError('Course does not exists: '.$courseInfo);
1572
                    continue;
1573
                }
1574
1575
                $userId = UserManager::get_user_id_from_username($chamiloUserName);
1576
1577
                if (empty($userId)) {
1578
                    $this->logger->addError('User does not exists: '.$chamiloUserName);
1579
                    continue;
1580
                }
1581
1582
                SessionManager::removeUsersFromCourseSession(
1583
                    array($userId),
1584
                    $chamiloSessionId,
1585
                    $courseInfo
1586
                );
1587
1588
                $this->logger->addError(
1589
                    "User '$chamiloUserName' was remove from Session: #$chamiloSessionId - Course: ".$courseInfo['code']
1590
                );
1591
1592
            }
1593
        }
1594
1595
        if ($moveFile) {
1596
            $this->moveFile($file);
1597
        }
1598
    }
1599
1600
    /**
1601
     *
1602
     * @param string $file
1603
     */
1604
    private function importSessionsExtIdStatic($file, $moveFile = true)
1605
    {
1606
        $data = Import::csv_reader($file);
1607
1608
        if (!empty($data)) {
1609
            $this->logger->addInfo(count($data)." records found.");
1610
            foreach ($data as $row) {
1611
                $chamiloUserName = $row['UserName'];
1612
                $chamiloCourseCode = $row['CourseCode'];
1613
                $externalSessionId = $row['ExtSessionID'];
1614
                $type = $row['Type'];
1615
1616
                $chamiloSessionId = null;
1617
                if (!empty($externalSessionId)) {
1618
                    $chamiloSessionId = SessionManager::getSessionIdFromOriginalId(
1619
                        $externalSessionId,
1620
                        $this->extraFieldIdNameList['session']
1621
                    );
1622
                }
1623
1624
                $sessionInfo = api_get_session_info($chamiloSessionId);
1625
1626
                if (empty($sessionInfo)) {
1627
                    $this->logger->addError('Session does not exists: '.$chamiloSessionId);
1628
                    continue;
1629
                }
1630
1631
                $courseInfo = api_get_course_info($chamiloCourseCode);
1632
                if (empty($courseInfo)) {
1633
                    $this->logger->addError('Course does not exists: '.$courseInfo);
1634
                    continue;
1635
                }
1636
1637
                $userId = UserManager::get_user_id_from_username($chamiloUserName);
1638
1639
                if (empty($userId)) {
1640
                    $this->logger->addError('User does not exists: '.$chamiloUserName);
1641
                    continue;
1642
                }
1643 View Code Duplication
                switch ($type) {
1644
                    case 'student':
1645
                        SessionManager::subscribe_users_to_session_course(
1646
                            array($userId),
1647
                            $chamiloSessionId,
1648
                            $courseInfo['code'],
1649
                            null,
1650
                            false
1651
                        );
1652
                        break;
1653
                    case 'teacher':
1654
                        SessionManager::set_coach_to_course_session(
1655
                            $userId,
1656
                            $chamiloSessionId,
1657
                            $courseInfo['code']
1658
                        );
1659
                        break;
1660
                }
1661
1662
                $this->logger->addError(
1663
                    "User '$chamiloUserName' with status $type was added to session: #$chamiloSessionId - Course: ".$courseInfo['code']
1664
                );
1665
            }
1666
        }
1667
1668
        if ($moveFile) {
1669
            $this->moveFile($file);
1670
        }
1671
    }
1672
1673
    /**
1674
     * Updates the session synchronize with the csv file.
1675
     * @param bool $moveFile
1676
     * @param string $file
1677
     */
1678
    private function importSessionsStatic($file, $moveFile = true)
1679
    {
1680
        $content = file($file);
1681
        $sessions = array();
1682
        $tag_names = array();
1683
1684
        foreach ($content as $key => $enreg) {
1685
            $enreg = explode(';', trim($enreg));
1686 View Code Duplication
            if ($key) {
1687
                foreach ($tag_names as $tag_key => $tag_name) {
1688
                    if (isset($enreg[$tag_key])) {
1689
                        $sessions[$key - 1][$tag_name] = $enreg[$tag_key];
1690
                    }
1691
                }
1692
            } else {
1693
                foreach ($enreg as $tag_name) {
1694
                    $tag_names[] = api_preg_replace(
1695
                        '/[^a-zA-Z0-9_\-]/',
1696
                        '',
1697
                        $tag_name
1698
                    );
1699
                }
1700
                if (!in_array('SessionName', $tag_names) ||
1701
                    !in_array('DateStart', $tag_names) || !in_array('DateEnd', $tag_names)
1702
                ) {
1703
                    $error_message = get_lang('NoNeededData');
1704
                    break;
1705
                }
1706
            }
1707
        }
1708
1709
1710
        if (!empty($sessions)) {
1711
            // Looping the sessions.
1712
            foreach ($sessions as $session) {
1713
                if (!empty($session['SessionID'])) {
1714
                    $sessionId = SessionManager::getSessionIdFromOriginalId(
1715
                        $session['SessionID'],
1716
                        $this->extraFieldIdNameList['session']
1717
                    );
1718
1719
                    $coachUserName = isset($session['Coach']) ? $session['Coach'] : null;
1720
                    $categoryId = isset($session['category_id']) ? $session['category_id'] : null;
1721
1722
                    // 2014-06-30
1723
                    $dateStart = explode('/', $session['DateStart']);
1724
                    $dateEnd = explode('/', $session['DateEnd']);
1725
                    $visibility = $this->defaultSessionVisibility;
1726
1727
                    $coachId = null;
1728
                    if (!empty($coachUserName)) {
1729
                        $coachInfo = api_get_user_info_from_username($coachUserName);
1730
                        $coachId = $coachInfo['user_id'];
1731
                    }
1732
1733
                    $dateStart = $dateStart[0].'-'.$dateStart[1].'-'.$dateStart[2].' 00:00:00';
1734
                    $dateEnd = $dateEnd[0].'-'.$dateEnd[1].'-'.$dateEnd[2].' 23:59:59';
1735
1736
                    $date = new \DateTime($dateStart);
1737
                    $interval = new DateInterval('P'.$this->daysCoachAccessBeforeBeginning.'D');
1738
                    $date->sub($interval);
1739
                    $coachBefore = $date->format('Y-m-d h:i');
1740
1741
                    $date = new \DateTime($dateEnd);
1742
                    $interval = new DateInterval('P'.$this->daysCoachAccessAfterBeginning.'D');
1743
                    $date->add($interval);
1744
                    $coachAfter = $date->format('Y-m-d h:i');
1745
1746
                    /*$dateStart = api_get_utc_datetime($dateStart);
1747
                    $dateEnd = api_get_utc_datetime($dateEnd);
1748
                    $coachBefore = api_get_utc_datetime($coachBefore);
1749
                    $coachAfter = api_get_utc_datetime($coachAfter);*/
1750
1751
                    if (empty($sessionId)) {
1752
                        $result = SessionManager::create_session(
1753
                            $session['SessionName'],
1754
                            $dateStart,
1755
                            $dateEnd,
1756
                            $dateStart,
1757
                            $dateEnd,
1758
                            $coachBefore,
1759
                            $coachAfter,
1760
                            $coachId,
1761
                            $categoryId,
1762
                            $visibility
1763
                        );
1764
1765
                        if (is_numeric($result)) {
1766
                            $sessionId = $result;
1767
                            $this->logger->addInfo("Session #$sessionId created: ".$session['SessionName']);
1768
                            SessionManager::update_session_extra_field_value(
1769
                                $sessionId,
1770
                                $this->extraFieldIdNameList['session'],
1771
                                $session['SessionID']
1772
                            );
1773
                        } else {
1774
                            $this->logger->addInfo("Failed creating session: ".$session['SessionName']);
1775
                        }
1776
                    } else {
1777
                        $sessionInfo = api_get_session_info($sessionId);
1778
                        $accessBefore = null;
1779
                        $accessAfter = null;
1780
1781 View Code Duplication
                        if (empty($sessionInfo['nb_days_access_before_beginning']) ||
1782
                            (!empty($sessionInfo['nb_days_access_before_beginning']) &&
1783
                                $sessionInfo['nb_days_access_before_beginning'] < $this->daysCoachAccessBeforeBeginning)
1784
                        ) {
1785
                            $accessBefore = $coachBefore;
1786
                        }
1787
1788
                        $accessAfter = null;
1789 View Code Duplication
                        if (empty($sessionInfo['nb_days_access_after_end']) ||
1790
                            (!empty($sessionInfo['nb_days_access_after_end']) &&
1791
                                $sessionInfo['nb_days_access_after_end'] < $this->daysCoachAccessAfterBeginning)
1792
                        ) {
1793
                            $accessAfter = $coachAfter;
1794
                        }
1795
1796
                        $showDescription = isset($sessionInfo['show_description']) ? $sessionInfo['show_description'] : 1;
1797
1798
                        $result = SessionManager::edit_session(
1799
                            $sessionId,
1800
                            $session['SessionName'],
1801
                            $dateStart,
1802
                            $dateEnd,
1803
                            $dateStart,
1804
                            $dateEnd,
1805
                            $accessBefore,
1806
                            $accessAfter,
1807
                            $coachId,
1808
                            $categoryId,
1809
                            $visibility,
1810
                            null, //$description = null,
1811
                            $showDescription
1812
                        );
1813
1814
                        if (is_numeric($result)) {
1815
                            $this->logger->addInfo("Session #$sessionId updated: ".$session['SessionName']);
1816
                            $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
1817
                            $params = array(
1818
                                'description' => $session['SessionDescription']
1819
                            );
1820
                            Database::update(
1821
                                $tbl_session,
1822
                                $params,
1823
                                array('id = ?' => $sessionId)
1824
                            );
1825
                        }
1826
                    }
1827
1828
                    if (!empty($sessionId)) {
1829
                        // Courses
1830
                        $courses = explode('|', $session['Courses']);
1831
                        $courseList = [];
1832
                        $courseListWithCoach = [];
1833
                        foreach ($courses as $course) {
1834
                            $courseArray = bracketsToArray($course);
1835
                            $courseCode = $courseArray[0];
1836
                            if (CourseManager::course_exists($courseCode)) {
1837
                                $courseInfo = api_get_course_info($courseCode);
1838
                                $courseList[] = $courseInfo['real_id'];
1839
                                // Extracting course coaches
1840
                                $courseCoaches = isset($courseArray[1]) ? $courseArray[1] : null;
1841
                                $courseCoaches = explode(',', $courseCoaches);
1842
1843
                                // Extracting students
1844
                                $courseUsers = isset($courseArray[2]) ? $courseArray[2] : null;
1845
                                $courseUsers = explode(',', $courseUsers);
1846
1847
                                $courseListWithCoach[] = [
1848
                                    'course_info' => $courseInfo,
1849
                                    'coaches' => $courseCoaches,
1850
                                    'course_users' => $courseUsers
1851
                                ];
1852
                            }
1853
                        }
1854
1855
                        SessionManager::add_courses_to_session(
1856
                            $sessionId,
1857
                            $courseList,
1858
                            true
1859
                        );
1860
1861
                        $this->logger->addInfo("Session #$sessionId: Courses added: '".implode(', ', $courseList)."'");
1862
1863
                        if (empty($courseListWithCoach)) {
1864
                            $this->logger->addInfo("No users/coaches to update");
1865
                            continue;
1866
                        }
1867
1868
                        foreach ($courseListWithCoach as $courseData) {
1869
                            $courseInfo = $courseData['course_info'];
1870
                            $courseCode = $courseInfo['code'];
1871
                            $courseId = $courseInfo['real_id'];
1872
                            $courseCoaches = $courseData['coaches'];
1873
                            $courseUsers = $courseData['course_users'];
1874
1875
                            // Coaches
1876
                            if (!empty($courseCoaches)) {
1877
                                $coachList = array();
1878
                                foreach ($courseCoaches as $courseCoach) {
1879
                                    $courseCoachId = UserManager::get_user_id_from_username(
1880
                                        $courseCoach
1881
                                    );
1882
                                    if ($courseCoachId !== false) {
1883
                                        // Just insert new coaches
1884
                                        $coachList[] = $courseCoachId;
1885
                                    }
1886
                                }
1887
1888
                                $this->logger->addInfo("Session #$sessionId: course '$courseCode' coaches added: '".implode(', ', $coachList)."'");
1889
1890
                                SessionManager::updateCoaches(
1891
                                    $sessionId,
1892
                                    $courseId,
1893
                                    $coachList,
1894
                                    true
1895
                                );
1896
                            } else {
1897
                                $this->logger->addInfo("No coaches added");
1898
                            }
1899
1900
                            // Students
1901
                            if (!empty($courseUsers)) {
1902
                                $userList = array();
1903
                                foreach ($courseUsers as $username) {
1904
                                    $userInfo = api_get_user_info_from_username(trim($username));
1905
                                    if (!empty($userInfo)) {
1906
                                        $userList[] = $userInfo['user_id'];
1907
                                    }
1908
                                }
1909
1910
                                $this->logger->addInfo("Session #$sessionId: course '$courseCode': Students added '".implode(', ', $userList)."'");
1911
                                SessionManager::subscribe_users_to_session_course(
1912
                                    $userList,
1913
                                    $sessionId,
1914
                                    $courseCode,
1915
                                    SESSION_VISIBLE_READ_ONLY,
1916
                                    true
1917
                                );
1918
                            } else {
1919
                                $this->logger->addInfo("No users to register.");
1920
                            }
1921
                        }
1922
                    } else {
1923
                        $this->logger->addInfo(
1924
                            'SessionID not found in system.'
1925
                        );
1926
                    }
1927
                } else {
1928
                    $this->logger->addInfo('SessionID does not exists');
1929
                }
1930
            }
1931
        } else {
1932
            $this->logger->addInfo($error_message);
1933
        }
1934
1935
        if ($moveFile) {
1936
            $this->moveFile($file);
1937
        }
1938
    }
1939
1940
    /**
1941
     * @param string $file
1942
     * @param bool $moveFile
1943
     * @param array $teacherBackup
1944
     * @param array $groupBackup
1945
     */
1946
    private function importSessions(
1947
        $file,
1948
        $moveFile = true,
1949
        &$teacherBackup = array(),
1950
        &$groupBackup = array()
1951
    ) {
1952
        $avoid = null;
1953
        if (isset($this->conditions['importSessions']) &&
1954
            isset($this->conditions['importSessions']['update'])
1955
        ) {
1956
            $avoid = $this->conditions['importSessions']['update'];
1957
        }
1958
        $result = SessionManager::importCSV(
1959
            $file,
1960
            true,
1961
            $this->defaultAdminId,
1962
            $this->logger,
1963
            array(
1964
                'SessionID' => 'extra_'.$this->extraFieldIdNameList['session'],
1965
                'CareerId' => 'extra_'.$this->extraFieldIdNameList['session_career']
1966
            ),
1967
            $this->extraFieldIdNameList['session'],
1968
            $this->daysCoachAccessBeforeBeginning,
1969
            $this->daysCoachAccessAfterBeginning,
1970
            $this->defaultSessionVisibility,
1971
            $avoid,
1972
            false, // deleteUsersNotInList
1973
            false, // updateCourseCoaches
1974
            true, // sessionWithCoursesModifier
1975
            true, //$addOriginalCourseTeachersAsCourseSessionCoaches
1976
            false, //$removeAllTeachersFromCourse
1977
            1, // $showDescription,
1978
            $teacherBackup,
1979
            $groupBackup
1980
        );
1981
1982
        if (!empty($result['error_message'])) {
1983
            $this->logger->addError($result['error_message']);
1984
        }
1985
        $this->logger->addInfo("Sessions - Sessions parsed: ".$result['session_counter']);
1986
1987
        if ($moveFile) {
1988
            $this->moveFile($file);
1989
        }
1990
    }
1991
1992
    /**
1993
     * @param string $file
1994
     * @param bool $moveFile
1995
     */
1996
    private function importSubscribeStatic($file, $moveFile = true)
1997
    {
1998
        $data = Import::csv_reader($file);
1999
2000
        if (!empty($data)) {
2001
            $this->logger->addInfo(count($data)." records found.");
2002
            foreach ($data as $row) {
2003
                $chamiloUserName = $row['UserName'];
2004
                $chamiloCourseCode = $row['CourseCode'];
2005
                $chamiloSessionId = $row['SessionID'];
2006
                $type = $row['Type'];
2007
2008
                $sessionInfo = api_get_session_info($chamiloSessionId);
2009
2010
                if (empty($sessionInfo)) {
2011
                    $this->logger->addError('Session does not exists: '.$chamiloSessionId);
2012
                    continue;
2013
                }
2014
2015
                $courseInfo = api_get_course_info($chamiloCourseCode);
2016
                if (empty($courseInfo)) {
2017
                    $this->logger->addError('Course does not exists: '.$courseInfo);
2018
                    continue;
2019
                }
2020
2021
                $userId = UserManager::get_user_id_from_username($chamiloUserName);
2022
2023
                if (empty($userId)) {
2024
                    $this->logger->addError('User does not exists: '.$chamiloUserName);
2025
                    continue;
2026
                }
2027
2028 View Code Duplication
                switch ($type) {
2029
                    case 'student':
2030
                        SessionManager::subscribe_users_to_session_course(
2031
                            array($userId),
2032
                            $chamiloSessionId,
2033
                            $courseInfo['code'],
2034
                            null,
2035
                            false
2036
                        );
2037
                        break;
2038
                    case 'teacher':
2039
                        SessionManager::set_coach_to_course_session(
2040
                            $userId,
2041
                            $chamiloSessionId,
2042
                            $courseInfo['real_id']
2043
                        );
2044
                        break;
2045
                }
2046
2047
                $this->logger->addError(
2048
                    "User '$chamiloUserName' with status $type was added to session: #$chamiloSessionId - Course: ".$courseInfo['code']
2049
                );
2050
            }
2051
        }
2052
2053
        if ($moveFile) {
2054
            $this->moveFile($file);
2055
        }
2056
    }
2057
2058
    /**
2059
     * @param $file
2060
     * @param bool $moveFile
2061
     */
2062
    private function importSubscribeUserToCourse($file, $moveFile = false, &$teacherBackup = [])
2063
    {
2064
        $data = Import::csv_reader($file);
2065
2066
        if (!empty($data)) {
2067
            $this->logger->addInfo(count($data)." records found.");
2068
            foreach ($data as $row) {
2069
                $chamiloUserName = $row['UserName'];
2070
                $chamiloCourseCode = $row['CourseCode'];
2071
                $status = $row['Status'];
2072
2073
                $courseInfo = api_get_course_info($chamiloCourseCode);
2074
2075
                if (empty($courseInfo)) {
2076
                    $this->logger->addError(
2077
                        'Course does not exists: '.$chamiloCourseCode
2078
                    );
2079
                    continue;
2080
                }
2081
2082
                $userId = UserManager::get_user_id_from_username(
2083
                    $chamiloUserName
2084
                );
2085
2086
                if (empty($userId)) {
2087
                    $this->logger->addError(
2088
                        'User does not exists: '.$chamiloUserName
2089
                    );
2090
                    continue;
2091
                }
2092
2093
                $userCourseCategory = '';
2094
                if (isset($teacherBackup[$userId]) &&
2095
                    isset($teacherBackup[$userId][$courseInfo['code']])
2096
                ) {
2097
                    $courseUserData = $teacherBackup[$userId][$courseInfo['code']];
2098
                    $userCourseCategory = $courseUserData['user_course_cat'];
2099
                }
2100
2101
                CourseManager::subscribe_user(
2102
                    $userId,
2103
                    $courseInfo['code'],
2104
                    $status,
2105
                    0,
2106
                    $userCourseCategory
2107
                );
2108
2109
                $this->logger->addInfo(
2110
                    "User $userId added to course ".$courseInfo['code']." with status '$status' with course category: '$userCourseCategory'"
2111
                );
2112
            }
2113
        }
2114
2115
        if ($moveFile) {
2116
            $this->moveFile($file);
2117
        }
2118
    }
2119
2120
    /**
2121
     * @param $file
2122
     * @param bool $moveFile
2123
     */
2124
    public function importCare($file, $moveFile = false)
2125
    {
2126
        $data = Import::csv_reader($file);
2127
        $counter = 1;
2128
        $batchSize = $this->batchSize;
2129
        $em = Database::getManager();
2130
2131
        if (!empty($data)) {
2132
            $this->logger->addInfo(count($data)." records found.");
2133
            $items = [];
2134
            foreach ($data as $list) {
2135
                $post = [];
2136 View Code Duplication
                foreach ($list as $key => $value) {
0 ignored issues
show
Bug introduced by
The expression $list of type string|array|null is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
2137
                    $key = (string) trim($key);
2138
                    // Remove utf8 bom
2139
                    $key = preg_replace('/[\x00-\x1F\x80-\xFF]/', '', $key);
2140
                    $post[$key] = $value;
2141
                }
2142
2143
                if (empty($post)) {
2144
                    continue;
2145
                }
2146
2147
                $externalId = $post['External_care_id'];
2148
                $items[$externalId] = $post;
2149
            }
2150
            ksort($items);
2151
2152
            foreach ($items as $row) {
2153
                // Insert user
2154
                $insertUserInfo = api_get_user_info_from_username($row['Added_by']);
2155
                if (empty($insertUserInfo)) {
2156
                    $this->logger->addInfo("User does '".$row['Added_by']."' not exists skip this entry.");
2157
                    continue;
2158
                }
2159
                $insertUserInfo = api_get_user_entity($insertUserInfo['user_id']);
2160
2161
                // User about the post
2162
                $userId = UserManager::get_user_id_from_original_id(
2163
                    $row['External_user_id'],
2164
                    $this->extraFieldIdNameList['user']
2165
                );
2166
2167
                if (empty($userId)) {
2168
                    if (empty($userInfo)) {
2169
                        $this->logger->addInfo("User does '".$row['External_user_id']."' not exists skip this entry.");
2170
                        continue;
2171
                    }
2172
                }
2173
                $userInfo = api_get_user_entity($userId);
2174
2175
                // Dates
2176
                $createdAt = $this->createDateTime($row['Added_On']);
2177
                $updatedAt = $this->createDateTime($row['Edited_on']);
2178
2179
                // Parent
2180
                $parent = null;
2181
                if (!empty($row['Parent_id'])) {
2182
                    $parentId = $items[$row['Parent_id']];
2183
                    $criteria = [
2184
                        'externalCareId' => $parentId
2185
                    ];
2186
                    $parent = $em->getRepository('ChamiloPluginBundle:StudentFollowUp\CarePost')->findOneBy($criteria);
2187
                }
2188
2189
                // Tags
2190
                $tags = explode(',', $row['Tags']);
2191
2192
                // Check if post already was added:
2193
                $criteria = [
2194
                    'externalCareId' => $row['External_care_id']
2195
                ];
2196
                $post = $em->getRepository('ChamiloPluginBundle:StudentFollowUp\CarePost')->findOneBy($criteria);
2197
2198
                if (empty($post)) {
2199
                    $post = new CarePost();
2200
                }
2201
2202
                $post
2203
                    ->setTitle($row['Title'])
2204
                    ->setContent($row['Article'])
2205
                    ->setExternalCareId($row['External_care_id'])
2206
                    ->setCreatedAt($createdAt)
2207
                    ->setUpdatedAt($updatedAt)
2208
                    ->setPrivate((int) $row['Private'])
2209
                    ->setInsertUser($insertUserInfo)
2210
                    ->setExternalSource((int) $row['Source_is_external'])
2211
                    ->setParent($parent)
2212
                    ->setTags($tags)
2213
                    ->setUser($userInfo)
2214
                ;
2215
                $em->persist($post);
2216
                $em->flush();
2217
2218
                if (($counter % $batchSize) === 0) {
2219
                    $em->flush();
2220
                    $em->clear(); // Detaches all objects from Doctrine!
2221
                }
2222
                $counter++;
2223
            }
2224
2225
            $em->clear(); // Detaches all objects from Doctrine!
2226
        }
2227
    }
2228
2229
    /**
2230
     * 23/4/2017 to datetime
2231
     * @param $string
2232
     * @return mixed
2233
     */
2234
    private function createDateTime($string)
2235
    {
2236
        if (empty($string)) {
2237
            return null;
2238
        }
2239
2240
        $date = DateTime::createFromFormat('j/m/Y', $string);
2241
2242
        return $date;
2243
    }
2244
2245
    /**
2246
     * @param $file
2247
     * @param bool $moveFile
2248
     * @param array $teacherBackup
2249
     * @param array $groupBackup
2250
     * @return bool
2251
     */
2252
    private function importCareers(
2253
        $file,
2254
        $moveFile = false,
2255
        &$teacherBackup = array(),
2256
        &$groupBackup = array()
2257
    ) {
2258
        $data = Import::csv_reader($file);
2259
2260
        if (!empty($data)) {
2261
            $this->logger->addInfo(count($data)." records found.");
2262
            $extraFieldValue = new ExtraFieldValue('career');
2263
            $extraFieldName = $this->extraFieldIdNameList['career'];
2264
            $externalEventId = null;
2265
2266
            $extraField = new ExtraField('career');
2267
            $extraFieldInfo = $extraField->get_handler_field_info_by_field_variable(
2268
                $extraFieldName
2269
            );
2270
2271
            if (empty($extraFieldInfo)) {
2272
                return false;
2273
            }
2274
2275
            foreach ($data as $row) {
2276 View Code Duplication
                foreach ($row as $key => $value) {
0 ignored issues
show
Bug introduced by
The expression $row of type string|array|null is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
2277
                    $key = (string)trim($key);
2278
                    // Remove utf8 bom
2279
                    $key = preg_replace('/[\x00-\x1F\x80-\xFF]/', '', $key);
2280
                    $row[$key] = $value;
2281
                }
2282
2283
                $itemId = $row['CareerId'];
2284
                $item = $extraFieldValue->get_item_id_from_field_variable_and_field_value(
2285
                    $extraFieldName,
2286
                    $itemId,
2287
                    false,
2288
                    false,
2289
                    false
2290
                );
2291
2292
                $career = new Career();
2293
                if (empty($item)) {
2294
                    $params = [
2295
                        'status' => 1,
2296
                        'name' => $row['CareerName']
2297
                    ];
2298
                    $careerId = $career->save($params);
2299
                    if ($careerId) {
2300
                        $params = [
2301
                            'item_id' => $careerId,
2302
                            'extra_'.$extraFieldName => $itemId,
2303
                        ];
2304
                        $extraFieldValue->saveFieldValues($params);
2305
                    }
2306
                } else {
2307
                    if (isset($item['item_id'])) {
2308
                        $params = [
2309
                            'id' => $item['item_id'],
2310
                            'name' => $row['CareerName']
2311
                        ];
2312
                        $career->update($params);
2313
                    }
2314
                }
2315
            }
2316
        }
2317
    }
2318
2319
    /**
2320
     * @param $file
2321
     * @param bool $moveFile
2322
     * @param array $teacherBackup
2323
     * @param array $groupBackup
2324
     */
2325
    private function importCareersDiagram(
2326
        $file,
2327
        $moveFile = false,
2328
        &$teacherBackup = array(),
2329
        &$groupBackup = array()
2330
    ) {
2331
        $data = Import::csv_reader($file);
2332
2333
        $extraFieldValue = new ExtraFieldValue('career');
2334
        $extraFieldName = $this->extraFieldIdNameList['career'];
2335
        $externalEventId = null;
2336
2337
        $extraField = new ExtraField('career');
2338
        $extraFieldInfo = $extraField->get_handler_field_info_by_field_variable(
2339
            $extraFieldName
2340
        );
2341
2342
        $careerDiagramExtraFieldName = $this->extraFieldIdNameList['career_diagram'];
2343
        $extraFieldDiagramInfo = $extraField->get_handler_field_info_by_field_variable(
2344
            $careerDiagramExtraFieldName
2345
        );
2346
2347
        if (empty($extraFieldInfo) || empty($extraFieldDiagramInfo)) {
2348
            return false;
2349
        }
2350
2351
        if (!empty($data)) {
2352
            $this->logger->addInfo(count($data)." records found.");
2353
            $values = [];
2354
            foreach ($data as $row) {
2355 View Code Duplication
                foreach ($row as $key => $value) {
0 ignored issues
show
Bug introduced by
The expression $row of type string|array|null is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
2356
                    $key = (string) trim($key);
2357
                    // Remove utf8 bom
2358
                    $key = preg_replace('/[\x00-\x1F\x80-\xFF]/', '', $key);
2359
                    $row[$key] = $value;
2360
                }
2361
                $values[$row['Column']][] = $row;
2362
            }
2363
2364
            $careerList = [];
2365
            $careerNameList = [];
2366
            ksort($values);
2367
            $careerChamiloIdList = [];
2368
            // 1. First create all items
2369
            foreach ($values as $column => $rowList) {
2370
                foreach ($rowList as $row) {
2371
                    $careerId = $row['CareerId'];
2372
                    $item = $extraFieldValue->get_item_id_from_field_variable_and_field_value(
2373
                        $extraFieldName,
2374
                        $careerId,
2375
                        false,
2376
                        false,
2377
                        false
2378
                    );
2379
2380
                    $chamiloCareerName = '';
2381
                    if (empty($item)) {
2382
                        $this->logger->addInfo("Career not found: $careerId");
2383
                        continue;
2384
                    } else {
2385
                        if (isset($item['item_id'])) {
2386
                            $careerChamiloId = $item['item_id'];
2387
                            $career = new Career();
2388
                            $career = $career->find($careerChamiloId);
2389
                            $chamiloCareerName = $career['name'];
2390
                            $careerNameList[$careerId] = $chamiloCareerName;
2391
                            $careerChamiloIdList[$careerId] = $careerChamiloId;
2392
                        } else {
2393
                            continue;
2394
                        }
2395
                    }
2396
2397
                    if (empty($chamiloCareerName)) {
2398
                        $this->logger->addInfo("Career not found: $careerId");
2399
                        continue;
2400
                    }
2401
2402
                    if (isset($careerList[$careerId])) {
2403
                        $graph = $careerList[$careerId];
2404
                    } else {
2405
                        $graph = new Graph($careerId);
2406
                        $graph->setAttribute('graphviz.graph.rankdir', 'LR');
2407
                        $careerList[$careerId] = $graph;
2408
                    }
2409
2410
                    $currentCourseId = (int) $row['CourseId'];
2411
                    $name = $row['CourseName'];
2412
                    $color = $row['DefinedColor'];
2413
                    $notes = $row['Notes'];
2414
                    $groupValue = $row['Group'];
2415
                    $rowValue = $row['Row'];
2416
                    $arrow = $row['DrawArrowFrom'];
2417
                    $subGroup = $row['SubGroup'];
2418
                    $connections = $row['Connections'];
2419
2420
                    if ($graph->hasVertex($currentCourseId)) {
2421
                        // Avoid double insertion
2422
                        continue;
2423
                    } else {
2424
                        $current = $graph->createVertex($currentCourseId);
2425
                        $current->setAttribute('graphviz.label', $name);
2426
                        $current->setAttribute('DefinedColor', $color);
2427
                        $current->setAttribute('Notes', $notes);
2428
                        $current->setAttribute('Row', $rowValue);
2429
                        $current->setAttribute('Group', $groupValue);
2430
                        $current->setAttribute('DrawArrowFrom', $arrow);
2431
                        $current->setAttribute('SubGroup', $subGroup);
2432
                        $current->setAttribute('Connections', $connections);
2433
2434
                        //$current->setAttribute('graphviz.color', 'blue');
2435
                        $current->setAttribute('graphviz.shape', 'box');
2436
                        $current->setGroup($column);
2437
                    }
2438
                }
2439
            }
2440
2441
            // 2. Create connections
2442
            // $column start with 1 (depending in Column row)
2443
            foreach ($values as $column => $rowList) {
2444
                foreach ($rowList as $row) {
2445
                    $careerId = $row['CareerId'];
2446
                    if (isset($careerList[$careerId])) {
2447
                        $graph = $careerList[$careerId];
2448
                    } else {
2449
                        continue;
2450
                    }
2451
2452
                    $currentCourseId = (int) $row['CourseId'];
2453
                    if ($graph->hasVertex($currentCourseId)) {
2454
                        $current = $graph->getVertex($currentCourseId);
2455
                    } else {
2456
                        continue;
2457
                    }
2458
2459
                    if (isset($row['DependedOn']) && !empty($row['DependedOn'])) {
2460
                        $parentList = explode(',', $row['DependedOn']);
2461
                        foreach ($parentList as $parentId) {
2462
                            $parentId = (int) $parentId;
2463
                            echo $parentId.PHP_EOL;
2464
                            if ($graph->hasVertex($parentId)) {
2465
                                /** @var Vertex $parent */
2466
                                $parent = $graph->getVertex($parentId);
2467
                                /*$parent->setAttribute('graphviz.color', 'red');
2468
                                $parent->setAttribute('graphviz.label', $name);
2469
                                $parent->setAttribute('graphviz.shape', 'square');*/
2470
                                $parent->createEdgeTo($current);
2471
                            }
2472
                        }
2473
                    }
2474
                }
2475
            }
2476
2477
            /** @var Graph $graph */
2478
            foreach ($careerList as $id => $graph) {
2479
                if (isset($careerChamiloIdList[$id])) {
2480
                    $params = [
2481
                        'item_id' => $careerChamiloIdList[$id],
2482
                        'extra_'.$careerDiagramExtraFieldName => serialize($graph),
2483
                        'extra_'.$extraFieldName => $id,
2484
                    ];
2485
                    $extraFieldValue->saveFieldValues($params);
2486
                }
2487
            }
2488
        }
2489
    }
2490
2491
2492
    /**
2493
     * @param string $file
2494
     * @param bool $moveFile
2495
     * @param array $teacherBackup
2496
     * @param array $groupBackup
2497
     */
2498
    private function importUnsubscribeStatic(
2499
        $file,
2500
        $moveFile = false,
2501
        &$teacherBackup = array(),
2502
        &$groupBackup = array()
2503
    ) {
2504
        $data = Import::csv_reader($file);
2505
2506
        if (!empty($data)) {
2507
            $this->logger->addInfo(count($data)." records found.");
2508
            foreach ($data as $row) {
2509
                $chamiloUserName = $row['UserName'];
2510
                $chamiloCourseCode = $row['CourseCode'];
2511
                $chamiloSessionId = $row['SessionID'];
2512
2513
                $sessionInfo = api_get_session_info($chamiloSessionId);
2514
2515
                if (empty($sessionInfo)) {
2516
                    $this->logger->addError('Session does not exists: '.$chamiloSessionId);
2517
                    continue;
2518
                }
2519
2520
                $courseInfo = api_get_course_info($chamiloCourseCode);
2521
                if (empty($courseInfo)) {
2522
                    $this->logger->addError('Course does not exists: '.$courseInfo);
2523
                    continue;
2524
                }
2525
2526
                $userId = UserManager::get_user_id_from_username($chamiloUserName);
2527
2528
                if (empty($userId)) {
2529
                    $this->logger->addError('User does not exists: '.$chamiloUserName);
2530
                    continue;
2531
                }
2532
2533
                $sql = "SELECT * FROM ".Database::get_main_table(TABLE_MAIN_COURSE_USER)."
2534
                        WHERE
2535
                            user_id = ".$userId." AND
2536
                            c_id = '".$courseInfo['real_id']."'
2537
                        ";
2538
                $result = Database::query($sql);
2539
                $rows = Database::num_rows($result);
2540
                if ($rows > 0) {
2541
                    $userCourseData = Database::fetch_array($result, 'ASSOC');
2542
                    if (!empty($userCourseData)) {
2543
                        $teacherBackup[$userId][$courseInfo['code']] = $userCourseData;
2544
                    }
2545
                }
2546
2547
                $sql = "SELECT * FROM ".Database::get_course_table(TABLE_GROUP_USER)."
2548
                        WHERE
2549
                            user_id = ".$userId." AND
2550
                            c_id = '".$courseInfo['real_id']."'
2551
                        ";
2552
2553
                $result = Database::query($sql);
2554
                while ($groupData = Database::fetch_array($result, 'ASSOC')) {
2555
                    $groupBackup['user'][$userId][$courseInfo['code']][$groupData['group_id']] = $groupData;
2556
                }
2557
2558
                $sql = "SELECT * FROM ".Database::get_course_table(TABLE_GROUP_TUTOR)."
2559
                        WHERE
2560
                            user_id = ".$userId." AND
2561
                            c_id = '".$courseInfo['real_id']."'
2562
                        ";
2563
2564
                $result = Database::query($sql);
2565
                while ($groupData = Database::fetch_array($result, 'ASSOC')) {
2566
                    $groupBackup['tutor'][$userId][$courseInfo['code']][$groupData['group_id']] = $groupData;
2567
                }
2568
2569
                CourseManager::unsubscribe_user(
2570
                    $userId,
2571
                    $courseInfo['code'],
2572
                    $chamiloSessionId
2573
                );
2574
2575
                $this->logger->addError(
2576
                    "User '$chamiloUserName' was removed from session: #$chamiloSessionId, Course: ".$courseInfo['code']
2577
                );
2578
            }
2579
        }
2580
2581
        if ($moveFile) {
2582
            $this->moveFile($file);
2583
        }
2584
    }
2585
2586
    /**
2587
     *  Dump database tables
2588
     */
2589
    private function dumpDatabaseTables()
2590
    {
2591
        echo 'Dumping tables'.PHP_EOL;
2592
2593
        // User
2594
        $table = Database::get_main_table(TABLE_MAIN_USER);
2595
        $tableAdmin = Database::get_main_table(TABLE_MAIN_ADMIN);
2596
        $sql = "DELETE FROM $table
2597
                WHERE user_id not in (select user_id from $tableAdmin) and status <> ".ANONYMOUS;
2598
        Database::query($sql);
2599
        echo $sql.PHP_EOL;
2600
2601
        // Truncate tables
2602
        $truncateTables = array(
2603
            Database::get_main_table(TABLE_MAIN_COURSE),
2604
            Database::get_main_table(TABLE_MAIN_COURSE_USER),
2605
            Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE),
2606
            Database::get_main_table(TABLE_MAIN_CATEGORY),
2607
            Database::get_main_table(TABLE_MAIN_COURSE_MODULE),
2608
            Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER),
2609
            Database::get_main_table(TABLE_MAIN_SESSION),
2610
            Database::get_main_table(TABLE_MAIN_SESSION_CATEGORY),
2611
            Database::get_main_table(TABLE_MAIN_SESSION_COURSE),
2612
            Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER),
2613
            Database::get_main_table(TABLE_MAIN_SESSION_USER),
2614
            Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_SESSION),
2615
            Database::get_main_table(TABLE_MAIN_SESSION_FIELD_VALUES),
2616
            Database::get_main_table(TABLE_MAIN_COURSE_FIELD_VALUES),
2617
            Database::get_main_table(TABLE_MAIN_USER_FIELD_VALUES),
2618
            Database::get_main_table(TABLE_MAIN_USER_FIELD),
2619
            Database::get_main_table(TABLE_MAIN_USER_FIELD_OPTIONS),
2620
            Database::get_main_table(TABLE_MAIN_COURSE_FIELD),
2621
            Database::get_main_table(TABLE_MAIN_COURSE_FIELD_VALUES),
2622
            Database::get_main_table(TABLE_MAIN_SESSION_FIELD),
2623
            Database::get_main_table(TABLE_MAIN_SESSION_FIELD_VALUES),
2624
            Database::get_course_table(TABLE_AGENDA),
2625
            Database::get_course_table(TABLE_AGENDA_ATTACHMENT),
2626
            Database::get_course_table(TABLE_AGENDA_REPEAT),
2627
            Database::get_course_table(TABLE_AGENDA_REPEAT_NOT),
2628
            Database::get_main_table(TABLE_PERSONAL_AGENDA),
2629
            Database::get_main_table(TABLE_PERSONAL_AGENDA_REPEAT_NOT),
2630
            Database::get_main_table(TABLE_PERSONAL_AGENDA_REPEAT),
2631
            Database::get_main_table(TABLE_MAIN_CALENDAR_EVENT_VALUES),
2632
            Database::get_main_table(TABLE_STATISTIC_TRACK_E_LASTACCESS),
2633
            Database::get_main_table(TABLE_STATISTIC_TRACK_E_ACCESS),
2634
            Database::get_main_table(TABLE_STATISTIC_TRACK_E_LOGIN),
2635
            Database::get_main_table(TABLE_STATISTIC_TRACK_E_DOWNLOADS),
2636
            Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCICES),
2637
            Database::get_main_table(TABLE_STATISTIC_TRACK_E_ATTEMPT),
2638
            Database::get_main_table(TABLE_STATISTIC_TRACK_E_ATTEMPT_RECORDING),
2639
            Database::get_main_table(TABLE_STATISTIC_TRACK_E_DEFAULT),
2640
            Database::get_main_table(TABLE_STATISTIC_TRACK_E_UPLOADS),
2641
            Database::get_main_table(TABLE_STATISTIC_TRACK_E_HOTSPOT),
2642
            Database::get_main_table(TABLE_STATISTIC_TRACK_E_ITEM_PROPERTY),
2643
            Database::get_main_table(TABLE_MAIN_GRADEBOOK_CATEGORY),
2644
            Database::get_main_table(TABLE_MAIN_GRADEBOOK_EVALUATION),
2645
            Database::get_main_table(TABLE_MAIN_GRADEBOOK_LINKEVAL_LOG),
2646
            Database::get_main_table(TABLE_MAIN_GRADEBOOK_RESULT),
2647
            Database::get_main_table(TABLE_MAIN_GRADEBOOK_RESULT_LOG),
2648
            Database::get_main_table(TABLE_MAIN_GRADEBOOK_LINK),
2649
            Database::get_main_table(TABLE_MAIN_GRADEBOOK_SCORE_DISPLAY),
2650
            Database::get_main_table(TABLE_MAIN_GRADEBOOK_CERTIFICATE),
2651
            Database::get_course_table(TABLE_STUDENT_PUBLICATION),
2652
            Database::get_course_table(TABLE_QUIZ_QUESTION),
2653
            Database::get_course_table(TABLE_QUIZ_TEST),
2654
            Database::get_course_table(TABLE_QUIZ_ORDER),
2655
            Database::get_course_table(TABLE_QUIZ_ANSWER),
2656
            Database::get_course_table(TABLE_QUIZ_TEST_QUESTION),
2657
            Database::get_course_table(TABLE_QUIZ_QUESTION_OPTION),
2658
            Database::get_course_table(TABLE_QUIZ_QUESTION_CATEGORY),
2659
            Database::get_course_table(TABLE_QUIZ_QUESTION_REL_CATEGORY),
2660
            Database::get_course_table(TABLE_LP_MAIN),
2661
            Database::get_course_table(TABLE_LP_ITEM),
2662
            Database::get_course_table(TABLE_LP_VIEW),
2663
            Database::get_course_table(TABLE_LP_ITEM_VIEW),
2664
            Database::get_course_table(TABLE_DOCUMENT),
2665
            Database::get_course_table(TABLE_ITEM_PROPERTY),
2666
            Database::get_course_table(TABLE_TOOL_LIST),
2667
            Database::get_course_table(TABLE_TOOL_INTRO),
2668
            Database::get_course_table(TABLE_COURSE_SETTING),
2669
            Database::get_course_table(TABLE_SURVEY),
2670
            Database::get_course_table(TABLE_SURVEY_QUESTION),
2671
            Database::get_course_table(TABLE_SURVEY_QUESTION_OPTION),
2672
            Database::get_course_table(TABLE_SURVEY_INVITATION),
2673
            Database::get_course_table(TABLE_SURVEY_ANSWER),
2674
            Database::get_course_table(TABLE_SURVEY_QUESTION_GROUP),
2675
            Database::get_course_table(TABLE_SURVEY_REPORT),
2676
            Database::get_course_table(TABLE_GLOSSARY),
2677
            Database::get_course_table(TABLE_LINK),
2678
            Database::get_course_table(TABLE_LINK_CATEGORY),
2679
            Database::get_course_table(TABLE_GROUP),
2680
            Database::get_course_table(TABLE_GROUP_USER),
2681
            Database::get_course_table(TABLE_GROUP_TUTOR),
2682
            Database::get_course_table(TABLE_GROUP_CATEGORY),
2683
            Database::get_course_table(TABLE_DROPBOX_CATEGORY),
2684
            Database::get_course_table(TABLE_DROPBOX_FEEDBACK),
2685
            Database::get_course_table(TABLE_DROPBOX_POST),
2686
            Database::get_course_table(TABLE_DROPBOX_FILE),
2687
            Database::get_course_table(TABLE_DROPBOX_PERSON)
2688
        );
2689
2690
        foreach ($truncateTables as $table) {
2691
            $sql = "TRUNCATE $table";
2692
            Database::query($sql);
2693
            echo $sql.PHP_EOL;
2694
        }
2695
2696
        $table = Database::get_course_table(TABLE_ITEM_PROPERTY);
2697
        $sql = "DELETE FROM $table WHERE tool = 'calendar_event'";
2698
        Database::query($sql);
2699
        echo $sql.PHP_EOL;
2700
    }
2701
2702
    /**
2703
     * If csv file ends with '"' character then a '";' is added
2704
     * @param string $file
2705
     */
2706
    private function fixCSVFile($file)
2707
    {
2708
        /*$f = fopen($file, 'r+');
2709
        $cursor = -1;
2710
2711
        fseek($f, $cursor, SEEK_END);
2712
        $char = fgetc($f);
2713
        while ($char === "\n" || $char === "\r") {
2714
            fseek($f, $cursor--, SEEK_END);
2715
            $char = fgetc($f);
2716
        }
2717
2718
        if ($char === "\"") {
2719
            fseek($f, -1, SEEK_CUR);
2720
            fwrite($f, '";');
2721
        }*/
2722
    }
2723
2724
    /**
2725
     * @return mixed
2726
     */
2727
    public function getUpdateEmailToDummy()
2728
    {
2729
        return $this->updateEmailToDummy;
2730
    }
2731
2732
    /**
2733
     * @param mixed $updateEmailToDummy
2734
     */
2735
    public function setUpdateEmailToDummy($updateEmailToDummy)
2736
    {
2737
        $this->updateEmailToDummy = $updateEmailToDummy;
2738
    }
2739
2740
    /**
2741
     * Change emails of all users except admins
2742
     *
2743
     */
2744
    public function updateUsersEmails()
2745
    {
2746
        if ($this->getUpdateEmailToDummy() === true) {
2747
            $sql = "UPDATE user SET email = CONCAT(username,'@example.com') WHERE id NOT IN (SELECT user_id FROM admin)";
2748
            Database::query($sql);
2749
        }
2750
    }
2751
}
2752
2753
$logger = new Logger('cron');
2754
$emails = isset($_configuration['cron_notification_mails']) ? $_configuration['cron_notification_mails'] : null;
2755
2756
$minLevel = Logger::DEBUG;
2757
2758
if (!is_array($emails)) {
2759
    $emails = array($emails);
2760
}
2761
$subject = "Cron main/cron/import_csv.php ".date('Y-m-d h:i:s');
2762
$from = api_get_setting('emailAdministrator');
2763
/*
2764
if (!empty($emails)) {
2765
    foreach ($emails as $email) {
2766
        $stream = new NativeMailerHandler($email, $subject, $from, $minLevel);
2767
        $logger->pushHandler(new BufferHandler($stream, 0, $minLevel));
2768
    }
2769
}*/
2770
2771
$stream = new StreamHandler(
2772
    api_get_path(SYS_ARCHIVE_PATH).'import_csv.log',
2773
    $minLevel
2774
);
2775
$logger->pushHandler(new BufferHandler($stream, 0, $minLevel));
2776
$logger->pushHandler(new RotatingFileHandler('import_csv', 5, $minLevel));
2777
2778
$cronImportCSVConditions = isset($_configuration['cron_import_csv_conditions']) ? $_configuration['cron_import_csv_conditions'] : null;
2779
2780
echo 'See the error log here: '.api_get_path(SYS_ARCHIVE_PATH).'import_csv.log'."\n";
2781
2782
$import = new ImportCsv($logger, $cronImportCSVConditions);
2783
2784
if (isset($_configuration['default_admin_user_id_for_cron'])) {
2785
    $import->defaultAdminId = $_configuration['default_admin_user_id_for_cron'];
2786
}
2787
// @todo in production disable the dump option
2788
$dump = false;
2789
2790
if (isset($argv[1]) && $argv[1] = '--dump') {
2791
    $dump = true;
2792
}
2793
2794
if (isset($_configuration['import_csv_disable_dump']) &&
2795
    $_configuration['import_csv_disable_dump'] == true
2796
) {
2797
    $import->setDumpValues(false);
2798
} else {
2799
    $import->setDumpValues($dump);
2800
}
2801
2802
$import->setUpdateEmailToDummy(api_get_configuration_value('update_users_email_to_dummy_except_admins'));
2803
2804
// Do not moves the files to treated
2805
if (isset($_configuration['import_csv_test'])) {
2806
    $import->test = $_configuration['import_csv_test'];
2807
} else {
2808
    $import->test = true;
2809
}
2810
2811
$timeStart = microtime(true);
2812
$import->run();
2813
2814
$timeEnd = microtime(true);
2815
$executionTime = round(($timeEnd - $timeStart) / 60, 2);
2816
$logger->addInfo("Total execution Time $executionTime Min");
2817
2818
if (isset($_configuration['import_csv_fix_permissions']) &&
2819
    $_configuration['import_csv_fix_permissions'] == true
2820
) {
2821
    $command = "sudo find ".api_get_path(SYS_COURSE_PATH)." -type d -exec chmod 777 {} \; ";
2822
    echo "Executing: ".$command.PHP_EOL;
2823
    system($command);
2824
2825
    $command = "sudo find ".api_get_path(SYS_CODE_PATH)."upload/users  -type d -exec chmod 777 {} \;";
2826
    echo "Executing: ".$command.PHP_EOL;
2827
    system($command);
2828
}
2829