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

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

370
    /** @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...
371
    @chmod('..', 0755); //set permissions on parent dir of install dir
372
}
373
374
/**
375
 * Write the main system config file.
376
 *
377
 * @param string $path Path to the config file
378
 */
379
function write_system_config_file($path)
380
{
381
    global $dbHostForm;
382
    global $dbPortForm;
383
    global $dbUsernameForm;
384
    global $dbPassForm;
385
    global $dbNameForm;
386
    global $urlForm;
387
    global $pathForm;
388
    global $urlAppendPath;
389
    global $languageForm;
390
    global $encryptPassForm;
391
    global $session_lifetime;
392
    global $new_version;
393
    global $new_version_stable;
394
395
    $root_sys = api_add_trailing_slash(str_replace('\\', '/', realpath($pathForm)));
396
    $content = file_get_contents(__DIR__.'/'.SYSTEM_CONFIG_FILENAME);
397
398
    $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...
399
    $config['{DATABASE_HOST}'] = $dbHostForm;
400
    $config['{DATABASE_PORT}'] = $dbPortForm;
401
    $config['{DATABASE_USER}'] = $dbUsernameForm;
402
    $config['{DATABASE_PASSWORD}'] = $dbPassForm;
403
    $config['{DATABASE_MAIN}'] = $dbNameForm;
404
    $config['{ROOT_WEB}'] = $urlForm;
405
    $config['{ROOT_SYS}'] = $root_sys;
406
    $config['{URL_APPEND_PATH}'] = $urlAppendPath;
407
    $config['{PLATFORM_LANGUAGE}'] = $languageForm;
408
    $config['{SECURITY_KEY}'] = md5(uniqid(rand().time()));
409
    $config['{ENCRYPT_PASSWORD}'] = $encryptPassForm;
410
411
    $config['SESSION_LIFETIME'] = $session_lifetime;
412
    $config['{NEW_VERSION}'] = $new_version;
413
    $config['NEW_VERSION_STABLE'] = trueFalse($new_version_stable);
414
415
    foreach ($config as $key => $value) {
416
        $content = str_replace($key, $value, $content);
417
    }
418
    $fp = @fopen($path, 'w');
419
420
    if (!$fp) {
0 ignored issues
show
introduced by
$fp is of type false|resource, thus it always evaluated to false.
Loading history...
421
        echo '<strong>
422
                <font color="red">Your script doesn\'t have write access to the config directory</font></strong><br />
423
                <em>('.str_replace('\\', '/', realpath($path)).')</em><br /><br />
424
                You probably do not have write access on Chamilo root directory,
425
                i.e. you should <em>CHMOD 777</em> or <em>755</em> or <em>775</em>.<br /><br />
426
                Your problems can be related on two possible causes:<br />
427
                <ul>
428
                  <li>Permission problems.<br />Try initially with <em>chmod -R 777</em> and increase restrictions gradually.</li>
429
                  <li>PHP is running in <a href="http://www.php.net/manual/en/features.safe-mode.php" target="_blank">Safe-Mode</a>.
430
                  If possible, try to switch it off.</li>
431
                </ul>
432
                <a href="http://forum.chamilo.org/" target="_blank">Read about this problem in Support Forum</a><br /><br />
433
                Please go back to step 5.
434
                <p><input type="submit" name="step5" value="&lt; Back" /></p>
435
                </td></tr></table></form></body></html>';
436
        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...
437
    }
438
439
    fwrite($fp, $content);
440
    fclose($fp);
441
}
442
443
/**
444
 * Returns a list of language directories.
445
 */
446
function &get_language_folder_list()
447
{
448
    static $result;
449
    if (!is_array($result)) {
450
        $result = [];
451
        $exceptions = ['.', '..', 'CVS', '.svn'];
452
        $search = ['_latin', '_unicode', '_corporate', '_org', '_KM', '_'];
453
        $replace_with = [' (Latin)', ' (unicode)', ' (corporate)', ' (org)', ' (KM)', ' '];
454
        $dirname = api_get_path(SYS_LANG_PATH);
455
        $handle = opendir($dirname);
456
        while ($entries = readdir($handle)) {
457
            if (in_array($entries, $exceptions)) {
458
                continue;
459
            }
460
            if (is_dir($dirname.$entries)) {
461
                if (is_file($dirname.$entries.'/install_disabled')) {
462
                    // Skip all languages that have this file present, just for
463
                    // the install process (languages incomplete)
464
                    continue;
465
                }
466
                $result[$entries] = ucwords(str_replace($search, $replace_with, $entries));
467
            }
468
        }
469
        closedir($handle);
470
        asort($result);
471
    }
472
473
    return $result;
474
}
475
476
/**
477
 * TODO: my_directory_to_array() - maybe within the main API there is already a suitable function?
478
 *
479
 * @param string $directory Full path to a directory
480
 *
481
 * @return array A list of files and dirs in the directory
482
 */
483
function my_directory_to_array($directory)
484
{
485
    $array_items = [];
486
    if ($handle = opendir($directory)) {
487
        while (false !== ($file = readdir($handle))) {
488
            if ($file != "." && $file != "..") {
489
                if (is_dir($directory."/".$file)) {
490
                    $array_items = array_merge($array_items, my_directory_to_array($directory.'/'.$file));
491
                    $file = $directory."/".$file;
492
                    $array_items[] = preg_replace("/\/\//si", '/', $file);
493
                }
494
            }
495
        }
496
        closedir($handle);
497
    }
498
499
    return $array_items;
500
}
501
502
/**
503
 * This function returns the value of a parameter from the configuration file.
504
 *
505
 * WARNING - this function relies heavily on global variables $updateFromConfigFile
506
 * and $configFile, and also changes these globals. This can be rewritten.
507
 *
508
 * @param string $param the parameter of which the value is returned
509
 * @param   string  If we want to give the path rather than take it from POST
510
 *
511
 * @return string the value of the parameter
512
 *
513
 * @author Olivier Brouckaert
514
 * @author Reworked by Ivan Tcholakov, 2010
515
 */
516
function get_config_param($param, $updatePath = '')
517
{
518
    global $configFile, $updateFromConfigFile;
519
520
    // Look if we already have the queried parameter.
521
    if (is_array($configFile) && isset($configFile[$param])) {
522
        return $configFile[$param];
523
    }
524
    if (empty($updatePath) && !empty($_POST['updatePath'])) {
525
        $updatePath = $_POST['updatePath'];
526
    }
527
528
    if (empty($updatePath)) {
529
        $updatePath = api_get_path(SYS_PATH);
530
    }
531
    $updatePath = api_add_trailing_slash(str_replace('\\', '/', realpath($updatePath)));
532
    $updateFromInstalledVersionFile = '';
533
534
    if (empty($updateFromConfigFile)) {
535
        // If update from previous install was requested,
536
        // try to recover config file from Chamilo 1.9.x
537
        if (file_exists($updatePath.'main/inc/conf/configuration.php')) {
538
            $updateFromConfigFile = 'main/inc/conf/configuration.php';
539
        } elseif (file_exists($updatePath.'app/config/configuration.php')) {
540
            $updateFromConfigFile = 'app/config/configuration.php';
541
        } else {
542
            // Give up recovering.
543
            //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);
544
            return null;
545
        }
546
    }
547
548
    if (file_exists($updatePath.$updateFromConfigFile) &&
549
        !is_dir($updatePath.$updateFromConfigFile)
550
    ) {
551
        require $updatePath.$updateFromConfigFile;
552
        $config = new Zend\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...
553
554
        return $config->get($param);
555
    }
556
557
    error_log('Config array could not be found in get_config_param()', 0);
558
559
    return null;
560
561
    /*if (file_exists($updatePath.$updateFromConfigFile)) {
562
        return $val;
563
    } else {
564
        error_log('Config array could not be found in get_config_param()', 0);
565
        return null;
566
    }*/
567
}
568
569
/*      DATABASE RELATED FUNCTIONS */
570
571
/**
572
 * Gets a configuration parameter from the database. Returns returns null on failure.
573
 *
574
 * @param string $param Name of param we want
575
 *
576
 * @return mixed The parameter value or null if not found
577
 */
578
function get_config_param_from_db($param = '')
579
{
580
    $param = Database::escape_string($param);
581
582
    if (($res = Database::query("SELECT * FROM settings_current WHERE variable = '$param'")) !== false) {
583
        if (Database::num_rows($res) > 0) {
584
            $row = Database::fetch_array($res);
585
586
            return $row['selected_value'];
587
        }
588
    }
589
590
    return null;
591
}
592
593
/**
594
 * Connect to the database and returns the entity manager.
595
 *
596
 * @param string $dbHostForm     DB host
597
 * @param string $dbUsernameForm DB username
598
 * @param string $dbPassForm     DB password
599
 * @param string $dbNameForm     DB name
600
 * @param int    $dbPortForm     DB port
601
 *
602
 * @return EntityManager
603
 */
604
function connectToDatabase(
605
    $dbHostForm,
606
    $dbUsernameForm,
607
    $dbPassForm,
608
    $dbNameForm,
609
    $dbPortForm = 3306
610
) {
611
    $dbParams = [
612
        'driver' => 'pdo_mysql',
613
        'host' => $dbHostForm,
614
        'port' => $dbPortForm,
615
        'user' => $dbUsernameForm,
616
        'password' => $dbPassForm,
617
        'dbname' => $dbNameForm,
618
    ];
619
620
    $database = new \Database();
621
    $database->connect($dbParams);
622
623
    return $database->getManager();
624
}
625
626
/*      DISPLAY FUNCTIONS */
627
628
/**
629
 * This function prints class=active_step $current_step=$param.
630
 *
631
 * @param int $param A step in the installer process
632
 *
633
 * @author Patrick Cool <[email protected]>, Ghent University
634
 */
635
function step_active($param)
636
{
637
    global $current_step;
638
    if ($param == $current_step) {
639
        echo 'class="current-step" ';
640
    }
641
}
642
643
/**
644
 * This function displays the Step X of Y -.
645
 *
646
 * @return string String that says 'Step X of Y' with the right values
647
 */
648
function display_step_sequence()
649
{
650
    global $current_step;
651
652
    return get_lang('Step'.$current_step).' &ndash; ';
653
}
654
655
/**
656
 * Displays a drop down box for selection the preferred language.
657
 */
658
function display_language_selection_box(
659
    $name = 'language_list',
660
    $default_language = 'english'
661
) {
662
    // Reading language list.
663
    $language_list = get_language_folder_list();
664
665
    /*
666
    // Reduction of the number of languages shown. Enable this fragment of code for customization purposes.
667
    // Modify the language list according to your preference. Don't exclude the 'english' item.
668
    $language_to_display = array('asturian', 'bulgarian', 'english', 'italian', 'french', 'slovenian', 'slovenian_unicode', 'spanish');
669
    foreach ($language_list as $key => & $value) {
670
        if (!in_array($key, $language_to_display)) {
671
            unset($language_list[$key]);
672
        }
673
    }
674
    */
675
676
    // Sanity checks due to the possibility for customizations.
677
    if (!is_array($language_list) || empty($language_list)) {
678
        $language_list = ['english' => 'English'];
679
    }
680
681
    // Sorting again, if it is necessary.
682
    //asort($language_list);
683
684
    // More sanity checks.
685
    if (!array_key_exists($default_language, $language_list)) {
686
        if (array_key_exists('english', $language_list)) {
687
            $default_language = 'english';
688
        } else {
689
            $language_keys = array_keys($language_list);
690
            $default_language = $language_keys[0];
691
        }
692
    }
693
694
    // Displaying the box.
695
    $html = '';
696
    $html .= "\t\t<select class='selectpicker show-tick' name=\"$name\">\n";
697
    foreach ($language_list as $key => $value) {
698
        if ($key == $default_language) {
699
            $option_end = ' selected="selected">';
700
        } else {
701
            $option_end = '>';
702
        }
703
        $html .= "\t\t\t<option value=\"$key\"$option_end";
704
        $html .= $value;
705
        $html .= "</option>\n";
706
    }
707
    $html .= "\t\t</select>\n";
708
709
    return $html;
710
}
711
712
/**
713
 * This function displays a language dropdown box so that the installatioin
714
 * can be done in the language of the user.
715
 */
716
function display_language_selection()
717
{
718
    ?>
719
    <h2><?php get_lang('WelcomeToTheChamiloInstaller'); ?></h2>
720
    <div class="RequirementHeading">
721
        <h2><?php echo display_step_sequence(); ?>
722
            <?php echo get_lang('InstallationLanguage'); ?>
723
        </h2>
724
        <p><?php echo get_lang('PleaseSelectInstallationProcessLanguage'); ?>:</p>
725
        <form id="lang_form" method="post" action="<?php echo api_get_self(); ?>">
726
        <div class="form-group">
727
            <div class="col-sm-4">
728
                <?php echo display_language_selection_box('language_list', api_get_interface_language()); ?>
729
            </div>
730
            <div class="col-sm-6">
731
                <button type="submit" name="step1" class="btn btn-success" value="<?php echo get_lang('Next'); ?>">
732
                    <em class="fa fa-forward"> </em>
733
                    <?php echo get_lang('Next'); ?></button>
734
            </div>
735
        </div>
736
737
        <input type="hidden" name="is_executable" id="is_executable" value="-" />
738
        </form>
739
740
    </div>
741
    <div class="RequirementHeading">
742
        <?php echo get_lang('YourLanguageNotThereContactUs'); ?>
743
    </div>
744
<?php
745
}
746
747
/**
748
 * This function displays the requirements for installing Chamilo.
749
 *
750
 * @param string $installType
751
 * @param bool   $badUpdatePath
752
 * @param string $updatePath            The updatePath given (if given)
753
 * @param array  $update_from_version_8 The different subversions from version 1.9
754
 *
755
 * @author unknow
756
 * @author Patrick Cool <[email protected]>, Ghent University
757
 */
758
function display_requirements(
759
    $installType,
760
    $badUpdatePath,
761
    $updatePath = '',
762
    $update_from_version_8 = []
763
) {
764
    global $_setting, $originalMemoryLimit;
765
    echo '<div class="RequirementHeading"><h2>'.display_step_sequence().get_lang('Requirements')."</h2></div>";
766
    echo '<div class="RequirementText">';
767
    echo '<strong>'.get_lang('ReadThoroughly').'</strong><br />';
768
    echo get_lang('MoreDetails').' <a href="../../documentation/installation_guide.html" target="_blank">'.
769
        get_lang('ReadTheInstallationGuide').'</a>.<br />'."\n";
770
771
    if ($installType == 'update') {
772
        echo get_lang('IfYouPlanToUpgradeFromOlderVersionYouMightWantToHaveAlookAtTheChangelog').'<br />';
773
    }
774
    echo '</div>';
775
776
    $properlyAccessUrl = checkAccessUrl();
777
778
    if (!$properlyAccessUrl) {
779
        echo '
780
            <div class="alert alert-danger">
781
                '.Display::return_icon('error.png', get_lang('Error'), [], ICON_SIZE_MEDIUM, true, false, true).
782
            ' '.
783
            sprintf(get_lang('InstallMultiURLDetectedNotMainURL'), api_get_configuration_value('root_web')).'
784
            </div>
785
        ';
786
    }
787
788
    //  SERVER REQUIREMENTS
789
    echo '<div class="RequirementHeading"><h4>'.get_lang('ServerRequirements').'</h4>';
790
    if (phpversion() < '7.0') {
791
        // If PHP < 7.0, then an undefined date.timezone would trigger a
792
        // warning, so ask for it to be defined. Above 7.0, date.timezone
793
        // defaults to UTC and does not trigger warnings.
794
        // See https://php.net/manual/en/migration70.other-changes.php
795
        $timezone = checkPhpSettingExists("date.timezone");
796
        if (!$timezone) {
797
            echo "<div class='alert alert-warning'>".
798
                Display::return_icon(
799
                    'warning.png',
800
                    get_lang('Warning'),
801
                    '',
802
                    ICON_SIZE_MEDIUM,
803
                    true,
804
                    false,
805
                    false
806
                ).
807
                get_lang("DateTimezoneSettingNotSet")."</div>";
808
        }
809
    }
810
811
    echo '<div class="RequirementText">'.get_lang('ServerRequirementsInfo').'</div>';
812
    echo '<div class="RequirementContent">';
813
    echo '<table class="table">
814
            <tr>
815
                <td class="requirements-item">'.get_lang('PHPVersion').' >= '.REQUIRED_PHP_VERSION.'</td>
816
                <td class="requirements-value">';
817
    if (phpversion() < REQUIRED_PHP_VERSION) {
818
        echo '<strong><font color="red">'.get_lang('PHPVersionError').'</font></strong>';
819
    } else {
820
        echo '<strong><font color="green">'.get_lang('PHPVersionOK').' '.phpversion().'</font></strong>';
821
    }
822
    echo '</td>
823
            </tr>
824
            <tr>
825
                <td class="requirements-item"><a href="https://php.net/manual/en/book.session.php" target="_blank">Session</a> '.get_lang('Support').'</td>
826
                <td class="requirements-value">'.checkExtension('session', get_lang('Yes'), get_lang('ExtensionSessionsNotAvailable')).'</td>
827
            </tr>
828
            <tr>
829
                <td class="requirements-item"><a href="https://php.net/manual/en/book.mysql.php" target="_blank">pdo_mysql</a> '.get_lang('Support').'</td>
830
                <td class="requirements-value">'.checkExtension('pdo_mysql', get_lang('Yes'), get_lang('ExtensionMySQLNotAvailable')).'</td>
831
            </tr>
832
            <tr>
833
                <td class="requirements-item"><a href="https://php.net/manual/en/book.zip.php" target="_blank">Zip</a> '.get_lang('Support').'</td>
834
                <td class="requirements-value">'.checkExtension('zip', get_lang('Yes'), get_lang('ExtensionNotAvailable')).'</td>
835
            </tr>
836
            <tr>
837
                <td class="requirements-item"><a href="https://php.net/manual/en/book.zlib.php" target="_blank">Zlib</a> '.get_lang('Support').'</td>
838
                <td class="requirements-value">'.checkExtension('zlib', get_lang('Yes'), get_lang('ExtensionZlibNotAvailable')).'</td>
839
            </tr>
840
            <tr>
841
                <td class="requirements-item"><a href="https://php.net/manual/en/book.pcre.php" target="_blank">Perl-compatible regular expressions</a> '.get_lang('Support').'</td>
842
                <td class="requirements-value">'.checkExtension('pcre', get_lang('Yes'), get_lang('ExtensionPCRENotAvailable')).'</td>
843
            </tr>
844
            <tr>
845
                <td class="requirements-item"><a href="https://php.net/manual/en/book.xml.php" target="_blank">XML</a> '.get_lang('Support').'</td>
846
                <td class="requirements-value">'.checkExtension('xml', get_lang('Yes'), get_lang('No')).'</td>
847
            </tr>
848
            <tr>
849
                <td class="requirements-item"><a href="https://php.net/manual/en/book.intl.php" target="_blank">Internationalization</a> '.get_lang('Support').'</td>
850
                <td class="requirements-value">'.checkExtension('intl', get_lang('Yes'), get_lang('No')).'</td>
851
            </tr>
852
               <tr>
853
                <td class="requirements-item"><a href="https://php.net/manual/en/book.json.php" target="_blank">JSON</a> '.get_lang('Support').'</td>
854
                <td class="requirements-value">'.checkExtension('json', get_lang('Yes'), get_lang('No')).'</td>
855
            </tr>
856
             <tr>
857
                <td class="requirements-item"><a href="https://php.net/manual/en/book.image.php" target="_blank">GD</a> '.get_lang('Support').'</td>
858
                <td class="requirements-value">'.checkExtension('gd', get_lang('Yes'), get_lang('ExtensionGDNotAvailable')).'</td>
859
            </tr>
860
            <tr>
861
                <td class="requirements-item"><a href="https://php.net/manual/en/book.curl.php" target="_blank">cURL</a>'.get_lang('Support').'</td>
862
                <td class="requirements-value">'.checkExtension('curl', get_lang('Yes'), get_lang('No')).'</td>
863
            </tr>
864
            <tr>
865
                <td class="requirements-item"><a href="https://php.net/manual/en/book.fileinfo.php" target="_blank">FileInfo</a>'.get_lang('Support').'</td>
866
                <td class="requirements-value">'.checkExtension('fileinfo', get_lang('Yes'), get_lang('No')).'</td>
867
            </tr>
868
869
            <tr>
870
                <td class="requirements-item"><a href="https://php.net/manual/en/book.mbstring.php" target="_blank">Multibyte string</a> '.get_lang('Support').' ('.get_lang('Optional').')</td>
871
                <td class="requirements-value">'.checkExtension('mbstring', get_lang('Yes'), get_lang('ExtensionMBStringNotAvailable'), true).'</td>
872
            </tr>
873
            <tr>
874
                <td class="requirements-item"><a href="https://php.net/opcache" target="_blank">Zend OpCache</a> '.get_lang('Support').' ('.get_lang('Optional').')</td>
875
                <td class="requirements-value">'.checkExtension('Zend OPcache', get_lang('Yes'), get_lang('No'), true, 'opcache.enable').'</td>
876
            </tr>
877
            <tr>
878
                <td class="requirements-item"><a href="https://php.net/apcu" target="_blank">APCu</a> '.get_lang('Support').' ('.get_lang('Optional').')</td>
879
                <td class="requirements-value">'.checkExtension('apcu', get_lang('Yes'), get_lang('No'), true, 'apc.enabled').'</td>
880
            </tr>
881
            <tr>
882
                <td class="requirements-item"><a href="https://php.net/manual/en/book.iconv.php" target="_blank">Iconv</a> '.get_lang('Support').' ('.get_lang('Optional').')</td>
883
                <td class="requirements-value">'.checkExtension('iconv', get_lang('Yes'), get_lang('No'), true).'</td>
884
            </tr>
885
            <tr>
886
                <td class="requirements-item"><a href="https://php.net/manual/en/book.ldap.php" target="_blank">LDAP</a> '.get_lang('Support').' ('.get_lang('Optional').')</td>
887
                <td class="requirements-value">'.checkExtension('ldap', get_lang('Yes'), get_lang('ExtensionLDAPNotAvailable'), true).'</td>
888
            </tr>
889
            <tr>
890
                <td class="requirements-item"><a href="https://xapian.org/" target="_blank">Xapian</a> '.get_lang('Support').' ('.get_lang('Optional').')</td>
891
                <td class="requirements-value">'.checkExtension('xapian', get_lang('Yes'), get_lang('No'), true).'</td>
892
            </tr>
893
            <tr>
894
                <td class="requirements-item"><a href="https://php.net/openssl" target="_blank">OpenSSL</a> '.get_lang('Support').' ('.get_lang('Optional').')</td>
895
                <td class="requirements-value">'.checkExtension('openssl', get_lang('Yes'), get_lang('No'), true).'</td>
896
            </tr>
897
        </table>';
898
    echo '</div>';
899
    echo '</div>';
900
901
    // RECOMMENDED SETTINGS
902
    // Note: these are the settings for Joomla, does this also apply for Chamilo?
903
    // Note: also add upload_max_filesize here so that large uploads are possible
904
    echo '<div class="RequirementHeading"><h4>'.get_lang('RecommendedSettings').'</h4>';
905
    echo '<div class="RequirementText">'.get_lang('RecommendedSettingsInfo').'</div>';
906
    echo '<div class="RequirementContent">';
907
    echo '<table class="table">
908
            <tr>
909
                <th>'.get_lang('Setting').'</th>
910
                <th>'.get_lang('Recommended').'</th>
911
                <th>'.get_lang('Actual').'</th>
912
            </tr>
913
            <tr>
914
                <td class="requirements-item"><a href="https://php.net/manual/features.safe-mode.php">Safe Mode</a></td>
915
                <td class="requirements-recommended">'.Display::label('OFF', 'success').'</td>
916
                <td class="requirements-value">'.checkPhpSetting('safe_mode', 'OFF').'</td>
917
            </tr>
918
            <tr>
919
                <td class="requirements-item"><a href="https://php.net/manual/ref.errorfunc.php#ini.display-errors">Display Errors</a></td>
920
                <td class="requirements-recommended">'.Display::label('OFF', 'success').'</td>
921
                <td class="requirements-value">'.checkPhpSetting('display_errors', 'OFF').'</td>
922
            </tr>
923
            <tr>
924
                <td class="requirements-item"><a href="https://php.net/manual/ini.core.php#ini.file-uploads">File Uploads</a></td>
925
                <td class="requirements-recommended">'.Display::label('ON', 'success').'</td>
926
                <td class="requirements-value">'.checkPhpSetting('file_uploads', 'ON').'</td>
927
            </tr>
928
            <tr>
929
                <td class="requirements-item"><a href="https://php.net/manual/ref.info.php#ini.magic-quotes-gpc">Magic Quotes GPC</a></td>
930
                <td class="requirements-recommended">'.Display::label('OFF', 'success').'</td>
931
                <td class="requirements-value">'.checkPhpSetting('magic_quotes_gpc', 'OFF').'</td>
932
            </tr>
933
            <tr>
934
                <td class="requirements-item"><a href="https://php.net/manual/ref.info.php#ini.magic-quotes-runtime">Magic Quotes Runtime</a></td>
935
                <td class="requirements-recommended">'.Display::label('OFF', 'success').'</td>
936
                <td class="requirements-value">'.checkPhpSetting('magic_quotes_runtime', 'OFF').'</td>
937
            </tr>
938
            <tr>
939
                <td class="requirements-item"><a href="https://php.net/manual/security.globals.php">Register Globals</a></td>
940
                <td class="requirements-recommended">'.Display::label('OFF', 'success').'</td>
941
                <td class="requirements-value">'.checkPhpSetting('register_globals', 'OFF').'</td>
942
            </tr>
943
            <tr>
944
                <td class="requirements-item"><a href="https://php.net/manual/ref.session.php#ini.session.auto-start">Session auto start</a></td>
945
                <td class="requirements-recommended">'.Display::label('OFF', 'success').'</td>
946
                <td class="requirements-value">'.checkPhpSetting('session.auto_start', 'OFF').'</td>
947
            </tr>
948
            <tr>
949
                <td class="requirements-item"><a href="https://php.net/manual/ini.core.php#ini.short-open-tag">Short Open Tag</a></td>
950
                <td class="requirements-recommended">'.Display::label('OFF', 'success').'</td>
951
                <td class="requirements-value">'.checkPhpSetting('short_open_tag', 'OFF').'</td>
952
            </tr>
953
            <tr>
954
                <td class="requirements-item"><a href="https://php.net/manual/en/session.configuration.php#ini.session.cookie-httponly">Cookie HTTP Only</a></td>
955
                <td class="requirements-recommended">'.Display::label('ON', 'success').'</td>
956
                <td class="requirements-value">'.checkPhpSetting('session.cookie_httponly', 'ON').'</td>
957
            </tr>
958
            <tr>
959
                <td class="requirements-item"><a href="https://php.net/manual/ini.core.php#ini.upload-max-filesize">Maximum upload file size</a></td>
960
                <td class="requirements-recommended">'.Display::label('>= '.REQUIRED_MIN_UPLOAD_MAX_FILESIZE.'M', 'success').'</td>
961
                <td class="requirements-value">'.compare_setting_values(ini_get('upload_max_filesize'), REQUIRED_MIN_UPLOAD_MAX_FILESIZE).'</td>
962
            </tr>
963
            <tr>
964
                <td class="requirements-item"><a href="https://php.net/manual/ini.core.php#ini.post-max-size">Maximum post size</a></td>
965
                <td class="requirements-recommended">'.Display::label('>= '.REQUIRED_MIN_POST_MAX_SIZE.'M', 'success').'</td>
966
                <td class="requirements-value">'.compare_setting_values(ini_get('post_max_size'), REQUIRED_MIN_POST_MAX_SIZE).'</td>
967
            </tr>
968
            <tr>
969
                <td class="requirements-item"><a href="https://php.net/manual/en/ini.core.php#ini.memory-limit">Memory Limit</a></td>
970
                <td class="requirements-recommended">'.Display::label('>= '.REQUIRED_MIN_MEMORY_LIMIT.'M', 'success').'</td>
971
                <td class="requirements-value">'.compare_setting_values($originalMemoryLimit, REQUIRED_MIN_MEMORY_LIMIT).'</td>
972
            </tr>
973
          </table>';
974
    echo '  </div>';
975
    echo '</div>';
976
977
    // DIRECTORY AND FILE PERMISSIONS
978
    echo '<div class="RequirementHeading"><h4>'.get_lang('DirectoryAndFilePermissions').'</h4>';
979
    echo '<div class="RequirementText">'.get_lang('DirectoryAndFilePermissionsInfo').'</div>';
980
    echo '<div class="RequirementContent">';
981
982
    $course_attempt_name = '__XxTestxX__';
983
    $course_dir = api_get_path(SYS_COURSE_PATH).$course_attempt_name;
984
    $fileToCreate = 'test.html';
985
    // Just in case
986
    @unlink($course_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

986
    /** @scrutinizer ignore-unhandled */ @unlink($course_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...
987
    @rmdir($course_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

987
    /** @scrutinizer ignore-unhandled */ @rmdir($course_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...
988
989
    $perms_dir = [0777, 0755, 0775, 0770, 0750, 0700];
990
    $perms_fil = [0666, 0644, 0664, 0660, 0640, 0600];
991
    $course_test_was_created = false;
992
    $dir_perm_verified = 0777;
993
    foreach ($perms_dir as $perm) {
994
        $r = @mkdir($course_dir, $perm);
995
        if ($r === true) {
996
            $dir_perm_verified = $perm;
997
            $course_test_was_created = true;
998
            break;
999
        }
1000
    }
1001
1002
    $fil_perm_verified = 0666;
1003
    $file_course_test_was_created = false;
1004
    if (is_dir($course_dir)) {
1005
        foreach ($perms_fil as $perm) {
1006
            if ($file_course_test_was_created == true) {
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...
1007
                break;
1008
            }
1009
            $r = @touch($course_dir.'/'.$fileToCreate, $perm);
1010
            if ($r === true) {
1011
                $fil_perm_verified = $perm;
1012
                if (checkCourseScriptCreation($course_dir, $course_attempt_name, $fileToCreate)) {
1013
                    $file_course_test_was_created = true;
1014
                }
1015
            }
1016
        }
1017
    }
1018
1019
    @unlink($course_dir.'/'.$fileToCreate);
1020
    @rmdir($course_dir);
1021
1022
    $_SESSION['permissions_for_new_directories'] = $_setting['permissions_for_new_directories'] = $dir_perm_verified;
1023
    $_SESSION['permissions_for_new_files'] = $_setting['permissions_for_new_files'] = $fil_perm_verified;
1024
1025
    $dir_perm = Display::label('0'.decoct($dir_perm_verified), 'info');
1026
    $file_perm = Display::label('0'.decoct($fil_perm_verified), 'info');
1027
1028
    $courseTestLabel = Display::label(get_lang('No'), 'important');
1029
    if ($course_test_was_created && $file_course_test_was_created) {
1030
        $courseTestLabel = Display::label(get_lang('Yes'), 'success');
1031
    }
1032
1033
    if ($course_test_was_created && !$file_course_test_was_created) {
1034
        $courseTestLabel = Display::label(get_lang('Warning'), 'warning');
1035
        $courseTestLabel .= '<br />'.sprintf(
1036
            get_lang('InstallWarningCouldNotInterpretPHP'),
1037
            api_get_path(WEB_COURSE_PATH).$course_attempt_name.'/'.$fileToCreate
1038
        );
1039
    }
1040
1041
    if (!$course_test_was_created && !$file_course_test_was_created) {
1042
        $courseTestLabel = Display::label(get_lang('No'), 'important');
1043
    }
1044
1045
    $oldConf = '';
1046
    if (file_exists(api_get_path(SYS_CODE_PATH).'inc/conf/configuration.php')) {
1047
        $oldConf = '<tr>
1048
            <td class="requirements-item">'.api_get_path(SYS_CODE_PATH).'inc/conf</td>
1049
            <td class="requirements-value">'.check_writable(api_get_path(SYS_CODE_PATH).'inc/conf').'</td>
1050
        </tr>';
1051
    }
1052
1053
    echo '<table class="table">
1054
            '.$oldConf.'
1055
            <tr>
1056
                <td class="requirements-item">'.api_get_path(SYS_APP_PATH).'</td>
1057
                <td class="requirements-value">'.check_writable(api_get_path(SYS_APP_PATH)).'</td>
1058
            </tr>
1059
            <tr>
1060
                <td class="requirements-item">'.api_get_path(SYS_CODE_PATH).'default_course_document/images/</td>
1061
                <td class="requirements-value">'.check_writable(api_get_path(SYS_CODE_PATH).'default_course_document/images/').'</td>
1062
            </tr>
1063
            <tr>
1064
                <td class="requirements-item">'.api_get_path(SYS_CODE_PATH).'lang/</td>
1065
                <td class="requirements-value">'.check_writable(api_get_path(SYS_CODE_PATH).'lang/', true).' <br />('.get_lang('SuggestionOnlyToEnableSubLanguageFeatureOrUpgradeProcess').')</td>
1066
            </tr>
1067
            <tr>
1068
                <td class="requirements-item">'.api_get_path(SYS_PATH).'vendor/</td>
1069
                <td class="requirements-value">'.checkReadable(api_get_path(SYS_PATH).'vendor').'</td>
1070
            </tr>
1071
            <tr>
1072
                <td class="requirements-item">'.api_get_path(SYS_PUBLIC_PATH).'</td>
1073
                <td class="requirements-value">'.check_writable(api_get_path(SYS_PUBLIC_PATH)).'</td>
1074
            </tr>
1075
            <tr>
1076
                <td class="requirements-item">'.get_lang('CourseTestWasCreated').'</td>
1077
                <td class="requirements-value">'.$courseTestLabel.' </td>
1078
            </tr>
1079
            <tr>
1080
                <td class="requirements-item">'.get_lang('PermissionsForNewDirs').'</td>
1081
                <td class="requirements-value">'.$dir_perm.' </td>
1082
            </tr>
1083
            <tr>
1084
                <td class="requirements-item">'.get_lang('PermissionsForNewFiles').'</td>
1085
                <td class="requirements-value">'.$file_perm.' </td>
1086
            </tr>
1087
        </table>';
1088
    echo '  </div>';
1089
    echo '</div>';
1090
1091
    if ($installType == 'update' && (empty($updatePath) || $badUpdatePath)) {
1092
        if ($badUpdatePath) {
1093
            ?>
1094
            <div class="alert alert-warning">
1095
                <?php echo get_lang('Error'); ?>!<br />
1096
                Chamilo <?php echo implode('|', $update_from_version_8).' '.get_lang('HasNotBeenFoundInThatDir'); ?>.
1097
            </div>
1098
        <?php
1099
        } else {
1100
            echo '<br />';
1101
        } ?>
1102
            <div class="row">
1103
                <div class="col-md-12">
1104
                    <p><?php echo get_lang('OldVersionRootPath'); ?>:
1105
                        <input type="text" name="updatePath" size="50" value="<?php echo ($badUpdatePath && !empty($updatePath)) ? htmlentities($updatePath) : ''; ?>" />
1106
                    </p>
1107
                    <p>
1108
                        <button type="submit" class="btn btn-default" name="step1" value="<?php echo get_lang('Back'); ?>" >
1109
                            <em class="fa fa-backward"> <?php echo get_lang('Back'); ?></em>
1110
                        </button>
1111
                        <input type="hidden" name="is_executable" id="is_executable" value="-" />
1112
                        <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;" >
1113
                            <em class="fa fa-forward"> </em> <?php echo get_lang('Next'); ?>
1114
                        </button>
1115
                    </p>
1116
                </div>
1117
            </div>
1118
1119
        <?php
1120
    } else {
1121
        $error = false;
1122
        // First, attempt to set writing permissions if we don't have them yet
1123
        $perm = api_get_permissions_for_new_directories();
1124
        $perm_file = api_get_permissions_for_new_files();
1125
        $notWritable = [];
1126
1127
        $checked_writable = api_get_path(SYS_APP_PATH);
1128
        if (!is_writable($checked_writable)) {
1129
            $notWritable[] = $checked_writable;
1130
            @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

1130
            /** @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...
1131
        }
1132
1133
        $checked_writable = api_get_path(SYS_PUBLIC_PATH);
1134
        if (!is_writable($checked_writable)) {
1135
            $notWritable[] = $checked_writable;
1136
            @chmod($checked_writable, $perm);
1137
        }
1138
1139
        $checked_writable = api_get_path(SYS_CODE_PATH).'default_course_document/images/';
1140
        if (!is_writable($checked_writable)) {
1141
            $notWritable[] = $checked_writable;
1142
            @chmod($checked_writable, $perm);
1143
        }
1144
1145
        if ($course_test_was_created == false) {
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...
1146
            $error = true;
1147
        }
1148
1149
        $checked_writable = api_get_path(CONFIGURATION_PATH).'configuration.php';
1150
        if (file_exists($checked_writable) && !is_writable($checked_writable)) {
1151
            $notWritable[] = $checked_writable;
1152
            @chmod($checked_writable, $perm_file);
1153
        }
1154
1155
        // Second, if this fails, report an error
1156
1157
        //--> The user would have to adjust the permissions manually
1158
        if (count($notWritable) > 0) {
1159
            $error = true; ?>
1160
            <div class="text-danger">
1161
                <h3 class="text-center"><?php echo get_lang('Warning'); ?></h3>
1162
                <p>
1163
                    <?php printf(get_lang('NoWritePermissionPleaseReadInstallGuide'), '<a href="../../documentation/installation_guide.html" target="blank">', '</a>'); ?>
1164
                </p>
1165
            </div>
1166
            <?php
1167
            echo '<ul>';
1168
            foreach ($notWritable as $value) {
1169
                echo '<li class="text-danger">'.$value.'</li>';
1170
            }
1171
            echo '</ul>';
1172
        } elseif (file_exists(api_get_path(CONFIGURATION_PATH).'configuration.php')) {
1173
            // Check wether a Chamilo configuration file already exists.
1174
            echo '<div class="alert alert-warning"><h4><center>';
1175
            echo get_lang('WarningExistingLMSInstallationDetected');
1176
            echo '</center></h4></div>';
1177
        }
1178
1179
        $deprecated = [
1180
            api_get_path(SYS_CODE_PATH).'exercice/',
1181
            api_get_path(SYS_CODE_PATH).'newscorm/',
1182
            api_get_path(SYS_PLUGIN_PATH).'ticket/',
1183
            api_get_path(SYS_PLUGIN_PATH).'skype/',
1184
        ];
1185
        $deprecatedToRemove = [];
1186
        foreach ($deprecated as $deprecatedDirectory) {
1187
            if (!is_dir($deprecatedDirectory)) {
1188
                continue;
1189
            }
1190
            $deprecatedToRemove[] = $deprecatedDirectory;
1191
        }
1192
1193
        if (count($deprecatedToRemove) > 0) {
1194
            ?>
1195
            <p class="text-danger"><?php echo get_lang('WarningForDeprecatedDirectoriesForUpgrade'); ?></p>
1196
            <ul>
1197
                <?php foreach ($deprecatedToRemove as $deprecatedDirectory) {
1198
                ?>
1199
                    <li class="text-danger"><?php echo $deprecatedDirectory; ?></li>
1200
                <?php
1201
            } ?>
1202
            </ul>
1203
            <?php
1204
        }
1205
1206
        if (!$properlyAccessUrl) {
1207
            $error = true;
1208
        }
1209
1210
        // And now display the choice buttons (go back or install)?>
1211
        <p align="center" style="padding-top:15px">
1212
        <button type="submit" name="step1" class="btn btn-default" onclick="javascript: window.location='index.php'; return false;" value="<?php echo get_lang('Previous'); ?>" >
1213
            <em class="fa fa-backward"> </em> <?php echo get_lang('Previous'); ?>
1214
        </button>
1215
        <button type="submit" name="step2_install" class="btn btn-success" value="<?php echo get_lang("NewInstallation"); ?>" <?php if ($error) {
1216
            echo 'disabled="disabled"';
1217
        } ?> >
1218
            <em class="fa fa-forward"> </em> <?php echo get_lang('NewInstallation'); ?>
1219
        </button>
1220
        <input type="hidden" name="is_executable" id="is_executable" value="-" />
1221
            <button type="submit" class="btn btn-default" <?php echo !$error ?: 'disabled="disabled"'; ?> name="step2_update_8" value="Upgrade from Chamilo 1.9.x">
1222
                <em class="fa fa-forward" aria-hidden="true"></em> <?php echo get_lang('UpgradeVersion'); ?>
1223
            </button>
1224
            </p>
1225
        <?php
1226
    }
1227
}
1228
1229
/**
1230
 * Displays the license (GNU GPL) as step 2, with
1231
 * - an "I accept" button named step3 to proceed to step 3;
1232
 * - a "Back" button named step1 to go back to the first step.
1233
 */
1234
function display_license_agreement()
1235
{
1236
    echo '<div class="RequirementHeading"><h2>'.display_step_sequence().get_lang('Licence').'</h2>';
1237
    echo '<p>'.get_lang('LMSLicenseInfo').'</p>';
1238
    echo '<p><a href="../../documentation/license.html" target="_blank">'.get_lang('PrintVers').'</a></p>';
1239
    echo '</div>'; ?>
1240
    <div class="row">
1241
        <div class="col-md-12">
1242
            <pre style="overflow: auto; height: 200px; margin-top: 5px;">
1243
                <?php echo api_htmlentities(@file_get_contents(api_get_path(SYS_PATH).'documentation/license.txt')); ?>
1244
            </pre>
1245
            <div class="checkbox">
1246
                <label>
1247
                    <input type="checkbox" name="accept" id="accept_licence" value="1" />
1248
                    <?php echo get_lang('IAccept'); ?>
1249
                </label>
1250
            </div>
1251
        </div>
1252
    </div>
1253
    <div class="row">
1254
        <div class="col-md-12">
1255
            <p class="alert alert-info"><?php echo get_lang('LMSMediaLicense'); ?></p>
1256
        </div>
1257
    </div>
1258
1259
    <!-- Contact information form -->
1260
    <div class="section-parameters">
1261
        <a href="javascript://" class = "advanced_parameters" >
1262
        <span id="img_plus_and_minus">&nbsp;<img src="<?php echo api_get_path(WEB_IMG_PATH); ?>div_hide.gif" alt="<?php echo get_lang('Hide'); ?>" title="<?php echo get_lang('Hide'); ?>" style ="vertical-align:middle" />&nbsp;<?php echo get_lang('ContactInformation'); ?></span>
1263
        </a>
1264
    </div>
1265
1266
    <div id="id_contact_form" style="display:block">
1267
        <div class="normal-message"><?php echo get_lang('ContactInformationDescription'); ?></div>
1268
        <div id="contact_registration">
1269
            <p><?php echo get_contact_registration_form(); ?></p><br />
1270
        </div>
1271
    </div>
1272
    <div class="text-center">
1273
    <button type="submit" class="btn btn-default" name="step1" value="&lt; <?php echo get_lang('Previous'); ?>" >
1274
        <em class="fa fa-backward"> </em> <?php echo get_lang('Previous'); ?>
1275
    </button>
1276
    <input type="hidden" name="is_executable" id="is_executable" value="-" />
1277
    <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('YouMustAcceptLicence'); ?>');return false;}" value="<?php echo get_lang('Next'); ?> &gt;" >
1278
        <em class="fa fa-forward"> </em> <?php echo get_lang('Next'); ?>
1279
    </button>
1280
    </div>
1281
    <?php
1282
}
1283
1284
/**
1285
 * Get contact registration form.
1286
 */
1287
function get_contact_registration_form()
1288
{
1289
    $html = '
1290
   <div class="form-horizontal">
1291
    <div class="panel panel-default">
1292
    <div class="panel-body">
1293
    <div id="div_sent_information"></div>
1294
    <div class="form-group">
1295
            <label class="col-sm-3"><span class="form_required">*</span>'.get_lang('Name').'</label>
1296
            <div class="col-sm-9"><input id="person_name" class="form-control" type="text" name="person_name" size="30" /></div>
1297
    </div>
1298
    <div class="form-group">
1299
            <label class="col-sm-3"><span class="form_required">*</span>'.get_lang('Email').'</label>
1300
            <div class="col-sm-9"><input id="person_email" class="form-control" type="text" name="person_email" size="30" /></div>
1301
    </div>
1302
    <div class="form-group">
1303
            <label class="col-sm-3"><span class="form_required">*</span>'.get_lang('CompanyName').'</label>
1304
            <div class="col-sm-9"><input id="company_name" class="form-control" type="text" name="company_name" size="30" /></div>
1305
    </div>
1306
    <div class="form-group">
1307
        <label class="col-sm-3"><span class="form_required">*</span>'.get_lang('CompanyActivity').'</label>
1308
        <div class="col-sm-9">
1309
            <select class="selectpicker show-tick" name="company_activity" id="company_activity" >
1310
                <option value="">--- '.get_lang('SelectOne').' ---</option>
1311
                <Option value="Advertising/Marketing/PR">Advertising/Marketing/PR</Option><Option value="Agriculture/Forestry">Agriculture/Forestry</Option>
1312
                <Option value="Architecture">Architecture</Option><Option value="Banking/Finance">Banking/Finance</Option>
1313
                <Option value="Biotech/Pharmaceuticals">Biotech/Pharmaceuticals</Option><Option value="Business Equipment">Business Equipment</Option>
1314
                <Option value="Business Services">Business Services</Option><Option value="Construction">Construction</Option>
1315
                <Option value="Consulting/Research">Consulting/Research</Option><Option value="Education">Education</Option>
1316
                <Option value="Engineering">Engineering</Option><Option value="Environmental">Environmental</Option>
1317
                <Option value="Government">Government</Option><Option value="Healthcare">Health Care</Option>
1318
                <Option value="Hospitality/Lodging/Travel">Hospitality/Lodging/Travel</Option><Option value="Insurance">Insurance</Option>
1319
                <Option value="Legal">Legal</Option><Option value="Manufacturing">Manufacturing</Option>
1320
                <Option value="Media/Entertainment">Media/Entertainment</Option><Option value="Mortgage">Mortgage</Option>
1321
                <Option value="Non-Profit">Non-Profit</Option><Option value="Real Estate">Real Estate</Option>
1322
                <Option value="Restaurant">Restaurant</Option><Option value="Retail">Retail</Option>
1323
                <Option value="Shipping/Transportation">Shipping/Transportation</Option>
1324
                <Option value="Technology">Technology</Option><Option value="Telecommunications">Telecommunications</Option>
1325
                <Option value="Other">Other</Option>
1326
            </select>
1327
        </div>
1328
    </div>
1329
1330
    <div class="form-group">
1331
        <label class="col-sm-3"><span class="form_required">*</span>'.get_lang('PersonRole').'</label>
1332
        <div class="col-sm-9">
1333
            <select class="selectpicker show-tick" name="person_role" id="person_role" >
1334
                <option value="">--- '.get_lang('SelectOne').' ---</option>
1335
                <Option value="Administration">Administration</Option><Option value="CEO/President/ Owner">CEO/President/ Owner</Option>
1336
                <Option value="CFO">CFO</Option><Option value="CIO/CTO">CIO/CTO</Option>
1337
                <Option value="Consultant">Consultant</Option><Option value="Customer Service">Customer Service</Option>
1338
                <Option value="Engineer/Programmer">Engineer/Programmer</Option><Option value="Facilities/Operations">Facilities/Operations</Option>
1339
                <Option value="Finance/ Accounting Manager">Finance/ Accounting Manager</Option><Option value="Finance/ Accounting Staff">Finance/ Accounting Staff</Option>
1340
                <Option value="General Manager">General Manager</Option><Option value="Human Resources">Human Resources</Option>
1341
                <Option value="IS/IT Management">IS/IT Management</Option><Option value="IS/ IT Staff">IS/ IT Staff</Option>
1342
                <Option value="Marketing Manager">Marketing Manager</Option><Option value="Marketing Staff">Marketing Staff</Option>
1343
                <Option value="Partner/Principal">Partner/Principal</Option><Option value="Purchasing Manager">Purchasing Manager</Option>
1344
                <Option value="Sales/ Business Dev. Manager">Sales/ Business Dev. Manager</Option><Option value="Sales/ Business Dev.">Sales/ Business Dev.</Option>
1345
                <Option value="Vice President/Senior Manager">Vice President/Senior Manager</Option><Option value="Other">Other</Option>
1346
            </select>
1347
        </div>
1348
    </div>
1349
1350
    <div class="form-group">
1351
        <label class="col-sm-3"><span class="form_required">*</span>'.get_lang('CompanyCountry').'</label>
1352
        <div class="col-sm-9">'.get_countries_list_from_array(true).'</div>
1353
    </div>
1354
    <div class="form-group">
1355
        <label class="col-sm-3">'.get_lang('CompanyCity').'</label>
1356
        <div class="col-sm-9">
1357
                <input type="text" class="form-control" id="company_city" name="company_city" size="30" />
1358
        </div>
1359
    </div>
1360
    <div class="form-group">
1361
        <label class="col-sm-3">'.get_lang('WhichLanguageWouldYouLikeToUseWhenContactingYou').'</label>
1362
        <div class="col-sm-9">
1363
            <select class="selectpicker show-tick" id="language" name="language">
1364
                <option value="bulgarian">Bulgarian</option>
1365
                <option value="indonesian">Bahasa Indonesia</option>
1366
                <option value="bosnian">Bosanski</option>
1367
                <option value="german">Deutsch</option>
1368
                <option selected="selected" value="english">English</option>
1369
                <option value="spanish">Spanish</option>
1370
                <option value="french">Français</option>
1371
                <option value="italian">Italian</option>
1372
                <option value="hungarian">Magyar</option>
1373
                <option value="dutch">Nederlands</option>
1374
                <option value="brazilian">Português do Brasil</option>
1375
                <option value="portuguese">Português europeu</option>
1376
                <option value="slovenian">Slovenčina</option>
1377
            </select>
1378
        </div>
1379
    </div>
1380
1381
    <div class="form-group">
1382
        <label class="col-sm-3">'.get_lang('HaveYouThePowerToTakeFinancialDecisions').'</label>
1383
        <div class="col-sm-9">
1384
            <div class="radio">
1385
                <label>
1386
                    <input type="radio" name="financial_decision" id="financial_decision1" value="1" checked /> '.get_lang('Yes').'
1387
                </label>
1388
            </div>
1389
            <div class="radio">
1390
                <label>
1391
                    <input type="radio" name="financial_decision" id="financial_decision2" value="0" /> '.get_lang('No').'
1392
                </label>
1393
            </div>
1394
        </div>
1395
    </div>
1396
    <div class="clear"></div>
1397
    <div class="form-group">
1398
            <div class="col-sm-3">&nbsp;</div>
1399
            <div class="col-sm-9"><button type="button" class="btn btn-default" onclick="javascript:send_contact_information();" value="'.get_lang('SendInformation').'" ><em class="fa fa-floppy-o"></em> '.get_lang('SendInformation').'</button> <span id="loader-button"></span></div>
1400
    </div>
1401
    <div class="form-group">
1402
            <div class="col-sm-3">&nbsp;</div>
1403
            <div class="col-sm-9"><span class="form_required">*</span><small>'.get_lang('FieldRequired').'</small></div>
1404
    </div></div></div>
1405
    </div>';
1406
1407
    return $html;
1408
}
1409
1410
/**
1411
 * Displays a parameter in a table row.
1412
 * Used by the display_database_settings_form function.
1413
 *
1414
 * @param   string  Type of install
1415
 * @param   string  Name of parameter
1416
 * @param   string  Field name (in the HTML form)
1417
 * @param   string  Field value
1418
 * @param   string  Extra notice (to show on the right side)
1419
 * @param   bool Whether to display in update mode
1420
 * @param   string  Additional attribute for the <tr> element
1421
 */
1422
function displayDatabaseParameter(
1423
    $installType,
1424
    $parameterName,
1425
    $formFieldName,
1426
    $parameterValue,
1427
    $extra_notice,
1428
    $displayWhenUpdate = true,
1429
    $tr_attribute = ''
1430
) {
1431
    //echo "<tr ".$tr_attribute.">";
1432
    echo "<label class='col-sm-4'>$parameterName</label>";
1433
1434
    if ($installType == INSTALL_TYPE_UPDATE && $displayWhenUpdate) {
1435
        echo '<input type="hidden" name="'.$formFieldName.'" id="'.$formFieldName.'" value="'.api_htmlentities($parameterValue).'" />'.$parameterValue;
1436
    } else {
1437
        $inputType = $formFieldName == 'dbPassForm' ? 'password' : 'text';
1438
1439
        //Slightly limit the length of the database prefix to avoid having to cut down the databases names later on
1440
        $maxLength = $formFieldName == 'dbPrefixForm' ? '15' : MAX_FORM_FIELD_LENGTH;
1441
        if ($installType == INSTALL_TYPE_UPDATE) {
1442
            echo '<input type="hidden" name="'.$formFieldName.'" id="'.$formFieldName.'" value="'.api_htmlentities($parameterValue).'" />';
1443
            echo api_htmlentities($parameterValue);
1444
        } else {
1445
            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>";
1446
            echo '<div class="col-sm-3">'.$extra_notice.'</div>';
1447
        }
1448
    }
1449
}
1450
1451
/**
1452
 * Displays step 3 - a form where the user can enter the installation settings
1453
 * regarding the databases - login and password, names, prefixes, single
1454
 * or multiple databases, tracking or not...
1455
 *
1456
 * @param string $installType
1457
 * @param string $dbHostForm
1458
 * @param string $dbUsernameForm
1459
 * @param string $dbPassForm
1460
 * @param string $dbNameForm
1461
 * @param int    $dbPortForm
1462
 * @param string $installationProfile
1463
 */
1464
function display_database_settings_form(
1465
    $installType,
1466
    $dbHostForm,
1467
    $dbUsernameForm,
1468
    $dbPassForm,
1469
    $dbNameForm,
1470
    $dbPortForm = 3306,
1471
    $installationProfile = ''
1472
) {
1473
    if ($installType == 'update') {
1474
        global $_configuration;
1475
        $dbHostForm = $_configuration['db_host'];
1476
        $dbUsernameForm = $_configuration['db_user'];
1477
        $dbPassForm = $_configuration['db_password'];
1478
        $dbNameForm = $_configuration['main_database'];
1479
        $dbPortForm = isset($_configuration['db_port']) ? $_configuration['db_port'] : '';
1480
1481
        echo '<div class="RequirementHeading"><h2>'.display_step_sequence().get_lang('DBSetting').'</h2></div>';
1482
        echo '<div class="RequirementContent">';
1483
        echo get_lang('DBSettingUpgradeIntro');
1484
        echo '</div>';
1485
    } else {
1486
        echo '<div class="RequirementHeading"><h2>'.display_step_sequence().get_lang('DBSetting').'</h2></div>';
1487
        echo '<div class="RequirementContent">';
1488
        echo get_lang('DBSettingIntro');
1489
        echo '</div>';
1490
    } ?>
1491
    <div class="panel panel-default">
1492
        <div class="panel-body">
1493
        <div class="form-group">
1494
            <label class="col-sm-4"><?php echo get_lang('DBHost'); ?> </label>
1495
            <?php if ($installType == 'update') {
1496
        ?>
1497
            <div class="col-sm-5">
1498
                <input type="hidden" name="dbHostForm" value="<?php echo htmlentities($dbHostForm); ?>" /><?php echo $dbHostForm; ?>
1499
            </div>
1500
            <div class="col-sm-3"></div>
1501
            <?php
1502
    } else {
1503
        ?>
1504
            <div class="col-sm-5">
1505
                <input type="text" class="form-control" size="25" maxlength="50" name="dbHostForm" value="<?php echo htmlentities($dbHostForm); ?>" />
1506
            </div>
1507
            <div class="col-sm-3"><?php echo get_lang('EG').' localhost'; ?></div>
1508
            <?php
1509
    } ?>
1510
        </div>
1511
        <div class="form-group">
1512
            <label class="col-sm-4"><?php echo get_lang('DBPort'); ?> </label>
1513
            <?php if ($installType == 'update') {
1514
        ?>
1515
            <div class="col-sm-5">
1516
                <input type="hidden" name="dbPortForm" value="<?php echo htmlentities($dbPortForm); ?>" /><?php echo $dbPortForm; ?>
1517
            </div>
1518
            <div class="col-sm-3"></div>
1519
            <?php
1520
    } else {
1521
        ?>
1522
            <div class="col-sm-5">
1523
                <input type="text" class="form-control" size="25" maxlength="50" name="dbPortForm" value="<?php echo htmlentities($dbPortForm); ?>" />
1524
            </div>
1525
            <div class="col-sm-3"><?php echo get_lang('EG').' 3306'; ?></div>
1526
            <?php
1527
    } ?>
1528
        </div>
1529
        <div class="form-group">
1530
            <?php
1531
                //database user username
1532
                $example_login = get_lang('EG').' root';
1533
    displayDatabaseParameter($installType, get_lang('DBLogin'), 'dbUsernameForm', $dbUsernameForm, $example_login); ?>
1534
        </div>
1535
        <div class="form-group">
1536
            <?php
1537
            //database user password
1538
            $example_password = get_lang('EG').' '.api_generate_password();
1539
    displayDatabaseParameter($installType, get_lang('DBPassword'), 'dbPassForm', $dbPassForm, $example_password); ?>
1540
        </div>
1541
        <div class="form-group">
1542
            <?php
1543
            //Database Name fix replace weird chars
1544
            if ($installType != INSTALL_TYPE_UPDATE) {
1545
                $dbNameForm = str_replace(['-', '*', '$', ' ', '.'], '', $dbNameForm);
1546
            }
1547
1548
    displayDatabaseParameter(
1549
                $installType,
1550
                get_lang('MainDB'),
1551
                'dbNameForm',
1552
                $dbNameForm,
1553
                '&nbsp;',
1554
                null,
1555
                'id="optional_param1"'
1556
                ); ?>
1557
        </div>
1558
       <?php if ($installType != INSTALL_TYPE_UPDATE) {
1559
                    ?>
1560
        <div class="form-group">
1561
            <div class="col-sm-3"></div>
1562
            <div class="col-sm-9">
1563
            <button type="submit" class="btn btn-primary" name="step3" value="step3">
1564
                <em class="fa fa-refresh"> </em>
1565
                <?php echo get_lang('CheckDatabaseConnection'); ?>
1566
            </button>
1567
            </div>
1568
        </div>
1569
        <?php
1570
                } ?>
1571
1572
        </div>
1573
    </div>
1574
    <?php
1575
        $database_exists_text = '';
1576
    $manager = null;
1577
    try {
1578
        $manager = connectToDatabase(
1579
                $dbHostForm,
1580
                $dbUsernameForm,
1581
                $dbPassForm,
1582
                null,
1583
                $dbPortForm
1584
            );
1585
        $databases = $manager->getConnection()->getSchemaManager()->listDatabases();
1586
        if (in_array($dbNameForm, $databases)) {
1587
            $database_exists_text = '<div class="alert alert-warning">'.get_lang('ADatabaseWithTheSameNameAlreadyExists').'</div>';
1588
        }
1589
    } catch (Exception $e) {
1590
        $database_exists_text = $e->getMessage();
1591
    }
1592
1593
    if ($manager && $manager->getConnection()->isConnected()): ?>
1594
        <?php echo $database_exists_text; ?>
1595
        <div id="db_status" class="alert alert-success">
1596
            Database host: <strong><?php echo $manager->getConnection()->getHost(); ?></strong><br/>
1597
            Database port: <strong><?php echo $manager->getConnection()->getPort(); ?></strong><br/>
1598
            Database driver: <strong><?php echo $manager->getConnection()->getDriver()->getName(); ?></strong><br/>
1599
        </div>
1600
    <?php else: ?>
1601
        <div id="db_status" class="alert alert-danger">
1602
            <p><?php echo get_lang('FailedConectionDatabase'); ?></strong></p>
1603
            <code><?php echo $database_exists_text; ?></code>
1604
        </div>
1605
    <?php endif; ?>
1606
   <div class="form-group">
1607
       <div class="col-sm-6">
1608
           <button type="submit" name="step2" class="btn btn-default pull-right" value="&lt; <?php echo get_lang('Previous'); ?>" >
1609
               <em class="fa fa-backward"> </em> <?php echo get_lang('Previous'); ?>
1610
           </button>
1611
       </div>
1612
      <div class="col-sm-6">
1613
       <input type="hidden" name="is_executable" id="is_executable" value="-" />
1614
       <?php if ($manager) {
0 ignored issues
show
introduced by
$manager is of type Doctrine\ORM\EntityManager, thus it always evaluated to true.
Loading history...
1615
        ?>
1616
           <button type="submit"  class="btn btn-success" name="step4" value="<?php echo get_lang('Next'); ?> &gt;" >
1617
               <em class="fa fa-forward"> </em> <?php echo get_lang('Next'); ?>
1618
           </button>
1619
       <?php
1620
    } else {
1621
        ?>
1622
           <button disabled="disabled" type="submit" class="btn btn-success disabled" name="step4" value="<?php echo get_lang('Next'); ?> &gt;" >
1623
               <em class="fa fa-forward"> </em> <?php echo get_lang('Next'); ?>
1624
           </button>
1625
       <?php
1626
    } ?>
1627
      </div>
1628
   </div>
1629
1630
    <?php
1631
}
1632
1633
function panel($content = null, $title = null, $id = null, $style = null)
1634
{
1635
    $html = '';
1636
    if (empty($style)) {
1637
        $style = 'default';
1638
    }
1639
    if (!empty($title)) {
1640
        $panelTitle = Display::div($title, ['class' => 'panel-heading']);
1641
        $panelBody = Display::div($content, ['class' => 'panel-body']);
1642
        $panelParent = Display::div($panelTitle.$panelBody, ['id' => $id, 'class' => 'panel panel-'.$style]);
1643
    } else {
1644
        $panelBody = Display::div($html, ['class' => 'panel-body']);
1645
        $panelParent = Display::div($panelBody, ['id' => $id, 'class' => 'panel panel-'.$style]);
1646
    }
1647
    $html .= $panelParent;
1648
1649
    return $html;
1650
}
1651
1652
/**
1653
 * Displays a parameter in a table row.
1654
 * Used by the display_configuration_settings_form function.
1655
 *
1656
 * @param string $installType
1657
 * @param string $parameterName
1658
 * @param string $formFieldName
1659
 * @param string $parameterValue
1660
 * @param string $displayWhenUpdate
1661
 *
1662
 * @return string
1663
 */
1664
function display_configuration_parameter(
1665
    $installType,
1666
    $parameterName,
1667
    $formFieldName,
1668
    $parameterValue,
1669
    $displayWhenUpdate = 'true'
1670
) {
1671
    $html = '<div class="form-group">';
1672
    $html .= '<label class="col-sm-6 control-label">'.$parameterName.'</label>';
1673
    if ($installType == INSTALL_TYPE_UPDATE && $displayWhenUpdate) {
1674
        $html .= '<input type="hidden" name="'.$formFieldName.'" value="'.api_htmlentities($parameterValue, ENT_QUOTES).'" />'.$parameterValue;
1675
    } else {
1676
        $hiddenPasswordClass = '';
1677
        $eyeForPassword = '';
1678
        $inputType = 'text';
1679
        if ($formFieldName == 'passForm') {
1680
            /* show/hide admin password in step 5*/
1681
            $hiddenPasswordClass = 'inputShowPwd';
1682
            $inputType = 'password';
1683
            $eyeForPassword =
1684
                '<input type="checkbox" id="showPassword" class="hidden">'.'<label for="showPassword">'.
1685
                Display::returnFontAwesomeIcon('eye', null, true, 'showPasswordEye').
1686
                '</label> ';
1687
        }
1688
        $html .= '<div class="col-sm-6 '.$hiddenPasswordClass.'"><input class="form-control" type="'.$inputType.'" size="'.FORM_FIELD_DISPLAY_LENGTH.'" maxlength="'.MAX_FORM_FIELD_LENGTH.'" name="'.$formFieldName.'" value="'.api_htmlentities($parameterValue,
1689
                ENT_QUOTES).'" />'.$eyeForPassword."</div>";
1690
    }
1691
    $html .= "</div>";
1692
1693
    return $html;
1694
}
1695
1696
/**
1697
 * Displays step 4 of the installation - configuration settings about Chamilo itself.
1698
 *
1699
 * @param string $installType
1700
 * @param string $urlForm
1701
 * @param string $languageForm
1702
 * @param string $emailForm
1703
 * @param string $adminFirstName
1704
 * @param string $adminLastName
1705
 * @param string $adminPhoneForm
1706
 * @param string $campusForm
1707
 * @param string $institutionForm
1708
 * @param string $institutionUrlForm
1709
 * @param string $encryptPassForm
1710
 * @param bool   $allowSelfReg
1711
 * @param bool   $allowSelfRegProf
1712
 * @param string $loginForm
1713
 * @param string $passForm
1714
 */
1715
function display_configuration_settings_form(
1716
    $installType,
1717
    $urlForm,
1718
    $languageForm,
1719
    $emailForm,
1720
    $adminFirstName,
1721
    $adminLastName,
1722
    $adminPhoneForm,
1723
    $campusForm,
1724
    $institutionForm,
1725
    $institutionUrlForm,
1726
    $encryptPassForm,
1727
    $allowSelfReg,
1728
    $allowSelfRegProf,
1729
    $loginForm,
1730
    $passForm
1731
) {
1732
    if ($installType != 'update' && empty($languageForm)) {
1733
        $languageForm = $_SESSION['install_language'];
1734
    }
1735
    echo '<div class="RequirementHeading">';
1736
    echo "<h2>".display_step_sequence().get_lang("CfgSetting")."</h2>";
1737
    echo '</div>';
1738
1739
    echo '<p>'.get_lang('ConfigSettingsInfo').' <strong>app/config/configuration.php</strong></p>';
1740
1741
    // Parameter 1: administrator's login
1742
    $html = '';
1743
    $html .= display_configuration_parameter(
1744
        $installType,
1745
        get_lang('AdminLogin'),
1746
        'loginForm',
1747
        $loginForm,
1748
        $installType == 'update'
1749
    );
1750
1751
    // Parameter 2: administrator's password
1752
    if ($installType != 'update') {
1753
        $html .= display_configuration_parameter($installType, get_lang('AdminPass'), 'passForm', $passForm, false);
1754
    }
1755
1756
    // Parameters 3 and 4: administrator's names
1757
1758
    $html .= display_configuration_parameter(
1759
        $installType,
1760
        get_lang('AdminFirstName'),
1761
        'adminFirstName',
1762
        $adminFirstName
1763
    );
1764
    $html .= display_configuration_parameter($installType, get_lang('AdminLastName'), 'adminLastName', $adminLastName);
1765
1766
    //Parameter 3: administrator's email
1767
    $html .= display_configuration_parameter($installType, get_lang('AdminEmail'), 'emailForm', $emailForm);
1768
1769
    //Parameter 6: administrator's telephone
1770
    $html .= display_configuration_parameter($installType, get_lang('AdminPhone'), 'adminPhoneForm', $adminPhoneForm);
1771
    echo panel($html, get_lang('Administrator'), 'administrator');
1772
1773
    //First parameter: language
1774
    $html = '<div class="form-group">';
1775
    $html .= '<label class="col-sm-6 control-label">'.get_lang('MainLang')."</label>";
1776
    if ($installType == 'update') {
1777
        $html .= '<input type="hidden" name="languageForm" value="'.api_htmlentities($languageForm, ENT_QUOTES).'" />'.$languageForm;
1778
    } else { // new installation
1779
        $html .= '<div class="col-sm-6">';
1780
        $html .= display_language_selection_box('languageForm', $languageForm);
1781
        $html .= '</div>';
1782
    }
1783
    $html .= "</div>";
1784
1785
    //Second parameter: Chamilo URL
1786
    $html .= '<div class="form-group">';
1787
    $html .= '<label class="col-sm-6 control-label"><span class="form_required">*</span>'.get_lang('ChamiloURL').'</label>';
1788
1789
    if ($installType == 'update') {
1790
        $html .= api_htmlentities($urlForm, ENT_QUOTES)."\n";
1791
    } else {
1792
        $html .= '<div class="col-sm-6">';
1793
        $html .= '<input class="form-control" type="text" size="40" maxlength="100" name="urlForm" value="'.api_htmlentities($urlForm, ENT_QUOTES).'" />';
1794
        $html .= '</div>';
1795
    }
1796
    $html .= '</div>';
1797
1798
    //Parameter 9: campus name
1799
    $html .= display_configuration_parameter(
1800
        $installType,
1801
        get_lang('CampusName'),
1802
        'campusForm',
1803
        $campusForm
1804
    );
1805
1806
    //Parameter 10: institute (short) name
1807
    $html .= display_configuration_parameter(
1808
        $installType,
1809
        get_lang('InstituteShortName'),
1810
        'institutionForm',
1811
        $institutionForm
1812
    );
1813
1814
    //Parameter 11: institute (short) name
1815
    $html .= display_configuration_parameter(
1816
        $installType,
1817
        get_lang('InstituteURL'),
1818
        'institutionUrlForm',
1819
        $institutionUrlForm
1820
    );
1821
1822
    $html .= '<div class="form-group">
1823
            <label class="col-sm-6 control-label">'.get_lang("EncryptMethodUserPass").'</label>
1824
        <div class="col-sm-6">';
1825
    if ($installType == 'update') {
1826
        $html .= '<input type="hidden" name="encryptPassForm" value="'.$encryptPassForm.'" />'.$encryptPassForm;
1827
    } else {
1828
        $html .= '<div class="checkbox">
1829
                    <label>
1830
                        <input  type="radio" name="encryptPassForm" value="bcrypt" id="encryptPass1" '.($encryptPassForm == 'bcrypt' ? 'checked="checked" ' : '').'/> bcrypt
1831
                    </label>';
1832
1833
        $html .= '<label>
1834
                        <input  type="radio" name="encryptPassForm" value="sha1" id="encryptPass1" '.($encryptPassForm == 'sha1' ? 'checked="checked" ' : '').'/> sha1
1835
                    </label>';
1836
1837
        $html .= '<label>
1838
                        <input type="radio" name="encryptPassForm" value="md5" id="encryptPass0" '.($encryptPassForm == 'md5' ? 'checked="checked" ' : '').'/> md5
1839
                    </label>';
1840
1841
        $html .= '<label>
1842
                        <input type="radio" name="encryptPassForm" value="none" id="encryptPass2" '.($encryptPassForm == 'none' ? 'checked="checked" ' : '').'/>'.get_lang('None').'
1843
                    </label>';
1844
        $html .= '</div>';
1845
    }
1846
    $html .= '</div></div>';
1847
1848
    $html .= '<div class="form-group">
1849
            <label class="col-sm-6 control-label">'.get_lang('AllowSelfReg').'</label>
1850
            <div class="col-sm-6">';
1851
    if ($installType == 'update') {
1852
        if ($allowSelfReg == 'true') {
1853
            $label = get_lang('Yes');
1854
        } elseif ($allowSelfReg == 'false') {
1855
            $label = get_lang('No');
1856
        } else {
1857
            $label = get_lang('AfterApproval');
1858
        }
1859
        $html .= '<input type="hidden" name="allowSelfReg" value="'.$allowSelfReg.'" />'.$label;
1860
    } else {
1861
        $html .= '<div class="control-group">';
1862
        $html .= '<label class="checkbox-inline">
1863
                        <input type="radio" name="allowSelfReg" value="true" id="allowSelfReg1" '.($allowSelfReg == 'true' ? 'checked="checked" ' : '').' /> '.get_lang('Yes').'
1864
                    </label>';
1865
        $html .= '<label class="checkbox-inline">
1866
                        <input type="radio" name="allowSelfReg" value="false" id="allowSelfReg0" '.($allowSelfReg == 'false' ? '' : 'checked="checked" ').' /> '.get_lang('No').'
1867
                    </label>';
1868
        $html .= '<label class="checkbox-inline">
1869
                    <input type="radio" name="allowSelfReg" value="approval" id="allowSelfReg2" '.($allowSelfReg == 'approval' ? '' : 'checked="checked" ').' /> '.get_lang('AfterApproval').'
1870
                </label>';
1871
        $html .= '</div>';
1872
    }
1873
    $html .= '</div>';
1874
    $html .= '</div>';
1875
1876
    $html .= '<div class="form-group">';
1877
    $html .= '<label class="col-sm-6 control-label">'.get_lang('AllowSelfRegProf').'</label>
1878
        <div class="col-sm-6">';
1879
    if ($installType == 'update') {
1880
        if ($allowSelfRegProf == 'true') {
1881
            $label = get_lang('Yes');
1882
        } else {
1883
            $label = get_lang('No');
1884
        }
1885
        $html .= '<input type="hidden" name="allowSelfRegProf" value="'.$allowSelfRegProf.'" />'.$label;
1886
    } else {
1887
        $html .= '<div class="control-group">
1888
                <label class="checkbox-inline">
1889
                    <input type="radio" name="allowSelfRegProf" value="1" id="allowSelfRegProf1" '.($allowSelfRegProf ? 'checked="checked" ' : '').'/>
1890
                '.get_lang('Yes').'
1891
                </label>';
1892
        $html .= '<label class="checkbox-inline">
1893
                    <input type="radio" name="allowSelfRegProf" value="0" id="allowSelfRegProf0" '.($allowSelfRegProf ? '' : 'checked="checked" ').' />
1894
                   '.get_lang('No').'
1895
                </label>';
1896
        $html .= '</div>';
1897
    }
1898
    $html .= '</div>
1899
    </div>';
1900
1901
    echo panel($html, get_lang('Platform'), 'platform'); ?>
1902
    <div class='form-group'>
1903
        <div class="col-sm-6">
1904
            <button type="submit" class="btn btn-default pull-right" name="step3" value="&lt; <?php echo get_lang('Previous'); ?>" ><em class="fa fa-backward"> </em> <?php echo get_lang('Previous'); ?></button>
1905
            <input type="hidden" name="is_executable" id="is_executable" value="-" />
1906
        </div>
1907
        <div class="col-sm-6">
1908
            <button class="btn btn-success" type="submit" name="step5" value="<?php echo get_lang('Next'); ?> &gt;" ><em class="fa fa-forward"> </em> <?php echo get_lang('Next'); ?></button>
1909
        </div>
1910
    </div>
1911
1912
    <?php
1913
}
1914
1915
/**
1916
 * After installation is completed (step 6), this message is displayed.
1917
 *
1918
 * @param string $installType
1919
 */
1920
function display_after_install_message($installType)
1921
{
1922
    echo '<div class="RequirementContent">'.get_lang('FirstUseTip').'</div>';
1923
    echo '<div class="alert alert-warning">';
1924
    echo '<strong>'.get_lang('SecurityAdvice').'</strong>';
1925
    echo ': ';
1926
    printf(get_lang('ToProtectYourSiteMakeXReadOnlyAndDeleteY'), 'app/config/', 'main/install/');
1927
    echo '</div>'; ?></form>
1928
    <br />
1929
    <a class="btn btn-success btn-block" href="../../index.php">
1930
        <?php echo get_lang('GoToYourNewlyCreatedPortal'); ?>
1931
    </a>
1932
    <?php
1933
}
1934
1935
/**
1936
 * This function return countries list from array (hardcoded).
1937
 *
1938
 * @param bool $combo (Optional) True for returning countries list with select html
1939
 *
1940
 * @return array|string countries list
1941
 */
1942
function get_countries_list_from_array($combo = false)
1943
{
1944
    $a_countries = [
1945
        "Afghanistan", "Albania", "Algeria", "Andorra", "Angola", "Antigua and Barbuda", "Argentina", "Armenia", "Australia", "Austria", "Azerbaijan",
1946
        "Bahamas", "Bahrain", "Bangladesh", "Barbados", "Belarus", "Belgium", "Belize", "Benin", "Bhutan", "Bolivia", "Bosnia and Herzegovina", "Botswana", "Brazil", "Brunei", "Bulgaria", "Burkina Faso", "Burundi",
1947
        "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",
1948
        "Denmark", "Djibouti", "Dominica", "Dominican Republic",
1949
        "East Timor (Timor Timur)", "Ecuador", "Egypt", "El Salvador", "Equatorial Guinea", "Eritrea", "Estonia", "Ethiopia",
1950
        "Fiji", "Finland", "France",
1951
        "Gabon", "Gambia, The", "Georgia", "Germany", "Ghana", "Greece", "Grenada", "Guatemala", "Guinea", "Guinea-Bissau", "Guyana",
1952
        "Haiti", "Honduras", "Hungary",
1953
        "Iceland", "India", "Indonesia", "Iran", "Iraq", "Ireland", "Israel", "Italy",
1954
        "Jamaica", "Japan", "Jordan",
1955
        "Kazakhstan", "Kenya", "Kiribati", "Korea, North", "Korea, South", "Kuwait", "Kyrgyzstan",
1956
        "Laos", "Latvia", "Lebanon", "Lesotho", "Liberia", "Libya", "Liechtenstein", "Lithuania", "Luxembourg",
1957
        "Macedonia", "Madagascar", "Malawi", "Malaysia", "Maldives", "Mali", "Malta", "Marshall Islands", "Mauritania", "Mauritius", "Mexico", "Micronesia", "Moldova", "Monaco", "Mongolia", "Morocco", "Mozambique", "Myanmar",
1958
        "Namibia", "Nauru", "Nepa", "Netherlands", "New Zealand", "Nicaragua", "Niger", "Nigeria", "Norway",
1959
        "Oman",
1960
        "Pakistan", "Palau", "Panama", "Papua New Guinea", "Paraguay", "Peru", "Philippines", "Poland", "Portugal",
1961
        "Qatar",
1962
        "Romania", "Russia", "Rwanda",
1963
        "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",
1964
        "Taiwan", "Tajikistan", "Tanzania", "Thailand", "Togo", "Tonga", "Trinidad and Tobago", "Tunisia", "Turkey", "Turkmenistan", "Tuvalu",
1965
        "Uganda", "Ukraine", "United Arab Emirates", "United Kingdom", "United States", "Uruguay", "Uzbekistan",
1966
        "Vanuatu", "Vatican City", "Venezuela", "Vietnam",
1967
        "Yemen",
1968
        "Zambia", "Zimbabwe",
1969
    ];
1970
    if ($combo) {
1971
        $country_select = '<select class="selectpicker show-tick" id="country" name="country">';
1972
        $country_select .= '<option value="">--- '.get_lang('SelectOne').' ---</option>';
1973
        foreach ($a_countries as $country) {
1974
            $country_select .= '<option value="'.$country.'">'.$country.'</option>';
1975
        }
1976
        $country_select .= '</select>';
1977
1978
        return $country_select;
1979
    }
1980
1981
    return $a_countries;
1982
}
1983
1984
/**
1985
 * Lock settings that can't be changed in other portals.
1986
 */
1987
function lockSettings()
1988
{
1989
    $access_url_locked_settings = api_get_locked_settings();
1990
    $table = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
1991
    foreach ($access_url_locked_settings as $setting) {
1992
        Database::update(
1993
            $table,
1994
            ['access_url_locked' => 1],
1995
            ['variable = ?' => $setting]
1996
        );
1997
    }
1998
}
1999
2000
/**
2001
 * Update dir values.
2002
 */
2003
function updateDirAndFilesPermissions()
2004
{
2005
    $table = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
2006
    $permissions_for_new_directories = isset($_SESSION['permissions_for_new_directories']) ? $_SESSION['permissions_for_new_directories'] : 0770;
2007
    $permissions_for_new_files = isset($_SESSION['permissions_for_new_files']) ? $_SESSION['permissions_for_new_files'] : 0660;
2008
    // use decoct() to store as string
2009
    Database::update(
2010
        $table,
2011
        ['selected_value' => '0'.decoct($permissions_for_new_directories)],
2012
        ['variable = ?' => 'permissions_for_new_directories']
2013
    );
2014
2015
    Database::update(
2016
        $table,
2017
        ['selected_value' => '0'.decoct($permissions_for_new_files)],
2018
        ['variable = ?' => 'permissions_for_new_files']
2019
    );
2020
2021
    if (isset($_SESSION['permissions_for_new_directories'])) {
2022
        unset($_SESSION['permissions_for_new_directories']);
2023
    }
2024
2025
    if (isset($_SESSION['permissions_for_new_files'])) {
2026
        unset($_SESSION['permissions_for_new_files']);
2027
    }
2028
}
2029
2030
/**
2031
 * @param $current_value
2032
 * @param $wanted_value
2033
 *
2034
 * @return string
2035
 */
2036
function compare_setting_values($current_value, $wanted_value)
2037
{
2038
    $current_value_string = $current_value;
2039
    $current_value = (float) $current_value;
2040
    $wanted_value = (float) $wanted_value;
2041
2042
    if ($current_value >= $wanted_value) {
2043
        return Display::label($current_value_string, 'success');
2044
    } else {
2045
        return Display::label($current_value_string, 'important');
2046
    }
2047
}
2048
2049
/**
2050
 * @param string $course_dir
2051
 * @param string $course_attempt_name
2052
 * @param string $file
2053
 *
2054
 * @return bool
2055
 */
2056
function checkCourseScriptCreation(
2057
    $course_dir,
2058
    $course_attempt_name,
2059
    $file
2060
) {
2061
    $output = false;
2062
    // Write in file
2063
    $file_name = $course_dir.'/'.$file;
2064
    $content = '123';
2065
2066
    if (is_writable($file_name)) {
2067
        if ($handler = @fopen($file_name, 'w')) {
2068
            //write content
2069
            if (fwrite($handler, $content)) {
2070
                $sock_errno = '';
2071
                $sock_errmsg = '';
2072
                $url = api_get_path(WEB_PATH).'app/courses/'.$course_attempt_name.'/'.$file;
2073
2074
                $parsed_url = parse_url($url);
2075
                //$scheme = isset($parsedUrl['scheme']) ? $parsedUrl['scheme'] : ''; //http
2076
                $host = isset($parsed_url['host']) ? $parsed_url['host'] : '';
2077
                // Patch if the host is the default host and is used through
2078
                // the IP address (sometimes the host is not taken correctly
2079
                // in this case)
2080
                if (empty($host) && !empty($_SERVER['HTTP_HOST'])) {
2081
                    $host = $_SERVER['HTTP_HOST'];
2082
                    $url = preg_replace('#:///#', '://'.$host.'/', $url);
2083
                }
2084
                $path = isset($parsed_url['path']) ? $parsed_url['path'] : '/';
2085
                $port = '';
2086
                $scheme = '';
2087
                switch ($parsed_url['scheme']) {
2088
                    case 'https':
2089
                        $scheme = 'ssl://';
2090
                        $port = 443;
2091
                        break;
2092
                    case 'http':
2093
                    default:
2094
                        $scheme = '';
2095
                        $port = 80;
2096
                }
2097
2098
                //Check fsockopen (not sure it works with https). If that is your case, you might want to try the
2099
                // suggestion at https://support.chamilo.org/issues/8260#note-3 (although it ignores SSL peer checks)
2100
                if ($fp = @fsockopen(str_replace('http://', $scheme, $url), $port, $sock_errno, $sock_errmsg, 60)) {
2101
                    $out = "GET $path HTTP/1.1\r\n";
2102
                    $out .= "Host: $host\r\n";
2103
                    $out .= "Connection: Close\r\n\r\n";
2104
2105
                    fwrite($fp, $out);
2106
                    while (!feof($fp)) {
2107
                        $result = str_replace("\r\n", '', fgets($fp, 128));
2108
                        if (!empty($result) && $result == '123') {
2109
                            $output = true;
2110
                        }
2111
                    }
2112
                    fclose($fp);
2113
                } elseif (ini_get('allow_url_fopen')) {
2114
                    // Check allow_url_fopen
2115
                    if ($fp = @fopen($url, 'r')) {
2116
                        while ($result = fgets($fp, 1024)) {
2117
                            if (!empty($result) && $result == '123') {
2118
                                $output = true;
2119
                            }
2120
                        }
2121
                        fclose($fp);
2122
                    }
2123
                } elseif (function_exists('curl_init')) {
2124
                    // Check if has support for cURL
2125
                    $ch = curl_init();
2126
                    curl_setopt($ch, CURLOPT_HEADER, 0);
2127
                    curl_setopt($ch, CURLOPT_URL, $url);
2128
                    //curl_setopt($ch, CURLOPT_TIMEOUT, 30);
2129
                    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
2130
                    $result = curl_exec($ch);
2131
                    if (!empty($result) && $result == '123') {
2132
                        $output = true;
2133
                    }
2134
                    curl_close($ch);
2135
                }
2136
            }
2137
            @fclose($handler);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for fclose(). 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

2137
            /** @scrutinizer ignore-unhandled */ @fclose($handler);

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...
2138
        }
2139
    }
2140
2141
    return $output;
2142
}
2143
2144
/**
2145
 * Save settings values.
2146
 *
2147
 * @param string $organizationName
2148
 * @param string $organizationUrl
2149
 * @param string $siteName
2150
 * @param string $adminEmail
2151
 * @param string $adminLastName
2152
 * @param string $adminFirstName
2153
 * @param string $language
2154
 * @param string $allowRegistration
2155
 * @param string $allowTeacherSelfRegistration
2156
 * @param string $installationProfile          The name of an installation profile file in main/install/profiles/
2157
 */
2158
function installSettings(
2159
    $organizationName,
2160
    $organizationUrl,
2161
    $siteName,
2162
    $adminEmail,
2163
    $adminLastName,
2164
    $adminFirstName,
2165
    $language,
2166
    $allowRegistration,
2167
    $allowTeacherSelfRegistration,
2168
    $installationProfile = ''
2169
) {
2170
    $allowTeacherSelfRegistration = $allowTeacherSelfRegistration ? 'true' : 'false';
2171
2172
    // Use PHP 5.3 to avoid issue with weird peripherical auto-installers like travis-ci
2173
    $settings = [
2174
        'Institution' => $organizationName,
2175
        'InstitutionUrl' => $organizationUrl,
2176
        'siteName' => $siteName,
2177
        'emailAdministrator' => $adminEmail,
2178
        'administratorSurname' => $adminLastName,
2179
        'administratorName' => $adminFirstName,
2180
        'platformLanguage' => $language,
2181
        'allow_registration' => $allowRegistration,
2182
        'allow_registration_as_teacher' => $allowTeacherSelfRegistration,
2183
    ];
2184
2185
    $tblSettings = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
2186
2187
    foreach ($settings as $variable => $value) {
2188
        Database::update(
2189
            $tblSettings,
2190
            ['selected_value' => $value],
2191
            ['variable = ?' => $variable]
2192
        );
2193
    }
2194
    installProfileSettings($installationProfile);
2195
}
2196
2197
/**
2198
 * Executes DB changes based in the classes defined in
2199
 * src/Chamilo/CoreBundle/Migrations/Schema/*.
2200
 *
2201
 * @param string $chamiloVersion
2202
 *
2203
 * @throws \Doctrine\DBAL\DBALException
2204
 *
2205
 * @return bool
2206
 */
2207
function migrate($chamiloVersion, EntityManager $manager)
2208
{
2209
    $debug = true;
2210
    $connection = $manager->getConnection();
2211
2212
    $config = new \Doctrine\DBAL\Migrations\Configuration\Configuration($connection);
2213
2214
    // Table name that will store migrations log (will be created automatically,
2215
    // default name is: doctrine_migration_versions)
2216
    $config->setMigrationsTableName('version');
2217
    // Namespace of your migration classes, do not forget escape slashes, do not add last slash
2218
    $config->setMigrationsNamespace('Application\Migrations\Schema\V'.$chamiloVersion);
2219
    // Directory where your migrations are located
2220
    $config->setMigrationsDirectory(api_get_path(SYS_PATH).'app/Migrations/Schema/V'.$chamiloVersion);
2221
    // Load your migrations
2222
    $config->registerMigrationsFromDirectory($config->getMigrationsDirectory());
2223
2224
    $migration = new \Doctrine\DBAL\Migrations\Migration($config);
2225
    $versions = $config->getMigrations();
2226
2227
    /** @var Doctrine\DBAL\Migrations\Version $migrationItem */
2228
    foreach ($versions as $version) {
2229
        $version->getMigration()->setEntityManager($manager);
2230
    }
2231
2232
    $to = null; // if $to == null then schema will be migrated to latest version
2233
2234
    echo "<pre>";
2235
    try {
2236
        // Execute migration!
2237
        $migratedSQL = $migration->migrate($to);
2238
2239
        if ($debug) {
2240
            foreach ($migratedSQL as $version => $sqlList) {
2241
                echo "VERSION: $version<br>";
2242
                echo "----------------------------------------------<br>";
2243
                $total = count($sqlList);
2244
                error_log("VERSION: $version");
2245
                error_log("# queries: ".$total);
2246
                $counter = 1;
2247
                foreach ($sqlList as $sql) {
2248
                    echo "<code>$sql</code><br>";
2249
                    error_log("$counter/$total : $sql");
2250
                    $counter++;
2251
                }
2252
            }
2253
2254
            echo "<br>DONE!<br>";
2255
        }
2256
2257
        return true;
2258
    } catch (Exception $ex) {
2259
        if ($debug) {
2260
            echo "ERROR: {$ex->getMessage()}<br>";
2261
2262
            return false;
2263
        }
2264
    }
2265
2266
    echo "</pre>";
2267
2268
    return false;
2269
}
2270
2271
/**
2272
 * @throws \Doctrine\DBAL\DBALException
2273
 */
2274
function fixIds(EntityManager $em)
2275
{
2276
    $connection = $em->getConnection();
2277
    $database = new Database();
2278
    $database->setManager($em);
2279
    $debug = true;
2280
    if ($debug) {
2281
        error_log('fixIds');
2282
    }
2283
2284
    // Create temporary indexes to increase speed of the following operations
2285
    // Adding and removing indexes will usually take much less time than
2286
    // the execution without indexes of the queries in this function, particularly
2287
    // for large tables
2288
    $sql = "ALTER TABLE c_document ADD INDEX tmpidx_doc(c_id, id)";
2289
    $connection->executeQuery($sql);
2290
    $sql = "ALTER TABLE c_student_publication ADD INDEX tmpidx_stud (c_id, id)";
2291
    $connection->executeQuery($sql);
2292
    $sql = "ALTER TABLE c_quiz ADD INDEX tmpidx_quiz (c_id, id)";
2293
    $connection->executeQuery($sql);
2294
    $sql = "ALTER TABLE c_item_property ADD INDEX tmpidx_ip (to_group_id)";
2295
    $connection->executeQuery($sql);
2296
2297
    $sql = "SELECT * FROM c_lp_item";
2298
    $result = $connection->fetchAll($sql);
2299
    foreach ($result as $item) {
2300
        $courseId = $item['c_id'];
2301
        $iid = isset($item['iid']) ? (int) $item['iid'] : 0;
2302
        $ref = isset($item['ref']) ? (int) $item['ref'] : 0;
2303
        $sql = null;
2304
2305
        $newId = '';
2306
        switch ($item['item_type']) {
2307
            case TOOL_LINK:
2308
                $sql = "SELECT * FROM c_link WHERE c_id = $courseId AND id = $ref";
2309
                $data = $connection->fetchAssoc($sql);
2310
                if ($data) {
2311
                    $newId = $data['iid'];
2312
                }
2313
                break;
2314
            case TOOL_STUDENTPUBLICATION:
2315
                $sql = "SELECT * FROM c_student_publication WHERE c_id = $courseId AND id = $ref";
2316
                $data = $connection->fetchAssoc($sql);
2317
                if ($data) {
2318
                    $newId = $data['iid'];
2319
                }
2320
                break;
2321
            case TOOL_QUIZ:
2322
                $sql = "SELECT * FROM c_quiz WHERE c_id = $courseId AND id = $ref";
2323
                $data = $connection->fetchAssoc($sql);
2324
                if ($data) {
2325
                    $newId = $data['iid'];
2326
                }
2327
                break;
2328
            case TOOL_DOCUMENT:
2329
                $sql = "SELECT * FROM c_document WHERE c_id = $courseId AND id = $ref";
2330
                $data = $connection->fetchAssoc($sql);
2331
                if ($data) {
2332
                    $newId = $data['iid'];
2333
                }
2334
                break;
2335
            case TOOL_FORUM:
2336
                $sql = "SELECT * FROM c_forum_forum WHERE c_id = $courseId AND forum_id = $ref";
2337
                $data = $connection->fetchAssoc($sql);
2338
                if ($data) {
2339
                    $newId = $data['iid'];
2340
                }
2341
                break;
2342
            case 'thread':
2343
                $sql = "SELECT * FROM c_forum_thread WHERE c_id = $courseId AND thread_id = $ref";
2344
                $data = $connection->fetchAssoc($sql);
2345
                if ($data) {
2346
                    $newId = $data['iid'];
2347
                }
2348
                break;
2349
        }
2350
2351
        if (!empty($sql) && !empty($newId) && !empty($iid)) {
2352
            $sql = "UPDATE c_lp_item SET ref = $newId WHERE iid = $iid";
2353
            $connection->executeQuery($sql);
2354
        }
2355
    }
2356
2357
    // Set NULL if session = 0
2358
    $sql = "UPDATE c_item_property SET session_id = NULL WHERE session_id = 0";
2359
    $connection->executeQuery($sql);
2360
2361
    // Set NULL if group = 0
2362
    $sql = "UPDATE c_item_property SET to_group_id = NULL WHERE to_group_id = 0";
2363
    $connection->executeQuery($sql);
2364
2365
    // Set NULL if insert_user_id = 0
2366
    $sql = "UPDATE c_item_property SET insert_user_id = NULL WHERE insert_user_id = 0";
2367
    $connection->executeQuery($sql);
2368
2369
    // Delete session data of sessions that don't exist.
2370
    $sql = "DELETE FROM c_item_property
2371
            WHERE session_id IS NOT NULL AND session_id NOT IN (SELECT id FROM session)";
2372
    $connection->executeQuery($sql);
2373
2374
    // Delete group data of groups that don't exist.
2375
    $sql = "DELETE FROM c_item_property
2376
            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)";
2377
    $connection->executeQuery($sql);
2378
2379
    // This updates the group_id with c_group_info.iid instead of c_group_info.id
2380
    if ($debug) {
2381
        error_log('update iids');
2382
    }
2383
2384
    $groupTableToFix = [
2385
        'c_group_rel_user',
2386
        'c_group_rel_tutor',
2387
        'c_permission_group',
2388
        'c_role_group',
2389
        'c_survey_invitation',
2390
        'c_attendance_calendar_rel_group',
2391
    ];
2392
2393
    foreach ($groupTableToFix as $table) {
2394
        $sql = "SELECT * FROM $table";
2395
        $result = $connection->fetchAll($sql);
2396
        foreach ($result as $item) {
2397
            $iid = $item['iid'];
2398
            $courseId = $item['c_id'];
2399
            $groupId = intval($item['group_id']);
2400
2401
            // Fix group id
2402
            if (!empty($groupId)) {
2403
                $sql = "SELECT * FROM c_group_info
2404
                        WHERE c_id = $courseId AND id = $groupId
2405
                        LIMIT 1";
2406
                $data = $connection->fetchAssoc($sql);
2407
                if (!empty($data)) {
2408
                    $newGroupId = $data['iid'];
2409
                    $sql = "UPDATE $table SET group_id = $newGroupId
2410
                            WHERE iid = $iid";
2411
                    $connection->executeQuery($sql);
2412
                } else {
2413
                    // The group does not exists clean this record
2414
                    $sql = "DELETE FROM $table WHERE iid = $iid";
2415
                    $connection->executeQuery($sql);
2416
                }
2417
            }
2418
        }
2419
    }
2420
2421
    // Fix c_item_property
2422
    if ($debug) {
2423
        error_log('update c_item_property');
2424
    }
2425
2426
    $sql = "SELECT * FROM course";
2427
    $courseList = $connection->fetchAll($sql);
2428
    if ($debug) {
2429
        error_log('Getting course list');
2430
    }
2431
2432
    $totalCourse = count($courseList);
2433
    $counter = 0;
2434
2435
    foreach ($courseList as $courseData) {
2436
        $courseId = $courseData['id'];
2437
        if ($debug) {
2438
            error_log('Updating course: '.$courseData['code']);
2439
        }
2440
2441
        $sql = "SELECT * FROM c_item_property WHERE c_id = $courseId";
2442
        $result = $connection->fetchAll($sql);
2443
        foreach ($result as $item) {
2444
            $sessionId = intval($item['session_id']);
2445
            $groupId = intval($item['to_group_id']);
2446
            $iid = $item['iid'];
2447
            $ref = $item['ref'];
2448
2449
            // Fix group id
2450
            // Commented group id is already fixed in Version20150603181728.php
2451
            /*if (!empty($groupId)) {
2452
                $sql = "SELECT * FROM c_group_info
2453
                        WHERE c_id = $courseId AND id = $groupId";
2454
                $data = $connection->fetchAssoc($sql);
2455
                if (!empty($data)) {
2456
                    $newGroupId = $data['iid'];
2457
                    $sql = "UPDATE c_item_property SET to_group_id = $newGroupId
2458
                            WHERE iid = $iid";
2459
                    $connection->executeQuery($sql);
2460
                } else {
2461
                    // The group does not exists clean this record
2462
                    $sql = "DELETE FROM c_item_property WHERE iid = $iid";
2463
                    $connection->executeQuery($sql);
2464
                }
2465
            }*/
2466
2467
            $sql = '';
2468
            //$newId = '';
2469
            switch ($item['tool']) {
2470
                case TOOL_LEARNPATH:
2471
                    $sql = "SELECT * FROM c_lp WHERE c_id = $courseId AND id = $ref ";
2472
                    break;
2473
                // already fixed in c_lp_item
2474
                /*case TOOL_LINK:
2475
                    $sql = "SELECT * FROM c_link WHERE c_id = $courseId AND id = $ref ";
2476
                    break;
2477
                case TOOL_STUDENTPUBLICATION:
2478
                    $sql = "SELECT * FROM c_student_publication WHERE c_id = $courseId AND id = $ref";
2479
                    break;
2480
                case TOOL_QUIZ:
2481
                    $sql = "SELECT * FROM c_quiz WHERE c_id = $courseId AND id = $ref";
2482
                    break;
2483
                case TOOL_DOCUMENT:
2484
                    $sql = "SELECT * FROM c_document WHERE c_id = $courseId AND id = $ref";
2485
                    break;
2486
                case TOOL_FORUM:
2487
                    $sql = "SELECT * FROM c_forum_forum WHERE c_id = $courseId AND id = $ref";
2488
                    break;
2489
                case 'thread':
2490
                    $sql = "SELECT * FROM c_forum_thread WHERE c_id = $courseId AND id = $ref";
2491
                    break;*/
2492
            }
2493
2494
            if (!empty($sql)) {
2495
                $data = $connection->fetchAssoc($sql);
2496
                if (isset($data['iid']) && !empty($data['iid'])) {
2497
                    $newId = $data['iid'];
2498
                    $sql = "UPDATE c_item_property SET ref = $newId WHERE iid = $iid";
2499
                    $connection->executeQuery($sql);
2500
                }
2501
            }
2502
        }
2503
2504
        if ($debug) {
2505
            // Print a status in the log once in a while
2506
            error_log("Course process #$counter/$totalCourse");
2507
        }
2508
        $counter++;
2509
    }
2510
2511
    if ($debug) {
2512
        error_log('update gradebook_link');
2513
    }
2514
2515
    // Fix gradebook_link
2516
    $sql = "SELECT * FROM gradebook_link";
2517
    $result = $connection->fetchAll($sql);
2518
    foreach ($result as $item) {
2519
        $courseCode = $item['course_code'];
2520
        $categoryId = (int) $item['category_id'];
2521
2522
        $sql = "SELECT * FROM course WHERE code = '$courseCode'";
2523
        $courseInfo = $connection->fetchAssoc($sql);
2524
        if (empty($courseInfo)) {
2525
            continue;
2526
        }
2527
2528
        $courseId = $courseInfo['id'];
2529
2530
        $ref = $item['ref_id'];
2531
        $iid = $item['id'];
2532
2533
        $sql = '';
2534
        switch ($item['type']) {
2535
            case LINK_LEARNPATH:
2536
                $sql = "SELECT * FROM c_link WHERE c_id = $courseId AND id = $ref ";
2537
                break;
2538
            case LINK_STUDENTPUBLICATION:
2539
                $sql = "SELECT * FROM c_student_publication WHERE c_id = $courseId AND id = $ref";
2540
                break;
2541
            case LINK_EXERCISE:
2542
                $sql = "SELECT * FROM c_quiz WHERE c_id = $courseId AND id = $ref";
2543
                break;
2544
            case LINK_ATTENDANCE:
2545
                //$sql = "SELECT * FROM c_document WHERE c_id = $courseId AND id = $ref";
2546
                break;
2547
            case LINK_FORUM_THREAD:
2548
                $sql = "SELECT * FROM c_forum_thread WHERE c_id = $courseId AND thread_id = $ref";
2549
                break;
2550
        }
2551
2552
        if (!empty($sql)) {
2553
            $data = $connection->fetchAssoc($sql);
2554
            if (isset($data) && isset($data['iid'])) {
2555
                $newId = $data['iid'];
2556
                $sql = "UPDATE gradebook_link SET ref_id = $newId
2557
                        WHERE id = $iid AND course_code = '$courseCode' AND category_id = $categoryId ";
2558
                $connection->executeQuery($sql);
2559
            }
2560
        }
2561
    }
2562
2563
    if ($debug) {
2564
        error_log('update groups');
2565
    }
2566
2567
    $sql = "SELECT * FROM groups";
2568
    $result = $connection->executeQuery($sql);
2569
    $groups = $result->fetchAll();
2570
    $oldGroups = [];
2571
    if (!empty($groups)) {
2572
        foreach ($groups as $group) {
2573
            if (empty($group['name'])) {
2574
                continue;
2575
            }
2576
2577
            $params = [
2578
                'name' => $group['name'],
2579
                'description' => $group['description'],
2580
                'group_type' => 1,
2581
                'picture' => $group['picture_uri'],
2582
                'url' => $group['url'],
2583
                'visibility' => $group['visibility'],
2584
                'updated_at' => $group['updated_on'],
2585
                'created_at' => $group['created_on'],
2586
            ];
2587
            $connection->insert('usergroup', $params);
2588
            $id = $connection->lastInsertId('id');
2589
            $oldGroups[$group['id']] = $id;
2590
        }
2591
    }
2592
2593
    if (!empty($oldGroups)) {
2594
        error_log('Moving group files');
2595
        foreach ($oldGroups as $oldId => $newId) {
2596
            $path = get_group_picture_path_by_id(
2597
                $oldId,
2598
                'system'
2599
            );
2600
2601
            if (!empty($path)) {
2602
                $newPath = str_replace(
2603
                    "groups/$oldId/",
2604
                    "groups/$newId/",
2605
                    $path['dir']
2606
                );
2607
                $command = "mv {$path['dir']} $newPath ";
2608
                error_log("Executing $command");
2609
                system($command);
2610
            }
2611
        }
2612
2613
        $sql = "SELECT * FROM group_rel_user";
2614
        $result = $connection->executeQuery($sql);
2615
        $dataList = $result->fetchAll();
2616
2617
        if (!empty($dataList)) {
2618
            foreach ($dataList as $data) {
2619
                if (isset($oldGroups[$data['group_id']])) {
2620
                    $data['group_id'] = $oldGroups[$data['group_id']];
2621
                    $userId = $data['user_id'];
2622
2623
                    $sql = "SELECT id FROM user WHERE user_id = $userId";
2624
                    $userResult = $connection->executeQuery($sql);
2625
                    $userInfo = $userResult->fetch();
2626
                    if (empty($userInfo)) {
2627
                        continue;
2628
                    }
2629
2630
                    $sql = "INSERT INTO usergroup_rel_user (usergroup_id, user_id, relation_type)
2631
                            VALUES ('{$data['group_id']}', '{$userId}', '{$data['relation_type']}')";
2632
                    $connection->executeQuery($sql);
2633
                }
2634
            }
2635
        }
2636
2637
        $sql = "SELECT * FROM group_rel_group";
2638
        $result = $connection->executeQuery($sql);
2639
        $dataList = $result->fetchAll();
2640
2641
        if (!empty($dataList)) {
2642
            foreach ($dataList as $data) {
2643
                if (isset($oldGroups[$data['group_id']]) && isset($oldGroups[$data['subgroup_id']])) {
2644
                    $data['group_id'] = $oldGroups[$data['group_id']];
2645
                    $data['subgroup_id'] = $oldGroups[$data['subgroup_id']];
2646
                    $sql = "INSERT INTO usergroup_rel_usergroup (group_id, subgroup_id, relation_type)
2647
                            VALUES ('{$data['group_id']}', '{$data['subgroup_id']}', '{$data['relation_type']}')";
2648
                    $connection->executeQuery($sql);
2649
                }
2650
            }
2651
        }
2652
2653
        $sql = "SELECT * FROM announcement_rel_group";
2654
        $result = $connection->executeQuery($sql);
2655
        $dataList = $result->fetchAll();
2656
2657
        if (!empty($dataList)) {
2658
            foreach ($dataList as $data) {
2659
                if (isset($oldGroups[$data['group_id']])) {
2660
                    // Deleting relation
2661
                    $sql = "DELETE FROM announcement_rel_group WHERE group_id = {$data['group_id']}";
2662
                    $connection->executeQuery($sql);
2663
2664
                    // Add new relation
2665
                    $data['group_id'] = $oldGroups[$data['group_id']];
2666
                    $sql = "INSERT INTO announcement_rel_group(group_id, announcement_id)
2667
                            VALUES ('{$data['group_id']}', '{$data['announcement_id']}')";
2668
                    $connection->executeQuery($sql);
2669
                }
2670
            }
2671
        }
2672
2673
        $sql = "SELECT * FROM group_rel_tag";
2674
        $result = $connection->executeQuery($sql);
2675
        $dataList = $result->fetchAll();
2676
        if (!empty($dataList)) {
2677
            foreach ($dataList as $data) {
2678
                if (isset($oldGroups[$data['group_id']])) {
2679
                    $data['group_id'] = $oldGroups[$data['group_id']];
2680
                    $sql = "INSERT INTO usergroup_rel_tag (tag_id, usergroup_id)
2681
                            VALUES ('{$data['tag_id']}', '{$data['group_id']}')";
2682
                    $connection->executeQuery($sql);
2683
                }
2684
            }
2685
        }
2686
    }
2687
2688
    if ($debug) {
2689
        error_log('update extra fields');
2690
    }
2691
2692
    // Extra fields
2693
    $extraFieldTables = [
2694
        ExtraField::USER_FIELD_TYPE => Database::get_main_table(TABLE_MAIN_USER_FIELD),
2695
        ExtraField::COURSE_FIELD_TYPE => Database::get_main_table(TABLE_MAIN_COURSE_FIELD),
2696
        //ExtraField::LP_FIELD_TYPE => Database::get_main_table(TABLE_MAIN_LP_FIELD),
2697
        ExtraField::SESSION_FIELD_TYPE => Database::get_main_table(TABLE_MAIN_SESSION_FIELD),
2698
        //ExtraField::CALENDAR_FIELD_TYPE => Database::get_main_table(TABLE_MAIN_CALENDAR_EVENT_FIELD),
2699
        //ExtraField::QUESTION_FIELD_TYPE => Database::get_main_table(TABLE_MAIN_CALENDAR_EVENT_FIELD),
2700
        //ExtraField::USER_FIELD_TYPE => //Database::get_main_table(TABLE_MAIN_SPECIFIC_FIELD),
2701
    ];
2702
2703
    foreach ($extraFieldTables as $type => $table) {
2704
        $sql = "SELECT * FROM $table ";
2705
        if ($debug) {
2706
            error_log($sql);
2707
        }
2708
        $result = $connection->query($sql);
2709
        $fields = $result->fetchAll();
2710
2711
        foreach ($fields as $field) {
2712
            if ($debug) {
2713
                error_log("Loading field: ".$field['field_variable']);
2714
            }
2715
            $originalId = $field['id'];
2716
2717
            $params = [
2718
                'extra_field_type' => $type,
2719
                'variable' => $field['field_variable'],
2720
                'field_type' => $field['field_type'],
2721
                'display_text' => $field['field_display_text'],
2722
                'default_value' => $field['field_default_value'],
2723
                'field_order' => $field['field_order'],
2724
                'visible' => $field['field_visible'],
2725
                'changeable' => $field['field_changeable'],
2726
                'filter' => $field['field_filter'],
2727
            ];
2728
2729
            $connection->insert('extra_field', $params);
2730
            $newExtraFieldId = $connection->lastInsertId();
2731
2732
            $values = [];
2733
            $handlerId = null;
2734
            switch ($type) {
2735
                case ExtraField::USER_FIELD_TYPE:
2736
                    $optionTable = Database::get_main_table(
2737
                        TABLE_MAIN_USER_FIELD_OPTIONS
2738
                    );
2739
                    $valueTable = Database::get_main_table(
2740
                        TABLE_MAIN_USER_FIELD_VALUES
2741
                    );
2742
                    $handlerId = 'user_id';
2743
                    break;
2744
                case ExtraField::COURSE_FIELD_TYPE:
2745
                    $optionTable = Database::get_main_table(
2746
                        TABLE_MAIN_COURSE_FIELD_OPTIONS
2747
                    );
2748
                    $valueTable = Database::get_main_table(
2749
                        TABLE_MAIN_COURSE_FIELD_VALUES
2750
                    );
2751
                    $handlerId = 'c_id';
2752
                    break;
2753
                case ExtraField::SESSION_FIELD_TYPE:
2754
                    $optionTable = Database::get_main_table(
2755
                        TABLE_MAIN_SESSION_FIELD_OPTIONS
2756
                    );
2757
                    $valueTable = Database::get_main_table(
2758
                        TABLE_MAIN_SESSION_FIELD_VALUES
2759
                    );
2760
                    $handlerId = 'session_id';
2761
                    break;
2762
            }
2763
2764
            if (!empty($optionTable)) {
2765
                $sql = "SELECT * FROM $optionTable WHERE field_id = $originalId ";
2766
                $result = $connection->query($sql);
2767
                $options = $result->fetchAll();
2768
2769
                foreach ($options as $option) {
2770
                    $params = [
2771
                        'display_text' => $option['option_display_text'],
2772
                        'field_id' => $newExtraFieldId,
2773
                        'option_order' => $option['option_order'],
2774
                        'option_value' => $option['option_value'],
2775
                    ];
2776
                    $connection->insert('extra_field_options', $params);
2777
                }
2778
2779
                $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...
2780
                $result = $connection->query($sql);
2781
                $values = $result->fetchAll();
2782
                if ($debug) {
2783
                    error_log("Fetch all values for field");
2784
                }
2785
            }
2786
2787
            if (!empty($values)) {
2788
                if ($debug) {
2789
                    error_log("Saving field value in new table");
2790
                }
2791
                $k = 0;
2792
                foreach ($values as $value) {
2793
                    if (isset($value[$handlerId])) {
2794
                        // Insert without the use of the entity as it reduces
2795
                        // speed to 2 records per second (much too slow)
2796
                        $params = [
2797
                            'field_id' => $newExtraFieldId,
2798
                            'value' => $value['field_value'],
2799
                            'item_id' => $value[$handlerId],
2800
                        ];
2801
                        $connection->insert('extra_field_values', $params);
2802
                        if ($debug && ($k % 10000 == 0)) {
2803
                            error_log("Saving field $k");
2804
                        }
2805
                        $k++;
2806
                    }
2807
                }
2808
            }
2809
        }
2810
    }
2811
2812
    if ($debug) {
0 ignored issues
show
introduced by
$debug is of type mixed, thus it always evaluated to true.
Loading history...
2813
        error_log('Remove index');
2814
    }
2815
2816
    // Drop temporary indexes added to increase speed of this function's queries
2817
    $sql = "ALTER TABLE c_document DROP INDEX tmpidx_doc";
2818
    $connection->executeQuery($sql);
2819
    $sql = "ALTER TABLE c_student_publication DROP INDEX tmpidx_stud";
2820
    $connection->executeQuery($sql);
2821
    $sql = "ALTER TABLE c_quiz DROP INDEX tmpidx_quiz";
2822
    $connection->executeQuery($sql);
2823
    $sql = "ALTER TABLE c_item_property DROP INDEX tmpidx_ip";
2824
    $connection->executeQuery($sql);
2825
2826
    if ($debug) {
2827
        error_log('Finish fixId function');
2828
    }
2829
2830
    fixLpId($connection, true);
2831
}
2832
2833
/**
2834
 * @param \Doctrine\DBAL\Connection $connection
2835
 * @param $debug
2836
 *
2837
 * @throws \Doctrine\DBAL\DBALException
2838
 */
2839
function fixLpId($connection, $debug)
2840
{
2841
    if ($debug) {
2842
        error_log('Fix lp.id lp.iids');
2843
    }
2844
2845
    $sql = 'SELECT id, title, code FROM course';
2846
    $result = $connection->query($sql);
2847
    $courses = $result->fetchAll();
2848
2849
    $sql = 'SELECT id FROM session';
2850
    $result = $connection->query($sql);
2851
    $sessions = $result->fetchAll();
2852
2853
    $tblCLp = Database::get_course_table(TABLE_LP_MAIN);
2854
    $tblCLpItem = Database::get_course_table(TABLE_LP_ITEM);
2855
    $toolTable = Database::get_course_table(TABLE_TOOL_LIST);
2856
2857
    if (!empty($sessions)) {
2858
        $sessions = array_column($sessions, 'id');
2859
        $sessions[] = 0;
2860
    } else {
2861
        $sessions = [0];
2862
    }
2863
2864
    foreach ($courses as $course) {
2865
        $courseId = $course['id'];
2866
        $sql = "SELECT * FROM $tblCLp WHERE c_id = $courseId AND iid <> id ORDER by iid";
2867
        $result = $connection->query($sql);
2868
        if ($debug) {
2869
            error_log('-------------');
2870
            error_log("Entering Lps in course #$courseId");
2871
            error_log($sql);
2872
        }
2873
        $lpList = $result->fetchAll();
2874
        $myOnlyLpList = [];
2875
        if (!empty($lpList)) {
2876
            foreach ($lpList as $lpInfo) {
2877
                $oldId = $lpInfo['id'];
2878
                $sql = "SELECT * FROM $tblCLpItem WHERE c_id = $courseId AND lp_id = $oldId ORDER by iid";
2879
                $result = $connection->query($sql);
2880
                $items = $result->fetchAll();
2881
                $lpInfo['lp_list'] = $items;
2882
                $myOnlyLpList[] = $lpInfo;
2883
            }
2884
        }
2885
2886
        if (!empty($myOnlyLpList)) {
2887
            foreach ($myOnlyLpList as $lpInfo) {
2888
                $lpIid = $lpInfo['iid'];
2889
                $oldId = $lpInfo['id'];
2890
                $items = $lpInfo['lp_list'];
2891
2892
                if (empty($items)) {
2893
                    continue;
2894
                }
2895
                $itemList = [];
2896
                foreach ($items as $subItem) {
2897
                    $itemList[$subItem['id']] = $subItem['iid'];
2898
                }
2899
                $variablesToFix = [
2900
                    'parent_item_id',
2901
                    'next_item_id',
2902
                    'prerequisite',
2903
                    'previous_item_id',
2904
                ];
2905
2906
                foreach ($sessions as $sessionId) {
2907
                    $correctLink = "lp/lp_controller.php?action=view&lp_id=$lpIid&id_session=$sessionId";
2908
                    $link = "newscorm/lp_controller.php?action=view&lp_id=$oldId&id_session=$sessionId";
2909
                    $secondLink = "lp/lp_controller.php?action=view&lp_id=$oldId&id_session=$sessionId";
2910
                    $sql = "UPDATE $toolTable
2911
                        SET link = '$correctLink'
2912
                        WHERE c_id = $courseId AND (link = '$link' OR link ='$secondLink')";
2913
                    $connection->query($sql);
2914
                    if ($debug) {
2915
                        //error_log("Fix wrong c_tool links");
2916
                        //error_log($sql);
2917
                    }
2918
                }
2919
2920
                foreach ($items as $item) {
2921
                    $itemIid = $item['iid'];
2922
                    $itemId = $item['id'];
2923
                    foreach ($variablesToFix as $variable) {
2924
                        if (!empty($item[$variable]) && isset($itemList[$item[$variable]])) {
2925
                            $newId = $itemList[$item[$variable]];
2926
                            $sql = "UPDATE $tblCLpItem SET $variable = $newId
2927
                                    WHERE iid = $itemIid AND c_id = $courseId AND lp_id = $oldId";
2928
                            $connection->query($sql);
2929
                            if ($debug) {
2930
                                //error_log($sql);
2931
                            }
2932
                        }
2933
                    }
2934
2935
                    if ($item['item_type'] === 'document' && !empty($item['path'])) {
2936
                        $oldDocumentId = $item['path'];
2937
                        $sql = "SELECT * FROM c_document WHERE c_id = $courseId AND id = $oldDocumentId";
2938
                        $result = $connection->query($sql);
2939
                        $document = $result->fetch();
2940
                        if (!empty($document)) {
2941
                            $newDocumentId = $document['iid'];
2942
                            if (!empty($newDocumentId)) {
2943
                                $sql = "UPDATE $tblCLpItem SET path = $newDocumentId
2944
                                        WHERE iid = $itemIid AND c_id = $courseId";
2945
                                $connection->query($sql);
2946
                            }
2947
                        }
2948
                    }
2949
2950
                    if ($item['item_type'] === 'link' && !empty($item['path'])) {
2951
                        $oldLinkId = $item['path'];
2952
                        $sql = "SELECT * FROM c_link WHERE c_id = $courseId AND id = $oldLinkId";
2953
                        $result = $connection->query($sql);
2954
                        $document = $result->fetch();
2955
                        if (!empty($document)) {
2956
                            $newLinkId = $document['iid'];
2957
                            if (!empty($newLinkId)) {
2958
                                $sql = "UPDATE $tblCLpItem SET path = $newLinkId
2959
                                        WHERE iid = $itemIid AND c_id = $courseId";
2960
                                $connection->query($sql);
2961
                            }
2962
                        }
2963
                    }
2964
2965
                    // c_lp_view
2966
                    $sql = "UPDATE c_lp_view SET last_item = $itemIid
2967
                            WHERE c_id = $courseId AND last_item = $itemId AND lp_id = $oldId";
2968
                    $connection->query($sql);
2969
2970
                    // c_lp_item_view
2971
                    $sql = "UPDATE c_lp_item_view SET lp_item_id = $itemIid
2972
                            WHERE c_id = $courseId AND lp_item_id = $itemId";
2973
                    $connection->query($sql);
2974
2975
                    // Update track_exercises
2976
                    $sql = "UPDATE track_e_exercises SET orig_lp_item_id = $itemIid
2977
                            WHERE c_id = $courseId AND orig_lp_id = $oldId AND orig_lp_item_id = $itemId";
2978
                    $connection->query($sql);
2979
2980
                    // c_forum_thread
2981
                    $sql = "UPDATE c_forum_thread SET lp_item_id = $itemIid
2982
                            WHERE c_id = $courseId AND lp_item_id = $itemId";
2983
                    $connection->query($sql);
2984
2985
                    // orig_lp_item_view_id
2986
                    $sql = "SELECT * FROM c_lp_view
2987
                            WHERE c_id = $courseId AND lp_id = $oldId";
2988
                    $result = $connection->query($sql);
2989
                    $itemViewList = $result->fetchAll();
2990
                    if ($itemViewList) {
2991
                        foreach ($itemViewList as $itemView) {
2992
                            $userId = $itemView['user_id'];
2993
                            $oldItemViewId = $itemView['id'];
2994
                            $newItemView = $itemView['iid'];
2995
2996
                            if (empty($oldItemViewId)) {
2997
                                continue;
2998
                            }
2999
3000
                            $sql = "UPDATE track_e_exercises
3001
                                SET orig_lp_item_view_id = $newItemView
3002
                                WHERE
3003
                                  c_id = $courseId AND
3004
                                  orig_lp_id = $oldId AND
3005
                                  orig_lp_item_id = $itemIid AND
3006
                                  orig_lp_item_view_id = $oldItemViewId AND
3007
                                  exe_user_id = $userId
3008
                                  ";
3009
                            $connection->query($sql);
3010
3011
                            /*$sql = "UPDATE c_lp_item_view
3012
                                    SET lp_view_id = $newItemView
3013
                                    WHERE
3014
                                      lp_view_id = $oldItemViewId AND
3015
                                      c_id = $courseId
3016
                                  ";
3017
                            $connection->query($sql);*/
3018
                        }
3019
                    }
3020
3021
                    $sql = "UPDATE $tblCLpItem SET lp_id = $lpIid
3022
                            WHERE c_id = $courseId AND lp_id = $oldId AND id = $itemId";
3023
                    $connection->query($sql);
3024
3025
                    $sql = "UPDATE $tblCLpItem SET id = iid
3026
                            WHERE c_id = $courseId AND lp_id = $oldId AND id = $itemId";
3027
                    $connection->query($sql);
3028
                }
3029
3030
                $sql = "UPDATE c_lp_view SET lp_id = $lpIid WHERE c_id = $courseId AND lp_id = $oldId";
3031
                $connection->query($sql);
3032
3033
                $sql = "UPDATE c_forum_forum SET lp_id = $lpIid WHERE c_id = $courseId AND lp_id = $oldId";
3034
                $connection->query($sql);
3035
3036
                // Update track_exercises.
3037
                $sql = "UPDATE track_e_exercises SET orig_lp_id = $lpIid
3038
                        WHERE c_id = $courseId AND orig_lp_id = $oldId";
3039
                $connection->query($sql);
3040
3041
                $sql = "UPDATE $tblCLp SET id = iid WHERE c_id = $courseId AND id = $oldId ";
3042
                $connection->query($sql);
3043
            }
3044
        }
3045
    }
3046
3047
    if ($debug) {
3048
        error_log('END Fix lp.id lp.iids');
3049
    }
3050
}
3051
3052
/**
3053
 * After the schema was created (table creation), the function adds
3054
 * admin/platform information.
3055
 *
3056
 * @param EntityManager $manager
3057
 * @param string        $sysPath
3058
 * @param string        $encryptPassForm
3059
 * @param string        $passForm
3060
 * @param string        $adminLastName
3061
 * @param string        $adminFirstName
3062
 * @param string        $loginForm
3063
 * @param string        $emailForm
3064
 * @param string        $adminPhoneForm
3065
 * @param string        $languageForm
3066
 * @param string        $institutionForm
3067
 * @param string        $institutionUrlForm
3068
 * @param string        $siteName
3069
 * @param string        $allowSelfReg
3070
 * @param string        $allowSelfRegProf
3071
 * @param string        $installationProfile Installation profile, if any was provided
3072
 */
3073
function finishInstallation(
3074
    $manager,
3075
    $sysPath,
3076
    $encryptPassForm,
3077
    $passForm,
3078
    $adminLastName,
3079
    $adminFirstName,
3080
    $loginForm,
3081
    $emailForm,
3082
    $adminPhoneForm,
3083
    $languageForm,
3084
    $institutionForm,
3085
    $institutionUrlForm,
3086
    $siteName,
3087
    $allowSelfReg,
3088
    $allowSelfRegProf,
3089
    $installationProfile = ''
3090
) {
3091
    $sysPath = !empty($sysPath) ? $sysPath : api_get_path(SYS_PATH);
3092
3093
    $connection = $manager->getConnection();
3094
    $sql = getVersionTable();
3095
    // Add version table
3096
    $connection->executeQuery($sql);
3097
3098
    // Add tickets defaults
3099
    $ticketProject = new TicketProject();
3100
    $ticketProject
3101
        ->setId(1)
3102
        ->setName('Ticket System')
3103
        ->setInsertUserId(1);
3104
3105
    $manager->persist($ticketProject);
3106
    $manager->flush();
3107
3108
    $categories = [
3109
        get_lang('TicketEnrollment') => get_lang('TicketsAboutEnrollment'),
3110
        get_lang('TicketGeneralInformation') => get_lang('TicketsAboutGeneralInformation'),
3111
        get_lang('TicketRequestAndPapework') => get_lang('TicketsAboutRequestAndPapework'),
3112
        get_lang('TicketAcademicIncidence') => get_lang('TicketsAboutAcademicIncidence'),
3113
        get_lang('TicketVirtualCampus') => get_lang('TicketsAboutVirtualCampus'),
3114
        get_lang('TicketOnlineEvaluation') => get_lang('TicketsAboutOnlineEvaluation'),
3115
    ];
3116
3117
    $i = 1;
3118
3119
    /**
3120
     * @var string
3121
     * @var string $description
3122
     */
3123
    foreach ($categories as $category => $description) {
3124
        // Online evaluation requires a course
3125
        $ticketCategory = new TicketCategory();
3126
        $ticketCategory
3127
            ->setId($i)
3128
            ->setName($category)
3129
            ->setDescription($description)
3130
            ->setProject($ticketProject)
3131
            ->setInsertUserId(1);
3132
3133
        $isRequired = $i == 6;
3134
        $ticketCategory->setCourseRequired($isRequired);
3135
3136
        $manager->persist($ticketCategory);
3137
        $manager->flush();
3138
3139
        $i++;
3140
    }
3141
3142
    // Default Priorities
3143
    $defaultPriorities = [
3144
        TicketManager::PRIORITY_NORMAL => get_lang('PriorityNormal'),
3145
        TicketManager::PRIORITY_HIGH => get_lang('PriorityHigh'),
3146
        TicketManager::PRIORITY_LOW => get_lang('PriorityLow'),
3147
    ];
3148
3149
    $i = 1;
3150
    foreach ($defaultPriorities as $code => $priority) {
3151
        $ticketPriority = new TicketPriority();
3152
        $ticketPriority
3153
            ->setId($i)
3154
            ->setName($priority)
3155
            ->setCode($code)
3156
            ->setInsertUserId(1);
3157
3158
        $manager->persist($ticketPriority);
3159
        $manager->flush();
3160
        $i++;
3161
    }
3162
3163
    $table = Database::get_main_table(TABLE_TICKET_STATUS);
3164
3165
    // Default status
3166
    $defaultStatus = [
3167
        TicketManager::STATUS_NEW => get_lang('StatusNew'),
3168
        TicketManager::STATUS_PENDING => get_lang('StatusPending'),
3169
        TicketManager::STATUS_UNCONFIRMED => get_lang('StatusUnconfirmed'),
3170
        TicketManager::STATUS_CLOSE => get_lang('StatusClose'),
3171
        TicketManager::STATUS_FORWARDED => get_lang('StatusForwarded'),
3172
    ];
3173
3174
    $i = 1;
3175
    foreach ($defaultStatus as $code => $status) {
3176
        $attributes = [
3177
            'id' => $i,
3178
            'code' => $code,
3179
            'name' => $status,
3180
        ];
3181
        Database::insert($table, $attributes);
3182
        $i++;
3183
    }
3184
3185
    // Inserting data.sql
3186
    $data = file_get_contents($sysPath.'main/install/data.sql');
3187
    $result = $manager->getConnection()->prepare($data);
3188
    $result->execute();
3189
    $result->closeCursor();
3190
3191
    UserManager::setPasswordEncryption($encryptPassForm);
3192
3193
    // Create admin user.
3194
    @UserManager::create_user(
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for create_user(). 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

3194
    /** @scrutinizer ignore-unhandled */ @UserManager::create_user(

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...
3195
        $adminFirstName,
3196
        $adminLastName,
3197
        1,
3198
        $emailForm,
3199
        $loginForm,
3200
        $passForm,
3201
        'ADMIN', //$official_code = '',
3202
        $languageForm,
3203
        $adminPhoneForm,
3204
        '', //$picture_uri = '',
3205
        PLATFORM_AUTH_SOURCE,
3206
        '', //$expirationDate,
3207
        1,
3208
        0,
3209
        null,
3210
        '',
3211
        false, //$send_mail = false,
3212
        true //$isAdmin = false
3213
    );
3214
3215
    // Create anonymous user.
3216
    @UserManager::create_user(
3217
        'Joe',
3218
        'Anonymous',
3219
        6,
3220
        '[email protected]',
3221
        'anon',
3222
        'anon',
3223
        'anonymous', //$official_code = '',
3224
        $languageForm,
3225
        '',
3226
        '', //$picture_uri = '',
3227
        PLATFORM_AUTH_SOURCE,
3228
        '',
3229
        1,
3230
        0,
3231
        null,
3232
        '',
3233
        false, //$send_mail = false,
3234
        false //$isAdmin = false
3235
    );
3236
3237
    // Set default language
3238
    Database::update(
3239
        Database::get_main_table(TABLE_MAIN_LANGUAGE),
3240
        ['available' => 1],
3241
        ['dokeos_folder = ?' => $languageForm]
3242
    );
3243
3244
    // Install settings
3245
    installSettings(
3246
        $institutionForm,
3247
        $institutionUrlForm,
3248
        $siteName,
3249
        $emailForm,
3250
        $adminLastName,
3251
        $adminFirstName,
3252
        $languageForm,
3253
        $allowSelfReg,
3254
        $allowSelfRegProf,
3255
        $installationProfile
3256
    );
3257
3258
    lockSettings();
3259
    updateDirAndFilesPermissions();
3260
3261
    // Set the latest version
3262
    $path = $sysPath.'app/Migrations/Schema/V111/';
3263
    $finder = new \Symfony\Component\Finder\Finder();
3264
    $files = $finder->files()->in($path);
3265
3266
    // Needed for chash
3267
    createVersionTable();
3268
3269
    foreach ($files as $version) {
3270
        $version = str_replace(['Version', '.php'], '', $version->getFilename());
3271
        $sql = "INSERT INTO version (version) VALUES ('$version')";
3272
        Database::query($sql);
3273
    }
3274
}
3275
3276
/**
3277
 * Creates 'version' table.
3278
 */
3279
function createVersionTable()
3280
{
3281
    $sql = getVersionTable();
3282
    Database::query($sql);
3283
}
3284
3285
/**
3286
 * Get version creation table query.
3287
 *
3288
 * @return string
3289
 */
3290
function getVersionTable()
3291
{
3292
    return 'CREATE TABLE IF NOT EXISTS version (id int unsigned NOT NULL AUTO_INCREMENT, version varchar(20), PRIMARY KEY(id), UNIQUE(version));';
3293
}
3294
3295
/**
3296
 * Update settings based on installation profile defined in a JSON file.
3297
 *
3298
 * @param string $installationProfile The name of the JSON file in main/install/profiles/ folder
3299
 *
3300
 * @throws \Doctrine\DBAL\DBALException
3301
 *
3302
 * @return bool false on failure (no bad consequences anyway, just ignoring profile)
3303
 */
3304
function installProfileSettings($installationProfile = '')
3305
{
3306
    if (empty($installationProfile)) {
3307
        return false;
3308
    }
3309
    $jsonPath = api_get_path(SYS_PATH).'main/install/profiles/'.$installationProfile.'.json';
3310
    // Make sure the path to the profile is not hacked
3311
    if (!Security::check_abs_path($jsonPath, api_get_path(SYS_PATH).'main/install/profiles/')) {
3312
        return false;
3313
    }
3314
    if (!is_file($jsonPath)) {
3315
        return false;
3316
    }
3317
    if (!is_readable($jsonPath)) {
3318
        return false;
3319
    }
3320
    if (!function_exists('json_decode')) {
3321
        // The php-json extension is not available. Ignore profile.
3322
        return false;
3323
    }
3324
    $json = file_get_contents($jsonPath);
3325
    $params = json_decode($json);
3326
    if ($params === false or $params === null) {
3327
        return false;
3328
    }
3329
    $settings = $params->params;
3330
    if (!empty($params->parent)) {
3331
        installProfileSettings($params->parent);
3332
    }
3333
3334
    $tblSettings = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
3335
3336
    foreach ($settings as $id => $param) {
3337
        $conditions = ['variable = ? ' => $param->variable];
3338
3339
        if (!empty($param->subkey)) {
3340
            $conditions['AND subkey = ? '] = $param->subkey;
3341
        }
3342
3343
        Database::update(
3344
            $tblSettings,
3345
            ['selected_value' => $param->selected_value],
3346
            $conditions
3347
        );
3348
    }
3349
3350
    return true;
3351
}
3352
3353
/**
3354
 * Quick function to remove a directory with its subdirectories.
3355
 *
3356
 * @param $dir
3357
 */
3358
function rrmdir($dir)
3359
{
3360
    if (is_dir($dir)) {
3361
        $objects = scandir($dir);
3362
        foreach ($objects as $object) {
3363
            if ($object != "." && $object != "..") {
3364
                if (filetype($dir."/".$object) == "dir") {
3365
                    @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

3365
                    /** @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...
3366
                } else {
3367
                    @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

3367
                    /** @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...
3368
                }
3369
            }
3370
        }
3371
        reset($objects);
3372
        rmdir($dir);
3373
    }
3374
}
3375
3376
/**
3377
 * @param        $id
3378
 * @param string $type
3379
 * @param bool   $preview
3380
 * @param bool   $anonymous
3381
 *
3382
 * @throws \Doctrine\DBAL\DBALException
3383
 *
3384
 * @return array
3385
 */
3386
function get_group_picture_path_by_id($id, $type = 'web', $preview = false, $anonymous = false)
3387
{
3388
    switch ($type) {
3389
        case 'system': // Base: absolute system path.
3390
            $base = api_get_path(SYS_UPLOAD_PATH);
3391
            break;
3392
        case 'web': // Base: absolute web path.
3393
        default:
3394
            $base = api_get_path(WEB_UPLOAD_PATH);
3395
            break;
3396
    }
3397
3398
    $noPicturePath = ['dir' => $base.'img/', 'file' => 'unknown.jpg'];
3399
3400
    if (empty($id) || empty($type)) {
3401
        return $anonymous ? $noPicturePath : ['dir' => '', 'file' => ''];
3402
    }
3403
3404
    $id = intval($id);
3405
3406
    //$group_table = Database::get_main_table(TABLE_MAIN_GROUP);
3407
    $group_table = 'groups';
3408
    $sql = "SELECT picture_uri FROM $group_table WHERE id=".$id;
3409
    $res = Database::query($sql);
3410
3411
    if (!Database::num_rows($res)) {
3412
        return $anonymous ? $noPicturePath : ['dir' => '', 'file' => ''];
3413
    }
3414
3415
    $user = Database::fetch_array($res);
3416
    $picture_filename = trim($user['picture_uri']);
3417
3418
    if (api_get_setting('split_users_upload_directory') === 'true') {
3419
        if (!empty($picture_filename)) {
3420
            $dir = $base.'groups/'.substr($picture_filename, 0, 1).'/'.$id.'/';
3421
        } elseif ($preview) {
3422
            $dir = $base.'groups/'.substr((string) $id, 0, 1).'/'.$id.'/';
3423
        } else {
3424
            $dir = $base.'groups/'.$id.'/';
3425
        }
3426
    } else {
3427
        $dir = $base.'groups/'.$id.'/';
3428
    }
3429
3430
    if (empty($picture_filename) && $anonymous) {
3431
        return $noPicturePath;
3432
    }
3433
3434
    return ['dir' => $dir, 'file' => $picture_filename];
3435
}
3436
3437
/**
3438
 * Control the different steps of the migration through a big switch.
3439
 *
3440
 * @param string        $fromVersion
3441
 * @param EntityManager $manager
3442
 * @param bool          $processFiles
3443
 *
3444
 * @throws \Doctrine\DBAL\DBALException
3445
 *
3446
 * @return bool Always returns true except if the process is broken
3447
 */
3448
function migrateSwitch($fromVersion, $manager, $processFiles = true)
3449
{
3450
    error_log('Starting migration process from '.$fromVersion.' ('.date('Y-m-d H:i:s').')');
3451
3452
    echo '<a class="btn btn-default" href="javascript:void(0)" id="details_button">'.get_lang('Details').'</a><br />';
3453
    echo '<div id="details" style="display:none">';
3454
3455
    $connection = $manager->getConnection();
3456
3457
    $database = new Database();
3458
    $database->setManager($manager);
3459
3460
    switch ($fromVersion) {
3461
        case '1.9.0':
3462
        case '1.9.2':
3463
        case '1.9.4':
3464
        case '1.9.6':
3465
        case '1.9.6.1':
3466
        case '1.9.8':
3467
        case '1.9.8.1':
3468
        case '1.9.8.2':
3469
        case '1.9.10':
3470
        case '1.9.10.2':
3471
        case '1.9.10.4':
3472
        case '1.9.10.6':
3473
            $database = new Database();
3474
            $database->setManager($manager);
3475
3476
            // Fix type "enum" before running the migration with Doctrine
3477
            $connection->executeQuery("ALTER TABLE course_category MODIFY COLUMN auth_course_child VARCHAR(40) DEFAULT 'TRUE'");
3478
            $connection->executeQuery("ALTER TABLE course_category MODIFY COLUMN auth_cat_child VARCHAR(40) DEFAULT 'TRUE'");
3479
            $connection->executeQuery("ALTER TABLE c_quiz_answer MODIFY COLUMN hotspot_type varchar(40) default NULL");
3480
            $connection->executeQuery("ALTER TABLE c_tool MODIFY COLUMN target varchar(20) NOT NULL default '_self'");
3481
            $connection->executeQuery("ALTER TABLE c_link MODIFY COLUMN on_homepage char(10) NOT NULL default '0'");
3482
            $connection->executeQuery("ALTER TABLE c_blog_rating MODIFY COLUMN rating_type char(40) NOT NULL default 'post'");
3483
            $connection->executeQuery("ALTER TABLE c_survey MODIFY COLUMN anonymous char(10) NOT NULL default '0'");
3484
            $connection->executeQuery("ALTER TABLE c_document MODIFY COLUMN filetype char(10) NOT NULL default 'file'");
3485
            $connection->executeQuery("ALTER TABLE c_student_publication MODIFY COLUMN filetype char(10) NOT NULL default 'file'");
3486
3487
            // Migrate using the migration files located in:
3488
            // src/Chamilo/CoreBundle/Migrations/Schema/V110
3489
            $result = migrate(
3490
                110,
3491
                $manager
3492
            );
3493
3494
            if ($result) {
3495
                error_log('Migrations files were executed ('.date('Y-m-d H:i:s').')');
3496
                fixIds($manager);
3497
                error_log('fixIds finished ('.date('Y-m-d H:i:s').')');
3498
3499
                $connection->executeQuery("UPDATE settings_current SET selected_value = '1.10.0' WHERE variable = 'chamilo_database_version'");
3500
3501
                if ($processFiles) {
3502
                    $fromVersionShort = '1.9';
3503
                    include __DIR__.'/update-files-1.9.0-1.10.0.inc.php';
3504
                    // Only updates the configuration.inc.php with the new version
3505
                    include __DIR__.'/update-configuration.inc.php';
3506
3507
                    $configurationFiles = [
3508
                        'mail.conf.php',
3509
                        'profile.conf.php',
3510
                        'course_info.conf.php',
3511
                        'add_course.conf.php',
3512
                        'events.conf.php',
3513
                        'auth.conf.php',
3514
                    ];
3515
3516
                    error_log('Copy conf files');
3517
3518
                    foreach ($configurationFiles as $file) {
3519
                        if (file_exists(api_get_path(SYS_CODE_PATH).'inc/conf/'.$file)) {
3520
                            copy(
3521
                                api_get_path(SYS_CODE_PATH).'inc/conf/'.$file,
3522
                                api_get_path(CONFIGURATION_PATH).$file
3523
                            );
3524
                        }
3525
                    }
3526
                }
3527
3528
                error_log('Upgrade 1.10.x process concluded! ('.date('Y-m-d H:i:s').')');
3529
            } else {
3530
                error_log('There was an error during running migrations. Check error.log');
3531
                break;
3532
            }
3533
            // no break
3534
        case '1.10.0':
3535
        case '1.10.2':
3536
        case '1.10.4':
3537
        case '1.10.6':
3538
        case '1.10.8':
3539
            $database = new Database();
3540
            $database->setManager($manager);
3541
            // Migrate using the migration files located in:
3542
            // src/Chamilo/CoreBundle/Migrations/Schema/V111
3543
            $result = migrate(
3544
                111,
3545
                $manager
3546
            );
3547
3548
            if ($result) {
3549
                fixLpId($connection, true);
3550
3551
                error_log('Migrations files were executed ('.date('Y-m-d H:i:s').')');
3552
3553
                fixPostGroupIds($connection);
3554
3555
                $sql = "UPDATE settings_current SET selected_value = '1.11.0' WHERE variable = 'chamilo_database_version'";
3556
                $connection->executeQuery($sql);
3557
                if ($processFiles) {
3558
                    error_log('Update config files');
3559
                    $fromVersionShort = '1.10';
3560
                    include __DIR__.'/update-files-1.10.0-1.11.0.inc.php';
3561
                    // Only updates the configuration.inc.php with the new version
3562
                    include __DIR__.'/update-configuration.inc.php';
3563
                }
3564
                error_log('Upgrade 1.11.x process concluded!  ('.date('Y-m-d H:i:s').')');
3565
            } else {
3566
                error_log('There was an error during running migrations. Check error.log');
3567
            }
3568
            break;
3569
        default:
3570
            break;
3571
    }
3572
3573
    echo '</div>';
3574
3575
    return true;
3576
}
3577
3578
/**
3579
 * @param \Doctrine\DBAL\Connection $connection
3580
 *
3581
 * @throws \Doctrine\DBAL\DBALException
3582
 */
3583
function fixPostGroupIds($connection)
3584
{
3585
    $connection->executeQuery("ALTER TABLE course_category MODIFY COLUMN auth_course_child VARCHAR(40) DEFAULT 'TRUE'");
3586
    error_log('Fix c_student_publication.post_group_id');
3587
3588
    // Fix post_group_id
3589
    $sql = "SELECT * FROM c_student_publication
3590
            WHERE (post_group_id <> 0 AND post_group_id is not null)";
3591
    $statement = $connection->executeQuery($sql);
3592
    $result = $statement->fetchAll();
3593
3594
    foreach ($result as $row) {
3595
        $groupId = $row['post_group_id'];
3596
        $courseId = $row['c_id'];
3597
        $workIid = $row['iid'];
3598
        $sql = "SELECT iid from c_group_info
3599
                WHERE c_id = $courseId AND id = $groupId";
3600
        $statement = $connection->executeQuery($sql);
3601
        $count = $statement->rowCount();
3602
        if ($count > 0) {
3603
            $rowGroup = $statement->fetch();
3604
            $newGroupId = $rowGroup['iid'];
3605
            if ($newGroupId == $groupId) {
3606
                continue;
3607
            }
3608
            if ($newGroupId) {
3609
                $sql = "UPDATE c_student_publication
3610
                        SET post_group_id = $newGroupId
3611
                        WHERE
3612
                            c_id = $courseId AND
3613
                            iid = $workIid
3614
                        ";
3615
                $connection->executeQuery($sql);
3616
            }
3617
        }
3618
    }
3619
3620
    error_log('End - Fix c_student_publication.post_group_id');
3621
3622
    // Delete c_student_publication from any session that doesn't exist anymore
3623
    $sql = "DELETE FROM c_student_publication
3624
            WHERE session_id NOT IN (SELECT id FROM session) AND (session_id <> 0 AND session_id is not null)";
3625
    $connection->executeQuery($sql);
3626
3627
    error_log('Fix work documents');
3628
    // Fix work documents that don't have c_item_property value
3629
    $sql = "SELECT * FROM c_student_publication WHERE parent_id IS NOT NULL";
3630
    $statement = $connection->executeQuery($sql);
3631
    $result = $statement->fetchAll();
3632
    foreach ($result as $row) {
3633
        $groupId = $row['post_group_id'];
3634
        $courseId = $row['c_id'];
3635
        $sessionId = $row['session_id'];
3636
        $workId = $row['id'];
3637
        $sessionCondition = " session_id = $sessionId";
3638
        if (empty($sessionId)) {
3639
            $sessionCondition = ' (session_id = 0 OR session_id IS NULL) ';
3640
        }
3641
        $sql = "SELECT * FROM c_item_property
3642
                WHERE
3643
                    c_id = $courseId AND
3644
                    tool = 'work' AND
3645
                    ref = $workId AND
3646
                    $sessionCondition ";
3647
        $itemInfo = $connection->fetchAssoc($sql);
3648
        if (empty($itemInfo)) {
3649
            $params = [
3650
                'c_id' => $courseId,
3651
                'to_group_id' => $groupId,
3652
                //'to_user_id' => null,
3653
                'insert_user_id' => 1,
3654
                'session_id' => $sessionId,
3655
                'tool' => 'work',
3656
                'insert_date' => api_get_utc_datetime(),
3657
                'lastedit_date' => api_get_utc_datetime(),
3658
                'ref' => $workId,
3659
                'lastedit_type' => 'visible',
3660
                'lastedit_user_id' => 1,
3661
                'visibility' => 1,
3662
            ];
3663
            $connection->insert('c_item_property', $params);
3664
            $id = $connection->lastInsertId();
3665
            $sql = "UPDATE c_item_property SET id = iid WHERE iid = $id";
3666
            $connection->executeQuery($sql);
3667
        }
3668
    }
3669
    error_log('End - Fix work documents');
3670
}
3671