Completed
Push — master ( 4fc9f8...d0e06e )
by Julito
12:04
created

rrmdir()   A

Complexity

Conditions 6
Paths 5

Size

Total Lines 15
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
eloc 10
nc 5
nop 1
dl 0
loc 15
rs 9.2222
c 0
b 0
f 0
1
<?php
2
/* For licensing terms, see /license.txt */
3
4
use Chamilo\CoreBundle\Entity\AccessUrl;
5
use Chamilo\CoreBundle\Entity\BranchSync;
6
use Chamilo\CoreBundle\Entity\ExtraField;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, ExtraField. Consider defining an alias.

Let?s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let?s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
7
use Chamilo\CoreBundle\Entity\Group;
8
use Chamilo\CoreBundle\Entity\TicketCategory;
9
use Chamilo\CoreBundle\Entity\TicketPriority;
10
use Chamilo\CoreBundle\Entity\TicketProject;
11
use Chamilo\CoreBundle\Framework\Container;
12
use Chamilo\CoreBundle\ToolChain;
13
use Doctrine\ORM\EntityManager;
14
use Symfony\Component\DependencyInjection\Container as SymfonyContainer;
15
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
16
17
/**
18
 * Chamilo LMS
19
 * This file contains functions used by the install and upgrade scripts.
20
 *
21
 * Ideas for future additions:
22
 * - a function get_old_version_settings to retrieve the config file settings
23
 *   of older versions before upgrading.
24
 */
25
26
define('SYSTEM_CONFIG_FILENAME', 'configuration.dist.php');
27
define('USERNAME_MAX_LENGTH', 100);
28
29
/**
30
 * This function detects whether the system has been already installed.
31
 * It should be used for prevention from second running the installation
32
 * script and as a result - destroying a production system.
33
 *
34
 * @return bool The detected result;
35
 *
36
 * @author Ivan Tcholakov, 2010;
37
 */
38
function isAlreadyInstalledSystem()
39
{
40
    global $new_version, $_configuration;
41
42
    if (empty($new_version)) {
43
        return true; // Must be initialized.
44
    }
45
46
    $current_config_file = api_get_path(CONFIGURATION_PATH).'configuration.php';
47
    if (!file_exists($current_config_file)) {
48
        return false; // Configuration file does not exist, install the system.
49
    }
50
    require $current_config_file;
51
52
    $current_version = null;
53
    if (isset($_configuration['system_version'])) {
54
        $current_version = trim($_configuration['system_version']);
55
    }
56
57
    // If the current version is old, upgrading is assumed, the installer goes ahead.
58
    return empty($current_version) ? false : version_compare($current_version, $new_version, '>=');
59
}
60
61
/**
62
 * This function checks if a php extension exists or not and returns an HTML status string.
63
 *
64
 * @param string $extensionName Name of the PHP extension to be checked
65
 * @param string $returnSuccess Text to show when extension is available (defaults to 'Yes')
66
 * @param string $returnFailure Text to show when extension is available (defaults to 'No')
67
 * @param bool   $optional      Whether this extension is optional (then show unavailable text in orange rather than red)
68
 * @param string $enabledTerm   If this string is not null, then use to check if the corresponding parameter is = 1.
69
 *                              If not, mention it's present but not enabled. For example, for opcache, this should be 'opcache.enable'
70
 *
71
 * @return string HTML string reporting the status of this extension. Language-aware.
72
 *
73
 * @author  Christophe Gesch??
74
 * @author  Patrick Cool <[email protected]>, Ghent University
75
 * @author  Yannick Warnier <[email protected]>
76
 */
77
function checkExtension(
78
    $extensionName,
79
    $returnSuccess = 'Yes',
80
    $returnFailure = 'No',
81
    $optional = false,
82
    $enabledTerm = ''
83
) {
84
    if (extension_loaded($extensionName)) {
85
        if (!empty($enabledTerm)) {
86
            $isEnabled = ini_get($enabledTerm);
87
            if ('1' == $isEnabled) {
88
                return Display::label($returnSuccess, 'success');
89
            } else {
90
                if ($optional) {
91
                    return Display::label(get_lang('Extension installed but not enabled'), 'warning');
92
                }
93
94
                return Display::label(get_lang('Extension installed but not enabled'), 'important');
95
            }
96
        }
97
        return Display::label($returnSuccess, 'success');
98
    } else {
99
        if ($optional) {
100
            return Display::label($returnFailure, 'warning');
101
        }
102
103
        return Display::label($returnFailure, 'important');
104
    }
105
}
106
107
/**
108
 * This function checks whether a php setting matches the recommended value.
109
 *
110
 * @param string $phpSetting       A PHP setting to check
111
 * @param string $recommendedValue A recommended value to show on screen
112
 * @param mixed  $returnSuccess    What to show on success
113
 * @param mixed  $returnFailure    What to show on failure
114
 *
115
 * @return string A label to show
116
 *
117
 * @author Patrick Cool <[email protected]>, Ghent University
118
 */
119
function checkPhpSetting(
120
    $phpSetting,
121
    $recommendedValue,
122
    $returnSuccess = false,
123
    $returnFailure = false
124
) {
125
    $currentPhpValue = getPhpSetting($phpSetting);
126
    if ($currentPhpValue == $recommendedValue) {
127
        return Display::label($currentPhpValue.' '.$returnSuccess, 'success');
0 ignored issues
show
Bug introduced by
Are you sure $returnSuccess of type false|mixed can be used in concatenation? ( Ignorable by Annotation )

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

127
        return Display::label($currentPhpValue.' './** @scrutinizer ignore-type */ $returnSuccess, 'success');
Loading history...
128
    }
129
130
    return Display::label($currentPhpValue.' '.$returnSuccess, 'important');
131
}
132
133
134
/**
135
 * This function return the value of a php.ini setting if not "" or if exists,
136
 * otherwise return false.
137
 *
138
 * @param string $phpSetting The name of a PHP setting
139
 *
140
 * @return mixed The value of the setting, or false if not found
141
 */
142
function checkPhpSettingExists($phpSetting)
143
{
144
    if ('' != ini_get($phpSetting)) {
145
        return ini_get($phpSetting);
146
    }
147
148
    return false;
149
}
150
151
/**
152
 * Returns a textual value ('ON' or 'OFF') based on a requester 2-state ini- configuration setting.
153
 *
154
 * @param string $val a php ini value
155
 *
156
 * @return bool ON or OFF
157
 *
158
 * @author Joomla <http://www.joomla.org>
159
 */
160
function getPhpSetting($val)
161
{
162
    $value = ini_get($val);
163
    switch ($val) {
164
        case 'display_errors':
165
            global $originalDisplayErrors;
166
            $value = $originalDisplayErrors;
167
            break;
168
    }
169
170
    return '1' == $value ? 'ON' : 'OFF';
171
}
172
173
/**
174
 * This function returns a string "true" or "false" according to the passed parameter.
175
 *
176
 * @param int $var The variable to present as text
177
 *
178
 * @return string the string "true" or "false"
179
 *
180
 * @author Christophe Gesch??
181
 */
182
function trueFalse($var)
183
{
184
    return $var ? 'true' : 'false';
185
}
186
187
/**
188
 * Removes memory and time limits as much as possible.
189
 */
190
function remove_memory_and_time_limits()
191
{
192
    if (function_exists('ini_set')) {
193
        ini_set('memory_limit', -1);
194
        ini_set('max_execution_time', 0);
195
        error_log('Update-db script: memory_limit set to -1', 0);
196
        error_log('Update-db script: max_execution_time 0', 0);
197
    } else {
198
        error_log('Update-db script: could not change memory and time limits', 0);
199
    }
200
}
201
202
/**
203
 * Detects browser's language.
204
 *
205
 * @return string Returns a language identificator, i.e. 'english', 'spanish', ...
206
 *
207
 * @author Ivan Tcholakov, 2010
208
 */
209
function detect_browser_language()
210
{
211
    static $language_index = [
212
        'ar' => 'arabic',
213
        'ast' => 'asturian',
214
        'bg' => 'bulgarian',
215
        'bs' => 'bosnian',
216
        'ca' => 'catalan',
217
        'zh' => 'simpl_chinese',
218
        'zh-tw' => 'trad_chinese',
219
        'cs' => 'czech',
220
        'da' => 'danish',
221
        'prs' => 'dari',
222
        'de' => 'german',
223
        'el' => 'greek',
224
        'en' => 'english',
225
        'es' => 'spanish',
226
        'eo' => 'esperanto',
227
        'eu' => 'basque',
228
        'fa' => 'persian',
229
        'fr' => 'french',
230
        'fur' => 'friulian',
231
        'gl' => 'galician',
232
        'ka' => 'georgian',
233
        'hr' => 'croatian',
234
        'he' => 'hebrew',
235
        'hi' => 'hindi',
236
        'id' => 'indonesian',
237
        'it' => 'italian',
238
        'ko' => 'korean',
239
        'lv' => 'latvian',
240
        'lt' => 'lithuanian',
241
        'mk' => 'macedonian',
242
        'hu' => 'hungarian',
243
        'ms' => 'malay',
244
        'nl' => 'dutch',
245
        'ja' => 'japanese',
246
        'no' => 'norwegian',
247
        'oc' => 'occitan',
248
        'ps' => 'pashto',
249
        'pl' => 'polish',
250
        'pt' => 'portuguese',
251
        'pt-br' => 'brazilian',
252
        'ro' => 'romanian',
253
        'qu' => 'quechua_cusco',
254
        'ru' => 'russian',
255
        'sk' => 'slovak',
256
        'sl' => 'slovenian',
257
        'sr' => 'serbian',
258
        'fi' => 'finnish',
259
        'sv' => 'swedish',
260
        'th' => 'thai',
261
        'tr' => 'turkish',
262
        'uk' => 'ukrainian',
263
        'vi' => 'vietnamese',
264
        'sw' => 'swahili',
265
        'yo' => 'yoruba',
266
    ];
267
268
    $system_available_languages = get_language_folder_list();
269
    $accept_languages = strtolower(str_replace('_', '-', $_SERVER['HTTP_ACCEPT_LANGUAGE']));
270
    foreach ($language_index as $code => $language) {
271
        if (0 === strpos($accept_languages, $code)) {
272
            if (!empty($system_available_languages[$language])) {
273
                return $language;
274
            }
275
        }
276
    }
277
278
    $user_agent = strtolower(str_replace('_', '-', $_SERVER['HTTP_USER_AGENT']));
279
    foreach ($language_index as $code => $language) {
280
        if (@preg_match("/[\[\( ]{$code}[;,_\-\)]/", $user_agent)) {
281
            if (!empty($system_available_languages[$language])) {
282
                return $language;
283
            }
284
        }
285
    }
286
287
    return 'english';
288
}
289
290
/*      FILESYSTEM RELATED FUNCTIONS */
291
292
/**
293
 * This function checks if the given folder is writable.
294
 *
295
 * @param string $folder     Full path to a folder
296
 * @param bool   $suggestion Whether to show a suggestion or not
297
 *
298
 * @return string
299
 */
300
function check_writable($folder, $suggestion = false)
301
{
302
    if (is_writable($folder)) {
303
        return Display::label(get_lang('Writable'), 'success');
304
    } else {
305
        if ($suggestion) {
306
            return Display::label(get_lang('Not writable'), 'info');
307
        } else {
308
            return Display::label(get_lang('Not writable'), 'important');
309
        }
310
    }
311
}
312
313
/**
314
 * This function checks if the given folder is readable.
315
 *
316
 * @param string $folder     Full path to a folder
317
 * @param bool   $suggestion Whether to show a suggestion or not
318
 *
319
 * @return string
320
 */
321
function checkReadable($folder, $suggestion = false)
322
{
323
    if (is_readable($folder)) {
324
        return Display::label(get_lang('Readable'), 'success');
325
    } else {
326
        if ($suggestion) {
327
            return Display::label(get_lang('Not readable'), 'info');
328
        } else {
329
            return Display::label(get_lang('Not readable'), 'important');
330
        }
331
    }
332
}
333
334
/**
335
 * This function is similar to the core file() function, except that it
336
 * works with line endings in Windows (which is not the case of file()).
337
 *
338
 * @param string $filename
339
 *
340
 * @return array The lines of the file returned as an array
341
 */
342
function file_to_array($filename)
343
{
344
    if (!is_readable($filename) || is_dir($filename)) {
345
        return [];
346
    }
347
    $fp = fopen($filename, 'rb');
348
    $buffer = fread($fp, filesize($filename));
349
    fclose($fp);
350
351
    return explode('<br />', nl2br($buffer));
352
}
353
354
/**
355
 * We assume this function is called from install scripts that reside inside the install folder.
356
 */
357
function set_file_folder_permissions()
358
{
359
    @chmod('.', 0755); //set permissions on install dir
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for chmod(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

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

359
    /** @scrutinizer ignore-unhandled */ @chmod('.', 0755); //set permissions on install dir

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

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

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
360
    @chmod('..', 0755); //set permissions on parent dir of install dir
361
}
362
363
/**
364
 * Write the main system config file.
365
 *
366
 * @param string $path Path to the config file
367
 */
368
function write_system_config_file($path)
369
{
370
    global $dbHostForm;
371
    global $dbPortForm;
372
    global $dbUsernameForm;
373
    global $dbPassForm;
374
    global $dbNameForm;
375
    global $urlForm;
376
    global $pathForm;
377
    global $urlAppendPath;
378
    global $languageForm;
379
    global $encryptPassForm;
380
    global $session_lifetime;
381
    global $new_version;
382
    global $new_version_stable;
383
384
    $content = file_get_contents(__DIR__.'/'.SYSTEM_CONFIG_FILENAME);
385
386
    $config['{DATE_GENERATED}'] = date('r');
0 ignored issues
show
Comprehensibility Best Practice introduced by
$config was never initialized. Although not strictly required by PHP, it is generally a good practice to add $config = array(); before regardless.
Loading history...
387
    $config['{DATABASE_HOST}'] = $dbHostForm;
388
    $config['{DATABASE_PORT}'] = $dbPortForm;
389
    $config['{DATABASE_USER}'] = $dbUsernameForm;
390
    $config['{DATABASE_PASSWORD}'] = $dbPassForm;
391
    $config['{DATABASE_MAIN}'] = $dbNameForm;
392
393
    $config['{URL_APPEND_PATH}'] = $urlAppendPath;
394
    $config['{PLATFORM_LANGUAGE}'] = $languageForm;
395
    $config['{SECURITY_KEY}'] = md5(uniqid(rand().time()));
396
    $config['{ENCRYPT_PASSWORD}'] = $encryptPassForm;
397
398
    $config['SESSION_LIFETIME'] = $session_lifetime;
399
    $config['{NEW_VERSION}'] = $new_version;
400
    $config['NEW_VERSION_STABLE'] = trueFalse($new_version_stable);
401
402
    foreach ($config as $key => $value) {
403
        $content = str_replace($key, $value, $content);
404
    }
405
    $fp = @fopen($path, 'w');
406
407
    if (!$fp) {
0 ignored issues
show
introduced by
$fp is of type false|resource, thus it always evaluated to false.
Loading history...
408
        echo '<strong>
409
                <font color="red">Your script doesn\'t have write access to the config directory</font></strong><br />
410
                <em>('.str_replace('\\', '/', realpath($path)).')</em><br /><br />
411
                You probably do not have write access on Chamilo root directory,
412
                i.e. you should <em>CHMOD 777</em> or <em>755</em> or <em>775</em>.<br /><br />
413
                Your problems can be related on two possible causes:<br />
414
                <ul>
415
                  <li>Permission problems.<br />Try initially with <em>chmod -R 777</em> and increase restrictions gradually.</li>
416
                  <li>PHP is running in <a href="http://www.php.net/manual/en/features.safe-mode.php" target="_blank">Safe-Mode</a>.
417
                  If possible, try to switch it off.</li>
418
                </ul>
419
                <a href="http://forum.chamilo.org/" target="_blank">Read about this problem in Support Forum</a><br /><br />
420
                Please go back to step 5.
421
                <p><input type="submit" name="step5" value="&lt; Back" /></p>
422
                </td></tr></table></form></body></html>';
423
        exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

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

Loading history...
424
    }
425
426
    fwrite($fp, $content);
427
    fclose($fp);
428
}
429
430
/**
431
 * Returns a list of language directories.
432
 */
433
function get_language_folder_list()
434
{
435
    return [
436
        'ar' => 'arabic',
437
        'ast' => 'asturian',
438
        'bg' => 'bulgarian',
439
        'bs' => 'bosnian',
440
        'ca' => 'catalan',
441
        'zh' => 'simpl_chinese',
442
        'zh-tw' => 'trad_chinese',
443
        'cs' => 'czech',
444
        'da' => 'danish',
445
        'prs' => 'dari',
446
        'de' => 'german',
447
        'el' => 'greek',
448
        'en' => 'english',
449
        'es' => 'spanish',
450
        'eo' => 'esperanto',
451
        'eu' => 'basque',
452
        'fa' => 'persian',
453
        'fr' => 'french',
454
        'fur' => 'friulian',
455
        'gl' => 'galician',
456
        'ka' => 'georgian',
457
        'hr' => 'croatian',
458
        'he' => 'hebrew',
459
        'hi' => 'hindi',
460
        'id' => 'indonesian',
461
        'it' => 'italian',
462
        'ko' => 'korean',
463
        'lv' => 'latvian',
464
        'lt' => 'lithuanian',
465
        'mk' => 'macedonian',
466
        'hu' => 'hungarian',
467
        'ms' => 'malay',
468
        'nl' => 'dutch',
469
        'ja' => 'japanese',
470
        'no' => 'norwegian',
471
        'oc' => 'occitan',
472
        'ps' => 'pashto',
473
        'pl' => 'polish',
474
        'pt' => 'portuguese',
475
        'pt-br' => 'brazilian',
476
        'ro' => 'romanian',
477
        'qu' => 'quechua_cusco',
478
        'ru' => 'russian',
479
        'sk' => 'slovak',
480
        'sl' => 'slovenian',
481
        'sr' => 'serbian',
482
        'fi' => 'finnish',
483
        'sv' => 'swedish',
484
        'th' => 'thai',
485
        'tr' => 'turkish',
486
        'uk' => 'ukrainian',
487
        'vi' => 'vietnamese',
488
        'sw' => 'swahili',
489
        'yo' => 'yoruba',
490
    ];
491
}
492
493
/**
494
 * This function returns the value of a parameter from the configuration file.
495
 *
496
 * WARNING - this function relies heavily on global variables $updateFromConfigFile
497
 * and $configFile, and also changes these globals. This can be rewritten.
498
 *
499
 * @param string $param      the parameter of which the value is returned
500
 * @param string $updatePath If we want to give the path rather than take it from POST
501
 *
502
 * @return string the value of the parameter
503
 *
504
 * @author Olivier Brouckaert
505
 * @author Reworked by Ivan Tcholakov, 2010
506
 */
507
function get_config_param($param, $updatePath = '')
508
{
509
    global $configFile, $updateFromConfigFile;
510
511
    // Look if we already have the queried parameter.
512
    if (is_array($configFile) && isset($configFile[$param])) {
513
        return $configFile[$param];
514
    }
515
    if (empty($updatePath) && !empty($_POST['updatePath'])) {
516
        $updatePath = $_POST['updatePath'];
517
    }
518
519
    if (empty($updatePath)) {
520
        $updatePath = api_get_path(SYS_PATH);
521
    }
522
    $updatePath = api_add_trailing_slash(str_replace('\\', '/', realpath($updatePath)));
523
    $updateFromInstalledVersionFile = '';
524
525
    if (empty($updateFromConfigFile)) {
526
        // If update from previous install was requested,
527
        // try to recover config file from Chamilo 1.9.x
528
        if (file_exists($updatePath.'main/inc/conf/configuration.php')) {
529
            $updateFromConfigFile = 'main/inc/conf/configuration.php';
530
        } elseif (file_exists($updatePath.'app/config/configuration.php')) {
531
            $updateFromConfigFile = 'app/config/configuration.php';
532
        } elseif (file_exists($updatePath.'config/configuration.php')) {
533
            $updateFromConfigFile = 'config/configuration.php';
534
        } else {
535
            // Give up recovering.
536
            //error_log('Chamilo Notice: Could not find previous config file at '.$updatePath.'main/inc/conf/configuration.php nor at '.$updatePath.'claroline/inc/conf/claro_main.conf.php in get_config_param(). Will start new config (in '.__FILE__.', line '.__LINE__.')', 0);
537
            return null;
538
        }
539
    }
540
541
    if (file_exists($updatePath.$updateFromConfigFile) &&
542
        !is_dir($updatePath.$updateFromConfigFile)
543
    ) {
544
        require $updatePath.$updateFromConfigFile;
545
        $config = new Laminas\Config\Config($_configuration);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $_configuration does not exist. Did you maybe mean $config?
Loading history...
546
547
        return $config->get($param);
548
    }
549
550
    error_log('Config array could not be found in get_config_param()', 0);
551
552
    return null;
553
}
554
555
/*      DATABASE RELATED FUNCTIONS */
556
557
/**
558
 * Gets a configuration parameter from the database. Returns returns null on failure.
559
 *
560
 * @param string $param Name of param we want
561
 *
562
 * @return mixed The parameter value or null if not found
563
 */
564
function get_config_param_from_db($param = '')
565
{
566
    $param = Database::escape_string($param);
567
568
    if (false !== ($res = Database::query("SELECT * FROM settings_current WHERE variable = '$param'"))) {
569
        if (Database::num_rows($res) > 0) {
570
            $row = Database::fetch_array($res);
571
572
            return $row['selected_value'];
573
        }
574
    }
575
576
    return null;
577
}
578
579
/**
580
 * Connect to the database and returns the entity manager.
581
 *
582
 * @param string $dbHostForm     DB host
583
 * @param string $dbUsernameForm DB username
584
 * @param string $dbPassForm     DB password
585
 * @param string $dbNameForm     DB name
586
 * @param int    $dbPortForm     DB port
587
 *
588
 * @return \Database
589
 */
590
function connectToDatabase(
591
    $dbHostForm,
592
    $dbUsernameForm,
593
    $dbPassForm,
594
    $dbNameForm,
595
    $dbPortForm = 3306
596
) {
597
    $dbParams = [
598
        'driver' => 'pdo_mysql',
599
        'host' => $dbHostForm,
600
        'port' => $dbPortForm,
601
        'user' => $dbUsernameForm,
602
        'password' => $dbPassForm,
603
        'dbname' => $dbNameForm,
604
    ];
605
606
    $database = new \Database();
607
    $database->connect($dbParams);
608
609
    return $database;
610
}
611
612
/*      DISPLAY FUNCTIONS */
613
614
/**
615
 * This function prints class=active_step $current_step=$param.
616
 *
617
 * @param int $param A step in the installer process
618
 *
619
 * @author Patrick Cool <[email protected]>, Ghent University
620
 */
621
function step_active($param)
622
{
623
    global $current_step;
624
    if ($param == $current_step) {
625
        echo 'active';
626
    }
627
}
628
629
/**
630
 * This function displays the Step X of Y -.
631
 *
632
 * @return string String that says 'Step X of Y' with the right values
633
 */
634
function display_step_sequence()
635
{
636
    global $current_step;
637
638
    return get_lang('Step'.$current_step).' &ndash; ';
639
}
640
641
/**
642
 * Displays a drop down box for selection the preferred language.
643
 */
644
function display_language_selection_box(
645
    $name = 'language_list',
646
    $default_language = 'english'
647
) {
648
    // Reading language list.
649
    $language_list = get_language_folder_list();
650
651
    // Sanity checks due to the possibility for customizations.
652
    if (!is_array($language_list) || empty($language_list)) {
653
        $language_list = ['en' => 'English'];
654
    }
655
656
    // Sorting again, if it is necessary.
657
    //asort($language_list);
658
659
    // More sanity checks.
660
    if (!array_key_exists($default_language, $language_list)) {
661
        if (array_key_exists('en', $language_list)) {
662
            $default_language = 'en';
663
        } else {
664
            $language_keys = array_keys($language_list);
665
            $default_language = $language_keys[0];
666
        }
667
    }
668
669
    // Displaying the box.
670
671
    $html = Display::select(
672
        'language_list',
673
        $language_list,
674
        $default_language,
675
        ['class' => 'selectpicker'],
676
        false
677
    );
678
679
    return $html;
680
}
681
682
/**
683
 * This function displays a language dropdown box so that the installatioin
684
 * can be done in the language of the user.
685
 */
686
function display_language_selection()
687
{
688
    ?>
689
        <div class="install-icon">
690
            <img width="150px;" src="chamilo-install.svg"/>
691
        </div>
692
        <h2 class="install-title">
693
            <?php echo display_step_sequence(); ?>
694
            <?php echo get_lang('Installation Language'); ?>
695
        </h2>
696
        <label for="language_list"><?php echo get_lang('Please select installation language'); ?></label>
697
        <div class="form-group">
698
            <?php echo display_language_selection_box('language_list', api_get_interface_language()); ?>
699
        </div>
700
        <button type="submit" name="step1" class="btn btn-success" value="<?php echo get_lang('Next'); ?>">
701
            <em class="fa fa-forward"> </em>
702
            <?php echo get_lang('Next'); ?>
703
        </button>
704
        <input type="hidden" name="is_executable" id="is_executable" value="-" />
705
        <div class="RequirementHeading">
706
            <?php echo get_lang('Cannot find your language in the list? Contact us at [email protected] to contribute as a translator.'); ?>
707
        </div>
708
<?php
709
}
710
711
/**
712
 * This function displays the requirements for installing Chamilo.
713
 *
714
 * @param string $installType
715
 * @param bool   $badUpdatePath
716
 * @param bool   $badUpdatePath
717
 * @param string $updatePath            The updatePath given (if given)
718
 * @param array  $update_from_version_8 The different subversions from version 1.9
719
 *
720
 * @author unknow
721
 * @author Patrick Cool <[email protected]>, Ghent University
722
 */
723
function display_requirements(
724
    $installType,
725
    $badUpdatePath,
726
    $updatePath = '',
727
    $update_from_version_8 = []
728
) {
729
    global $_setting, $originalMemoryLimit;
730
731
    $dir = api_get_path(SYS_ARCHIVE_PATH).'temp/';
732
    $fileToCreate = 'test';
733
734
    $perms_dir = [0777, 0755, 0775, 0770, 0750, 0700];
735
    $perms_fil = [0666, 0644, 0664, 0660, 0640, 0600];
736
    $course_test_was_created = false;
737
    $dir_perm_verified = 0777;
738
739
    foreach ($perms_dir as $perm) {
740
        $r = @mkdir($dir, $perm);
741
        if (true === $r) {
742
            $dir_perm_verified = $perm;
743
            $course_test_was_created = true;
744
            break;
745
        }
746
    }
747
748
    $fil_perm_verified = 0666;
749
    $file_course_test_was_created = false;
750
    if (is_dir($dir)) {
751
        foreach ($perms_fil as $perm) {
752
            if (true == $file_course_test_was_created) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
753
                break;
754
            }
755
            $r = @touch($dir.'/'.$fileToCreate, $perm);
756
            if (true === $r) {
757
                $fil_perm_verified = $perm;
758
                $file_course_test_was_created = true;
759
            }
760
        }
761
    }
762
763
    @unlink($dir.'/'.$fileToCreate);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for unlink(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

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

763
    /** @scrutinizer ignore-unhandled */ @unlink($dir.'/'.$fileToCreate);

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

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

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
764
    @rmdir($dir);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for rmdir(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

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

764
    /** @scrutinizer ignore-unhandled */ @rmdir($dir);

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

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

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
765
766
    echo '<h2 class="install-title">'.display_step_sequence().get_lang('Requirements')."</h2>";
767
    echo '<div class="RequirementText">';
768
    echo '<strong>'.get_lang('Please read the following requirements thoroughly.').'</strong><br />';
769
    echo get_lang('For more details').' <a href="../../documentation/installation_guide.html" target="_blank">'.get_lang('Read the installation guide').'</a>.<br />'."\n";
770
771
    if ('update' == $installType) {
772
        echo get_lang('If you plan to upgrade from an older version of Chamilo, you might want to <a href="../../documentation/changelog.html" target="_blank">have a look at the changelog</a> to know what\'s new and what has been changed').'<br />';
773
    }
774
    echo '</div>';
775
776
    //  SERVER REQUIREMENTS
777
    echo '<h4 class="install-subtitle">'.get_lang('Server requirements').'</h4>';
778
    $timezone = checkPhpSettingExists('date.timezone');
779
    if (!$timezone) {
780
        echo "<div class='alert alert-warning'>
781
            <i class=\"fa fa-exclamation-triangle\" aria-hidden=\"true\"></i>&nbsp;".
782
            get_lang('We have detected that your PHP installation does not define the date.timezone setting. This is a requirement of Chamilo. Please make sure it is configured by checking your php.ini configuration, otherwise you will run into problems. We warned you!')."</div>";
783
    }
784
785
    echo '<div class="install-requirement">'.get_lang('Server requirementsInfo').'</div>';
786
    echo '<div class="table-responsive">';
787
    echo '<table class="table table-bordered">
788
            <tr>
789
                <td class="requirements-item">'.get_lang('PHP version').' >= '.REQUIRED_PHP_VERSION.'</td>
790
                <td class="requirements-value">';
791
    if (version_compare(phpversion(), REQUIRED_PHP_VERSION, '>=') > 1) {
792
        echo '<strong class="text-danger">'.get_lang('PHP versionError').'</strong>';
793
    } else {
794
        echo '<strong class="text-success">'.get_lang('PHP versionOK').' '.phpversion().'</strong>';
795
    }
796
    echo '</td>
797
            </tr>
798
            <tr>
799
                <td class="requirements-item"><a href="http://php.net/manual/en/book.session.php" target="_blank">Session</a> '.get_lang('Support').'</td>
800
                <td class="requirements-value">'.checkExtension('session', get_lang('Yes'), get_lang('Sessions extension not available')).'</td>
801
            </tr>
802
            <tr>
803
                <td class="requirements-item"><a href="http://php.net/manual/en/book.mysql.php" target="_blank">pdo_mysql</a> '.get_lang('Support').'</td>
804
                <td class="requirements-value">'.checkExtension('pdo_mysql', get_lang('Yes'), get_lang('MySQL extension not available')).'</td>
805
            </tr>
806
            <tr>
807
                <td class="requirements-item"><a href="http://php.net/manual/en/book.zip.php" target="_blank">Zip</a> '.get_lang('Support').'</td>
808
                <td class="requirements-value">'.checkExtension('zip', get_lang('Yes'), get_lang('Extension not available')).'</td>
809
            </tr>
810
            <tr>
811
                <td class="requirements-item"><a href="http://php.net/manual/en/book.zlib.php" target="_blank">Zlib</a> '.get_lang('Support').'</td>
812
                <td class="requirements-value">'.checkExtension('zlib', get_lang('Yes'), get_lang('Zlib extension not available')).'</td>
813
            </tr>
814
            <tr>
815
                <td class="requirements-item"><a href="http://php.net/manual/en/book.pcre.php" target="_blank">Perl-compatible regular expressions</a> '.get_lang('Support').'</td>
816
                <td class="requirements-value">'.checkExtension('pcre', get_lang('Yes'), get_lang('PCRE extension not available')).'</td>
817
            </tr>
818
            <tr>
819
                <td class="requirements-item"><a href="http://php.net/manual/en/book.xml.php" target="_blank">XML</a> '.get_lang('Support').'</td>
820
                <td class="requirements-value">'.checkExtension('xml', get_lang('Yes'), get_lang('No')).'</td>
821
            </tr>
822
            <tr>
823
                <td class="requirements-item"><a href="http://php.net/manual/en/book.intl.php" target="_blank">Internationalization</a> '.get_lang('Support').'</td>
824
                <td class="requirements-value">'.checkExtension('intl', get_lang('Yes'), get_lang('No')).'</td>
825
            </tr>
826
               <tr>
827
                <td class="requirements-item"><a href="http://php.net/manual/en/book.json.php" target="_blank">JSON</a> '.get_lang('Support').'</td>
828
                <td class="requirements-value">'.checkExtension('json', get_lang('Yes'), get_lang('No')).'</td>
829
            </tr>
830
             <tr>
831
                <td class="requirements-item"><a href="http://php.net/manual/en/book.image.php" target="_blank">GD</a> '.get_lang('Support').'</td>
832
                <td class="requirements-value">'.checkExtension('gd', get_lang('Yes'), get_lang('GD Extension not available')).'</td>
833
            </tr>
834
            <tr>
835
                <td class="requirements-item"><a href="http://php.net/manual/en/book.curl.php" target="_blank">cURL</a>'.get_lang('Support').'</td>
836
                <td class="requirements-value">'.checkExtension('curl', get_lang('Yes'), get_lang('No')).'</td>
837
            </tr>
838
            <tr>
839
                <td class="requirements-item"><a href="http://php.net/manual/en/book.mbstring.php" target="_blank">Multibyte string</a> '.get_lang('Support').'</td>
840
                <td class="requirements-value">'.checkExtension('mbstring', get_lang('Yes'), get_lang('MBString extension not available'), true).'</td>
841
            </tr>
842
           <tr>
843
                <td class="requirements-item"><a href="http://php.net/manual/en/book.exif.php" target="_blank">Exif</a> '.get_lang('Support').'</td>
844
                <td class="requirements-value">'.checkExtension('exif', get_lang('Yes'), get_lang('Exif extension not available'), true).'</td>
845
            </tr>
846
            <tr>
847
                <td class="requirements-item"><a href="http://php.net/opcache" target="_blank">Zend OpCache</a> '.get_lang('Support').' ('.get_lang('Optional').')</td>
848
                <td class="requirements-value">'.checkExtension('Zend OPcache', get_lang('Yes'), get_lang('No'), true, 'opcache.enable').'</td>
849
            </tr>
850
            <tr>
851
                <td class="requirements-item"><a href="http://php.net/apcu" target="_blank">APCu</a> '.get_lang('Support').' ('.get_lang('Optional').')</td>
852
                <td class="requirements-value">'.checkExtension('apcu', get_lang('Yes'), get_lang('No'), true, 'apc.enabled').'</td>
853
            </tr>
854
            <tr>
855
                <td class="requirements-item"><a href="http://php.net/manual/en/book.iconv.php" target="_blank">Iconv</a> '.get_lang('Support').' ('.get_lang('Optional').')</td>
856
                <td class="requirements-value">'.checkExtension('iconv', get_lang('Yes'), get_lang('No'), true).'</td>
857
            </tr>
858
            <tr>
859
                <td class="requirements-item"><a href="http://php.net/manual/en/book.ldap.php" target="_blank">LDAP</a> '.get_lang('Support').' ('.get_lang('Optional').')</td>
860
                <td class="requirements-value">'.checkExtension('ldap', get_lang('Yes'), get_lang('LDAP Extension not available'), true).'</td>
861
            </tr>
862
            <tr>
863
                <td class="requirements-item"><a href="http://xapian.org/" target="_blank">Xapian</a> '.get_lang('Support').' ('.get_lang('Optional').')</td>
864
                <td class="requirements-value">'.checkExtension('xapian', get_lang('Yes'), get_lang('No'), true).'</td>
865
            </tr>
866
        </table>';
867
    echo '</div>';
868
869
    // RECOMMENDED SETTINGS
870
    // Note: these are the settings for Joomla, does this also apply for Chamilo?
871
    // Note: also add upload_max_filesize here so that large uploads are possible
872
    echo '<h4 class="install-subtitle">'.get_lang('(recommended) settings').'</h4>';
873
    echo '<div class="install-requirement">'.get_lang('(recommended) settingsInfo').'</div>';
874
    echo '<div class="table-responsive">';
875
    echo '<table class="table table-bordered">
876
            <tr>
877
                <th>'.get_lang('Setting').'</th>
878
                <th>'.get_lang('(recommended)').'</th>
879
                <th>'.get_lang('Currently').'</th>
880
            </tr>
881
882
            <tr>
883
                <td class="requirements-item"><a href="http://php.net/manual/ref.errorfunc.php#ini.display-errors">Display Errors</a></td>
884
                <td class="requirements-recommended">'.Display::label('OFF', 'success').'</td>
885
                <td class="requirements-value">'.checkPhpSetting('display_errors', 'OFF').'</td>
886
            </tr>
887
            <tr>
888
                <td class="requirements-item"><a href="http://php.net/manual/ini.core.php#ini.file-uploads">File Uploads</a></td>
889
                <td class="requirements-recommended">'.Display::label('ON', 'success').'</td>
890
                <td class="requirements-value">'.checkPhpSetting('file_uploads', 'ON').'</td>
891
            </tr>
892
            <tr>
893
                <td class="requirements-item"><a href="http://php.net/manual/ref.session.php#ini.session.auto-start">Session auto start</a></td>
894
                <td class="requirements-recommended">'.Display::label('OFF', 'success').'</td>
895
                <td class="requirements-value">'.checkPhpSetting('session.auto_start', 'OFF').'</td>
896
            </tr>
897
            <tr>
898
                <td class="requirements-item"><a href="http://php.net/manual/ini.core.php#ini.short-open-tag">Short Open Tag</a></td>
899
                <td class="requirements-recommended">'.Display::label('OFF', 'success').'</td>
900
                <td class="requirements-value">'.checkPhpSetting('short_open_tag', 'OFF').'</td>
901
            </tr>
902
            <tr>
903
                <td class="requirements-item"><a href="http://www.php.net/manual/en/session.configuration.php#ini.session.cookie-httponly">Cookie HTTP Only</a></td>
904
                <td class="requirements-recommended">'.Display::label('ON', 'success').'</td>
905
                <td class="requirements-value">'.checkPhpSetting('session.cookie_httponly', 'ON').'</td>
906
            </tr>
907
            <tr>
908
                <td class="requirements-item"><a href="http://php.net/manual/ini.core.php#ini.upload-max-filesize">Maximum upload file size</a></td>
909
                <td class="requirements-recommended">'.Display::label('>= '.REQUIRED_MIN_UPLOAD_MAX_FILESIZE.'M', 'success').'</td>
910
                <td class="requirements-value">'.compare_setting_values(ini_get('upload_max_filesize'), REQUIRED_MIN_UPLOAD_MAX_FILESIZE).'</td>
911
            </tr>
912
            <tr>
913
                <td class="requirements-item"><a href="http://php.net/manual/ini.core.php#ini.post-max-size">Maximum post size</a></td>
914
                <td class="requirements-recommended">'.Display::label('>= '.REQUIRED_MIN_POST_MAX_SIZE.'M', 'success').'</td>
915
                <td class="requirements-value">'.compare_setting_values(ini_get('post_max_size'), REQUIRED_MIN_POST_MAX_SIZE).'</td>
916
            </tr>
917
            <tr>
918
                <td class="requirements-item"><a href="http://www.php.net/manual/en/ini.core.php#ini.memory-limit">Memory Limit</a></td>
919
                <td class="requirements-recommended">'.Display::label('>= '.REQUIRED_MIN_MEMORY_LIMIT.'M', 'success').'</td>
920
                <td class="requirements-value">'.compare_setting_values($originalMemoryLimit, REQUIRED_MIN_MEMORY_LIMIT).'</td>
921
            </tr>
922
          </table>';
923
    echo '</div>';
924
925
    // DIRECTORY AND FILE PERMISSIONS
926
    echo '<h4 class="install-subtitle">'.get_lang('Directory and files permissions').'</h4>';
927
    echo '<div class="install-requirement">'.get_lang('Directory and files permissionsInfo').'</div>';
928
    echo '<div class="table-responsive">';
929
930
    $_SESSION['permissions_for_new_directories'] = $_setting['permissions_for_new_directories'] = $dir_perm_verified;
931
    $_SESSION['permissions_for_new_files'] = $_setting['permissions_for_new_files'] = $fil_perm_verified;
932
933
    $dir_perm = Display::label('0'.decoct($dir_perm_verified), 'info');
934
    $file_perm = Display::label('0'.decoct($fil_perm_verified), 'info');
935
936
    $oldConf = '';
937
    if (file_exists(api_get_path(SYS_CODE_PATH).'inc/conf/configuration.php')) {
938
        $oldConf = '<tr>
939
            <td class="requirements-item">'.api_get_path(SYS_CODE_PATH).'inc/conf</td>
940
            <td class="requirements-value">'.check_writable(api_get_path(SYS_CODE_PATH).'inc/conf').'</td>
941
        </tr>';
942
    }
943
    $basePath = api_get_path(SYMFONY_SYS_PATH);
944
    echo '<table class="table table-bordered">
945
            '.$oldConf.'
946
            <tr>
947
                <td class="requirements-item">'.$basePath.'var/</td>
948
                <td class="requirements-value">'.check_writable($basePath.'var').'</td>
949
            </tr>
950
            <tr>
951
                <td class="requirements-item">'.$basePath.'.env.local</td>
952
                <td class="requirements-value">'.checkCanCreateFile($basePath.'.env.local').'</td>
953
            </tr>
954
            <tr>
955
                <td class="requirements-item">'.$basePath.'config/</td>
956
                <td class="requirements-value">'.check_writable($basePath.'config').'</td>
957
            </tr>
958
            <tr>
959
                <td class="requirements-item">'.get_lang('Permissions for new directories').'</td>
960
                <td class="requirements-value">'.$dir_perm.' </td>
961
            </tr>
962
            <tr>
963
                <td class="requirements-item">'.get_lang('Permissions for new files').'</td>
964
                <td class="requirements-value">'.$file_perm.' </td>
965
            </tr>
966
        </table>';
967
968
    echo '</div>';
969
970
    if ('update' === $installType && (empty($updatePath) || $badUpdatePath)) {
971
        if ($badUpdatePath) {
972
            ?>
973
            <div class="alert alert-warning">
974
                <?php echo get_lang('Error'); ?>!<br />
975
                Chamilo <?php echo implode('|', $update_from_version_8).' '.get_lang('has not been found in that directory'); ?>.
976
            </div>
977
        <?php
978
        } else {
979
            echo '<br />';
980
        } ?>
981
            <div class="row">
982
                <div class="col-md-12">
983
                    <p><?php echo get_lang('Old version\'s root path'); ?>:
984
                        <input type="text" name="updatePath" size="50" value="<?php echo ($badUpdatePath && !empty($updatePath)) ? htmlentities($updatePath) : ''; ?>" />
985
                    </p>
986
                    <p>
987
                        <div class="btn-group">
988
                            <button type="submit" class="btn btn-secondary" name="step1" value="<?php echo get_lang('Back'); ?>" >
989
                                <em class="fa fa-backward"> <?php echo get_lang('Back'); ?></em>
990
                            </button>
991
                            <input type="hidden" name="is_executable" id="is_executable" value="-" />
992
                            <button type="submit" class="btn btn-success" name="<?php echo isset($_POST['step2_update_6']) ? 'step2_update_6' : 'step2_update_8'; ?>" value="<?php echo get_lang('Next'); ?> &gt;" >
993
                                <em class="fa fa-forward"> </em> <?php echo get_lang('Next'); ?>
994
                            </button>
995
                        </div>
996
                    </p>
997
                </div>
998
            </div>
999
        <?php
1000
    } else {
1001
        $error = false;
1002
        // First, attempt to set writing permissions if we don't have them yet
1003
        //$perm = api_get_permissions_for_new_directories();
1004
        $perm = octdec('0777');
1005
        //$perm_file = api_get_permissions_for_new_files();
1006
        $perm_file = octdec('0666');
1007
        $notWritable = [];
1008
1009
        $checked_writable = api_get_path(SYS_PUBLIC_PATH);
1010
        if (!is_writable($checked_writable)) {
1011
            $notWritable[] = $checked_writable;
1012
            @chmod($checked_writable, $perm);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for chmod(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

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

1012
            /** @scrutinizer ignore-unhandled */ @chmod($checked_writable, $perm);

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

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

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
1013
        }
1014
1015
        if (false == $course_test_was_created) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
1016
            error_log('Installer: Could not create test course - Make sure permissions are fine.');
1017
            $error = true;
1018
        }
1019
1020
        $checked_writable = api_get_path(CONFIGURATION_PATH).'configuration.php';
1021
        if (file_exists($checked_writable) && !is_writable($checked_writable)) {
1022
            $notWritable[] = $checked_writable;
1023
            @chmod($checked_writable, $perm_file);
1024
        }
1025
1026
        // Second, if this fails, report an error
1027
        //--> The user would have to adjust the permissions manually
1028
        if (count($notWritable) > 0) {
1029
            error_log('Installer: At least one needed directory or file is not writeable');
1030
            $error = true; ?>
1031
            <div class="text-danger">
1032
                <h3 class="text-center"><?php echo get_lang('Warning !'); ?></h3>
1033
                <p>
1034
                    <?php printf(get_lang('Some files or folders don\'t have writing permission. To be able to install Chamilo you should first change their permissions (using CHMOD). Please read the %s installation guide %s'), '<a href="../../documentation/installation_guide.html" target="blank">', '</a>'); ?>
1035
                </p>
1036
            </div>
1037
            <?php
1038
            echo '<ul>';
1039
            foreach ($notWritable as $value) {
1040
                echo '<li class="text-danger">'.$value.'</li>';
1041
            }
1042
            echo '</ul>';
1043
        } elseif (file_exists(api_get_path(CONFIGURATION_PATH).'configuration.php')) {
1044
            // Check wether a Chamilo configuration file already exists.
1045
            echo '<div class="alert alert-warning"><h4><center>';
1046
            echo get_lang('Warning !ExistingLMSInstallationDetected');
1047
            echo '</center></h4></div>';
1048
        }
1049
1050
        $deprecated = [
1051
            api_get_path(SYS_CODE_PATH).'exercice/',
1052
            api_get_path(SYS_CODE_PATH).'newscorm/',
1053
            api_get_path(SYS_PLUGIN_PATH).'ticket/',
1054
            api_get_path(SYS_PLUGIN_PATH).'skype/',
1055
        ];
1056
        $deprecatedToRemove = [];
1057
        foreach ($deprecated as $deprecatedDirectory) {
1058
            if (!is_dir($deprecatedDirectory)) {
1059
                continue;
1060
            }
1061
            $deprecatedToRemove[] = $deprecatedDirectory;
1062
        }
1063
1064
        if (count($deprecatedToRemove) > 0) {
1065
            ?>
1066
            <p class="text-danger"><?php echo get_lang('Warning !ForDeprecatedDirectoriesForUpgrade'); ?></p>
1067
            <ul>
1068
                <?php foreach ($deprecatedToRemove as $deprecatedDirectory) {
1069
                ?>
1070
                    <li class="text-danger"><?php echo $deprecatedDirectory; ?></li>
1071
                <?php
1072
            } ?>
1073
            </ul>
1074
            <?php
1075
        }
1076
1077
        // And now display the choice buttons (go back or install)?>
1078
        <p align="center" style="padding-top:15px">
1079
            <button type="submit" name="step1" class="btn btn-default" onclick="javascript: window.location='index.php'; return false;" value="<?php echo get_lang('Previous'); ?>" >
1080
                <em class="fa fa-backward"> </em> <?php echo get_lang('Previous'); ?>
1081
            </button>
1082
            <button type="submit" name="step2_install" class="btn btn-success" value="<?php echo get_lang("New installation"); ?>" <?php if ($error) {
1083
            echo 'disabled="disabled"';
1084
        } ?> >
1085
                <em class="fa fa-forward"> </em> <?php echo get_lang('New installation'); ?>
1086
            </button>
1087
        <input type="hidden" name="is_executable" id="is_executable" value="-" />
1088
            <button type="submit" class="btn btn-default" <?php echo !$error ?: 'disabled="disabled"'; ?> name="step2_update_8" value="Upgrade from Chamilo 1.9.x">
1089
                <em class="fa fa-forward" aria-hidden="true"></em> <?php echo get_lang('Upgrade Chamilo LMS version'); ?>
1090
            </button>
1091
            </p>
1092
        <?php
1093
    }
1094
}
1095
1096
/**
1097
 * Displays the license (GNU GPL) as step 2, with
1098
 * - an "I accept" button named step3 to proceed to step 3;
1099
 * - a "Back" button named step1 to go back to the first step.
1100
 */
1101
function display_license_agreement()
1102
{
1103
    echo '<div class="RequirementHeading"><h2>'.display_step_sequence().get_lang('Licence').'</h2>';
1104
    echo '<p>'.get_lang('Chamilo is free software distributed under the GNU General Public licence (GPL).').'</p>';
1105
    echo '<p><a href="../../documentation/license.html" target="_blank">'.get_lang('Printable version').'</a></p>';
1106
    echo '</div>'; ?>
1107
    <div class="form-group">
1108
        <pre style="overflow: auto; height: 200px; margin-top: 5px;">
1109
            <?php echo api_htmlentities(@file_get_contents(api_get_path(SYMFONY_SYS_PATH).'documentation/license.txt')); ?>
1110
        </pre>
1111
    </div>
1112
    <div class="form-group form-check">
1113
        <input type="checkbox" name="accept" id="accept_licence" value="1">
1114
        <label for="accept_licence"><?php echo get_lang('I Accept'); ?></label>
1115
    </div>
1116
    <div class="row">
1117
        <div class="col-md-12">
1118
            <p class="alert alert-info"><?php echo get_lang('The images and media galleries of Chamilo use images from Nuvola, Crystal Clear and Tango icon galleries. Other images and media like diagrams and Flash animations are borrowed from Wikimedia and Ali Pakdel\'s and Denis Hoa\'s courses with their agreement and released under BY-SA Creative Commons license. You may find the license details at <a href="http://creativecommons.org/licenses/by-sa/3.0/">the CC website</a>, where a link to the full text of the license is provided at the bottom of the page.'); ?></p>
1119
        </div>
1120
    </div>
1121
1122
    <!-- Contact information form -->
1123
    <div class="section-parameters">
1124
        <a href="javascript://" class = "advanced_parameters" >
1125
        <span id="img_plus_and_minus">&nbsp;<i class="fa fa-eye" aria-hidden="true"></i>&nbsp;<?php echo get_lang('Contact information'); ?></span>
1126
        </a>
1127
    </div>
1128
1129
    <div id="id_contact_form" style="display:block">
1130
        <div class="normal-message"><?php echo get_lang('Contact informationDescription'); ?></div>
1131
        <div id="contact_registration">
1132
            <p><?php echo get_contact_registration_form(); ?></p><br />
1133
        </div>
1134
    </div>
1135
    <div class="text-center">
1136
    <button type="submit" class="btn btn-default" name="step1" value="&lt; <?php echo get_lang('Previous'); ?>" >
1137
        <em class="fa fa-backward"> </em> <?php echo get_lang('Previous'); ?>
1138
    </button>
1139
    <input type="hidden" name="is_executable" id="is_executable" value="-" />
1140
    <button type="submit" id="license-next" class="btn btn-success" name="step3" onclick="javascript: if(!document.getElementById('accept_licence').checked) { alert('<?php echo get_lang('You must accept the licence'); ?>');return false;}" value="<?php echo get_lang('Next'); ?> &gt;" >
1141
        <em class="fa fa-forward"> </em> <?php echo get_lang('Next'); ?>
1142
    </button>
1143
    </div>
1144
    <?php
1145
}
1146
1147
/**
1148
 * Get contact registration form.
1149
 */
1150
function get_contact_registration_form()
1151
{
1152
    $html = '
1153
   <div class="form-horizontal">
1154
    <div class="panel panel-default">
1155
    <div class="panel-body">
1156
    <div id="div_sent_information"></div>
1157
    <div class="form-group row">
1158
            <label class="col-sm-3"><span class="form_required">*</span>'.get_lang('Name').'</label>
1159
            <div class="col-sm-9"><input id="person_name" class="form-control" type="text" name="person_name" size="30" /></div>
1160
    </div>
1161
    <div class="form-group row">
1162
            <label class="col-sm-3"><span class="form_required">*</span>'.get_lang('e-mail').'</label>
1163
            <div class="col-sm-9"><input id="person_email" class="form-control" type="text" name="person_email" size="30" /></div>
1164
    </div>
1165
    <div class="form-group row">
1166
            <label class="col-sm-3"><span class="form_required">*</span>'.get_lang('Your company\'s name').'</label>
1167
            <div class="col-sm-9"><input id="company_name" class="form-control" type="text" name="company_name" size="30" /></div>
1168
    </div>
1169
    <div class="form-group row">
1170
        <label class="col-sm-3"><span class="form_required">*</span>'.get_lang('Your company\'s activity').'</label>
1171
        <div class="col-sm-9">
1172
            <select class="selectpicker show-tick" name="company_activity" id="company_activity" >
1173
                <option value="">--- '.get_lang('Select one').' ---</option>
1174
                <Option value="Advertising/Marketing/PR">Advertising/Marketing/PR</Option><Option value="Agriculture/Forestry">Agriculture/Forestry</Option>
1175
                <Option value="Architecture">Architecture</Option><Option value="Banking/Finance">Banking/Finance</Option>
1176
                <Option value="Biotech/Pharmaceuticals">Biotech/Pharmaceuticals</Option><Option value="Business Equipment">Business Equipment</Option>
1177
                <Option value="Business Services">Business Services</Option><Option value="Construction">Construction</Option>
1178
                <Option value="Consulting/Research">Consulting/Research</Option><Option value="Education">Education</Option>
1179
                <Option value="Engineering">Engineering</Option><Option value="Environmental">Environmental</Option>
1180
                <Option value="Government">Government</Option><Option value="Healthcare">Health Care</Option>
1181
                <Option value="Hospitality/Lodging/Travel">Hospitality/Lodging/Travel</Option><Option value="Insurance">Insurance</Option>
1182
                <Option value="Legal">Legal</Option><Option value="Manufacturing">Manufacturing</Option>
1183
                <Option value="Media/Entertainment">Media/Entertainment</Option><Option value="Mortgage">Mortgage</Option>
1184
                <Option value="Non-Profit">Non-Profit</Option><Option value="Real Estate">Real Estate</Option>
1185
                <Option value="Restaurant">Restaurant</Option><Option value="Retail">Retail</Option>
1186
                <Option value="Shipping/Transportation">Shipping/Transportation</Option>
1187
                <Option value="Technology">Technology</Option><Option value="Telecommunications">Telecommunications</Option>
1188
                <Option value="Other">Other</Option>
1189
            </select>
1190
        </div>
1191
    </div>
1192
1193
    <div class="form-group row">
1194
        <label class="col-sm-3"><span class="form_required">*</span>'.get_lang('Your job\'s description').'</label>
1195
        <div class="col-sm-9">
1196
            <select class="selectpicker show-tick" name="person_role" id="person_role" >
1197
                <option value="">--- '.get_lang('Select one').' ---</option>
1198
                <Option value="Administration">Administration</Option><Option value="CEO/President/ Owner">CEO/President/ Owner</Option>
1199
                <Option value="CFO">CFO</Option><Option value="CIO/CTO">CIO/CTO</Option>
1200
                <Option value="Consultant">Consultant</Option><Option value="Customer Service">Customer Service</Option>
1201
                <Option value="Engineer/Programmer">Engineer/Programmer</Option><Option value="Facilities/Operations">Facilities/Operations</Option>
1202
                <Option value="Finance/ Accounting Manager">Finance/ Accounting Manager</Option><Option value="Finance/ Accounting Staff">Finance/ Accounting Staff</Option>
1203
                <Option value="General Manager">General Manager</Option><Option value="Human Resources">Human Resources</Option>
1204
                <Option value="IS/IT Management">IS/IT Management</Option><Option value="IS/ IT Staff">IS/ IT Staff</Option>
1205
                <Option value="Marketing Manager">Marketing Manager</Option><Option value="Marketing Staff">Marketing Staff</Option>
1206
                <Option value="Partner/Principal">Partner/Principal</Option><Option value="Purchasing Manager">Purchasing Manager</Option>
1207
                <Option value="Sales/ Business Dev. Manager">Sales/ Business Dev. Manager</Option><Option value="Sales/ Business Dev.">Sales/ Business Dev.</Option>
1208
                <Option value="Vice President/Senior Manager">Vice President/Senior Manager</Option><Option value="Other">Other</Option>
1209
            </select>
1210
        </div>
1211
    </div>
1212
1213
    <div class="form-group row">
1214
        <label class="col-sm-3"><span class="form_required">*</span>'.get_lang('Your company\'s home country').'</label>
1215
        <div class="col-sm-9">'.get_countries_list_from_array(true).'</div>
1216
    </div>
1217
    <div class="form-group row">
1218
        <label class="col-sm-3">'.get_lang('Company city').'</label>
1219
        <div class="col-sm-9">
1220
                <input type="text" class="form-control" id="company_city" name="company_city" size="30" />
1221
        </div>
1222
    </div>
1223
    <div class="form-group row">
1224
        <label class="col-sm-3">'.get_lang('Preferred contact language').'</label>
1225
        <div class="col-sm-9">
1226
            <select class="selectpicker show-tick" id="language" name="language">
1227
                <option value="bulgarian">Bulgarian</option>
1228
                <option value="indonesian">Bahasa Indonesia</option>
1229
                <option value="bosnian">Bosanski</option>
1230
                <option value="german">Deutsch</option>
1231
                <option selected="selected" value="english">English</option>
1232
                <option value="spanish">Spanish</option>
1233
                <option value="french">Français</option>
1234
                <option value="italian">Italian</option>
1235
                <option value="hungarian">Magyar</option>
1236
                <option value="dutch">Nederlands</option>
1237
                <option value="brazilian">Português do Brasil</option>
1238
                <option value="portuguese">Português europeu</option>
1239
                <option value="slovenian">Slovenčina</option>
1240
            </select>
1241
        </div>
1242
    </div>
1243
1244
    <div class="form-group row">
1245
        <label class="col-sm-3">'.get_lang('Do you have the power to take financial decisions on behalf of your company?').'</label>
1246
        <div class="col-sm-9">
1247
            <div class="radio">
1248
                <label>
1249
                    <input type="radio" name="financial_decision" id="financial_decision1" value="1" checked /> '.get_lang('Yes').'
1250
                </label>
1251
            </div>
1252
            <div class="radio">
1253
                <label>
1254
                    <input type="radio" name="financial_decision" id="financial_decision2" value="0" /> '.get_lang('No').'
1255
                </label>
1256
            </div>
1257
        </div>
1258
    </div>
1259
    <div class="clear"></div>
1260
    <div class="form-group row">
1261
            <div class="col-sm-3">&nbsp;</div>
1262
            <div class="col-sm-9"><button type="button" class="btn btn-default" onclick="javascript:send_contact_information();" value="'.get_lang('Send information').'" ><em class="fa fa-floppy-o"></em> '.get_lang('Send information').'</button> <span id="loader-button"></span></div>
1263
    </div>
1264
    <div class="form-group row">
1265
            <div class="col-sm-3">&nbsp;</div>
1266
            <div class="col-sm-9"><span class="form_required">*</span><small>'.get_lang('Mandatory field').'</small></div>
1267
    </div></div></div>
1268
    </div>';
1269
1270
    return $html;
1271
}
1272
1273
/**
1274
 * Displays a parameter in a table row.
1275
 * Used by the display_database_settings_form function.
1276
 *
1277
 * @param   string  Type of install
1278
 * @param   string  Name of parameter
1279
 * @param   string  Field name (in the HTML form)
1280
 * @param   string  Field value
1281
 * @param   string  Extra notice (to show on the right side)
1282
 * @param   bool Whether to display in update mode
1283
 * @param   string  Additional attribute for the <tr> element
1284
 */
1285
function displayDatabaseParameter(
1286
    $installType,
1287
    $parameterName,
1288
    $formFieldName,
1289
    $parameterValue,
1290
    $extra_notice,
1291
    $displayWhenUpdate = true,
1292
    $tr_attribute = ''
1293
) {
1294
    //echo "<tr ".$tr_attribute.">";
1295
    echo "<label class='col-sm-4'>$parameterName</label>";
1296
1297
    if (INSTALL_TYPE_UPDATE == $installType && $displayWhenUpdate) {
1298
        echo '<input type="hidden" name="'.$formFieldName.'" id="'.$formFieldName.'" value="'.api_htmlentities($parameterValue).'" />'.$parameterValue;
1299
    } else {
1300
        $inputType = 'dbPassForm' == $formFieldName ? 'password' : 'text';
1301
1302
        //Slightly limit the length of the database prefix to avoid having to cut down the databases names later on
1303
        $maxLength = 'dbPrefixForm' == $formFieldName ? '15' : MAX_FORM_FIELD_LENGTH;
1304
        if (INSTALL_TYPE_UPDATE == $installType) {
1305
            echo '<input type="hidden" name="'.$formFieldName.'" id="'.$formFieldName.'" value="'.api_htmlentities($parameterValue).'" />';
1306
            echo api_htmlentities($parameterValue);
1307
        } else {
1308
            echo '<div class="col-sm-5"><input type="'.$inputType.'" class="form-control" size="'.DATABASE_FORM_FIELD_DISPLAY_LENGTH.'" maxlength="'.$maxLength.'" name="'.$formFieldName.'" id="'.$formFieldName.'" value="'.api_htmlentities($parameterValue).'" />'."</div>";
1309
            echo '<div class="col-sm-3">'.$extra_notice.'</div>';
1310
        }
1311
    }
1312
}
1313
1314
/**
1315
 * Displays step 3 - a form where the user can enter the installation settings
1316
 * regarding the databases - login and password, names, prefixes, single
1317
 * or multiple databases, tracking or not...
1318
 *
1319
 * @param string $installType
1320
 * @param string $dbHostForm
1321
 * @param string $dbUsernameForm
1322
 * @param string $dbPassForm
1323
 * @param string $dbNameForm
1324
 * @param int    $dbPortForm
1325
 * @param string $installationProfile
1326
 */
1327
function display_database_settings_form(
1328
    $installType,
1329
    $dbHostForm,
1330
    $dbUsernameForm,
1331
    $dbPassForm,
1332
    $dbNameForm,
1333
    $dbPortForm = 3306,
1334
    $installationProfile = ''
1335
) {
1336
    if ('update' == $installType) {
1337
        global $_configuration;
1338
        $dbHostForm = $_configuration['db_host'];
1339
        $dbUsernameForm = $_configuration['db_user'];
1340
        $dbPassForm = $_configuration['db_password'];
1341
        $dbNameForm = $_configuration['main_database'];
1342
        $dbPortForm = isset($_configuration['db_port']) ? $_configuration['db_port'] : '';
1343
1344
        echo '<div class="RequirementHeading"><h2>'.display_step_sequence().get_lang('Database settings').'</h2></div>';
1345
        echo '<div class="RequirementContent">';
1346
        echo get_lang('The upgrade script will recover and update the Chamilo database(s). In order to do this, this script will use the databases and settings defined below. Because our software runs on a wide range of systems and because all of them might not have been tested, we strongly recommend you do a full backup of your databases before you proceed with the upgrade!');
1347
        echo '</div>';
1348
    } else {
1349
        echo '<div class="RequirementHeading"><h2>'.display_step_sequence().get_lang('Database settings').'</h2></div>';
1350
        echo '<div class="RequirementContent">';
1351
        echo get_lang('The install script will create (or use) the Chamilo database using the database name given here. Please make sure the user you give has the right to create the database by the name given here. If a database with this name exists, it will be overwritten. Please do not use the root user as the Chamilo database user. This can lead to serious security issues.');
1352
        echo '</div>';
1353
    } ?>
1354
    <div class="panel panel-default">
1355
        <div class="panel-body">
1356
        <div class="form-group row">
1357
            <label class="col-sm-4"><?php echo get_lang('Database Host'); ?> </label>
1358
            <?php if ('update' == $installType) {
1359
        ?>
1360
            <div class="col-sm-5">
1361
                <input type="hidden" name="dbHostForm" value="<?php echo htmlentities($dbHostForm); ?>" /><?php echo $dbHostForm; ?>
1362
            </div>
1363
            <div class="col-sm-3"></div>
1364
            <?php
1365
    } else {
1366
        ?>
1367
            <div class="col-sm-5">
1368
                <input type="text" class="form-control" size="25" maxlength="50" name="dbHostForm" value="<?php echo htmlentities($dbHostForm); ?>" />
1369
            </div>
1370
            <div class="col-sm-3"><?php echo get_lang('ex.').' localhost'; ?></div>
1371
            <?php
1372
    } ?>
1373
        </div>
1374
        <div class="form-group row">
1375
            <label class="col-sm-4"><?php echo get_lang('Port'); ?> </label>
1376
            <?php if ('update' == $installType) {
1377
        ?>
1378
            <div class="col-sm-5">
1379
                <input type="hidden" name="dbPortForm" value="<?php echo htmlentities($dbPortForm); ?>" /><?php echo $dbPortForm; ?>
1380
            </div>
1381
            <div class="col-sm-3"></div>
1382
            <?php
1383
    } else {
1384
        ?>
1385
            <div class="col-sm-5">
1386
                <input type="text" class="form-control" size="25" maxlength="50" name="dbPortForm" value="<?php echo htmlentities($dbPortForm); ?>" />
1387
            </div>
1388
            <div class="col-sm-3"><?php echo get_lang('ex.').' 3306'; ?></div>
1389
            <?php
1390
    } ?>
1391
        </div>
1392
        <div class="form-group row">
1393
            <?php
1394
                //database user username
1395
                $example_login = get_lang('ex.').' root';
1396
    displayDatabaseParameter($installType, get_lang('Database Login'), 'dbUsernameForm', $dbUsernameForm, $example_login); ?>
1397
        </div>
1398
        <div class="form-group row">
1399
            <?php
1400
            //database user password
1401
            $example_password = get_lang('ex.').' '.api_generate_password();
1402
    displayDatabaseParameter($installType, get_lang('Database Password'), 'dbPassForm', $dbPassForm, $example_password); ?>
1403
        </div>
1404
        <div class="form-group row">
1405
            <?php
1406
            //Database Name fix replace weird chars
1407
            if (INSTALL_TYPE_UPDATE != $installType) {
1408
                $dbNameForm = str_replace(['-', '*', '$', ' ', '.'], '', $dbNameForm);
1409
            }
1410
1411
    displayDatabaseParameter(
1412
                $installType,
1413
                get_lang('Main Chamilo database (DB)'),
1414
                'dbNameForm',
1415
                $dbNameForm,
1416
                '&nbsp;',
1417
                null,
1418
                'id="optional_param1"'
1419
                ); ?>
1420
        </div>
1421
       <?php if (INSTALL_TYPE_UPDATE != $installType) {
1422
                    ?>
1423
        <div class="form-group row">
1424
            <div class="col-sm-4"></div>
1425
            <div class="col-sm-8">
1426
            <button type="submit" class="btn btn-primary" name="step3" value="step3">
1427
                <em class="fa fa-refresh"> </em>
1428
                <?php echo get_lang('Check database connection'); ?>
1429
            </button>
1430
            </div>
1431
        </div>
1432
        <?php
1433
                } ?>
1434
1435
        </div>
1436
    </div>
1437
    <?php
1438
        $database_exists_text = '';
1439
    $manager = null;
1440
    try {
1441
        if ('update' === $installType) {
1442
            /** @var \Database $manager */
1443
            $manager = connectToDatabase(
1444
                $dbHostForm,
1445
                $dbUsernameForm,
1446
                $dbPassForm,
1447
                $dbNameForm,
1448
                $dbPortForm
1449
            );
1450
1451
            $connection = $manager->getConnection();
1452
            $connection->connect();
1453
            $schemaManager = $connection->getSchemaManager();
1454
1455
            // Test create/alter/drop table
1456
            $table = 'zXxTESTxX_'.mt_rand(0, 1000);
1457
            $sql = "CREATE TABLE $table (id INT AUTO_INCREMENT NOT NULL, name varchar(255), PRIMARY KEY(id))";
1458
            $connection->query($sql);
1459
            $tableCreationWorks = false;
1460
            $tableDropWorks = false;
1461
            if ($schemaManager->tablesExist($table)) {
1462
                $tableCreationWorks = true;
1463
                $sql = "ALTER TABLE $table ADD COLUMN name2 varchar(140) ";
1464
                $connection->query($sql);
1465
                $schemaManager->dropTable($table);
1466
                $tableDropWorks = false === $schemaManager->tablesExist($table);
1467
            }
1468
        } else {
1469
            $manager = connectToDatabase(
1470
                $dbHostForm,
1471
                $dbUsernameForm,
1472
                $dbPassForm,
1473
                null,
1474
                $dbPortForm
1475
            );
1476
1477
            $schemaManager = $manager->getConnection()->getSchemaManager();
1478
            $databases = $schemaManager->listDatabases();
1479
            if (in_array($dbNameForm, $databases)) {
1480
                $database_exists_text = '<div class="alert alert-warning">'.get_lang('A database with the same name <b>already exists</b>.').'</div>';
1481
            }
1482
        }
1483
    } catch (Exception $e) {
1484
        $database_exists_text = $e->getMessage();
1485
        $manager = false;
1486
    }
1487
1488
    if ($manager && $manager->getConnection()->isConnected()): ?>
1489
        <?php echo $database_exists_text; ?>
1490
        <div id="db_status" class="alert alert-success">
1491
            Database host: <strong><?php echo $manager->getConnection()->getHost(); ?></strong><br/>
1492
            Database port: <strong><?php echo $manager->getConnection()->getPort(); ?></strong><br/>
1493
            Database driver: <strong><?php echo $manager->getConnection()->getDriver()->getName(); ?></strong><br/>
1494
            <?php
1495
                if ('update' === $installType) {
1496
                    echo get_lang('CreateTableWorks').' <strong>Ok</strong>';
1497
                    echo '<br/ >';
1498
                    echo get_lang('AlterTableWorks').' <strong>Ok</strong>';
1499
                    echo '<br/ >';
1500
                    echo get_lang('DropColumnWorks').' <strong>Ok</strong>';
1501
                } ?>
1502
        </div>
1503
    <?php else: ?>
1504
        <div id="db_status" class="alert alert-danger">
1505
            <p><?php echo get_lang('The database connection has failed. This is generally due to the wrong user, the wrong password or the wrong database prefix being set above. Please review these settings and try again.'); ?></strong></p>
1506
            <code><?php echo $database_exists_text; ?></code>
1507
        </div>
1508
    <?php endif; ?>
1509
1510
   <div class="btn-group" role="group">
1511
       <button type="submit" name="step2"
1512
               class="btn btn-secondary float-right" value="&lt; <?php echo get_lang('Previous'); ?>" >
1513
           <em class="fa fa-backward"> </em> <?php echo get_lang('Previous'); ?>
1514
       </button>
1515
       <input type="hidden" name="is_executable" id="is_executable" value="-" />
1516
       <?php if ($manager) {
1517
                    ?>
1518
           <button type="submit" class="btn btn-success" name="step4" value="<?php echo get_lang('Next'); ?> &gt;" >
1519
               <em class="fa fa-forward"> </em> <?php echo get_lang('Next'); ?>
1520
           </button>
1521
       <?php
1522
                } else {
1523
                    ?>
1524
           <button
1525
                   disabled="disabled"
1526
                   type="submit" class="btn btn-success disabled" name="step4" value="<?php echo get_lang('Next'); ?> &gt;" >
1527
               <em class="fa fa-forward"> </em> <?php echo get_lang('Next'); ?>
1528
           </button>
1529
       <?php
1530
                } ?>
1531
   </div>
1532
    <?php
1533
}
1534
1535
function panel($content = null, $title = null, $id = null, $style = null)
1536
{
1537
    $html = '';
1538
    if (empty($style)) {
1539
        $style = 'default';
1540
    }
1541
    if (!empty($title)) {
1542
        $panelTitle = Display::div($title, ['class' => 'panel-heading']);
1543
        $panelBody = Display::div($content, ['class' => 'panel-body']);
1544
        $panelParent = Display::div($panelTitle.$panelBody, ['id' => $id, 'class' => 'panel panel-'.$style]);
1545
    } else {
1546
        $panelBody = Display::div($html, ['class' => 'panel-body']);
1547
        $panelParent = Display::div($panelBody, ['id' => $id, 'class' => 'panel panel-'.$style]);
1548
    }
1549
    $html .= $panelParent;
1550
1551
    return $html;
1552
}
1553
1554
/**
1555
 * Displays a parameter in a table row.
1556
 * Used by the display_configuration_settings_form function.
1557
 *
1558
 * @param string $installType
1559
 * @param string $parameterName
1560
 * @param string $formFieldName
1561
 * @param string $parameterValue
1562
 * @param string $displayWhenUpdate
1563
 *
1564
 * @return string
1565
 */
1566
function display_configuration_parameter(
1567
    $installType,
1568
    $parameterName,
1569
    $formFieldName,
1570
    $parameterValue,
1571
    $displayWhenUpdate = 'true'
1572
) {
1573
    $html = '<div class="form-group row">';
1574
    $html .= '<label class="col-sm-6 control-label">'.$parameterName.'</label>';
1575
    if (INSTALL_TYPE_UPDATE == $installType && $displayWhenUpdate) {
1576
        $html .= '<input type="hidden" name="'.$formFieldName.'" value="'.api_htmlentities($parameterValue, ENT_QUOTES).'" />'.$parameterValue;
1577
    } else {
1578
        $html .= '<div class="col-sm-6"><input class="form-control" type="text" size="'.FORM_FIELD_DISPLAY_LENGTH.'" maxlength="'.MAX_FORM_FIELD_LENGTH.'" name="'.$formFieldName.'" value="'.api_htmlentities($parameterValue, ENT_QUOTES).'" />'."</div>";
1579
    }
1580
    $html .= "</div>";
1581
1582
    return $html;
1583
}
1584
1585
/**
1586
 * Displays step 4 of the installation - configuration settings about Chamilo itself.
1587
 *
1588
 * @param string $installType
1589
 * @param string $urlForm
1590
 * @param string $languageForm
1591
 * @param string $emailForm
1592
 * @param string $adminFirstName
1593
 * @param string $adminLastName
1594
 * @param string $adminPhoneForm
1595
 * @param string $campusForm
1596
 * @param string $institutionForm
1597
 * @param string $institutionUrlForm
1598
 * @param string $encryptPassForm
1599
 * @param bool   $allowSelfReg
1600
 * @param bool   $allowSelfRegProf
1601
 * @param string $loginForm
1602
 * @param string $passForm
1603
 */
1604
function display_configuration_settings_form(
1605
    $installType,
1606
    $urlForm,
1607
    $languageForm,
1608
    $emailForm,
1609
    $adminFirstName,
1610
    $adminLastName,
1611
    $adminPhoneForm,
1612
    $campusForm,
1613
    $institutionForm,
1614
    $institutionUrlForm,
1615
    $encryptPassForm,
1616
    $allowSelfReg,
1617
    $allowSelfRegProf,
1618
    $loginForm,
1619
    $passForm
1620
) {
1621
    if ('update' != $installType && empty($languageForm)) {
1622
        $languageForm = $_SESSION['install_language'];
1623
    }
1624
    echo '<div class="RequirementHeading">';
1625
    echo "<h2>".display_step_sequence().get_lang("ConfigurationSettings")."</h2>";
1626
    echo '</div>';
1627
1628
    // Parameter 1: administrator's login
1629
    $html = '';
1630
    $html .= display_configuration_parameter(
1631
        $installType,
1632
        get_lang('Administrator login'),
1633
        'loginForm',
1634
        $loginForm,
1635
        'update' == $installType
1636
    );
1637
1638
    // Parameter 2: administrator's password
1639
    if ('update' != $installType) {
1640
        $html .= display_configuration_parameter(
1641
            $installType,
1642
            get_lang('Administrator password (<font color="red">you may want to change this</font>)'),
1643
            'passForm',
1644
            $passForm,
1645
            false
1646
        );
1647
    }
1648
1649
    // Parameters 3 and 4: administrator's names
1650
1651
    $html .= display_configuration_parameter(
1652
        $installType,
1653
        get_lang('Administrator first name'),
1654
        'adminFirstName',
1655
        $adminFirstName
1656
    );
1657
    $html .= display_configuration_parameter($installType, get_lang('Administrator last name'), 'adminLastName', $adminLastName);
1658
1659
    //Parameter 3: administrator's email
1660
    $html .= display_configuration_parameter($installType, get_lang('Admine-mail'), 'emailForm', $emailForm);
1661
1662
    //Parameter 6: administrator's telephone
1663
    $html .= display_configuration_parameter($installType, get_lang('Administrator telephone'), 'adminPhoneForm', $adminPhoneForm);
1664
    echo panel($html, get_lang('Administrator'), 'administrator');
1665
1666
    //First parameter: language
1667
    $html = '<div class="form-group row">';
1668
    $html .= '<label class="col-sm-6 control-label">'.get_lang('Main language')."</label>";
1669
    if ('update' == $installType) {
1670
        $html .= '<input type="hidden" name="languageForm" value="'.api_htmlentities($languageForm, ENT_QUOTES).'" />'.$languageForm;
1671
    } else { // new installation
1672
        $html .= '<div class="col-sm-6">';
1673
        $html .= display_language_selection_box('languageForm', $languageForm);
1674
        $html .= '</div>';
1675
    }
1676
    $html .= "</div>";
1677
1678
    //Second parameter: Chamilo URL
1679
    $html .= '<div class="form-group row">';
1680
    $html .= '<label class="col-sm-6 control-label">'.get_lang('Chamilo URL').get_lang('Required field').'</label>';
1681
1682
    if ('update' == $installType) {
1683
        $html .= api_htmlentities($urlForm, ENT_QUOTES)."\n";
1684
    } else {
1685
        $html .= '<div class="col-sm-6">';
1686
        $html .= '<input class="form-control" type="text" size="40" maxlength="100" name="urlForm" value="'.api_htmlentities($urlForm, ENT_QUOTES).'" />';
1687
        $html .= '</div>';
1688
    }
1689
    $html .= '</div>';
1690
1691
    //Parameter 9: campus name
1692
    $html .= display_configuration_parameter(
1693
        $installType,
1694
        get_lang('Your portal name'),
1695
        'campusForm',
1696
        $campusForm
1697
    );
1698
1699
    //Parameter 10: institute (short) name
1700
    $html .= display_configuration_parameter(
1701
        $installType,
1702
        get_lang('Your company short name'),
1703
        'institutionForm',
1704
        $institutionForm
1705
    );
1706
1707
    //Parameter 11: institute (short) name
1708
    $html .= display_configuration_parameter(
1709
        $installType,
1710
        get_lang('URL of this company'),
1711
        'institutionUrlForm',
1712
        $institutionUrlForm
1713
    );
1714
1715
    $html .= '<div class="form-group row">
1716
            <label class="col-sm-6 control-label">'.get_lang("Encryption method").'</label>
1717
        <div class="col-sm-6">';
1718
    if ('update' == $installType) {
1719
        $html .= '<input type="hidden" name="encryptPassForm" value="'.$encryptPassForm.'" />'.$encryptPassForm;
1720
    } else {
1721
        $html .= '<div class="checkbox">
1722
                    <label>
1723
                        <input  type="radio" name="encryptPassForm" value="bcrypt" id="encryptPass1" '.('bcrypt' == $encryptPassForm ? 'checked="checked" ' : '').'/> bcrypt
1724
                    </label>';
1725
1726
        $html .= '<label>
1727
                        <input  type="radio" name="encryptPassForm" value="sha1" id="encryptPass1" '.('sha1' == $encryptPassForm ? 'checked="checked" ' : '').'/> sha1
1728
                    </label>';
1729
1730
        $html .= '<label>
1731
                        <input type="radio" name="encryptPassForm" value="md5" id="encryptPass0" '.('md5' == $encryptPassForm ? 'checked="checked" ' : '').'/> md5
1732
                    </label>';
1733
1734
        $html .= '<label>
1735
                        <input type="radio" name="encryptPassForm" value="none" id="encryptPass2" '.('none' == $encryptPassForm ? 'checked="checked" ' : '').'/>'.get_lang('none').'
1736
                    </label>';
1737
        $html .= '</div>';
1738
    }
1739
    $html .= '</div></div>';
1740
1741
    $html .= '<div class="form-group row">
1742
            <label class="col-sm-6 control-label">'.get_lang('Allow self-registration').'</label>
1743
            <div class="col-sm-6">';
1744
    if ('update' == $installType) {
1745
        if ('true' == $allowSelfReg) {
1746
            $label = get_lang('Yes');
1747
        } elseif ('false' == $allowSelfReg) {
1748
            $label = get_lang('No');
1749
        } else {
1750
            $label = get_lang('After approval');
1751
        }
1752
        $html .= '<input type="hidden" name="allowSelfReg" value="'.$allowSelfReg.'" />'.$label;
1753
    } else {
1754
        $html .= '<div class="control-group">';
1755
        $html .= '<label class="checkbox-inline">
1756
                        <input type="radio" name="allowSelfReg" value="true" id="allowSelfReg1" '.('true' == $allowSelfReg ? 'checked="checked" ' : '').' /> '.get_lang('Yes').'
1757
                    </label>';
1758
        $html .= '<label class="checkbox-inline">
1759
                        <input type="radio" name="allowSelfReg" value="false" id="allowSelfReg0" '.('false' == $allowSelfReg ? '' : 'checked="checked" ').' /> '.get_lang('No').'
1760
                    </label>';
1761
        $html .= '<label class="checkbox-inline">
1762
                    <input type="radio" name="allowSelfReg" value="approval" id="allowSelfReg2" '.('approval' == $allowSelfReg ? '' : 'checked="checked" ').' /> '.get_lang('After approval').'
1763
                </label>';
1764
        $html .= '</div>';
1765
    }
1766
    $html .= '</div>';
1767
    $html .= '</div>';
1768
1769
    $html .= '<div class="form-group row">';
1770
    $html .= '<label class="col-sm-6 control-label">'.get_lang('Allow self-registrationProf').'</label>
1771
        <div class="col-sm-6">';
1772
    if ('update' == $installType) {
1773
        if ('true' == $allowSelfRegProf) {
1774
            $label = get_lang('Yes');
1775
        } else {
1776
            $label = get_lang('No');
1777
        }
1778
        $html .= '<input type="hidden" name="allowSelfRegProf" value="'.$allowSelfRegProf.'" />'.$label;
1779
    } else {
1780
        $html .= '<div class="control-group">
1781
                <label class="checkbox-inline">
1782
                    <input type="radio" name="allowSelfRegProf" value="1" id="allowSelfRegProf1" '.($allowSelfRegProf ? 'checked="checked" ' : '').'/>
1783
                '.get_lang('Yes').'
1784
                </label>';
1785
        $html .= '<label class="checkbox-inline">
1786
                    <input type="radio" name="allowSelfRegProf" value="0" id="allowSelfRegProf0" '.($allowSelfRegProf ? '' : 'checked="checked" ').' />
1787
                   '.get_lang('No').'
1788
                </label>';
1789
        $html .= '</div>';
1790
    }
1791
    $html .= '</div>
1792
    </div>';
1793
1794
    echo panel($html, get_lang('Portal'), 'platform'); ?>
1795
    <div class='btn-group'>
1796
        <button type="submit" class="btn btn-secondary pull-right" name="step3" value="&lt; <?php echo get_lang('Previous'); ?>" ><em class="fa fa-backward"> </em> <?php echo get_lang('Previous'); ?></button>
1797
        <input type="hidden" name="is_executable" id="is_executable" value="-" />
1798
        <button class="btn btn-success" type="submit" name="step5">
1799
            <em class="fa fa-forward"> </em> <?php echo get_lang('Next'); ?>
1800
        </button>
1801
    </div>
1802
    <?php
1803
}
1804
1805
/**
1806
 * After installation is completed (step 6), this message is displayed.
1807
 */
1808
function display_after_install_message()
1809
{
1810
    $container = Container::$container;
1811
1812
    $trans = $container->get('translator');
1813
    $html = '<div class="RequirementContent">'.
1814
        $trans->trans(
1815
            'When you enter your portal for the first time, the best way to understand it is to create a course with the \'Create course\' link in the menu and play around a little.').'</div>';
1816
    $html .= '<div class="alert alert-warning">';
1817
    $html .= '<strong>'.$trans->trans('Security advice').'</strong>';
1818
    $html .= ': ';
1819
    $html .= sprintf($trans->trans(
1820
        'To protect your site, make the whole %s directory read-only (chmod -R 0555 on Linux) and delete the %s directory.'), 'var/config/', 'main/install/');
1821
    $html .= '</div></form>
1822
    <br />
1823
    <a class="btn btn-success btn-block" href="../../">
1824
        '.$trans->trans('Go to your newly created portal.').'
1825
    </a>';
1826
1827
    return $html;
1828
}
1829
1830
/**
1831
 * This function return countries list from array (hardcoded).
1832
 *
1833
 * @param bool $combo (Optional) True for returning countries list with select html
1834
 *
1835
 * @return array|string countries list
1836
 */
1837
function get_countries_list_from_array($combo = false)
1838
{
1839
    $a_countries = [
1840
        "Afghanistan", "Albania", "Algeria", "Andorra", "Angola", "Antigua and Barbuda", "Argentina", "Armenia", "Australia", "Austria", "Azerbaijan",
1841
        "Bahamas", "Bahrain", "Bangladesh", "Barbados", "Belarus", "Belgium", "Belize", "Benin", "Bhutan", "Bolivia", "Bosnia and Herzegovina", "Botswana", "Brazil", "Brunei", "Bulgaria", "Burkina Faso", "Burundi",
1842
        "Cambodia", "Cameroon", "Canada", "Cape Verde", "Central African Republic", "Chad", "Chile", "China", "Colombi", "Comoros", "Congo (Brazzaville)", "Congo", "Costa Rica", "Cote d'Ivoire", "Croatia", "Cuba", "Cyprus", "Czech Republic",
1843
        "Denmark", "Djibouti", "Dominica", "Dominican Republic",
1844
        "East Timor (Timor Timur)", "Ecuador", "Egypt", "El Salvador", "Equatorial Guinea", "Eritrea", "Estonia", "Ethiopia",
1845
        "Fiji", "Finland", "France",
1846
        "Gabon", "Gambia, The", "Georgia", "Germany", "Ghana", "Greece", "Grenada", "Guatemala", "Guinea", "Guinea-Bissau", "Guyana",
1847
        "Haiti", "Honduras", "Hungary",
1848
        "Iceland", "India", "Indonesia", "Iran", "Iraq", "Ireland", "Israel", "Italy",
1849
        "Jamaica", "Japan", "Jordan",
1850
        "Kazakhstan", "Kenya", "Kiribati", "Korea, North", "Korea, South", "Kuwait", "Kyrgyzstan",
1851
        "Laos", "Latvia", "Lebanon", "Lesotho", "Liberia", "Libya", "Liechtenstein", "Lithuania", "Luxembourg",
1852
        "Macedonia", "Madagascar", "Malawi", "Malaysia", "Maldives", "Mali", "Malta", "Marshall Islands", "Mauritania", "Mauritius", "Mexico", "Micronesia", "Moldova", "Monaco", "Mongolia", "Morocco", "Mozambique", "Myanmar",
1853
        "Namibia", "Nauru", "Nepa", "Netherlands", "New Zealand", "Nicaragua", "Niger", "Nigeria", "Norway",
1854
        "Oman",
1855
        "Pakistan", "Palau", "Panama", "Papua New Guinea", "Paraguay", "Peru", "Philippines", "Poland", "Portugal",
1856
        "Qatar",
1857
        "Romania", "Russia", "Rwanda",
1858
        "Saint Kitts and Nevis", "Saint Lucia", "Saint Vincent", "Samoa", "San Marino", "Sao Tome and Principe", "Saudi Arabia", "Senegal", "Serbia and Montenegro", "Seychelles", "Sierra Leone", "Singapore", "Slovakia", "Slovenia", "Solomon Islands", "Somalia", "South Africa", "Spain", "Sri Lanka", "Sudan", "Suriname", "Swaziland", "Sweden", "Switzerland", "Syria",
1859
        "Taiwan", "Tajikistan", "Tanzania", "Thailand", "Togo", "Tonga", "Trinidad and Tobago", "Tunisia", "Turkey", "Turkmenistan", "Tuvalu",
1860
        "Uganda", "Ukraine", "United Arab Emirates", "United Kingdom", "United States", "Uruguay", "Uzbekistan",
1861
        "Vanuatu", "Vatican City", "Venezuela", "Vietnam",
1862
        "Yemen",
1863
        "Zambia", "Zimbabwe",
1864
    ];
1865
    if ($combo) {
1866
        $country_select = '<select class="selectpicker show-tick" id="country" name="country">';
1867
        $country_select .= '<option value="">--- '.get_lang('Select one').' ---</option>';
1868
        foreach ($a_countries as $country) {
1869
            $country_select .= '<option value="'.$country.'">'.$country.'</option>';
1870
        }
1871
        $country_select .= '</select>';
1872
1873
        return $country_select;
1874
    }
1875
1876
    return $a_countries;
1877
}
1878
1879
/**
1880
 * Lock settings that can't be changed in other portals.
1881
 */
1882
function lockSettings()
1883
{
1884
    $settings = api_get_locked_settings();
1885
    $table = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
1886
    foreach ($settings as $setting) {
1887
        $sql = "UPDATE $table SET access_url_locked = 1 WHERE variable  = '$setting'";
1888
        Database::query($sql);
1889
    }
1890
}
1891
1892
/**
1893
 * Update dir values.
1894
 */
1895
function updateDirAndFilesPermissions()
1896
{
1897
    $table = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
1898
    $permissions_for_new_directories = isset($_SESSION['permissions_for_new_directories']) ? $_SESSION['permissions_for_new_directories'] : 0770;
1899
    $permissions_for_new_files = isset($_SESSION['permissions_for_new_files']) ? $_SESSION['permissions_for_new_files'] : 0660;
1900
    // use decoct() to store as string
1901
    Database::update(
1902
        $table,
1903
        ['selected_value' => '0'.decoct($permissions_for_new_directories)],
1904
        ['variable = ?' => 'permissions_for_new_directories']
1905
    );
1906
1907
    Database::update(
1908
        $table,
1909
        ['selected_value' => '0'.decoct($permissions_for_new_files)],
1910
        ['variable = ?' => 'permissions_for_new_files']
1911
    );
1912
1913
    if (isset($_SESSION['permissions_for_new_directories'])) {
1914
        unset($_SESSION['permissions_for_new_directories']);
1915
    }
1916
1917
    if (isset($_SESSION['permissions_for_new_files'])) {
1918
        unset($_SESSION['permissions_for_new_files']);
1919
    }
1920
}
1921
1922
/**
1923
 * @param $current_value
1924
 * @param $wanted_value
1925
 *
1926
 * @return string
1927
 */
1928
function compare_setting_values($current_value, $wanted_value)
1929
{
1930
    $current_value_string = $current_value;
1931
    $current_value = (float) $current_value;
1932
    $wanted_value = (float) $wanted_value;
1933
1934
    if ($current_value >= $wanted_value) {
1935
        return Display::label($current_value_string, 'success');
1936
    } else {
1937
        return Display::label($current_value_string, 'important');
1938
    }
1939
}
1940
1941
/**
1942
 * Save settings values.
1943
 *
1944
 * @param string $organizationName
1945
 * @param string $organizationUrl
1946
 * @param string $siteName
1947
 * @param string $adminEmail
1948
 * @param string $adminLastName
1949
 * @param string $adminFirstName
1950
 * @param string $language
1951
 * @param string $allowRegistration
1952
 * @param string $allowTeacherSelfRegistration
1953
 * @param string $installationProfile          The name of an installation profile file in main/install/profiles/
1954
 */
1955
function installSettings(
1956
    $organizationName,
1957
    $organizationUrl,
1958
    $siteName,
1959
    $adminEmail,
1960
    $adminLastName,
1961
    $adminFirstName,
1962
    $language,
1963
    $allowRegistration,
1964
    $allowTeacherSelfRegistration,
1965
    $installationProfile = ''
1966
) {
1967
    error_log('installSettings');
1968
    $allowTeacherSelfRegistration = $allowTeacherSelfRegistration ? 'true' : 'false';
1969
1970
    $settings = [
1971
        'institution' => $organizationName,
1972
        'institution_url' => $organizationUrl,
1973
        'site_name' => $siteName,
1974
        'administrator_email' => $adminEmail,
1975
        'administrator_surname' => $adminLastName,
1976
        'administrator_name' => $adminFirstName,
1977
        'platform_language' => $language,
1978
        'allow_registration' => $allowRegistration,
1979
        'allow_registration_as_teacher' => $allowTeacherSelfRegistration,
1980
    ];
1981
1982
    foreach ($settings as $variable => $value) {
1983
        $sql = "UPDATE settings_current
1984
                SET selected_value = '$value'
1985
                WHERE variable = '$variable'";
1986
        Database::query($sql);
1987
    }
1988
    installProfileSettings($installationProfile);
1989
}
1990
1991
/**
1992
 * Executes DB changes based in the classes defined in
1993
 * src/CoreBundle/Migrations/Schema/*.
1994
 *
1995
 * @param string $chamiloVersion
1996
 *
1997
 * @throws \Doctrine\DBAL\DBALException
1998
 *
1999
 * @return bool
2000
 */
2001
function migrate($chamiloVersion, EntityManager $manager)
2002
{
2003
    $debug = true;
2004
    $connection = $manager->getConnection();
2005
2006
    $config = new \Doctrine\DBAL\Migrations\Configuration\Configuration($connection);
2007
2008
    // Table name that will store migrations log (will be created automatically,
2009
    // default name is: doctrine_migration_versions)
2010
    $config->setMigrationsTableName('version');
2011
    // Namespace of your migration classes, do not forget escape slashes, do not add last slash
2012
    $config->setMigrationsNamespace('Chamilo\CoreBundle\Migrations\Schema\V'.$chamiloVersion);
2013
    // Directory where your migrations are located
2014
    $versionPath = api_get_path(SYS_PATH).'src/CoreBundle/Migrations/Schema/V'.$chamiloVersion;
2015
    error_log("Reading files from dir: $versionPath");
2016
    $config->setMigrationsDirectory($versionPath);
2017
    // Load your migrations
2018
    $config->registerMigrationsFromDirectory($config->getMigrationsDirectory());
2019
2020
    $migration = new \Doctrine\DBAL\Migrations\Migration($config);
2021
    $versions = $config->getMigrations();
2022
2023
    /** @var Doctrine\DBAL\Migrations\Version $migrationItem */
2024
    foreach ($versions as $version) {
2025
        $version->getMigration()->setEntityManager($manager);
2026
    }
2027
2028
    $to = null; // if $to == null then schema will be migrated to latest version
2029
    echo '<pre>';
2030
    try {
2031
        // Execute migration!
2032
        $migratedSQL = $migration->migrate($to);
2033
2034
        if ($debug) {
2035
            foreach ($migratedSQL as $version => $sqlList) {
2036
                echo "VERSION: $version<br>";
2037
                echo '----------------------------------------------<br />';
2038
                $total = count($sqlList);
2039
                error_log("VERSION: $version");
2040
                error_log("# queries: $total");
2041
                $counter = 1;
2042
                foreach ($sqlList as $sql) {
2043
                    echo "<code>$sql</code><br>";
2044
                    error_log("$counter/$total : $sql");
2045
                    $counter++;
2046
                }
2047
            }
2048
2049
            echo "<br>DONE!<br>";
2050
        }
2051
2052
        return true;
2053
    } catch (Exception $ex) {
2054
        if ($debug) {
2055
            echo "ERROR: {$ex->getMessage()}<br>";
2056
2057
            return false;
2058
        }
2059
    }
2060
2061
    echo '</pre>';
2062
2063
    return false;
2064
}
2065
2066
/**
2067
 * @throws \Doctrine\DBAL\DBALException
2068
 */
2069
function fixIds(EntityManager $em)
2070
{
2071
    $connection = $em->getConnection();
2072
    $database = new Database();
2073
    $database->setManager($em);
2074
    $debug = true;
2075
    if ($debug) {
2076
        error_log('fixIds');
2077
    }
2078
2079
    // Create temporary indexes to increase speed of the following operations
2080
    // Adding and removing indexes will usually take much less time than
2081
    // the execution without indexes of the queries in this function, particularly
2082
    // for large tables
2083
    $sql = "ALTER TABLE c_document ADD INDEX tmpidx_doc(c_id, id)";
2084
    $connection->executeQuery($sql);
2085
    $sql = "ALTER TABLE c_student_publication ADD INDEX tmpidx_stud (c_id, id)";
2086
    $connection->executeQuery($sql);
2087
    $sql = "ALTER TABLE c_quiz ADD INDEX tmpidx_quiz (c_id, id)";
2088
    $connection->executeQuery($sql);
2089
    $sql = "ALTER TABLE c_item_property ADD INDEX tmpidx_ip (to_group_id)";
2090
    $connection->executeQuery($sql);
2091
2092
    $sql = "SELECT * FROM c_lp_item";
2093
    $result = $connection->fetchAll($sql);
2094
    foreach ($result as $item) {
2095
        $courseId = $item['c_id'];
2096
        $iid = isset($item['iid']) ? intval($item['iid']) : 0;
2097
        $ref = isset($item['ref']) ? intval($item['ref']) : 0;
2098
        $sql = null;
2099
2100
        $newId = '';
2101
2102
        switch ($item['item_type']) {
2103
            case TOOL_LINK:
2104
                $sql = "SELECT * FROM c_link WHERE c_id = $courseId AND id = $ref";
2105
                $data = $connection->fetchAssoc($sql);
2106
                if ($data) {
2107
                    $newId = $data['iid'];
2108
                }
2109
                break;
2110
            case TOOL_STUDENTPUBLICATION:
2111
                $sql = "SELECT * FROM c_student_publication WHERE c_id = $courseId AND id = $ref";
2112
                $data = $connection->fetchAssoc($sql);
2113
                if ($data) {
2114
                    $newId = $data['iid'];
2115
                }
2116
                break;
2117
            case TOOL_QUIZ:
2118
                $sql = "SELECT * FROM c_quiz WHERE c_id = $courseId AND id = $ref";
2119
                $data = $connection->fetchAssoc($sql);
2120
                if ($data) {
2121
                    $newId = $data['iid'];
2122
                }
2123
                break;
2124
            case TOOL_DOCUMENT:
2125
                $sql = "SELECT * FROM c_document WHERE c_id = $courseId AND id = $ref";
2126
                $data = $connection->fetchAssoc($sql);
2127
                if ($data) {
2128
                    $newId = $data['iid'];
2129
                }
2130
                break;
2131
            case TOOL_FORUM:
2132
                $sql = "SELECT * FROM c_forum_forum WHERE c_id = $courseId AND forum_id = $ref";
2133
                $data = $connection->fetchAssoc($sql);
2134
                if ($data) {
2135
                    $newId = $data['iid'];
2136
                }
2137
                break;
2138
            case 'thread':
2139
                $sql = "SELECT * FROM c_forum_thread WHERE c_id = $courseId AND thread_id = $ref";
2140
                $data = $connection->fetchAssoc($sql);
2141
                if ($data) {
2142
                    $newId = $data['iid'];
2143
                }
2144
                break;
2145
        }
2146
2147
        if (!empty($sql) && !empty($newId) && !empty($iid)) {
2148
            $sql = "UPDATE c_lp_item SET ref = $newId WHERE iid = $iid";
2149
            $connection->executeQuery($sql);
2150
        }
2151
    }
2152
2153
    // Set NULL if session = 0
2154
    $sql = "UPDATE c_item_property SET session_id = NULL WHERE session_id = 0";
2155
    $connection->executeQuery($sql);
2156
2157
    // Set NULL if group = 0
2158
    $sql = "UPDATE c_item_property SET to_group_id = NULL WHERE to_group_id = 0";
2159
    $connection->executeQuery($sql);
2160
2161
    // Set NULL if insert_user_id = 0
2162
    $sql = "UPDATE c_item_property SET insert_user_id = NULL WHERE insert_user_id = 0";
2163
    $connection->executeQuery($sql);
2164
2165
    // Delete session data of sessions that don't exist.
2166
    $sql = "DELETE FROM c_item_property
2167
            WHERE session_id IS NOT NULL AND session_id NOT IN (SELECT id FROM session)";
2168
    $connection->executeQuery($sql);
2169
2170
    // Delete group data of groups that don't exist.
2171
    $sql = "DELETE FROM c_item_property
2172
            WHERE to_group_id <> 0 AND to_group_id IS NOT NULL AND to_group_id NOT IN (SELECT DISTINCT iid FROM c_group_info)";
2173
    $connection->executeQuery($sql);
2174
    // This updates the group_id with c_group_info.iid instead of c_group_info.id
2175
2176
    if ($debug) {
2177
        error_log('update iids');
2178
    }
2179
2180
    $groupTableToFix = [
2181
        'c_group_rel_user',
2182
        'c_group_rel_tutor',
2183
        'c_permission_group',
2184
        'c_role_group',
2185
        'c_survey_invitation',
2186
        'c_attendance_calendar_rel_group',
2187
    ];
2188
2189
    foreach ($groupTableToFix as $table) {
2190
        $sql = "SELECT * FROM $table";
2191
        $result = $connection->fetchAll($sql);
2192
        foreach ($result as $item) {
2193
            $iid = $item['iid'];
2194
            $courseId = $item['c_id'];
2195
            $groupId = intval($item['group_id']);
2196
2197
            // Fix group id
2198
            if (!empty($groupId)) {
2199
                $sql = "SELECT * FROM c_group_info
2200
                        WHERE c_id = $courseId AND id = $groupId
2201
                        LIMIT 1";
2202
                $data = $connection->fetchAssoc($sql);
2203
                if (!empty($data)) {
2204
                    $newGroupId = $data['iid'];
2205
                    $sql = "UPDATE $table SET group_id = $newGroupId
2206
                            WHERE iid = $iid";
2207
                    $connection->executeQuery($sql);
2208
                } else {
2209
                    // The group does not exists clean this record
2210
                    $sql = "DELETE FROM $table WHERE iid = $iid";
2211
                    $connection->executeQuery($sql);
2212
                }
2213
            }
2214
        }
2215
    }
2216
2217
    // Fix c_item_property
2218
    if ($debug) {
2219
        error_log('update c_item_property');
2220
    }
2221
2222
    $sql = "SELECT * FROM course";
2223
    $courseList = $connection->fetchAll($sql);
2224
    if ($debug) {
2225
        error_log('Getting course list');
2226
    }
2227
2228
    $totalCourse = count($courseList);
2229
    $counter = 0;
2230
2231
    foreach ($courseList as $courseData) {
2232
        $courseId = $courseData['id'];
2233
        if ($debug) {
2234
            error_log('Updating course: '.$courseData['code']);
2235
        }
2236
2237
        $sql = "SELECT * FROM c_item_property WHERE c_id = $courseId";
2238
        $result = $connection->fetchAll($sql);
2239
        foreach ($result as $item) {
2240
            $sessionId = intval($item['session_id']);
2241
            $groupId = intval($item['to_group_id']);
2242
            $iid = $item['iid'];
2243
            $ref = $item['ref'];
2244
2245
            // Fix group id
2246
            // Commented group id is already fixed in Version20150603181728.php
2247
            /*if (!empty($groupId)) {
2248
                $sql = "SELECT * FROM c_group_info
2249
                        WHERE c_id = $courseId AND id = $groupId";
2250
                $data = $connection->fetchAssoc($sql);
2251
                if (!empty($data)) {
2252
                    $newGroupId = $data['iid'];
2253
                    $sql = "UPDATE c_item_property SET to_group_id = $newGroupId
2254
                            WHERE iid = $iid";
2255
                    $connection->executeQuery($sql);
2256
                } else {
2257
                    // The group does not exists clean this record
2258
                    $sql = "DELETE FROM c_item_property WHERE iid = $iid";
2259
                    $connection->executeQuery($sql);
2260
                }
2261
            }*/
2262
2263
            $sql = '';
2264
            $newId = '';
2265
            switch ($item['tool']) {
2266
                case TOOL_LINK:
2267
                    $sql = "SELECT * FROM c_link WHERE c_id = $courseId AND id = $ref ";
2268
                    break;
2269
                case TOOL_STUDENTPUBLICATION:
2270
                    $sql = "SELECT * FROM c_student_publication WHERE c_id = $courseId AND id = $ref";
2271
                    break;
2272
                case TOOL_QUIZ:
2273
                    $sql = "SELECT * FROM c_quiz WHERE c_id = $courseId AND id = $ref";
2274
                    break;
2275
                case TOOL_DOCUMENT:
2276
                    $sql = "SELECT * FROM c_document WHERE c_id = $courseId AND id = $ref";
2277
                    break;
2278
                case TOOL_FORUM:
2279
                    $sql = "SELECT * FROM c_forum_forum WHERE c_id = $courseId AND id = $ref";
2280
                    break;
2281
                case 'thread':
2282
                    $sql = "SELECT * FROM c_forum_thread WHERE c_id = $courseId AND id = $ref";
2283
                    break;
2284
            }
2285
2286
            if (!empty($sql) && !empty($newId)) {
2287
                $data = $connection->fetchAssoc($sql);
2288
                if (isset($data['iid'])) {
2289
                    $newId = $data['iid'];
2290
                }
2291
                $sql = "UPDATE c_item_property SET ref = $newId WHERE iid = $iid";
2292
                error_log($sql);
2293
                $connection->executeQuery($sql);
2294
            }
2295
        }
2296
2297
        if ($debug) {
2298
            // Print a status in the log once in a while
2299
            error_log("Course process #$counter/$totalCourse");
2300
        }
2301
        $counter++;
2302
    }
2303
2304
    if ($debug) {
2305
        error_log('update gradebook_link');
2306
    }
2307
2308
    // Fix gradebook_link
2309
    $sql = "SELECT * FROM gradebook_link";
2310
    $result = $connection->fetchAll($sql);
2311
    foreach ($result as $item) {
2312
        $courseCode = $item['course_code'];
2313
        $categoryId = (int) $item['category_id'];
2314
2315
        $sql = "SELECT * FROM course WHERE code = '$courseCode'";
2316
        $courseInfo = $connection->fetchAssoc($sql);
2317
        if (empty($courseInfo)) {
2318
            continue;
2319
        }
2320
2321
        $courseId = $courseInfo['id'];
2322
2323
        $ref = $item['ref_id'];
2324
        $iid = $item['id'];
2325
2326
        $sql = '';
2327
        switch ($item['type']) {
2328
            case LINK_LEARNPATH:
2329
                $sql = "SELECT * FROM c_link WHERE c_id = $courseId AND id = $ref ";
2330
                break;
2331
            case LINK_STUDENTPUBLICATION:
2332
                $sql = "SELECT * FROM c_student_publication WHERE c_id = $courseId AND id = $ref";
2333
                break;
2334
            case LINK_EXERCISE:
2335
                $sql = "SELECT * FROM c_quiz WHERE c_id = $courseId AND id = $ref";
2336
                break;
2337
            case LINK_ATTENDANCE:
2338
                //$sql = "SELECT * FROM c_document WHERE c_id = $courseId AND id = $ref";
2339
                break;
2340
            case LINK_FORUM_THREAD:
2341
                $sql = "SELECT * FROM c_forum_thread WHERE c_id = $courseId AND thread_id = $ref";
2342
                break;
2343
        }
2344
2345
        if (!empty($sql)) {
2346
            $data = $connection->fetchAssoc($sql);
2347
            if (isset($data) && isset($data['iid'])) {
2348
                $newId = $data['iid'];
2349
                $sql = "UPDATE gradebook_link SET ref_id = $newId
2350
                        WHERE id = $iid AND course_code = '$courseCode' AND category_id = $categoryId ";
2351
                $connection->executeQuery($sql);
2352
            }
2353
        }
2354
    }
2355
2356
    if ($debug) {
2357
        error_log('update groups');
2358
    }
2359
2360
    $sql = 'SELECT * FROM groups';
2361
    $result = $connection->executeQuery($sql);
2362
    $groups = $result->fetchAll();
2363
    $oldGroups = [];
2364
    if (!empty($groups)) {
2365
        foreach ($groups as $group) {
2366
            if (empty($group['name'])) {
2367
                continue;
2368
            }
2369
2370
            $params = [
2371
                'name' => $group['name'],
2372
                'description' => $group['description'],
2373
                'group_type' => 1,
2374
                'picture' => $group['picture_uri'],
2375
                'url' => $group['url'],
2376
                'visibility' => $group['visibility'],
2377
                'updated_at' => $group['updated_on'],
2378
                'created_at' => $group['created_on'],
2379
            ];
2380
            $connection->insert('usergroup', $params);
2381
            $id = $connection->lastInsertId('id');
2382
            $oldGroups[$group['id']] = $id;
2383
        }
2384
    }
2385
2386
    if (!empty($oldGroups)) {
2387
        error_log('Moving group files');
2388
        foreach ($oldGroups as $oldId => $newId) {
2389
            $path = get_group_picture_path_by_id(
2390
                $oldId,
2391
                'system'
2392
            );
2393
2394
            if (!empty($path)) {
2395
                $newPath = str_replace(
2396
                    "groups/$oldId/",
2397
                    "groups/$newId/",
2398
                    $path['dir']
2399
                );
2400
                $command = "mv {$path['dir']} $newPath ";
2401
                error_log("Executing $command");
2402
                system($command);
2403
            }
2404
        }
2405
2406
        $sql = "SELECT * FROM group_rel_user";
2407
        $result = $connection->executeQuery($sql);
2408
        $dataList = $result->fetchAll();
2409
2410
        if (!empty($dataList)) {
2411
            foreach ($dataList as $data) {
2412
                if (isset($oldGroups[$data['group_id']])) {
2413
                    $data['group_id'] = $oldGroups[$data['group_id']];
2414
                    $userId = $data['user_id'];
2415
2416
                    $sql = "SELECT id FROM user WHERE user_id = $userId";
2417
                    $userResult = $connection->executeQuery($sql);
2418
                    $userInfo = $userResult->fetch();
2419
                    if (empty($userInfo)) {
2420
                        continue;
2421
                    }
2422
2423
                    $sql = "INSERT INTO usergroup_rel_user (usergroup_id, user_id, relation_type)
2424
                            VALUES ('{$data['group_id']}', '{$userId}', '{$data['relation_type']}')";
2425
                    $connection->executeQuery($sql);
2426
                }
2427
            }
2428
        }
2429
2430
        $sql = "SELECT * FROM group_rel_group";
2431
        $result = $connection->executeQuery($sql);
2432
        $dataList = $result->fetchAll();
2433
2434
        if (!empty($dataList)) {
2435
            foreach ($dataList as $data) {
2436
                if (isset($oldGroups[$data['group_id']]) && isset($oldGroups[$data['subgroup_id']])) {
2437
                    $data['group_id'] = $oldGroups[$data['group_id']];
2438
                    $data['subgroup_id'] = $oldGroups[$data['subgroup_id']];
2439
                    $sql = "INSERT INTO usergroup_rel_usergroup (group_id, subgroup_id, relation_type)
2440
                            VALUES ('{$data['group_id']}', '{$data['subgroup_id']}', '{$data['relation_type']}')";
2441
                    $connection->executeQuery($sql);
2442
                }
2443
            }
2444
        }
2445
2446
        $sql = "SELECT * FROM announcement_rel_group";
2447
        $result = $connection->executeQuery($sql);
2448
        $dataList = $result->fetchAll();
2449
2450
        if (!empty($dataList)) {
2451
            foreach ($dataList as $data) {
2452
                if (isset($oldGroups[$data['group_id']])) {
2453
                    // Deleting relation
2454
                    $sql = "DELETE FROM announcement_rel_group WHERE group_id = {$data['group_id']}";
2455
                    $connection->executeQuery($sql);
2456
2457
                    // Add new relation
2458
                    $data['group_id'] = $oldGroups[$data['group_id']];
2459
                    $sql = "INSERT INTO announcement_rel_group(group_id, announcement_id)
2460
                            VALUES ('{$data['group_id']}', '{$data['announcement_id']}')";
2461
                    $connection->executeQuery($sql);
2462
                }
2463
            }
2464
        }
2465
2466
        $sql = "SELECT * FROM group_rel_tag";
2467
        $result = $connection->executeQuery($sql);
2468
        $dataList = $result->fetchAll();
2469
        if (!empty($dataList)) {
2470
            foreach ($dataList as $data) {
2471
                if (isset($oldGroups[$data['group_id']])) {
2472
                    $data['group_id'] = $oldGroups[$data['group_id']];
2473
                    $sql = "INSERT INTO usergroup_rel_tag (tag_id, usergroup_id)
2474
                            VALUES ('{$data['tag_id']}', '{$data['group_id']}')";
2475
                    $connection->executeQuery($sql);
2476
                }
2477
            }
2478
        }
2479
    }
2480
2481
    if ($debug) {
2482
        error_log('update extra fields');
2483
    }
2484
2485
    // Extra fields
2486
    $extraFieldTables = [
2487
        ExtraField::USER_FIELD_TYPE => Database::get_main_table(TABLE_MAIN_USER_FIELD),
2488
        ExtraField::COURSE_FIELD_TYPE => Database::get_main_table(TABLE_MAIN_COURSE_FIELD),
2489
        //ExtraField::LP_FIELD_TYPE => Database::get_main_table(TABLE_MAIN_LP_FIELD),
2490
        ExtraField::SESSION_FIELD_TYPE => Database::get_main_table(TABLE_MAIN_SESSION_FIELD),
2491
        //ExtraField::CALENDAR_FIELD_TYPE => Database::get_main_table(TABLE_MAIN_CALENDAR_EVENT_FIELD),
2492
        //ExtraField::QUESTION_FIELD_TYPE => Database::get_main_table(TABLE_MAIN_CALENDAR_EVENT_FIELD),
2493
        //ExtraField::USER_FIELD_TYPE => //Database::get_main_table(TABLE_MAIN_SPECIFIC_FIELD),
2494
    ];
2495
2496
    foreach ($extraFieldTables as $type => $table) {
2497
        $sql = "SELECT * FROM $table ";
2498
        if ($debug) {
2499
            error_log($sql);
2500
        }
2501
        $result = $connection->query($sql);
2502
        $fields = $result->fetchAll();
2503
2504
        foreach ($fields as $field) {
2505
            if ($debug) {
2506
                error_log("Loading field: ".$field['field_variable']);
2507
            }
2508
            $originalId = $field['id'];
2509
2510
            $params = [
2511
                'extra_field_type' => $type,
2512
                'variable' => $field['field_variable'],
2513
                'field_type' => $field['field_type'],
2514
                'display_text' => $field['field_display_text'],
2515
                'default_value' => $field['field_default_value'],
2516
                'field_order' => $field['field_order'],
2517
                'visible' => $field['field_visible'],
2518
                'changeable' => $field['field_changeable'],
2519
                'filter' => $field['field_filter'],
2520
            ];
2521
2522
            $connection->insert('extra_field', $params);
2523
            $newExtraFieldId = $connection->lastInsertId();
2524
2525
            $values = [];
2526
            $handlerId = null;
2527
            switch ($type) {
2528
                case ExtraField::USER_FIELD_TYPE:
2529
                    $optionTable = Database::get_main_table(
2530
                        TABLE_MAIN_USER_FIELD_OPTIONS
2531
                    );
2532
                    $valueTable = Database::get_main_table(
2533
                        TABLE_MAIN_USER_FIELD_VALUES
2534
                    );
2535
                    $handlerId = 'user_id';
2536
                    break;
2537
                case ExtraField::COURSE_FIELD_TYPE:
2538
                    $optionTable = Database::get_main_table(
2539
                        TABLE_MAIN_COURSE_FIELD_OPTIONS
2540
                    );
2541
                    $valueTable = Database::get_main_table(
2542
                        TABLE_MAIN_COURSE_FIELD_VALUES
2543
                    );
2544
                    $handlerId = 'c_id';
2545
                    break;
2546
                case ExtraField::SESSION_FIELD_TYPE:
2547
                    $optionTable = Database::get_main_table(
2548
                        TABLE_MAIN_SESSION_FIELD_OPTIONS
2549
                    );
2550
                    $valueTable = Database::get_main_table(
2551
                        TABLE_MAIN_SESSION_FIELD_VALUES
2552
                    );
2553
                    $handlerId = 'session_id';
2554
                    break;
2555
            }
2556
2557
            if (!empty($optionTable)) {
2558
                $sql = "SELECT * FROM $optionTable WHERE field_id = $originalId ";
2559
                $result = $connection->query($sql);
2560
                $options = $result->fetchAll();
2561
2562
                foreach ($options as $option) {
2563
                    $params = [
2564
                        'display_text' => $option['option_display_text'],
2565
                        'field_id' => $newExtraFieldId,
2566
                        'option_order' => $option['option_order'],
2567
                        'option_value' => $option['option_value'],
2568
                    ];
2569
                    $connection->insert('extra_field_options', $params);
2570
                }
2571
2572
                $sql = "SELECT * FROM $valueTable WHERE field_id = $originalId ";
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $valueTable does not seem to be defined for all execution paths leading up to this point.
Loading history...
2573
                $result = $connection->query($sql);
2574
                $values = $result->fetchAll();
2575
                if ($debug) {
2576
                    error_log("Fetch all values for field");
2577
                }
2578
            }
2579
2580
            if (!empty($values)) {
2581
                if ($debug) {
2582
                    error_log("Saving field value in new table");
2583
                }
2584
                $k = 0;
2585
                foreach ($values as $value) {
2586
                    if (isset($value[$handlerId])) {
2587
                        // Insert without the use of the entity as it reduces
2588
                        // speed to 2 records per second (much too slow)
2589
                        $params = [
2590
                            'field_id' => $newExtraFieldId,
2591
                            'value' => $value['field_value'],
2592
                            'item_id' => $value[$handlerId],
2593
                        ];
2594
                        $connection->insert('extra_field_values', $params);
2595
                        if ($debug && (0 == $k % 10000)) {
2596
                            error_log("Saving field $k");
2597
                        }
2598
                        $k++;
2599
                    }
2600
                }
2601
            }
2602
        }
2603
    }
2604
2605
    if ($debug) {
0 ignored issues
show
introduced by
$debug is of type mixed, thus it always evaluated to true.
Loading history...
2606
        error_log('Remove index');
2607
    }
2608
2609
    // Drop temporary indexes added to increase speed of this function's queries
2610
    $sql = "ALTER TABLE c_document DROP INDEX tmpidx_doc";
2611
    $connection->executeQuery($sql);
2612
    $sql = "ALTER TABLE c_student_publication DROP INDEX tmpidx_stud";
2613
    $connection->executeQuery($sql);
2614
    $sql = "ALTER TABLE c_quiz DROP INDEX tmpidx_quiz";
2615
    $connection->executeQuery($sql);
2616
    $sql = "ALTER TABLE c_item_property DROP INDEX tmpidx_ip";
2617
    $connection->executeQuery($sql);
2618
2619
    if ($debug) {
2620
        error_log('Finish fixId function');
2621
    }
2622
2623
    fixLpId($connection, true);
2624
}
2625
2626
/**
2627
 * @param \Doctrine\DBAL\Connection $connection
2628
 * @param $debug
2629
 *
2630
 * @throws \Doctrine\DBAL\DBALException
2631
 */
2632
function fixLpId($connection, $debug)
2633
{
2634
    if ($debug) {
2635
        error_log('Fix lp.id lp.iids');
2636
    }
2637
2638
    $sql = 'SELECT id, title, code FROM course';
2639
    $result = $connection->query($sql);
2640
    $courses = $result->fetchAll();
2641
2642
    $sql = 'SELECT id FROM session';
2643
    $result = $connection->query($sql);
2644
    $sessions = $result->fetchAll();
2645
2646
    $tblCLp = Database::get_course_table(TABLE_LP_MAIN);
2647
    $tblCLpItem = Database::get_course_table(TABLE_LP_ITEM);
2648
    $toolTable = Database::get_course_table(TABLE_TOOL_LIST);
2649
2650
    if (!empty($sessions)) {
2651
        $sessions = array_column($sessions, 'id');
2652
        $sessions[] = 0;
2653
    } else {
2654
        $sessions = [0];
2655
    }
2656
2657
    foreach ($courses as $course) {
2658
        $courseId = $course['id'];
2659
        $sql = "SELECT * FROM $tblCLp WHERE c_id = $courseId AND iid <> id ORDER by iid";
2660
        $result = $connection->query($sql);
2661
        if ($debug) {
2662
            error_log('-------------');
2663
            error_log("Entering Lps in course #$courseId");
2664
            error_log($sql);
2665
        }
2666
        $lpList = $result->fetchAll();
2667
        $myOnlyLpList = [];
2668
        if (!empty($lpList)) {
2669
            foreach ($lpList as $lpInfo) {
2670
                $oldId = $lpInfo['id'];
2671
                $sql = "SELECT * FROM $tblCLpItem WHERE c_id = $courseId AND lp_id = $oldId ORDER by iid";
2672
                $result = $connection->query($sql);
2673
                $items = $result->fetchAll();
2674
                $lpInfo['lp_list'] = $items;
2675
                $myOnlyLpList[] = $lpInfo;
2676
            }
2677
        }
2678
2679
        if (!empty($myOnlyLpList)) {
2680
            foreach ($myOnlyLpList as $lpInfo) {
2681
                $lpIid = $lpInfo['iid'];
2682
                $oldId = $lpInfo['id'];
2683
                $items = $lpInfo['lp_list'];
2684
2685
                if (empty($items)) {
2686
                    continue;
2687
                }
2688
                $itemList = [];
2689
                foreach ($items as $subItem) {
2690
                    $itemList[$subItem['id']] = $subItem['iid'];
2691
                }
2692
                $variablesToFix = [
2693
                    'parent_item_id',
2694
                    'next_item_id',
2695
                    'prerequisite',
2696
                    'previous_item_id',
2697
                ];
2698
2699
                foreach ($sessions as $sessionId) {
2700
                    $correctLink = "lp/lp_controller.php?action=view&lp_id=$lpIid&id_session=$sessionId";
2701
                    $link = "newscorm/lp_controller.php?action=view&lp_id=$oldId&id_session=$sessionId";
2702
                    $secondLink = "lp/lp_controller.php?action=view&lp_id=$oldId&id_session=$sessionId";
2703
                    $sql = "UPDATE $toolTable
2704
                        SET link = '$correctLink'
2705
                        WHERE c_id = $courseId AND (link = '$link' OR link ='$secondLink')";
2706
                    $connection->query($sql);
2707
                }
2708
2709
                foreach ($items as $item) {
2710
                    $itemIid = $item['iid'];
2711
                    $itemId = $item['id'];
2712
                    foreach ($variablesToFix as $variable) {
2713
                        if (!empty($item[$variable]) && isset($itemList[$item[$variable]])) {
2714
                            $newId = $itemList[$item[$variable]];
2715
                            $sql = "UPDATE $tblCLpItem SET $variable = $newId
2716
                                    WHERE iid = $itemIid AND c_id = $courseId AND lp_id = $oldId";
2717
                            $connection->query($sql);
2718
                        }
2719
                    }
2720
2721
                    if ('document' == $item['item_type'] && !empty($item['path'])) {
2722
                        $oldDocumentId = $item['path'];
2723
                        $sql = "SELECT * FROM c_document WHERE c_id = $courseId AND id = $oldDocumentId";
2724
                        $result = $connection->query($sql);
2725
                        $document = $result->fetch();
2726
                        if (!empty($document)) {
2727
                            $newDocumentId = $document['iid'];
2728
                            if (!empty($newDocumentId)) {
2729
                                $sql = "UPDATE $tblCLpItem SET path = $newDocumentId
2730
                                    WHERE iid = $itemIid AND c_id = $courseId";
2731
                                $connection->query($sql);
2732
                                if ($debug) {
2733
                                    //error_log("Fix document: ");
2734
                                    //error_log($sql);
2735
                                }
2736
                            }
2737
                        }
2738
                    }
2739
2740
                    // c_lp_view
2741
                    $sql = "UPDATE c_lp_view SET last_item = $itemIid
2742
                            WHERE c_id = $courseId AND last_item = $itemId AND lp_id = $oldId";
2743
                    $connection->query($sql);
2744
2745
                    // c_lp_item_view
2746
                    $sql = "UPDATE c_lp_item_view SET lp_item_id = $itemIid
2747
                            WHERE c_id = $courseId AND lp_item_id = $itemId";
2748
                    $connection->query($sql);
2749
2750
                    // Update track_exercises
2751
                    $sql = "UPDATE track_e_exercises SET orig_lp_item_id = $itemIid
2752
                            WHERE c_id = $courseId AND orig_lp_id = $oldId AND orig_lp_item_id = $itemId";
2753
                    $connection->query($sql);
2754
2755
                    // c_forum_thread
2756
                    $sql = "UPDATE c_forum_thread SET lp_item_id = $itemIid
2757
                            WHERE c_id = $courseId AND lp_item_id = $itemId";
2758
                    $connection->query($sql);
2759
2760
                    // orig_lp_item_view_id
2761
                    $sql = "SELECT * FROM c_lp_view
2762
                            WHERE c_id = $courseId AND lp_id = $oldId";
2763
                    $result = $connection->query($sql);
2764
                    $itemViewList = $result->fetchAll();
2765
                    if ($itemViewList) {
2766
                        foreach ($itemViewList as $itemView) {
2767
                            $userId = $itemView['user_id'];
2768
                            $oldItemViewId = $itemView['id'];
2769
                            $newItemView = $itemView['iid'];
2770
2771
                            if (empty($oldItemViewId)) {
2772
                                continue;
2773
                            }
2774
2775
                            $sql = "UPDATE track_e_exercises
2776
                                SET orig_lp_item_view_id = $newItemView
2777
                                WHERE
2778
                                  c_id = $courseId AND
2779
                                  orig_lp_id = $oldId AND
2780
                                  orig_lp_item_id = $itemIid AND
2781
                                  orig_lp_item_view_id = $oldItemViewId AND
2782
                                  exe_user_id = $userId
2783
                                  ";
2784
                            $connection->query($sql);
2785
2786
                            /*$sql = "UPDATE c_lp_item_view
2787
                                    SET lp_view_id = $newItemView
2788
                                    WHERE
2789
                                      lp_view_id = $oldItemViewId AND
2790
                                      c_id = $courseId
2791
                                  ";
2792
                            $connection->query($sql);*/
2793
                        }
2794
                    }
2795
2796
                    $sql = "UPDATE $tblCLpItem SET lp_id = $lpIid
2797
                            WHERE c_id = $courseId AND lp_id = $oldId AND id = $itemId";
2798
                    $connection->query($sql);
2799
2800
                    $sql = "UPDATE $tblCLpItem SET id = iid
2801
                            WHERE c_id = $courseId AND lp_id = $oldId AND id = $itemId";
2802
                    $connection->query($sql);
2803
                }
2804
2805
                $sql = "UPDATE c_lp_view SET lp_id = $lpIid WHERE c_id = $courseId AND lp_id = $oldId";
2806
                $connection->query($sql);
2807
2808
                $sql = "UPDATE c_forum_forum SET lp_id = $lpIid WHERE c_id = $courseId AND lp_id = $oldId";
2809
                $connection->query($sql);
2810
2811
                // Update track_exercises.
2812
                $sql = "UPDATE track_e_exercises SET orig_lp_id = $lpIid
2813
                        WHERE c_id = $courseId AND orig_lp_id = $oldId";
2814
                $connection->query($sql);
2815
2816
                $sql = "UPDATE $tblCLp SET id = iid WHERE c_id = $courseId AND id = $oldId ";
2817
                $connection->query($sql);
2818
            }
2819
        }
2820
    }
2821
2822
    if ($debug) {
2823
        error_log('END Fix lp.id lp.iids');
2824
    }
2825
}
2826
2827
/**
2828
 * @param string $distFile
2829
 * @param string $envFile
2830
 * @param array  $params
2831
 */
2832
function updateEnvFile($distFile, $envFile, $params)
2833
{
2834
    $requirements = [
2835
        'DATABASE_HOST',
2836
        'DATABASE_PORT',
2837
        'DATABASE_NAME',
2838
        'DATABASE_USER',
2839
        'DATABASE_PASSWORD',
2840
        'APP_INSTALLED',
2841
        'APP_ENCRYPT_METHOD',
2842
    ];
2843
2844
    foreach ($requirements as $requirement) {
2845
        if (!isset($params['{{'.$requirement.'}}'])) {
2846
            throw new \Exception("The parameter $requirement is needed in order to edit the .env.local file");
2847
        }
2848
    }
2849
2850
    $contents = file_get_contents($distFile);
2851
    $contents = str_replace(array_keys($params), array_values($params), $contents);
2852
    file_put_contents($envFile, $contents);
2853
    error_log("File env saved here: $envFile");
2854
}
2855
2856
/**
2857
 * @param SymfonyContainer $container
2858
 * @param EntityManager    $manager
2859
 */
2860
function installGroups($container, $manager)
2861
{
2862
    // Creating fos_group (groups and roles)
2863
    $groups = [
2864
        [
2865
            'code' => 'ADMIN',
2866
            'title' => 'Administrators',
2867
            'roles' => ['ROLE_ADMIN'],
2868
        ],
2869
        [
2870
            'code' => 'STUDENT',
2871
            'title' => 'Students',
2872
            'roles' => ['ROLE_STUDENT'],
2873
        ],
2874
        [
2875
            'code' => 'TEACHER',
2876
            'title' => 'Teachers',
2877
            'roles' => ['ROLE_TEACHER'],
2878
        ],
2879
        [
2880
            'code' => 'RRHH',
2881
            'title' => 'Human resources manager',
2882
            'roles' => ['ROLE_RRHH'],
2883
        ],
2884
        [
2885
            'code' => 'SESSION_MANAGER',
2886
            'title' => 'Session',
2887
            'roles' => ['ROLE_SESSION_MANAGER'],
2888
        ],
2889
        [
2890
            'code' => 'QUESTION_MANAGER',
2891
            'title' => 'Question manager',
2892
            'roles' => ['ROLE_QUESTION_MANAGER'],
2893
        ],
2894
        [
2895
            'code' => 'STUDENT_BOSS',
2896
            'title' => 'Student boss',
2897
            'roles' => ['ROLE_STUDENT_BOSS'],
2898
        ],
2899
        [
2900
            'code' => 'INVITEE',
2901
            'title' => 'Invitee',
2902
            'roles' => ['ROLE_INVITEE'],
2903
        ],
2904
    ];
2905
    $repo = $manager->getRepository('ChamiloCoreBundle:Group');
2906
    foreach ($groups as $groupData) {
2907
        $criteria = ['code' => $groupData['code']];
2908
        $groupExists = $repo->findOneBy($criteria);
2909
        if (!$groupExists) {
2910
            $group = new Group($groupData['title']);
2911
            $group
2912
                ->setCode($groupData['code']);
2913
2914
            foreach ($groupData['roles'] as $role) {
2915
                $group->addRole($role);
2916
            }
2917
            $manager->persist($group);
2918
        }
2919
    }
2920
    $manager->flush();
2921
}
2922
2923
/**
2924
 * @param SymfonyContainer $container
2925
 */
2926
function installPages($container)
2927
{
2928
    error_log('installPages');
2929
2930
    //$siteManager = Container::getSiteManager();
2931
2932
    // Create site
2933
    /** @var Chamilo\PageBundle\Entity\Site $site */
2934
    /*$site = $siteManager->create();
2935
    $site->setHost('localhost');
2936
    $site->setEnabled(true);
2937
    $site->setName('localhost');
2938
    $site->setEnabledFrom(new \DateTime('now'));
2939
    $site->setEnabledTo(new \DateTime('+20 years'));
2940
    $site->setRelativePath('');
2941
    $site->setIsDefault(true);
2942
    $site->setLocale('en');
2943
    $siteManager->save($site);*/
2944
2945
    // Create home page
2946
    /** @var PageManager $pageManager */
2947
    /*$pageManager = $container->get('sonata.page.manager.page');
2948
    $page = $pageManager->create();
2949
    $page->setSlug('homepage');
2950
    $page->setUrl('/');
2951
    $page->setName('homepage');
2952
    $page->setTitle('home');
2953
    $page->setEnabled(true);
2954
    $page->setDecorate(1);
2955
    $page->setRequestMethod('GET|POST|HEAD|DELETE|PUT');
2956
    $page->setTemplateCode('default');
2957
    $page->setRouteName('homepage');
2958
    //$page->setParent($this->getReference('page-homepage'));
2959
    $page->setSite($site);
2960
    $pageManager->save($page);
2961
2962
    // Create welcome page
2963
    $pageWelcome = $pageManager->create();
2964
    $pageWelcome->setSlug('welcome');
2965
    $pageWelcome->setUrl('/welcome');
2966
    $pageWelcome->setName('welcome');
2967
    $pageWelcome->setTitle('welcome');
2968
    $pageWelcome->setEnabled(true);
2969
    $pageWelcome->setDecorate(1);
2970
    $pageWelcome->setRequestMethod('GET');
2971
    $pageWelcome->setTemplateCode('default');
2972
    $pageWelcome->setRouteName('welcome');
2973
    $pageWelcome->setParent($page);
2974
    $pageWelcome->setSite($site);
2975
    $pageManager->save($pageWelcome);
2976
2977
    // Creating page blocks
2978
    $templateManager = $container->get('sonata.page.template_manager');
2979
    $template = $templateManager->get('default');
2980
    $templateContainers = $template->getContainers();
2981
2982
    $containers = [];
2983
    foreach ($templateContainers as $id => $area) {
2984
        $containers[$id] = [
2985
            'area' => $area,
2986
            'block' => false,
2987
        ];
2988
    }
2989
2990
    // Create blocks for this page
2991
    $blockInteractor = $container->get('sonata.page.block_interactor');
2992
    $parentBlock = null;
2993
    foreach ($containers as $id => $area) {
2994
        if (false === $area['block'] && false === $templateContainers[$id]['shared']) {
2995
            $block = $blockInteractor->createNewContainer(
2996
                [
2997
                    'page' => $pageWelcome,
2998
                    'name' => $templateContainers[$id]['name'],
2999
                    'code' => $id,
3000
                ]
3001
            );
3002
3003
            if ('content' === $id && 'Main content' == $templateContainers[$id]['name']) {
3004
                $parentBlock = $block;
3005
            }
3006
        }
3007
    }*/
3008
3009
    // Create block in main content
3010
    //$block = $container->get('sonata.page.manager.block');
3011
    /** @var \Sonata\BlockBundle\Model\Block $myBlock */
3012
    /*$myBlock = $block->create();
3013
    $myBlock->setType('sonata.formatter.block.formatter');
3014
    $myBlock->setSetting('format', 'richhtml');
3015
    $myBlock->setSetting('content', '');
3016
    $myBlock->setSetting('rawContent', '');
3017
    $myBlock->setSetting('template', '@SonataFormatter/Block/block_formatter.html.twig');
3018
    $myBlock->setParent($parentBlock);
3019
    $pageWelcome->addBlocks($myBlock);
3020
    $pageManager->save($pageWelcome);*/
3021
}
3022
3023
/**
3024
 * @param SymfonyContainer $container
3025
 * @param EntityManager    $manager
3026
 * @param bool             $upgrade
3027
 */
3028
function installSchemas($container, $manager, $upgrade = false)
3029
{
3030
    $settingsManager = $container->get('chamilo.settings.manager');
3031
3032
    // Install course tools (table "tool")
3033
    $toolChain = $container->get(ToolChain::class);
3034
    $toolChain->createTools($manager);
3035
3036
    $urlRepo = $container->get('Chamilo\CoreBundle\Repository\AccessUrlRepository');
3037
    $accessUrl = $urlRepo->find(1);
3038
    if (!$accessUrl) {
3039
        $em = $urlRepo->getEntityManager();
3040
3041
        // Creating AccessUrl
3042
        $accessUrl = new AccessUrl();
3043
        $accessUrl
3044
            ->setUrl('http://localhost/')
3045
            ->setDescription('')
3046
            ->setActive(1)
3047
            ->setCreatedBy(1)
3048
        ;
3049
        $em->persist($accessUrl);
3050
        $em->flush();
3051
    }
3052
3053
    if ($upgrade) {
3054
        $settingsManager->updateSchemas($accessUrl);
3055
    } else {
3056
        // Installing schemas (filling settings_current table)
3057
        $settingsManager->installSchemas($accessUrl);
3058
    }
3059
}
3060
3061
/**
3062
 * @param SymfonyContainer $container
3063
 */
3064
function upgradeWithContainer($container)
3065
{
3066
    Container::setContainer($container);
3067
    Container::setLegacyServices($container, false);
3068
    error_log('setLegacyServices');
3069
    $manager = Database::getManager();
3070
    installGroups($container, $manager);
3071
    error_log('installGroups');
3072
    // @todo check if adminId = 1
3073
    installSchemas($container, $manager, 1, true);
3074
    installPages($container);
3075
    fixMedia($container);
3076
}
3077
3078
function fixMedia($container)
3079
{
3080
    return;
3081
    error_log('fix medias');
0 ignored issues
show
Unused Code introduced by
error_log('fix medias') is not reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
3082
    $pool = $container->get('sonata.media.pool');
3083
    $contextManager = $container->get('sonata.classification.manager.context');
3084
    $categoryManager = $container->get('sonata.media.manager.category');
3085
3086
    foreach ($pool->getContexts() as $context => $contextAttrs) {
3087
        /** @var ContextInterface $defaultContext */
3088
        $defaultContext = $contextManager->findOneBy([
3089
            'id' => $context,
3090
        ]);
3091
3092
        if (!$defaultContext) {
3093
            $defaultContext = $contextManager->create();
3094
            $defaultContext->setId($context);
3095
            $defaultContext->setName(ucfirst($context));
3096
            $defaultContext->setEnabled(true);
3097
3098
            $contextManager->save($defaultContext);
3099
        }
3100
3101
        $defaultCategory = $categoryManager->getRootCategory($defaultContext);
3102
3103
        if (!$defaultCategory) {
3104
            $defaultCategory = $categoryManager->create();
3105
            $defaultCategory->setContext($defaultContext);
3106
            $defaultCategory->setName(ucfirst($context));
3107
            $defaultCategory->setEnabled(true);
3108
            $defaultCategory->setPosition(0);
3109
3110
            $categoryManager->save($defaultCategory);
3111
        }
3112
    }
3113
}
3114
3115
/**
3116
 * After the schema was created (table creation), the function adds
3117
 * admin/platform information.
3118
 *
3119
 * @param \Psr\Container\ContainerInterface $container
3120
 * @param string                            $sysPath
3121
 * @param string                            $encryptPassForm
3122
 * @param string                            $passForm
3123
 * @param string                            $adminLastName
3124
 * @param string                            $adminFirstName
3125
 * @param string                            $loginForm
3126
 * @param string                            $emailForm
3127
 * @param string                            $adminPhoneForm
3128
 * @param string                            $languageForm
3129
 * @param string                            $institutionForm
3130
 * @param string                            $institutionUrlForm
3131
 * @param string                            $siteName
3132
 * @param string                            $allowSelfReg
3133
 * @param string                            $allowSelfRegProf
3134
 * @param string                            $installationProfile Installation profile, if any was provided
3135
 */
3136
function finishInstallationWithContainer(
3137
    $container,
3138
    $sysPath,
3139
    $encryptPassForm,
3140
    $passForm,
3141
    $adminLastName,
3142
    $adminFirstName,
3143
    $loginForm,
3144
    $emailForm,
3145
    $adminPhoneForm,
3146
    $languageForm,
3147
    $institutionForm,
3148
    $institutionUrlForm,
3149
    $siteName,
3150
    $allowSelfReg,
3151
    $allowSelfRegProf,
3152
    $installationProfile = ''
3153
) {
3154
    error_log('finishInstallationWithContainer');
3155
    $sysPath = !empty($sysPath) ? $sysPath : api_get_path(SYMFONY_SYS_PATH);
3156
    Container::setContainer($container);
3157
    Container::setLegacyServices($container, false);
3158
    error_log('setLegacyServices');
3159
3160
    $manager = Database::getManager();
3161
    $connection = $manager->getConnection();
3162
    $trans = $container->get('translator');
3163
    $sql = getVersionTable();
3164
3165
    // Add version table
3166
    $connection->executeQuery($sql);
3167
3168
    error_log("Create $sql ");
3169
3170
    // Add tickets defaults
3171
    $ticketProject = new TicketProject();
3172
    $ticketProject
3173
        ->setId(1)
3174
        ->setName('Ticket System')
3175
        ->setInsertUserId(1);
3176
3177
    $manager->persist($ticketProject);
3178
3179
    $categories = [
3180
        $trans->trans('Enrollment') => $trans->trans('Tickets about enrollment'),
3181
        $trans->trans('General information') => $trans->trans('Tickets about general information'),
3182
        $trans->trans('Requests and paperwork') => $trans->trans('Tickets about requests and paperwork'),
3183
        $trans->trans('Academic Incidents') => $trans->trans('Tickets about academic incidents, like exams, practices, tasks, etc.'),
3184
        $trans->trans('Virtual campus') => $trans->trans('Tickets about virtual campus'),
3185
        $trans->trans('Online evaluation') => $trans->trans('Tickets about online evaluation'),
3186
    ];
3187
3188
    $i = 1;
3189
    foreach ($categories as $category => $description) {
3190
        // Online evaluation requires a course
3191
        $ticketCategory = new TicketCategory();
3192
        $ticketCategory
3193
            ->setId($i)
3194
            ->setName($category)
3195
            ->setDescription($description)
3196
            ->setProject($ticketProject)
3197
            ->setInsertUserId(1);
3198
3199
        $isRequired = 6 == $i;
3200
        $ticketCategory->setCourseRequired($isRequired);
3201
3202
        $manager->persist($ticketCategory);
3203
        $i++;
3204
    }
3205
3206
    // Default Priorities
3207
    $defaultPriorities = [
3208
        TicketManager::PRIORITY_NORMAL => $trans->trans('Normal'),
3209
        TicketManager::PRIORITY_HIGH => $trans->trans('High'),
3210
        TicketManager::PRIORITY_LOW => $trans->trans('Low'),
3211
    ];
3212
3213
    $i = 1;
3214
    foreach ($defaultPriorities as $code => $priority) {
3215
        $ticketPriority = new TicketPriority();
3216
        $ticketPriority
3217
            ->setId($i)
3218
            ->setName($priority)
3219
            ->setCode($code)
3220
            ->setInsertUserId(1);
3221
3222
        $manager->persist($ticketPriority);
3223
        $i++;
3224
    }
3225
    error_log("Save ticket data");
3226
    $manager->flush();
3227
3228
    $table = Database::get_main_table(TABLE_TICKET_STATUS);
3229
3230
    // Default status
3231
    $defaultStatus = [
3232
        TicketManager::STATUS_NEW => $trans->trans('New'),
3233
        TicketManager::STATUS_PENDING => $trans->trans('Pending'),
3234
        TicketManager::STATUS_UNCONFIRMED => $trans->trans('Unconfirmed'),
3235
        TicketManager::STATUS_CLOSE => $trans->trans('Close'),
3236
        TicketManager::STATUS_FORWARDED => $trans->trans('Forwarded'),
3237
    ];
3238
3239
    $i = 1;
3240
    foreach ($defaultStatus as $code => $status) {
3241
        $attributes = [
3242
            'id' => $i,
3243
            'code' => $code,
3244
            'name' => $status,
3245
        ];
3246
        Database::insert($table, $attributes);
3247
        $i++;
3248
    }
3249
3250
    installGroups($container, $manager);
3251
3252
3253
    error_log('Inserting data.sql');
3254
    // Inserting default data
3255
    $data = file_get_contents($sysPath.'public/main/install/data.sql');
3256
    $result = $manager->getConnection()->prepare($data);
3257
    $result->execute();
3258
    $result->closeCursor();
3259
3260
    UserManager::setPasswordEncryption($encryptPassForm);
3261
3262
    error_log('user creation - admin');
3263
3264
    // Create admin user.
3265
    $adminId = UserManager::create_user(
3266
        $adminFirstName,
3267
        $adminLastName,
3268
        1,
3269
        $emailForm,
3270
        $loginForm,
3271
        $passForm,
3272
        'ADMIN',
3273
        $languageForm,
3274
        $adminPhoneForm,
3275
        '',
3276
        PLATFORM_AUTH_SOURCE,
3277
        '',
3278
        1,
3279
        0,
3280
        null,
3281
        '',
3282
        false,
3283
        true,
3284
        '',
3285
        false,
3286
        '',
3287
        0,
3288
        [],
3289
        '',
3290
        false,
3291
        false
3292
    );
3293
    error_log('user creation - anon');
3294
    // Create anonymous user.
3295
    $anonId = UserManager::create_user(
3296
        'Joe',
3297
        'Anonymous',
3298
        6,
3299
        'anonymous@localhost',
3300
        'anon',
3301
        'anon',
3302
        'anonymous',
3303
        $languageForm,
3304
        '',
3305
        '',
3306
        PLATFORM_AUTH_SOURCE,
3307
        '',
3308
        1,
3309
        0,
3310
        null,
3311
        '',
3312
        false,
3313
        false,
3314
        '',
3315
        false,
3316
        '',
3317
        $adminId,
3318
        [],
3319
        '',
3320
        false,
3321
        false
3322
    );
3323
    $userManager = $container->get('Chamilo\CoreBundle\Repository\UserRepository');
3324
    $urlRepo = $container->get('Chamilo\CoreBundle\Repository\AccessUrlRepository');
3325
3326
    $admin = $userManager->find($adminId);
3327
3328
    // Login as admin
3329
    $token = new UsernamePasswordToken(
3330
        $admin,
3331
        $admin->getPassword(),
3332
        "public",
3333
        $admin->getRoles()
3334
    );
3335
    $container->get('security.token_storage')->setToken($token);
3336
3337
    /*$event = new \Symfony\Component\Security\Http\Event\InteractiveLoginEvent(
3338
        $container->get('request_stack'), $token
3339
    );
3340
    $container->get('event_dispatcher')->dispatch('security.interactive_login', $event);*/
3341
3342
3343
    installSchemas($container, $manager, false);
3344
3345
    error_log('Adding access url as a node');
3346
3347
    $accessUrl = $urlRepo->find(1);
3348
3349
    $branch = new BranchSync();
3350
    $branch->setBranchName('localhost');
3351
    $branch->setUrl($accessUrl);
3352
    $manager->persist($branch);
3353
3354
3355
    $userManager->addUserToResourceNode($adminId, $adminId);
3356
    $userManager->addUserToResourceNode($anonId, $adminId);
3357
3358
    $urlRepo->addResourceNode($accessUrl, $admin);
3359
3360
    UrlManager::add_user_to_url($adminId, 1);
3361
    UrlManager::add_user_to_url($anonId, 1);
3362
3363
    $manager->flush();
3364
3365
    // Set default language
3366
    Database::update(
3367
        Database::get_main_table(TABLE_MAIN_LANGUAGE),
3368
        ['available' => 1],
3369
        ['dokeos_folder = ?' => $languageForm]
3370
    );
3371
3372
    // Install settings
3373
    installSettings(
3374
        $institutionForm,
3375
        $institutionUrlForm,
3376
        $siteName,
3377
        $emailForm,
3378
        $adminLastName,
3379
        $adminFirstName,
3380
        $languageForm,
3381
        $allowSelfReg,
3382
        $allowSelfRegProf,
3383
        $installationProfile
3384
    );
3385
3386
    lockSettings();
3387
    updateDirAndFilesPermissions();
3388
    //fixMedia($container);
3389
}
3390
3391
/**
3392
 * Creates 'version' table.
3393
 */
3394
function createVersionTable()
3395
{
3396
    $sql = getVersionTable();
3397
    Database::query($sql);
3398
}
3399
3400
/**
3401
 * Get version creation table query.
3402
 *
3403
 * @return string
3404
 */
3405
function getVersionTable()
3406
{
3407
    return 'CREATE TABLE IF NOT EXISTS version (id int unsigned NOT NULL AUTO_INCREMENT, version varchar(20), PRIMARY KEY(id), UNIQUE(version));';
3408
}
3409
3410
/**
3411
 * Update settings based on installation profile defined in a JSON file.
3412
 *
3413
 * @param string $installationProfile The name of the JSON file in main/install/profiles/ folder
3414
 *
3415
 * @return bool false on failure (no bad consequences anyway, just ignoring profile)
3416
 */
3417
function installProfileSettings($installationProfile = '')
3418
{
3419
    if (empty($installationProfile)) {
3420
        return false;
3421
    }
3422
    $jsonPath = api_get_path(SYS_PATH).'main/install/profiles/'.$installationProfile.'.json';
3423
    // Make sure the path to the profile is not hacked
3424
    if (!Security::check_abs_path($jsonPath, api_get_path(SYS_PATH).'main/install/profiles/')) {
3425
        return false;
3426
    }
3427
    if (!is_file($jsonPath)) {
3428
        return false;
3429
    }
3430
    if (!is_readable($jsonPath)) {
3431
        return false;
3432
    }
3433
    if (!function_exists('json_decode')) {
3434
        // The php-json extension is not available. Ignore profile.
3435
        return false;
3436
    }
3437
    $json = file_get_contents($jsonPath);
3438
    $params = json_decode($json);
3439
    if (false === $params or null === $params) {
3440
        return false;
3441
    }
3442
    $settings = $params->params;
3443
    if (!empty($params->parent)) {
3444
        installProfileSettings($params->parent);
3445
    }
3446
3447
    $tblSettings = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
3448
3449
    foreach ($settings as $id => $param) {
3450
        $conditions = ['variable = ? ' => $param->variable];
3451
3452
        if (!empty($param->subkey)) {
3453
            $conditions['AND subkey = ? '] = $param->subkey;
3454
        }
3455
3456
        Database::update(
3457
            $tblSettings,
3458
            ['selected_value' => $param->selected_value],
3459
            $conditions
3460
        );
3461
    }
3462
3463
    return true;
3464
}
3465
3466
/**
3467
 * Quick function to remove a directory with its subdirectories.
3468
 *
3469
 * @param $dir
3470
 */
3471
function rrmdir($dir)
3472
{
3473
    if (is_dir($dir)) {
3474
        $objects = scandir($dir);
3475
        foreach ($objects as $object) {
3476
            if ("." != $object && ".." != $object) {
3477
                if ("dir" == filetype($dir."/".$object)) {
3478
                    @rrmdir($dir."/".$object);
0 ignored issues
show
Bug introduced by
Are you sure the usage of rrmdir($dir . '/' . $object) is correct as it seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
Security Best Practice introduced by
It seems like you do not handle an error condition for rrmdir(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

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

3478
                    /** @scrutinizer ignore-unhandled */ @rrmdir($dir."/".$object);

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

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

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
3479
                } else {
3480
                    @unlink($dir."/".$object);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for unlink(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

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

3480
                    /** @scrutinizer ignore-unhandled */ @unlink($dir."/".$object);

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

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

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
3481
                }
3482
            }
3483
        }
3484
        reset($objects);
3485
        rmdir($dir);
3486
    }
3487
}
3488
3489
/**
3490
 * @param        $id
3491
 * @param string $type
3492
 * @param bool   $preview
3493
 * @param bool   $anonymous
3494
 *
3495
 * @throws \Doctrine\DBAL\DBALException
3496
 *
3497
 * @return array
3498
 */
3499
function get_group_picture_path_by_id($id, $type = 'web', $preview = false, $anonymous = false)
3500
{
3501
    switch ($type) {
3502
        case 'system': // Base: absolute system path.
3503
            $base = api_get_path(SYS_UPLOAD_PATH);
3504
            break;
3505
        case 'web': // Base: absolute web path.
3506
        default:
3507
            $base = api_get_path(WEB_UPLOAD_PATH);
3508
            break;
3509
    }
3510
3511
    $noPicturePath = ['dir' => $base.'img/', 'file' => 'unknown.jpg'];
3512
3513
    if (empty($id) || empty($type)) {
3514
        return $anonymous ? $noPicturePath : ['dir' => '', 'file' => ''];
3515
    }
3516
3517
    $id = intval($id);
3518
3519
    //$group_table = Database::get_main_table(TABLE_MAIN_GROUP);
3520
    $group_table = 'groups';
3521
    $sql = "SELECT picture_uri FROM $group_table WHERE id=".$id;
3522
    $res = Database::query($sql);
3523
3524
    if (!Database::num_rows($res)) {
3525
        return $anonymous ? $noPicturePath : ['dir' => '', 'file' => ''];
3526
    }
3527
3528
    $user = Database::fetch_array($res);
3529
    $picture_filename = trim($user['picture_uri']);
3530
3531
    if ('true' === api_get_setting('split_users_upload_directory')) {
3532
        if (!empty($picture_filename)) {
3533
            $dir = $base.'groups/'.substr($picture_filename, 0, 1).'/'.$id.'/';
3534
        } elseif ($preview) {
3535
            $dir = $base.'groups/'.substr((string) $id, 0, 1).'/'.$id.'/';
3536
        } else {
3537
            $dir = $base.'groups/'.$id.'/';
3538
        }
3539
    } else {
3540
        $dir = $base.'groups/'.$id.'/';
3541
    }
3542
3543
    if (empty($picture_filename) && $anonymous) {
3544
        return $noPicturePath;
3545
    }
3546
3547
    return ['dir' => $dir, 'file' => $picture_filename];
3548
}
3549
3550
/**
3551
 * Control the different steps of the migration through a big switch.
3552
 *
3553
 * @param string        $fromVersion
3554
 * @param EntityManager $manager
3555
 * @param bool          $processFiles
3556
 *
3557
 * @throws \Doctrine\DBAL\DBALException
3558
 *
3559
 * @return bool Always returns true except if the process is broken
3560
 */
3561
function migrateSwitch($fromVersion, $manager, $processFiles = true)
3562
{
3563
    error_log('Starting migration process from '.$fromVersion.' ('.date('Y-m-d H:i:s').')');
3564
3565
    echo '<a class="btn btn-secondary" href="javascript:void(0)" id="details_button">'.get_lang('Details').'</a><br />';
3566
    echo '<div id="details" style="display:none">';
3567
3568
    $connection = $manager->getConnection();
3569
3570
    $database = new Database();
3571
    $database->setManager($manager);
3572
3573
    switch ($fromVersion) {
3574
        case '1.11.0':
3575
        case '1.11.1':
3576
        case '1.11.2':
3577
        case '1.11.4':
3578
        case '1.11.6':
3579
        case '1.11.8':
3580
        case '1.11.10':
3581
        case '1.11.12':
3582
        case '1.11.14':
3583
            $database = new Database();
3584
            $database->setManager($manager);
3585
            // Migrate using the migration files located in:
3586
            // src/Chamilo/CoreBundle/Migrations/Schema/V111
3587
            $result = migrate(200, $manager);
3588
3589
            if ($result) {
3590
                error_log('Migrations files were executed ('.date('Y-m-d H:i:s').')');
3591
                $sql = "UPDATE settings_current SET selected_value = '2.0.0' WHERE variable = 'chamilo_database_version'";
3592
                $connection->executeQuery($sql);
3593
                if ($processFiles) {
3594
                    error_log('Update config files');
3595
                    $fromVersionShort = '1.11';
3596
                    include __DIR__.'/update-files-1.11.0-2.0.0.inc.php';
3597
                    // Only updates the configuration.inc.php with the new version
3598
                    include __DIR__.'/update-configuration.inc.php';
3599
                }
3600
                error_log('Upgrade 2.0.0 process concluded!  ('.date('Y-m-d H:i:s').')');
3601
            } else {
3602
                error_log('There was an error during running migrations. Check error.log');
3603
            }
3604
            break;
3605
        default:
3606
            break;
3607
    }
3608
3609
    echo '</div>';
3610
3611
    return true;
3612
}
3613
3614
/**
3615
 * @param \Doctrine\DBAL\Connection $connection
3616
 *
3617
 * @throws \Doctrine\DBAL\DBALException
3618
 */
3619
function fixPostGroupIds($connection)
3620
{
3621
    $connection->executeQuery("ALTER TABLE course_category MODIFY COLUMN auth_course_child VARCHAR(40) DEFAULT 'TRUE'");
3622
    error_log('Fix c_student_publication.post_group_id');
3623
3624
    // Fix post_group_id
3625
    $sql = "SELECT * FROM c_student_publication
3626
            WHERE (post_group_id <> 0 AND post_group_id is not null)";
3627
    $statement = $connection->executeQuery($sql);
3628
    $result = $statement->fetchAll();
3629
3630
    foreach ($result as $row) {
3631
        $groupId = $row['post_group_id'];
3632
        $courseId = $row['c_id'];
3633
        $workIid = $row['iid'];
3634
        $sql = "SELECT iid from c_group_info
3635
                WHERE c_id = $courseId AND id = $groupId";
3636
        $statement = $connection->executeQuery($sql);
3637
        $count = $statement->rowCount();
3638
        if ($count > 0) {
3639
            $rowGroup = $statement->fetch();
3640
            $newGroupId = $rowGroup['iid'];
3641
            if ($newGroupId == $groupId) {
3642
                continue;
3643
            }
3644
            if ($newGroupId) {
3645
                $sql = "UPDATE c_student_publication
3646
                        SET post_group_id = $newGroupId
3647
                        WHERE
3648
                            c_id = $courseId AND
3649
                            iid = $workIid
3650
                        ";
3651
                $connection->executeQuery($sql);
3652
            }
3653
        }
3654
    }
3655
3656
    error_log('End - Fix c_student_publication.post_group_id');
3657
3658
    // Delete c_student_publication from any session that doesn't exist anymore
3659
    $sql = "DELETE FROM c_student_publication
3660
            WHERE session_id NOT IN (SELECT id FROM session) AND (session_id <> 0 AND session_id is not null)";
3661
    $connection->executeQuery($sql);
3662
3663
    error_log('Fix work documents');
3664
    // Fix work documents that don't have c_item_property value
3665
    $sql = "SELECT * FROM c_student_publication WHERE parent_id IS NOT NULL";
3666
    $statement = $connection->executeQuery($sql);
3667
    $result = $statement->fetchAll();
3668
    foreach ($result as $row) {
3669
        $groupId = $row['post_group_id'];
3670
        $courseId = $row['c_id'];
3671
        $sessionId = $row['session_id'];
3672
        $workId = $row['id'];
3673
        $sessionCondition = " session_id = $sessionId";
3674
        if (empty($sessionId)) {
3675
            $sessionCondition = ' (session_id = 0 OR session_id IS NULL) ';
3676
        }
3677
        $sql = "SELECT * FROM c_item_property
3678
                WHERE
3679
                    c_id = $courseId AND
3680
                    tool = 'work' AND
3681
                    ref = $workId AND
3682
                    $sessionCondition ";
3683
        $itemInfo = $connection->fetchAssoc($sql);
3684
        if (empty($itemInfo)) {
3685
            $params = [
3686
                'c_id' => $courseId,
3687
                'to_group_id' => $groupId,
3688
                //'to_user_id' => null,
3689
                'insert_user_id' => 1,
3690
                'session_id' => $sessionId,
3691
                'tool' => 'work',
3692
                'insert_date' => api_get_utc_datetime(),
3693
                'lastedit_date' => api_get_utc_datetime(),
3694
                'ref' => $workId,
3695
                'lastedit_type' => 'visible',
3696
                'lastedit_user_id' => 1,
3697
                'visibility' => 1,
3698
            ];
3699
            $connection->insert('c_item_property', $params);
3700
            $id = $connection->lastInsertId();
3701
            $sql = "UPDATE c_item_property SET id = iid WHERE iid = $id";
3702
            $connection->executeQuery($sql);
3703
        }
3704
    }
3705
    error_log('End - Fix work documents');
3706
}
3707
3708
/**
3709
 * @return string
3710
 */
3711
function generateRandomToken()
3712
{
3713
    return hash('sha1', uniqid(mt_rand(), true));
3714
}
3715
3716
/**
3717
 * This function checks if the given file can be created or overwritten
3718
 *
3719
 * @param string $file     Full path to a file
3720
 *
3721
 * @return string   An HTML coloured label showing success or failure
3722
 */
3723
function checkCanCreateFile($file)
3724
{
3725
    if (file_exists($file)) {
3726
        if (is_writeable($file)) {
3727
            return Display::label(get_lang('Writable'), 'success');
3728
        } else {
3729
            return Display::label(get_lang('Not writable'), 'important');
3730
        }
3731
    } else {
3732
        $write = @file_put_contents($file, '');
3733
        if ($write) {
3734
            unlink($file);
3735
            return Display::label(get_lang('Writable'), 'success');
3736
        } else {
3737
            return Display::label(get_lang('Not writable'), 'important');
3738
        }
3739
    }
3740
}
3741