Passed
Push — dependabot/npm_and_yarn/highli... ( cb1e44...34f0f6 )
by
unknown
13:27 queued 06:04
created

write_system_config_file()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 32
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

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

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

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

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

// Bar.php
namespace OtherDir;

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

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

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

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

// Bar.php
namespace OtherDir;

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

133
        return Display::label($currentPhpValue.' './** @scrutinizer ignore-type */ $returnSuccess, 'success');
Loading history...
134
    }
135
136
    return Display::label($currentPhpValue.' '.$returnSuccess, 'important');
137
}
138
139
/**
140
 * This function return the value of a php.ini setting if not "" or if exists,
141
 * otherwise return false.
142
 *
143
 * @param string $phpSetting The name of a PHP setting
144
 *
145
 * @return mixed The value of the setting, or false if not found
146
 */
147
function checkPhpSettingExists($phpSetting)
148
{
149
    if ('' != ini_get($phpSetting)) {
150
        return ini_get($phpSetting);
151
    }
152
153
    return false;
154
}
155
156
/**
157
 * Returns a textual value ('ON' or 'OFF') based on a requester 2-state ini- configuration setting.
158
 *
159
 * @param string $val a php ini value
160
 *
161
 * @return bool ON or OFF
162
 *
163
 * @author Joomla <http://www.joomla.org>
164
 */
165
function getPhpSetting($val)
166
{
167
    $value = ini_get($val);
168
    switch ($val) {
169
        case 'display_errors':
170
            global $originalDisplayErrors;
171
            $value = $originalDisplayErrors;
172
            break;
173
    }
174
175
    return '1' == $value ? 'ON' : 'OFF';
176
}
177
178
/**
179
 * This function returns a string "true" or "false" according to the passed parameter.
180
 *
181
 * @param int $var The variable to present as text
182
 *
183
 * @return string the string "true" or "false"
184
 *
185
 * @author Christophe Gesch??
186
 */
187
function trueFalse($var)
188
{
189
    return $var ? 'true' : 'false';
190
}
191
192
/**
193
 * Detects browser's language.
194
 *
195
 * @return string Returns a language identificator, i.e. 'english', 'spanish', ...
196
 *
197
 * @author Ivan Tcholakov, 2010
198
 */
199
function detect_browser_language()
200
{
201
    static $language_index = [
202
        'ar' => 'arabic',
203
        'ast' => 'asturian',
204
        'bg' => 'bulgarian',
205
        'bs' => 'bosnian',
206
        'ca' => 'catalan',
207
        'zh' => 'simpl_chinese',
208
        'zh-tw' => 'trad_chinese',
209
        'cs' => 'czech',
210
        'da' => 'danish',
211
        'prs' => 'dari',
212
        'de' => 'german',
213
        'el' => 'greek',
214
        'en' => 'english',
215
        'es' => 'spanish',
216
        'eo' => 'esperanto',
217
        'eu' => 'basque',
218
        'fa' => 'persian',
219
        'fr' => 'french',
220
        'fur' => 'friulian',
221
        'gl' => 'galician',
222
        'ka' => 'georgian',
223
        'hr' => 'croatian',
224
        'he' => 'hebrew',
225
        'hi' => 'hindi',
226
        'id' => 'indonesian',
227
        'it' => 'italian',
228
        'ko' => 'korean',
229
        'lv' => 'latvian',
230
        'lt' => 'lithuanian',
231
        'mk' => 'macedonian',
232
        'hu' => 'hungarian',
233
        'ms' => 'malay',
234
        'nl' => 'dutch',
235
        'ja' => 'japanese',
236
        'no' => 'norwegian',
237
        'oc' => 'occitan',
238
        'ps' => 'pashto',
239
        'pl' => 'polish',
240
        'pt' => 'portuguese',
241
        'pt-br' => 'brazilian',
242
        'ro' => 'romanian',
243
        'qu' => 'quechua_cusco',
244
        'ru' => 'russian',
245
        'sk' => 'slovak',
246
        'sl' => 'slovenian',
247
        'sr' => 'serbian',
248
        'fi' => 'finnish',
249
        'sv' => 'swedish',
250
        'th' => 'thai',
251
        'tr' => 'turkish',
252
        'uk' => 'ukrainian',
253
        'vi' => 'vietnamese',
254
        'sw' => 'swahili',
255
        'yo' => 'yoruba',
256
    ];
257
258
    $system_available_languages = get_language_folder_list();
259
    $accept_languages = strtolower(str_replace('_', '-', $_SERVER['HTTP_ACCEPT_LANGUAGE']));
260
    foreach ($language_index as $code => $language) {
261
        if (0 === strpos($accept_languages, $code)) {
262
            if (!empty($system_available_languages[$language])) {
263
                return $language;
264
            }
265
        }
266
    }
267
268
    $user_agent = strtolower(str_replace('_', '-', $_SERVER['HTTP_USER_AGENT']));
269
    foreach ($language_index as $code => $language) {
270
        if (@preg_match("/[\[\( ]{$code}[;,_\-\)]/", $user_agent)) {
271
            if (!empty($system_available_languages[$language])) {
272
                return $language;
273
            }
274
        }
275
    }
276
277
    return 'english';
278
}
279
280
/**
281
 * This function checks if the given folder is writable.
282
 *
283
 * @param string $folder     Full path to a folder
284
 * @param bool   $suggestion Whether to show a suggestion or not
285
 *
286
 * @return string
287
 */
288
function check_writable($folder, $suggestion = false)
289
{
290
    if (is_writable($folder)) {
291
        return Display::label(get_lang('Writable'), 'success');
292
    } else {
293
        if ($suggestion) {
294
            return Display::label(get_lang('Not writable'), 'info');
295
        } else {
296
            return Display::label(get_lang('Not writable'), 'important');
297
        }
298
    }
299
}
300
301
/**
302
 * This function checks if the given folder is readable.
303
 *
304
 * @param string $folder     Full path to a folder
305
 * @param bool   $suggestion Whether to show a suggestion or not
306
 *
307
 * @return string
308
 */
309
function checkReadable($folder, $suggestion = false)
310
{
311
    if (is_readable($folder)) {
312
        return Display::label(get_lang('Readable'), 'success');
313
    } else {
314
        if ($suggestion) {
315
            return Display::label(get_lang('Not readable'), 'info');
316
        } else {
317
            return Display::label(get_lang('Not readable'), 'important');
318
        }
319
    }
320
}
321
322
/**
323
 * We assume this function is called from install scripts that reside inside the install folder.
324
 */
325
function set_file_folder_permissions()
326
{
327
    @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

327
    /** @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...
328
    @chmod('..', 0755); //set permissions on parent dir of install dir
329
}
330
331
/**
332
 * Write the main system config file.
333
 *
334
 * @param string $path Path to the config file
335
 */
336
function write_system_config_file($path)
337
{
338
    $content = file_get_contents(__DIR__.'/'.SYSTEM_CONFIG_FILENAME);
339
    $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...
340
    $config['{SECURITY_KEY}'] = md5(uniqid(rand().time()));
341
342
    foreach ($config as $key => $value) {
343
        $content = str_replace($key, $value, $content);
344
    }
345
    $fp = @fopen($path, 'w');
346
347
    if (!$fp) {
0 ignored issues
show
introduced by
$fp is of type false|resource, thus it always evaluated to false.
Loading history...
348
        echo '<strong>
349
                <font color="red">Your script doesn\'t have write access to the config directory</font></strong><br />
350
                <em>('.str_replace('\\', '/', realpath($path)).')</em><br /><br />
351
                You probably do not have write access on Chamilo root directory,
352
                i.e. you should <em>CHMOD 777</em> or <em>755</em> or <em>775</em>.<br /><br />
353
                Your problems can be related on two possible causes:<br />
354
                <ul>
355
                  <li>Permission problems.<br />Try initially with <em>chmod -R 777</em> and increase restrictions gradually.</li>
356
                  <li>PHP is running in <a href="http://www.php.net/manual/en/features.safe-mode.php" target="_blank">Safe-Mode</a>.
357
                  If possible, try to switch it off.</li>
358
                </ul>
359
                <a href="http://forum.chamilo.org/" target="_blank">Read about this problem in Support Forum</a><br /><br />
360
                Please go back to step 5.
361
                <p><input type="submit" name="step5" value="&lt; Back" /></p>
362
                </td></tr></table></form></body></html>';
363
        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...
364
    }
365
366
    fwrite($fp, $content);
367
    fclose($fp);
368
}
369
370
/**
371
 * Returns a list of language directories.
372
 */
373
function get_language_folder_list()
374
{
375
    return [
376
        'ar' => 'arabic',
377
        'ast' => 'asturian',
378
        'bg' => 'bulgarian',
379
        'bs' => 'bosnian',
380
        'ca' => 'catalan',
381
        'zh' => 'simpl_chinese',
382
        'zh-tw' => 'trad_chinese',
383
        'cs' => 'czech',
384
        'da' => 'danish',
385
        'prs' => 'dari',
386
        'de' => 'german',
387
        'el' => 'greek',
388
        'en' => 'english',
389
        'es' => 'spanish',
390
        'eo' => 'esperanto',
391
        'eu' => 'basque',
392
        'fa' => 'persian',
393
        'fr' => 'french',
394
        'fur' => 'friulian',
395
        'gl' => 'galician',
396
        'ka' => 'georgian',
397
        'hr' => 'croatian',
398
        'he' => 'hebrew',
399
        'hi' => 'hindi',
400
        'id' => 'indonesian',
401
        'it' => 'italian',
402
        'ko' => 'korean',
403
        'lv' => 'latvian',
404
        'lt' => 'lithuanian',
405
        'mk' => 'macedonian',
406
        'hu' => 'hungarian',
407
        'ms' => 'malay',
408
        'nl' => 'dutch',
409
        'ja' => 'japanese',
410
        'no' => 'norwegian',
411
        'oc' => 'occitan',
412
        'ps' => 'pashto',
413
        'pl' => 'polish',
414
        'pt' => 'portuguese',
415
        'pt-br' => 'brazilian',
416
        'ro' => 'romanian',
417
        'qu' => 'quechua_cusco',
418
        'ru' => 'russian',
419
        'sk' => 'slovak',
420
        'sl' => 'slovenian',
421
        'sr' => 'serbian',
422
        'fi' => 'finnish',
423
        'sv' => 'swedish',
424
        'th' => 'thai',
425
        'tr' => 'turkish',
426
        'uk' => 'ukrainian',
427
        'vi' => 'vietnamese',
428
        'sw' => 'swahili',
429
        'yo' => 'yoruba',
430
    ];
431
}
432
433
/**
434
 * This function returns the value of a parameter from the configuration file.
435
 *
436
 * WARNING - this function relies heavily on global variables $updateFromConfigFile
437
 * and $configFile, and also changes these globals. This can be rewritten.
438
 *
439
 * @param string $param      the parameter of which the value is returned
440
 * @param string $updatePath If we want to give the path rather than take it from POST
441
 *
442
 * @return string the value of the parameter
443
 *
444
 * @author Olivier Brouckaert
445
 * @author Reworked by Ivan Tcholakov, 2010
446
 */
447
function get_config_param($param, $updatePath = '')
448
{
449
    global $updateFromConfigFile;
450
    if (empty($updatePath) && !empty($_POST['updatePath'])) {
451
        $updatePath = $_POST['updatePath'];
452
    }
453
454
    if (empty($updatePath)) {
455
        $updatePath = api_get_path(SYMFONY_SYS_PATH);
456
    }
457
    $updatePath = api_add_trailing_slash(str_replace('\\', '/', realpath($updatePath)));
458
459
    if (empty($updateFromConfigFile)) {
460
        // If update from previous install was requested,
461
        if (file_exists($updatePath.'app/config/configuration.php')) {
462
            $updateFromConfigFile = 'app/config/configuration.php';
463
        } else {
464
            // Give up recovering.
465
            return null;
466
        }
467
    }
468
469
    if (file_exists($updatePath.$updateFromConfigFile) &&
470
        !is_dir($updatePath.$updateFromConfigFile)
471
    ) {
472
        require $updatePath.$updateFromConfigFile;
473
        $config = new Laminas\Config\Config($_configuration);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $_configuration does not exist. Did you maybe mean $config?
Loading history...
474
475
        return $config->get($param);
476
    }
477
478
    error_log('Config array could not be found in get_config_param()', 0);
479
480
    return null;
481
}
482
483
/**
484
 * Gets a configuration parameter from the database. Returns returns null on failure.
485
 *
486
 * @param string $param Name of param we want
487
 *
488
 * @return mixed The parameter value or null if not found
489
 */
490
function get_config_param_from_db($param = '')
491
{
492
    $param = Database::escape_string($param);
493
494
    if (false !== ($res = Database::query("SELECT * FROM settings_current WHERE variable = '$param'"))) {
495
        if (Database::num_rows($res) > 0) {
496
            $row = Database::fetch_array($res);
497
498
            return $row['selected_value'];
499
        }
500
    }
501
502
    return null;
503
}
504
505
/**
506
 * Connect to the database and returns the entity manager.
507
 *
508
 * @param string $host
509
 * @param string $username
510
 * @param string $password
511
 * @param string $databaseName
512
 * @param int    $port
513
 *
514
 * @return \Database
515
 */
516
function connectToDatabase(
517
    $host,
518
    $username,
519
    $password,
520
    $databaseName,
521
    $port = 3306
522
) {
523
    $database = new \Database();
524
    $database->connect(
525
        [
526
            'driver' => 'pdo_mysql',
527
            'host' => $host,
528
            'port' => $port,
529
            'user' => $username,
530
            'password' => $password,
531
            'dbname' => $databaseName,
532
        ]
533
    );
534
535
    return $database;
536
}
537
538
/**
539
 * This function prints class=active_step $current_step=$param.
540
 *
541
 * @param int $param A step in the installer process
542
 *
543
 * @author Patrick Cool <[email protected]>, Ghent University
544
 */
545
function step_active($param)
546
{
547
    global $current_step;
548
    if ($param == $current_step) {
549
        echo 'active';
550
    }
551
}
552
553
/**
554
 * This function displays the Step X of Y -.
555
 *
556
 * @return string String that says 'Step X of Y' with the right values
557
 */
558
function display_step_sequence()
559
{
560
    global $current_step;
561
562
    return get_lang('Step'.$current_step).' &ndash; ';
563
}
564
565
/**
566
 * Displays a drop down box for selection the preferred language.
567
 */
568
function display_language_selection_box(
569
    $name = 'language_list',
570
    $default_language = 'english'
571
) {
572
    // Reading language list.
573
    $language_list = get_language_folder_list();
574
575
    // Sanity checks due to the possibility for customizations.
576
    if (!is_array($language_list) || empty($language_list)) {
577
        $language_list = ['en' => 'English'];
578
    }
579
580
    // Sorting again, if it is necessary.
581
    //asort($language_list);
582
583
    // More sanity checks.
584
    if (!array_key_exists($default_language, $language_list)) {
585
        if (array_key_exists('en', $language_list)) {
586
            $default_language = 'en';
587
        } else {
588
            $language_keys = array_keys($language_list);
589
            $default_language = $language_keys[0];
590
        }
591
    }
592
593
    // Displaying the box.
594
    $html = Display::select(
595
        'language_list',
596
        $language_list,
597
        $default_language,
598
        ['class' => 'selectpicker'],
599
        false
600
    );
601
602
    return $html;
603
}
604
605
/**
606
 * This function displays a language dropdown box so that the installatioin
607
 * can be done in the language of the user.
608
 */
609
function display_language_selection()
610
{
611
    ?>
612
        <div class="install-icon">
613
            <img width="150px;" src="chamilo-install.svg"/>
614
        </div>
615
        <h2 class="install-title">
616
            <?php echo display_step_sequence(); ?>
617
            <?php echo get_lang('Installation Language'); ?>
618
        </h2>
619
        <label for="language_list"><?php echo get_lang('Please select installation language'); ?></label>
620
        <div class="form-group">
621
            <?php echo display_language_selection_box('language_list', api_get_interface_language()); ?>
622
        </div>
623
        <button type="submit" name="step1" class="btn btn-success" value="<?php echo get_lang('Next'); ?>">
624
            <em class="fa fa-forward"> </em>
625
            <?php echo get_lang('Next'); ?>
626
        </button>
627
        <input type="hidden" name="is_executable" id="is_executable" value="-" />
628
        <div class="RequirementHeading">
629
            <?php echo get_lang('Cannot find your language in the list? Contact us at [email protected] to contribute as a translator.'); ?>
630
        </div>
631
<?php
632
}
633
634
/**
635
 * This function displays the requirements for installing Chamilo.
636
 *
637
 * @param string $installType
638
 * @param bool   $badUpdatePath
639
 * @param bool   $badUpdatePath
640
 * @param string $updatePath         The updatePath given (if given)
641
 * @param array  $upgradeFromVersion The different subversions from version 1.9
642
 *
643
 * @author unknow
644
 * @author Patrick Cool <[email protected]>, Ghent University
645
 */
646
function display_requirements(
647
    $installType,
648
    $badUpdatePath,
649
    $updatePath = '',
650
    $upgradeFromVersion = []
651
) {
652
    global $_setting, $originalMemoryLimit;
653
654
    $dir = api_get_path(SYS_ARCHIVE_PATH).'temp/';
655
    $fileToCreate = 'test';
656
657
    $perms_dir = [0777, 0755, 0775, 0770, 0750, 0700];
658
    $perms_fil = [0666, 0644, 0664, 0660, 0640, 0600];
659
    $course_test_was_created = false;
660
    $dir_perm_verified = 0777;
661
662
    foreach ($perms_dir as $perm) {
663
        $r = @mkdir($dir, $perm);
664
        if (true === $r) {
665
            $dir_perm_verified = $perm;
666
            $course_test_was_created = true;
667
            break;
668
        }
669
    }
670
671
    $fil_perm_verified = 0666;
672
    $file_course_test_was_created = false;
673
    if (is_dir($dir)) {
674
        foreach ($perms_fil as $perm) {
675
            if (true == $file_course_test_was_created) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

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

Loading history...
676
                break;
677
            }
678
            $r = @touch($dir.'/'.$fileToCreate, $perm);
679
            if (true === $r) {
680
                $fil_perm_verified = $perm;
681
                $file_course_test_was_created = true;
682
            }
683
        }
684
    }
685
686
    @unlink($dir.'/'.$fileToCreate);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for unlink(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

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

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

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

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

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

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

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

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

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

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

986
            /** @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...
987
        }
988
989
        if (false == $course_test_was_created) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

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

Loading history...
990
            error_log('Installer: Could not create test course - Make sure permissions are fine.');
991
            $error = true;
992
        }
993
994
        $checked_writable = api_get_path(CONFIGURATION_PATH).'configuration.php';
995
        if (file_exists($checked_writable) && !is_writable($checked_writable)) {
996
            $notWritable[] = $checked_writable;
997
            @chmod($checked_writable, $perm_file);
998
        }
999
1000
        // Second, if this fails, report an error
1001
        //--> The user would have to adjust the permissions manually
1002
        if (count($notWritable) > 0) {
1003
            error_log('Installer: At least one needed directory or file is not writeable');
1004
            $error = true; ?>
1005
            <div class="text-danger">
1006
                <h3 class="text-center"><?php echo get_lang('Warning !'); ?></h3>
1007
                <p>
1008
                    <?php printf(get_lang('Some files or folders don\'t have writing permission. To be able to install Chamilo you should first change their permissions (using CHMOD). Please read the %s installation guide %s'), '<a href="../../documentation/installation_guide.html" target="blank">', '</a>'); ?>
1009
                </p>
1010
            </div>
1011
            <?php
1012
            echo '<ul>';
1013
            foreach ($notWritable as $value) {
1014
                echo '<li class="text-danger">'.$value.'</li>';
1015
            }
1016
            echo '</ul>';
1017
        } elseif (file_exists(api_get_path(CONFIGURATION_PATH).'configuration.php')) {
1018
            // Check wether a Chamilo configuration file already exists.
1019
            echo '<div class="alert alert-warning"><h4><center>';
1020
            echo get_lang('Warning !ExistingLMSInstallationDetected');
1021
            echo '</center></h4></div>';
1022
        }
1023
1024
        $deprecated = [
1025
            api_get_path(SYS_CODE_PATH).'exercice/',
1026
            api_get_path(SYS_CODE_PATH).'newscorm/',
1027
            api_get_path(SYS_PLUGIN_PATH).'ticket/',
1028
            api_get_path(SYS_PLUGIN_PATH).'skype/',
1029
        ];
1030
        $deprecatedToRemove = [];
1031
        foreach ($deprecated as $deprecatedDirectory) {
1032
            if (!is_dir($deprecatedDirectory)) {
1033
                continue;
1034
            }
1035
            $deprecatedToRemove[] = $deprecatedDirectory;
1036
        }
1037
1038
        if (count($deprecatedToRemove) > 0) {
1039
            ?>
1040
            <p class="text-danger"><?php echo get_lang('Warning !ForDeprecatedDirectoriesForUpgrade'); ?></p>
1041
            <ul>
1042
                <?php foreach ($deprecatedToRemove as $deprecatedDirectory) {
1043
                ?>
1044
                    <li class="text-danger"><?php echo $deprecatedDirectory; ?></li>
1045
                <?php
1046
            } ?>
1047
            </ul>
1048
            <?php
1049
        }
1050
1051
        // And now display the choice buttons (go back or install)?>
1052
        <p align="center" style="padding-top:15px">
1053
            <button
1054
                type="submit"
1055
                name="step1"
1056
                class="btn btn-default"
1057
                onclick="javascript: window.location='index.php'; return false;"
1058
                value="<?php echo get_lang('Previous'); ?>" >
1059
                <em class="fa fa-backward"> </em> <?php echo get_lang('Previous'); ?>
1060
            </button>
1061
            <button
1062
                type="submit" name="step2_install"
1063
                class="btn btn-success"
1064
                value="<?php echo get_lang("New installation"); ?>" <?php if ($error) {
1065
            echo 'disabled="disabled"';
1066
        } ?> >
1067
                <em class="fa fa-forward"> </em> <?php echo get_lang('New installation'); ?>
1068
            </button>
1069
            <input type="hidden" name="is_executable" id="is_executable" value="-" />
1070
            <button
1071
                type="submit"
1072
                class="btn btn-default" <?php echo !$error ?: 'disabled="disabled"'; ?>
1073
                name="step2_update_8"
1074
                value="Upgrade from Chamilo 1.11.x">
1075
                <em class="fa fa-forward" aria-hidden="true"></em>
1076
                <?php echo get_lang('Upgrade Chamilo LMS version'); ?>
1077
            </button>
1078
            </p>
1079
        <?php
1080
    }
1081
}
1082
1083
/**
1084
 * Displays the license (GNU GPL) as step 2, with
1085
 * - an "I accept" button named step3 to proceed to step 3;
1086
 * - a "Back" button named step1 to go back to the first step.
1087
 */
1088
function display_license_agreement()
1089
{
1090
    echo '<div class="RequirementHeading"><h2>'.display_step_sequence().get_lang('Licence').'</h2>';
1091
    echo '<p>'.get_lang('Chamilo is free software distributed under the GNU General Public licence (GPL).').'</p>';
1092
    echo '<p><a href="../../documentation/license.html" target="_blank">'.get_lang('Printable version').'</a></p>';
1093
    echo '</div>'; ?>
1094
    <div class="form-group">
1095
        <pre style="overflow: auto; height: 200px; margin-top: 5px;">
1096
            <?php echo api_htmlentities(@file_get_contents(api_get_path(SYMFONY_SYS_PATH).'documentation/license.txt')); ?>
1097
        </pre>
1098
    </div>
1099
    <div class="form-group form-check">
1100
        <input type="checkbox" name="accept" id="accept_licence" value="1">
1101
        <label for="accept_licence"><?php echo get_lang('I Accept'); ?></label>
1102
    </div>
1103
    <div class="row">
1104
        <div class="col-md-12">
1105
            <p class="alert alert-info"><?php echo get_lang('The images and media galleries of Chamilo use images from Nuvola, Crystal Clear and Tango icon galleries. Other images and media like diagrams and Flash animations are borrowed from Wikimedia and Ali Pakdel\'s and Denis Hoa\'s courses with their agreement and released under BY-SA Creative Commons license. You may find the license details at <a href="http://creativecommons.org/licenses/by-sa/3.0/">the CC website</a>, where a link to the full text of the license is provided at the bottom of the page.'); ?></p>
1106
        </div>
1107
    </div>
1108
1109
    <!-- Contact information form -->
1110
    <div class="section-parameters">
1111
        <a href="javascript://" class = "advanced_parameters" >
1112
        <span id="img_plus_and_minus">&nbsp;<i class="fa fa-eye" aria-hidden="true"></i>&nbsp;<?php echo get_lang('Contact information'); ?></span>
1113
        </a>
1114
    </div>
1115
1116
    <div id="id_contact_form" style="display:block">
1117
        <div class="normal-message"><?php echo get_lang('Contact informationDescription'); ?></div>
1118
        <div id="contact_registration">
1119
            <p><?php echo get_contact_registration_form(); ?></p><br />
1120
        </div>
1121
    </div>
1122
    <div class="text-center">
1123
    <button type="submit" class="btn btn-default" name="step1" value="&lt; <?php echo get_lang('Previous'); ?>" >
1124
        <em class="fa fa-backward"> </em> <?php echo get_lang('Previous'); ?>
1125
    </button>
1126
    <input type="hidden" name="is_executable" id="is_executable" value="-" />
1127
    <button type="submit" id="license-next" class="btn btn-success" name="step3" onclick="javascript: if(!document.getElementById('accept_licence').checked) { alert('<?php echo get_lang('You must accept the licence'); ?>');return false;}" value="<?php echo get_lang('Next'); ?> &gt;" >
1128
        <em class="fa fa-forward"> </em> <?php echo get_lang('Next'); ?>
1129
    </button>
1130
    </div>
1131
    <?php
1132
}
1133
1134
/**
1135
 * Get contact registration form.
1136
 */
1137
function get_contact_registration_form()
1138
{
1139
    return '
1140
    <div class="form-horizontal">
1141
        <div class="panel panel-default">
1142
        <div class="panel-body">
1143
        <div id="div_sent_information"></div>
1144
        <div class="form-group row">
1145
                <label class="col-sm-3">
1146
                <span class="form_required">*</span>'.get_lang('Name').'</label>
1147
                <div class="col-sm-9">
1148
                    <input id="person_name" class="form-control" type="text" name="person_name" size="30" />
1149
                </div>
1150
        </div>
1151
        <div class="form-group row">
1152
            <label class="col-sm-3">
1153
            <span class="form_required">*</span>'.get_lang('e-mail').'</label>
1154
            <div class="col-sm-9">
1155
            <input id="person_email" class="form-control" type="text" name="person_email" size="30" /></div>
1156
        </div>
1157
        <div class="form-group row">
1158
                <label class="col-sm-3">
1159
                <span class="form_required">*</span>'.get_lang('Your company\'s name').'</label>
1160
                <div class="col-sm-9">
1161
                <input id="company_name" class="form-control" type="text" name="company_name" size="30" /></div>
1162
        </div>
1163
        <div class="form-group row">
1164
            <label class="col-sm-3"><span class="form_required">*</span>'.get_lang('Your company\'s activity').'</label>
1165
            <div class="col-sm-9">
1166
                <select class="selectpicker show-tick" name="company_activity" id="company_activity" >
1167
                    <option value="">--- '.get_lang('Select one').' ---</option>
1168
                    <Option value="Advertising/Marketing/PR">Advertising/Marketing/PR</Option>
1169
                    <Option value="Agriculture/Forestry">Agriculture/Forestry</Option>
1170
                    <Option value="Architecture">Architecture</Option>
1171
                    <Option value="Banking/Finance">Banking/Finance</Option>
1172
                    <Option value="Biotech/Pharmaceuticals">Biotech/Pharmaceuticals</Option>
1173
                    <Option value="Business Equipment">Business Equipment</Option>
1174
                    <Option value="Business Services">Business Services</Option>
1175
                    <Option value="Construction">Construction</Option>
1176
                    <Option value="Consulting/Research">Consulting/Research</Option>
1177
                    <Option value="Education">Education</Option>
1178
                    <Option value="Engineering">Engineering</Option>
1179
                    <Option value="Environmental">Environmental</Option>
1180
                    <Option value="Government">Government</Option>
1181
                    <Option value="Healthcare">Health Care</Option>
1182
                    <Option value="Hospitality/Lodging/Travel">Hospitality/Lodging/Travel</Option>
1183
                    <Option value="Insurance">Insurance</Option>
1184
                    <Option value="Legal">Legal</Option><Option value="Manufacturing">Manufacturing</Option>
1185
                    <Option value="Media/Entertainment">Media/Entertainment</Option>
1186
                    <Option value="Mortgage">Mortgage</Option>
1187
                    <Option value="Non-Profit">Non-Profit</Option>
1188
                    <Option value="Real Estate">Real Estate</Option>
1189
                    <Option value="Restaurant">Restaurant</Option>
1190
                    <Option value="Retail">Retail</Option>
1191
                    <Option value="Shipping/Transportation">Shipping/Transportation</Option>
1192
                    <Option value="Technology">Technology</Option>
1193
                    <Option value="Telecommunications">Telecommunications</Option>
1194
                    <Option value="Other">Other</Option>
1195
                </select>
1196
            </div>
1197
        </div>
1198
1199
        <div class="form-group row">
1200
            <label class="col-sm-3"><span class="form_required">*</span>'.get_lang('Your job\'s description').'</label>
1201
            <div class="col-sm-9">
1202
                <select class="selectpicker show-tick" name="person_role" id="person_role" >
1203
                    <option value="">--- '.get_lang('Select one').' ---</option>
1204
                    <Option value="Administration">Administration</Option>
1205
                    <Option value="CEO/President/ Owner">CEO/President/ Owner</Option>
1206
                    <Option value="CFO">CFO</Option><Option value="CIO/CTO">CIO/CTO</Option>
1207
                    <Option value="Consultant">Consultant</Option>
1208
                    <Option value="Customer Service">Customer Service</Option>
1209
                    <Option value="Engineer/Programmer">Engineer/Programmer</Option>
1210
                    <Option value="Facilities/Operations">Facilities/Operations</Option>
1211
                    <Option value="Finance/ Accounting Manager">Finance/ Accounting Manager</Option>
1212
                    <Option value="Finance/ Accounting Staff">Finance/ Accounting Staff</Option>
1213
                    <Option value="General Manager">General Manager</Option>
1214
                    <Option value="Human Resources">Human Resources</Option>
1215
                    <Option value="IS/IT Management">IS/IT Management</Option>
1216
                    <Option value="IS/ IT Staff">IS/ IT Staff</Option>
1217
                    <Option value="Marketing Manager">Marketing Manager</Option>
1218
                    <Option value="Marketing Staff">Marketing Staff</Option>
1219
                    <Option value="Partner/Principal">Partner/Principal</Option>
1220
                    <Option value="Purchasing Manager">Purchasing Manager</Option>
1221
                    <Option value="Sales/ Business Dev. Manager">Sales/ Business Dev. Manager</Option>
1222
                    <Option value="Sales/ Business Dev.">Sales/ Business Dev.</Option>
1223
                    <Option value="Vice President/Senior Manager">Vice President/Senior Manager</Option>
1224
                    <Option value="Other">Other</Option>
1225
                </select>
1226
            </div>
1227
        </div>
1228
1229
        <div class="form-group row">
1230
            <label class="col-sm-3">
1231
                <span class="form_required">*</span>'.get_lang('Your company\'s home country').'</label>
1232
            <div class="col-sm-9">'.get_countries_list_from_array(true).'</div>
1233
        </div>
1234
        <div class="form-group row">
1235
            <label class="col-sm-3">'.get_lang('Company city').'</label>
1236
            <div class="col-sm-9">
1237
                    <input type="text" class="form-control" id="company_city" name="company_city" size="30" />
1238
            </div>
1239
        </div>
1240
        <div class="form-group row">
1241
            <label class="col-sm-3">'.get_lang('Preferred contact language').'</label>
1242
            <div class="col-sm-9">
1243
                <select class="selectpicker show-tick" id="language" name="language">
1244
                    <option value="bulgarian">Bulgarian</option>
1245
                    <option value="indonesian">Bahasa Indonesia</option>
1246
                    <option value="bosnian">Bosanski</option>
1247
                    <option value="german">Deutsch</option>
1248
                    <option selected="selected" value="english">English</option>
1249
                    <option value="spanish">Spanish</option>
1250
                    <option value="french">Français</option>
1251
                    <option value="italian">Italian</option>
1252
                    <option value="hungarian">Magyar</option>
1253
                    <option value="dutch">Nederlands</option>
1254
                    <option value="brazilian">Português do Brasil</option>
1255
                    <option value="portuguese">Português europeu</option>
1256
                    <option value="slovenian">Slovenčina</option>
1257
                </select>
1258
            </div>
1259
        </div>
1260
1261
        <div class="form-group row">
1262
            <label class="col-sm-3">'.
1263
                get_lang('Do you have the power to take financial decisions on behalf of your company?').'</label>
1264
            <div class="col-sm-9">
1265
                <div class="radio">
1266
                    <label>
1267
                        <input type="radio" name="financial_decision" id="financial_decision1" value="1" checked /> '.
1268
                        get_lang('Yes').'
1269
                    </label>
1270
                </div>
1271
                <div class="radio">
1272
                    <label>
1273
                        <input type="radio" name="financial_decision" id="financial_decision2" value="0" /> '.
1274
                        get_lang('No').'
1275
                    </label>
1276
                </div>
1277
            </div>
1278
        </div>
1279
        <div class="clear"></div>
1280
        <div class="form-group row">
1281
            <div class="col-sm-3">&nbsp;</div>
1282
            <div class="col-sm-9">
1283
            <button
1284
                type="button"
1285
                class="btn btn-default"
1286
                onclick="javascript:send_contact_information();"
1287
                value="'.get_lang('Send information').'" >
1288
                <em class="fa fa-floppy-o"></em> '.get_lang('Send information').'
1289
            </button>
1290
            <span id="loader-button"></span></div>
1291
        </div>
1292
        <div class="form-group row">
1293
            <div class="col-sm-3">&nbsp;</div>
1294
            <div class="col-sm-9">
1295
                <span class="form_required">*</span><small>'.get_lang('Mandatory field').'</small>
1296
            </div>
1297
        </div></div></div>
1298
        </div>';
1299
}
1300
1301
/**
1302
 * Displays a parameter in a table row.
1303
 * Used by the display_database_settings_form function.
1304
 *
1305
 * @param   string  Type of install
1306
 * @param   string  Name of parameter
1307
 * @param   string  Field name (in the HTML form)
1308
 * @param   string  Field value
1309
 * @param   string  Extra notice (to show on the right side)
1310
 * @param   bool Whether to display in update mode
1311
 * @param   string  Additional attribute for the <tr> element
1312
 */
1313
function displayDatabaseParameter(
1314
    $installType,
1315
    $parameterName,
1316
    $formFieldName,
1317
    $parameterValue,
1318
    $extra_notice,
1319
    $displayWhenUpdate = true
1320
) {
1321
    echo "<dt class='col-sm-4'>$parameterName</dt>";
1322
    echo '<dd class="col-sm-8">';
1323
    if (INSTALL_TYPE_UPDATE == $installType && $displayWhenUpdate) {
1324
        echo '<input
1325
                type="hidden"
1326
                name="'.$formFieldName.'"
1327
                id="'.$formFieldName.'"
1328
                value="'.api_htmlentities($parameterValue).'" />'.$parameterValue;
1329
    } else {
1330
        $inputType = 'dbPassForm' === $formFieldName ? 'password' : 'text';
1331
        //Slightly limit the length of the database prefix to avoid having to cut down the databases names later on
1332
        $maxLength = 'dbPrefixForm' === $formFieldName ? '15' : MAX_FORM_FIELD_LENGTH;
1333
        if (INSTALL_TYPE_UPDATE == $installType) {
1334
            echo '<input
1335
                type="hidden" name="'.$formFieldName.'" id="'.$formFieldName.'"
1336
                value="'.api_htmlentities($parameterValue).'" />';
1337
            echo api_htmlentities($parameterValue);
1338
        } else {
1339
            echo '<input
1340
                        type="'.$inputType.'"
1341
                        class="form-control"
1342
                        size="'.DATABASE_FORM_FIELD_DISPLAY_LENGTH.'"
1343
                        maxlength="'.$maxLength.'"
1344
                        name="'.$formFieldName.'"
1345
                        id="'.$formFieldName.'"
1346
                        value="'.api_htmlentities($parameterValue).'" />
1347
                    '.$extra_notice.'
1348
                  ';
1349
        }
1350
        echo '</dd>';
1351
    }
1352
}
1353
1354
/**
1355
 * Displays step 3 - a form where the user can enter the installation settings
1356
 * regarding the databases - login and password, names, prefixes, single
1357
 * or multiple databases, tracking or not...
1358
 *
1359
 * @param string $installType
1360
 * @param string $dbHostForm
1361
 * @param string $dbUsernameForm
1362
 * @param string $dbPassForm
1363
 * @param string $dbNameForm
1364
 * @param int    $dbPortForm
1365
 * @param string $installationProfile
1366
 */
1367
function display_database_settings_form(
1368
    $installType,
1369
    $dbHostForm,
1370
    $dbUsernameForm,
1371
    $dbPassForm,
1372
    $dbNameForm,
1373
    $dbPortForm = 3306,
1374
    $installationProfile = ''
1375
) {
1376
    if ('update' === $installType) {
1377
        $dbHostForm = get_config_param('db_host');
1378
        $dbUsernameForm = get_config_param('db_user');
1379
        $dbPassForm = get_config_param('db_password');
1380
        $dbNameForm = get_config_param('main_database');
1381
        $dbPortForm = get_config_param('db_port');
1382
1383
        echo '<div class="RequirementHeading"><h2>'.display_step_sequence().get_lang('Database settings').'</h2></div>';
1384
        echo '<div class="RequirementContent">';
1385
        echo get_lang('The upgrade script will recover and update the Chamilo database(s). In order to do this, this script will use the databases and settings defined below. Because our software runs on a wide range of systems and because all of them might not have been tested, we strongly recommend you do a full backup of your databases before you proceed with the upgrade!');
1386
        echo '</div>';
1387
    } else {
1388
        echo '<div class="RequirementHeading"><h2>'.display_step_sequence().get_lang('Database settings').'</h2></div>';
1389
        echo '<div class="RequirementContent">';
1390
        echo get_lang('The install script will create (or use) the Chamilo database using the database name given here. Please make sure the user you give has the right to create the database by the name given here. If a database with this name exists, it will be overwritten. Please do not use the root user as the Chamilo database user. This can lead to serious security issues.');
1391
        echo '</div>';
1392
    }
1393
1394
    echo '
1395
        <div class="card">
1396
            <div class="card-body">
1397
            <dl class="row">
1398
                <dt class="col-sm-4">'.get_lang('Database Host').'</dt>';
1399
    if ('update' === $installType) {
1400
       echo '<dd class="col-sm-8">
1401
                <input
1402
                    type="hidden"
1403
                    name="dbHostForm" value="'.htmlentities($dbHostForm).'" />'.$dbHostForm.'
1404
                </dd>';
1405
    } else {
1406
        echo '<dd class="col-sm-8">
1407
                <input
1408
                    type="text"
1409
                    class="form-control"
1410
                    size="25"
1411
                    maxlength="50" name="dbHostForm" value="'.htmlentities($dbHostForm).'" />
1412
                    '.get_lang('ex.').'localhost
1413
            </dd>';
1414
    }
1415
1416
    echo '<dt class="col-sm-4">'.get_lang('Port').'</dt>';
1417
    if ('update' === $installType) {
1418
    echo '<dd class="col-sm-8">
1419
            <input
1420
                type="hidden"
1421
                name="dbPortForm" value="'.htmlentities($dbPortForm).'" />'.$dbPortForm.'
1422
            </dd>';
1423
    } else {
1424
        echo '
1425
        <dd class="col-sm-8">
1426
            <input
1427
            type="text"
1428
            class="form-control"
1429
            size="25"
1430
            maxlength="50" name="dbPortForm" value="'.htmlentities($dbPortForm).'" />
1431
            '.get_lang('ex.').' 3306
1432
        </dd>';
1433
    }
1434
    //database user username
1435
    $example_login = get_lang('ex.').' root';
1436
    displayDatabaseParameter(
1437
        $installType,
1438
        get_lang('Database Login'),
1439
        'dbUsernameForm',
1440
        $dbUsernameForm,
1441
        $example_login
1442
    );
1443
1444
    //database user password
1445
    $example_password = get_lang('ex.').' '.api_generate_password();
1446
    displayDatabaseParameter($installType, get_lang('Database Password'), 'dbPassForm', $dbPassForm, $example_password);
1447
    // Database Name fix replace weird chars
1448
    if (INSTALL_TYPE_UPDATE != $installType) {
1449
        $dbNameForm = str_replace(['-', '*', '$', ' ', '.'], '', $dbNameForm);
1450
    }
1451
    displayDatabaseParameter(
1452
        $installType,
1453
        get_lang('Database name'),
1454
        'dbNameForm',
1455
        $dbNameForm,
1456
        '&nbsp;',
1457
        null,
1458
        'id="optional_param1"'
1459
    );
1460
    echo '</dl></div></div>';
1461
    if (INSTALL_TYPE_UPDATE != $installType) { ?>
1462
        <button type="submit" class="btn btn-primary" name="step3" value="step3">
1463
            <em class="fa fa-refresh"> </em>
1464
            <?php echo get_lang('Check database connection'); ?>
1465
        </button>
1466
        <?php
1467
    }
1468
1469
    $database_exists_text = '';
1470
    $manager = null;
1471
    try {
1472
        if ('update' === $installType) {
1473
            /** @var \Database $manager */
1474
            $manager = connectToDatabase(
1475
                $dbHostForm,
1476
                $dbUsernameForm,
1477
                $dbPassForm,
1478
                $dbNameForm,
1479
                $dbPortForm
1480
            );
1481
1482
            $connection = $manager->getConnection();
1483
            $connection->connect();
1484
            $schemaManager = $connection->getSchemaManager();
1485
1486
            // Test create/alter/drop table
1487
            $table = 'zXxTESTxX_'.mt_rand(0, 1000);
1488
            $sql = "CREATE TABLE $table (id INT AUTO_INCREMENT NOT NULL, name varchar(255), PRIMARY KEY(id))";
1489
            $connection->executeQuery($sql);
1490
            $tableCreationWorks = false;
1491
            $tableDropWorks = false;
1492
            if ($schemaManager->tablesExist($table)) {
1493
                $sql = "ALTER TABLE $table ADD COLUMN name2 varchar(140) ";
1494
                $connection->executeQuery($sql);
1495
                $schemaManager->dropTable($table);
1496
                $tableDropWorks = false === $schemaManager->tablesExist($table);
1497
            }
1498
        } else {
1499
            $manager = connectToDatabase(
1500
                $dbHostForm,
1501
                $dbUsernameForm,
1502
                $dbPassForm,
1503
                null,
1504
                $dbPortForm
1505
            );
1506
1507
            $schemaManager = $manager->getConnection()->getSchemaManager();
1508
            $databases = $schemaManager->listDatabases();
1509
            if (in_array($dbNameForm, $databases)) {
1510
                $database_exists_text = '<div class="alert alert-warning">'.
1511
                get_lang('A database with the same name <b>already exists</b>.').'</div>';
1512
            }
1513
        }
1514
    } catch (Exception $e) {
1515
        $database_exists_text = $e->getMessage();
1516
        $manager = false;
1517
    }
1518
1519
    if ($manager && $manager->getConnection()->isConnected()) {
1520
        echo $database_exists_text; ?>
1521
        <div id="db_status" class="alert alert-success">
1522
            Database host: <strong><?php echo $manager->getConnection()->getHost(); ?></strong><br/>
1523
            Database port: <strong><?php echo $manager->getConnection()->getPort(); ?></strong><br/>
1524
            Database driver: <strong><?php echo $manager->getConnection()->getDriver()->getName(); ?></strong><br/>
1525
            <?php
1526
                if ('update' === $installType) {
1527
                    echo get_lang('CreateTableWorks').' <strong>Ok</strong>';
1528
                    echo '<br/ >';
1529
                    echo get_lang('AlterTableWorks').' <strong>Ok</strong>';
1530
                    echo '<br/ >';
1531
                    echo get_lang('DropColumnWorks').' <strong>Ok</strong>';
1532
                } ?>
1533
        </div>
1534
    <?php } else { ?>
1535
        <div id="db_status" class="alert alert-danger">
1536
            <p>
1537
                <?php echo get_lang('The database connection has failed. This is generally due to the wrong user, the wrong password or the wrong database prefix being set above. Please review these settings and try again.'); ?>
1538
            </p>
1539
            <code><?php echo $database_exists_text; ?></code>
1540
        </div>
1541
    <?php } ?>
1542
1543
   <div class="btn-group" role="group">
1544
       <button type="submit" name="step2"
1545
               class="btn btn-secondary float-right" value="&lt; <?php echo get_lang('Previous'); ?>" >
1546
           <em class="fa fa-backward"> </em> <?php echo get_lang('Previous'); ?>
1547
       </button>
1548
       <input type="hidden" name="is_executable" id="is_executable" value="-" />
1549
       <?php if ($manager) {
1550
                    ?>
1551
           <button type="submit" class="btn btn-success" name="step4" value="<?php echo get_lang('Next'); ?> &gt;" >
1552
               <em class="fa fa-forward"> </em> <?php echo get_lang('Next'); ?>
1553
           </button>
1554
       <?php
1555
                } else {
1556
                    ?>
1557
           <button
1558
                   disabled="disabled"
1559
                   type="submit" class="btn btn-success disabled" name="step4" value="<?php echo get_lang('Next'); ?> &gt;" >
1560
               <em class="fa fa-forward"> </em> <?php echo get_lang('Next'); ?>
1561
           </button>
1562
       <?php
1563
                } ?>
1564
   </div>
1565
    <?php
1566
}
1567
1568
/**
1569
 * Displays a parameter in a table row.
1570
 * Used by the display_configuration_settings_form function.
1571
 *
1572
 * @param string $installType
1573
 * @param string $parameterName
1574
 * @param string $formFieldName
1575
 * @param string $parameterValue
1576
 * @param string $displayWhenUpdate
1577
 *
1578
 * @return string
1579
 */
1580
function display_configuration_parameter(
1581
    $installType,
1582
    $parameterName,
1583
    $formFieldName,
1584
    $parameterValue,
1585
    $displayWhenUpdate = 'true'
1586
) {
1587
    $html = '<div class="form-group row">';
1588
    $html .= '<label class="col-sm-6 control-label">'.$parameterName.'</label>';
1589
    if (INSTALL_TYPE_UPDATE == $installType && $displayWhenUpdate) {
1590
        $html .= '<input
1591
            type="hidden"
1592
            name="'.$formFieldName.'"
1593
            value="'.api_htmlentities($parameterValue, ENT_QUOTES).'" />'.$parameterValue;
1594
    } else {
1595
        $html .= '<div class="col-sm-6">
1596
                    <input
1597
                        class="form-control"
1598
                        type="text"
1599
                        size="'.FORM_FIELD_DISPLAY_LENGTH.'"
1600
                        maxlength="'.MAX_FORM_FIELD_LENGTH.'"
1601
                        name="'.$formFieldName.'"
1602
                        value="'.api_htmlentities($parameterValue, ENT_QUOTES).'" />
1603
                    '."</div>";
1604
    }
1605
    $html .= "</div>";
1606
1607
    return $html;
1608
}
1609
1610
/**
1611
 * Displays step 4 of the installation - configuration settings about Chamilo itself.
1612
 *
1613
 * @param string $installType
1614
 * @param string $urlForm
1615
 * @param string $languageForm
1616
 * @param string $emailForm
1617
 * @param string $adminFirstName
1618
 * @param string $adminLastName
1619
 * @param string $adminPhoneForm
1620
 * @param string $campusForm
1621
 * @param string $institutionForm
1622
 * @param string $institutionUrlForm
1623
 * @param string $encryptPassForm
1624
 * @param bool   $allowSelfReg
1625
 * @param bool   $allowSelfRegProf
1626
 * @param string $loginForm
1627
 * @param string $passForm
1628
 */
1629
function display_configuration_settings_form(
1630
    $installType,
1631
    $urlForm,
1632
    $languageForm,
1633
    $emailForm,
1634
    $adminFirstName,
1635
    $adminLastName,
1636
    $adminPhoneForm,
1637
    $campusForm,
1638
    $institutionForm,
1639
    $institutionUrlForm,
1640
    $encryptPassForm,
1641
    $allowSelfReg,
1642
    $allowSelfRegProf,
1643
    $loginForm,
1644
    $passForm
1645
) {
1646
    if ('update' !== $installType && empty($languageForm)) {
1647
        $languageForm = $_SESSION['install_language'];
1648
    }
1649
    echo '<div class="RequirementHeading">';
1650
    echo "<h2>".display_step_sequence().get_lang("ConfigurationSettings")."</h2>";
1651
    echo '</div>';
1652
1653
    // Parameter 1: administrator's login
1654
    $html = '';
1655
    $html .= display_configuration_parameter(
1656
        $installType,
1657
        get_lang('Administrator login'),
1658
        'loginForm',
1659
        $loginForm,
1660
        'update' == $installType
1661
    );
1662
1663
    // Parameter 2: administrator's password
1664
    if ('update' !== $installType) {
1665
        $html .= display_configuration_parameter(
1666
            $installType,
1667
            get_lang('Administrator password (<font color="red">you may want to change this</font>)'),
1668
            'passForm',
1669
            $passForm,
1670
            false
1671
        );
1672
    }
1673
1674
    // Parameters 3 and 4: administrator's names
1675
    $html .= display_configuration_parameter(
1676
        $installType,
1677
        get_lang('Administrator first name'),
1678
        'adminFirstName',
1679
        $adminFirstName
1680
    );
1681
    $html .= display_configuration_parameter(
1682
        $installType,
1683
        get_lang('Administrator last name'),
1684
        'adminLastName',
1685
        $adminLastName
1686
    );
1687
1688
    // Parameter 3: administrator's email
1689
    $html .= display_configuration_parameter($installType, get_lang('Admin-mail'), 'emailForm', $emailForm);
1690
1691
    // Parameter 6: administrator's telephone
1692
    $html .= display_configuration_parameter(
1693
        $installType,
1694
        get_lang('Administrator telephone'),
1695
        'adminPhoneForm',
1696
        $adminPhoneForm
1697
    );
1698
    echo Display::panel($html, get_lang('Administrator'));
1699
1700
    // First parameter: language.
1701
    $html = '<div class="form-group row">';
1702
    $html .= '<label class="col-sm-6 control-label">'.get_lang('Main language')."</label>";
1703
    if ('update' === $installType) {
1704
        $html .= '<input
1705
            type="hidden"
1706
            name="languageForm" value="'.api_htmlentities($languageForm, ENT_QUOTES).'" />'.$languageForm;
1707
    } else {
1708
        $html .= '<div class="col-sm-6">';
1709
        $html .= display_language_selection_box('languageForm', $languageForm);
1710
        $html .= '</div>';
1711
    }
1712
    $html .='</div>';
1713
1714
    // Second parameter: Chamilo URL
1715
    $html .= '<div class="form-group row">';
1716
    $html .= '<label class="col-sm-6 control-label">'.get_lang('Chamilo URL').get_lang('Required field').'</label>';
1717
1718
    if ('update' === $installType) {
1719
        $html .= api_htmlentities($urlForm, ENT_QUOTES)."\n";
1720
    } else {
1721
        $html .= '<div class="col-sm-6">';
1722
        $html .= '<input
1723
            class="form-control"
1724
            type="text" size="40"
1725
            maxlength="100" name="urlForm" value="'.api_htmlentities($urlForm, ENT_QUOTES).'" />';
1726
        $html .= '</div>';
1727
    }
1728
    $html .= '</div>';
1729
1730
    // Parameter 9: campus name
1731
    $html .= display_configuration_parameter(
1732
        $installType,
1733
        get_lang('Your portal name'),
1734
        'campusForm',
1735
        $campusForm
1736
    );
1737
1738
    // Parameter 10: institute (short) name
1739
    $html .= display_configuration_parameter(
1740
        $installType,
1741
        get_lang('Your company short name'),
1742
        'institutionForm',
1743
        $institutionForm
1744
    );
1745
1746
    // Parameter 11: institute (short) name
1747
    $html .= display_configuration_parameter(
1748
        $installType,
1749
        get_lang('URL of this company'),
1750
        'institutionUrlForm',
1751
        $institutionUrlForm
1752
    );
1753
1754
    $html .= '<div class="form-group row">
1755
            <label class="col-sm-6 control-label">'.get_lang("Encryption method").'</label>
1756
        <div class="col-sm-6">';
1757
    if ('update' === $installType) {
1758
        $html .= '<input type="hidden" name="encryptPassForm" value="'.$encryptPassForm.'" />'.$encryptPassForm;
1759
    } else {
1760
        $html .= '<div class="checkbox">
1761
                    <label>
1762
                        <input
1763
                            type="radio"
1764
                            name="encryptPassForm"
1765
                            value="bcrypt"
1766
                            id="encryptPass1" '.('bcrypt' == $encryptPassForm ? 'checked="checked" ' : '').'/> bcrypt
1767
                    </label>';
1768
1769
        $html .= '<label>
1770
                        <input
1771
                            type="radio"
1772
                            name="encryptPassForm"
1773
                            value="sha1"
1774
                            id="encryptPass1" '.('sha1' == $encryptPassForm ? 'checked="checked" ' : '').'/> sha1
1775
                    </label>';
1776
1777
        $html .= '<label>
1778
                        <input type="radio"
1779
                            name="encryptPassForm"
1780
                            value="md5"
1781
                            id="encryptPass0" '.('md5' == $encryptPassForm ? 'checked="checked" ' : '').'/> md5
1782
                    </label>';
1783
1784
        $html .= '<label>
1785
                        <input
1786
                            type="radio"
1787
                            name="encryptPassForm"
1788
                            value="none"
1789
                            id="encryptPass2" '.
1790
                            ('none' == $encryptPassForm ? 'checked="checked" ' : '').'/>'.get_lang('none').'
1791
                    </label>';
1792
        $html .= '</div>';
1793
    }
1794
    $html .= '</div></div>';
1795
1796
    $html .= '<div class="form-group row">
1797
            <label class="col-sm-6 control-label">'.get_lang('Allow self-registration').'</label>
1798
            <div class="col-sm-6">';
1799
    if ('update' === $installType) {
1800
        if ('true' == $allowSelfReg) {
1801
            $label = get_lang('Yes');
1802
        } elseif ('false' == $allowSelfReg) {
1803
            $label = get_lang('No');
1804
        } else {
1805
            $label = get_lang('After approval');
1806
        }
1807
        $html .= '<input type="hidden" name="allowSelfReg" value="'.$allowSelfReg.'" />'.$label;
1808
    } else {
1809
        $html .= '<div class="control-group">';
1810
        $html .= '<label class="checkbox-inline">
1811
                    <input type="radio"
1812
                        name="allowSelfReg" value="true"
1813
                        id="allowSelfReg1" '.('true' == $allowSelfReg ? 'checked="checked" ' : '').' /> '.get_lang('Yes').'
1814
                  </label>';
1815
        $html .= '<label class="checkbox-inline">
1816
                    <input
1817
                        type="radio"
1818
                        name="allowSelfReg"
1819
                        value="false"
1820
                        id="allowSelfReg0" '.('false' == $allowSelfReg ? '' : 'checked="checked" ').' /> '.get_lang('No').'
1821
                </label>';
1822
        $html .= '<label class="checkbox-inline">
1823
                    <input
1824
                        type="radio"
1825
                        name="allowSelfReg"
1826
                        value="approval"
1827
                        id="allowSelfReg2" '.('approval' == $allowSelfReg ? '' : 'checked="checked" ').' /> '.get_lang('After approval').'
1828
                </label>';
1829
        $html .= '</div>';
1830
    }
1831
    $html .= '</div>';
1832
    $html .= '</div>';
1833
1834
    $html .= '<div class="form-group row">';
1835
    $html .= '<label class="col-sm-6 control-label">'.get_lang('Allow self-registrationProf').'</label>
1836
                <div class="col-sm-6">';
1837
    if ('update' === $installType) {
1838
        if ('true' === $allowSelfRegProf) {
1839
            $label = get_lang('Yes');
1840
        } else {
1841
            $label = get_lang('No');
1842
        }
1843
        $html .= '<input type="hidden" name="allowSelfRegProf" value="'.$allowSelfRegProf.'" />'.$label;
1844
    } else {
1845
        $html .= '<div class="control-group">
1846
                <label class="checkbox-inline">
1847
                    <input
1848
                        type="radio"
1849
                        name="allowSelfRegProf" value="1"
1850
                        id="allowSelfRegProf1" '.($allowSelfRegProf ? 'checked="checked" ' : '').'/>
1851
                '.get_lang('Yes').'
1852
                </label>';
1853
        $html .= '<label class="checkbox-inline">
1854
                    <input
1855
                        type="radio" name="allowSelfRegProf" value="0"
1856
                        id="allowSelfRegProf0" '.($allowSelfRegProf ? '' : 'checked="checked" ').' />
1857
                   '.get_lang('No').'
1858
                </label>';
1859
        $html .= '</div>';
1860
    }
1861
    $html .= '</div>
1862
    </div>';
1863
    echo Display::panel($html, get_lang('Portal'));
1864
    ?>
1865
    <div class='btn-group'>
1866
        <button
1867
            type="submit"
1868
            class="btn btn-secondary pull-right"
1869
            name="step3" value="&lt; <?php echo get_lang('Previous'); ?>" >
1870
                <em class="fa fa-backward"> </em> <?php echo get_lang('Previous'); ?>
1871
        </button>
1872
        <input type="hidden" name="is_executable" id="is_executable" value="-" />
1873
        <button class="btn btn-success" type="submit" name="step5">
1874
            <em class="fa fa-forward"> </em> <?php echo get_lang('Next'); ?>
1875
        </button>
1876
    </div>
1877
    <?php
1878
}
1879
1880
/**
1881
 * After installation is completed (step 6), this message is displayed.
1882
 */
1883
function display_after_install_message()
1884
{
1885
    $container = Container::$container;
1886
    $trans = $container->get('translator');
1887
    $html = '<div class="RequirementContent">'.
1888
    $trans->trans(
1889
        'When you enter your portal for the first time, the best way to understand it is to create a course with the \'Create course\' link in the menu and play around a little.').'</div>';
1890
    $html .= '<div class="alert alert-warning">';
1891
    $html .= '<strong>'.$trans->trans('Security advice').'</strong>';
1892
    $html .= ': ';
1893
    $html .= sprintf($trans->trans(
1894
        'To protect your site, make the whole %s directory read-only (chmod -R 0555 on Linux) and delete the %s directory.'), 'var/config/', 'main/install/');
1895
    $html .= '</div></form>
1896
    <br />
1897
    <a class="btn btn-success btn-block" href="../../">
1898
        '.$trans->trans('Go to your newly created portal.').'
1899
    </a>';
1900
1901
    return $html;
1902
}
1903
1904
/**
1905
 * This function return countries list from array (hardcoded).
1906
 *
1907
 * @param bool $combo (Optional) True for returning countries list with select html
1908
 *
1909
 * @return array|string countries list
1910
 */
1911
function get_countries_list_from_array($combo = false)
1912
{
1913
    $a_countries = [
1914
        "Afghanistan", "Albania", "Algeria", "Andorra", "Angola", "Antigua and Barbuda", "Argentina", "Armenia", "Australia", "Austria", "Azerbaijan",
1915
        "Bahamas", "Bahrain", "Bangladesh", "Barbados", "Belarus", "Belgium", "Belize", "Benin", "Bhutan", "Bolivia", "Bosnia and Herzegovina", "Botswana", "Brazil", "Brunei", "Bulgaria", "Burkina Faso", "Burundi",
1916
        "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",
1917
        "Denmark", "Djibouti", "Dominica", "Dominican Republic",
1918
        "East Timor (Timor Timur)", "Ecuador", "Egypt", "El Salvador", "Equatorial Guinea", "Eritrea", "Estonia", "Ethiopia",
1919
        "Fiji", "Finland", "France",
1920
        "Gabon", "Gambia, The", "Georgia", "Germany", "Ghana", "Greece", "Grenada", "Guatemala", "Guinea", "Guinea-Bissau", "Guyana",
1921
        "Haiti", "Honduras", "Hungary",
1922
        "Iceland", "India", "Indonesia", "Iran", "Iraq", "Ireland", "Israel", "Italy",
1923
        "Jamaica", "Japan", "Jordan",
1924
        "Kazakhstan", "Kenya", "Kiribati", "Korea, North", "Korea, South", "Kuwait", "Kyrgyzstan",
1925
        "Laos", "Latvia", "Lebanon", "Lesotho", "Liberia", "Libya", "Liechtenstein", "Lithuania", "Luxembourg",
1926
        "Macedonia", "Madagascar", "Malawi", "Malaysia", "Maldives", "Mali", "Malta", "Marshall Islands", "Mauritania", "Mauritius", "Mexico", "Micronesia", "Moldova", "Monaco", "Mongolia", "Morocco", "Mozambique", "Myanmar",
1927
        "Namibia", "Nauru", "Nepa", "Netherlands", "New Zealand", "Nicaragua", "Niger", "Nigeria", "Norway",
1928
        "Oman",
1929
        "Pakistan", "Palau", "Panama", "Papua New Guinea", "Paraguay", "Peru", "Philippines", "Poland", "Portugal",
1930
        "Qatar",
1931
        "Romania", "Russia", "Rwanda",
1932
        "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",
1933
        "Taiwan", "Tajikistan", "Tanzania", "Thailand", "Togo", "Tonga", "Trinidad and Tobago", "Tunisia", "Turkey", "Turkmenistan", "Tuvalu",
1934
        "Uganda", "Ukraine", "United Arab Emirates", "United Kingdom", "United States", "Uruguay", "Uzbekistan",
1935
        "Vanuatu", "Vatican City", "Venezuela", "Vietnam",
1936
        "Yemen",
1937
        "Zambia", "Zimbabwe",
1938
    ];
1939
    if ($combo) {
1940
        $country_select = '<select class="selectpicker show-tick" id="country" name="country">';
1941
        $country_select .= '<option value="">--- '.get_lang('Select one').' ---</option>';
1942
        foreach ($a_countries as $country) {
1943
            $country_select .= '<option value="'.$country.'">'.$country.'</option>';
1944
        }
1945
        $country_select .= '</select>';
1946
1947
        return $country_select;
1948
    }
1949
1950
    return $a_countries;
1951
}
1952
1953
/**
1954
 * Lock settings that can't be changed in other portals.
1955
 */
1956
function lockSettings()
1957
{
1958
    $settings = api_get_locked_settings();
1959
    $table = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
1960
    foreach ($settings as $setting) {
1961
        $sql = "UPDATE $table SET access_url_locked = 1 WHERE variable  = '$setting'";
1962
        Database::query($sql);
1963
    }
1964
}
1965
1966
/**
1967
 * Update dir values.
1968
 */
1969
function updateDirAndFilesPermissions()
1970
{
1971
    $table = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
1972
    $permissions_for_new_directories = isset($_SESSION['permissions_for_new_directories']) ? $_SESSION['permissions_for_new_directories'] : 0770;
1973
    $permissions_for_new_files = isset($_SESSION['permissions_for_new_files']) ? $_SESSION['permissions_for_new_files'] : 0660;
1974
    // use decoct() to store as string
1975
    Database::update(
1976
        $table,
1977
        ['selected_value' => '0'.decoct($permissions_for_new_directories)],
1978
        ['variable = ?' => 'permissions_for_new_directories']
1979
    );
1980
1981
    Database::update(
1982
        $table,
1983
        ['selected_value' => '0'.decoct($permissions_for_new_files)],
1984
        ['variable = ?' => 'permissions_for_new_files']
1985
    );
1986
1987
    if (isset($_SESSION['permissions_for_new_directories'])) {
1988
        unset($_SESSION['permissions_for_new_directories']);
1989
    }
1990
1991
    if (isset($_SESSION['permissions_for_new_files'])) {
1992
        unset($_SESSION['permissions_for_new_files']);
1993
    }
1994
}
1995
1996
/**
1997
 * @param $current_value
1998
 * @param $wanted_value
1999
 *
2000
 * @return string
2001
 */
2002
function compare_setting_values($current_value, $wanted_value)
2003
{
2004
    $current_value_string = $current_value;
2005
    $current_value = (float) $current_value;
2006
    $wanted_value = (float) $wanted_value;
2007
2008
    if ($current_value >= $wanted_value) {
2009
        return Display::label($current_value_string, 'success');
2010
    }
2011
2012
    return Display::label($current_value_string, 'important');
2013
}
2014
2015
/**
2016
 * Save settings values.
2017
 *
2018
 * @param string $organizationName
2019
 * @param string $organizationUrl
2020
 * @param string $siteName
2021
 * @param string $adminEmail
2022
 * @param string $adminLastName
2023
 * @param string $adminFirstName
2024
 * @param string $language
2025
 * @param string $allowRegistration
2026
 * @param string $allowTeacherSelfRegistration
2027
 * @param string $installationProfile          The name of an installation profile file in main/install/profiles/
2028
 */
2029
function installSettings(
2030
    $organizationName,
2031
    $organizationUrl,
2032
    $siteName,
2033
    $adminEmail,
2034
    $adminLastName,
2035
    $adminFirstName,
2036
    $language,
2037
    $allowRegistration,
2038
    $allowTeacherSelfRegistration,
2039
    $installationProfile = ''
2040
) {
2041
    error_log('installSettings');
2042
    $allowTeacherSelfRegistration = $allowTeacherSelfRegistration ? 'true' : 'false';
2043
2044
    $settings = [
2045
        'institution' => $organizationName,
2046
        'institution_url' => $organizationUrl,
2047
        'site_name' => $siteName,
2048
        'administrator_email' => $adminEmail,
2049
        'administrator_surname' => $adminLastName,
2050
        'administrator_name' => $adminFirstName,
2051
        'platform_language' => $language,
2052
        'allow_registration' => $allowRegistration,
2053
        'allow_registration_as_teacher' => $allowTeacherSelfRegistration,
2054
    ];
2055
2056
    foreach ($settings as $variable => $value) {
2057
        $sql = "UPDATE settings_current
2058
                SET selected_value = '$value'
2059
                WHERE variable = '$variable'";
2060
        Database::query($sql);
2061
    }
2062
    installProfileSettings($installationProfile);
2063
}
2064
2065
/**
2066
 * Executes DB changes based in the classes defined in
2067
 * /src/CoreBundle/Migrations/Schema/V200/*.
2068
 *
2069
 * @return bool
2070
 */
2071
function migrate(EntityManager $manager)
2072
{
2073
    $debug = true;
2074
    $connection = $manager->getConnection();
2075
    $to = null; // if $to == null then schema will be migrated to latest version
2076
    //echo '<pre>';
2077
    //try {
2078
        $config = new PhpFile('./migrations.php');
2079
        $dependency = DependencyFactory::fromConnection($config, new ExistingConnection($connection));
2080
        $dependency->getMetadataStorage()->ensureInitialized();
2081
        $migratorConfigurationFactory = $dependency->getConsoleInputMigratorConfigurationFactory();
2082
        $result = '';
2083
        $input = new Symfony\Component\Console\Input\StringInput($result);
2084
        $migratorConfiguration = $migratorConfigurationFactory->getMigratorConfiguration($input);
2085
        $migrator = $dependency->getMigrator();
2086
        $planCalculator = $dependency->getMigrationPlanCalculator();
2087
        $migrations = $planCalculator->getMigrations();
2088
        $lastVersion = $migrations->getLast();
2089
        $plan = $dependency->getMigrationPlanCalculator()->getPlanUntilVersion($lastVersion->getVersion());
2090
        foreach ($plan->getItems() as $item) {
2091
            $item->getMigration()->setEntityManager($manager);
2092
        }
2093
        // Execute migration!
2094
        $migratedSQL = $migrator->migrate($plan, $migratorConfiguration);
2095
2096
        if ($debug) {
2097
            foreach ($migratedSQL as $version => $sqlList) {
2098
                echo "VERSION: $version<br>";
2099
                echo '----------------------------------------------<br />';
2100
                $total = count($sqlList);
2101
                error_log("VERSION: $version");
2102
                error_log("# queries: $total");
2103
                $counter = 1;
2104
                foreach ($sqlList as $sql) {
2105
                    echo "<code>$sql</code><br>";
2106
                    error_log("$counter/$total : $sql");
2107
                    $counter++;
2108
                }
2109
            }
2110
            echo "<br>DONE!<br>";
2111
        }
2112
2113
        return true;
2114
    /*} catch (Exception $ex) {
2115
        if ($debug) {
2116
            echo "ERROR: {$ex->getMessage()}<br>";
2117
2118
            return false;
2119
        }
2120
    }*/
2121
2122
//    echo '</pre>';
2123
2124
    return false;
0 ignored issues
show
Unused Code introduced by
return false is not reachable.

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

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

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

    return false;
}

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

Loading history...
2125
}
2126
2127
/**
2128
 * @param string $distFile
2129
 * @param string $envFile
2130
 * @param array  $params
2131
 */
2132
function updateEnvFile($distFile, $envFile, $params)
2133
{
2134
    $requirements = [
2135
        'DATABASE_HOST',
2136
        'DATABASE_PORT',
2137
        'DATABASE_NAME',
2138
        'DATABASE_USER',
2139
        'DATABASE_PASSWORD',
2140
        'APP_INSTALLED',
2141
        'APP_ENCRYPT_METHOD',
2142
    ];
2143
2144
    foreach ($requirements as $requirement) {
2145
        if (!isset($params['{{'.$requirement.'}}'])) {
2146
            throw new \Exception("The parameter $requirement is needed in order to edit the .env.local file");
2147
        }
2148
    }
2149
2150
    $contents = file_get_contents($distFile);
2151
    $contents = str_replace(array_keys($params), array_values($params), $contents);
2152
    file_put_contents($envFile, $contents);
2153
    error_log("File env saved here: $envFile");
2154
}
2155
2156
/**
2157
 * @param EntityManager $manager
2158
 */
2159
function installGroups($manager)
2160
{
2161
    error_log('installGroups');
2162
    // Creating fos_group (groups and roles)
2163
    $groups = [
2164
        [
2165
            'code' => 'ADMIN',
2166
            'title' => 'Administrators',
2167
            'roles' => ['ROLE_ADMIN'],
2168
        ],
2169
        [
2170
            'code' => 'STUDENT',
2171
            'title' => 'Students',
2172
            'roles' => ['ROLE_STUDENT'],
2173
        ],
2174
        [
2175
            'code' => 'TEACHER',
2176
            'title' => 'Teachers',
2177
            'roles' => ['ROLE_TEACHER'],
2178
        ],
2179
        [
2180
            'code' => 'RRHH',
2181
            'title' => 'Human resources manager',
2182
            'roles' => ['ROLE_RRHH'],
2183
        ],
2184
        [
2185
            'code' => 'SESSION_MANAGER',
2186
            'title' => 'Session',
2187
            'roles' => ['ROLE_SESSION_MANAGER'],
2188
        ],
2189
        [
2190
            'code' => 'QUESTION_MANAGER',
2191
            'title' => 'Question manager',
2192
            'roles' => ['ROLE_QUESTION_MANAGER'],
2193
        ],
2194
        [
2195
            'code' => 'STUDENT_BOSS',
2196
            'title' => 'Student boss',
2197
            'roles' => ['ROLE_STUDENT_BOSS'],
2198
        ],
2199
        [
2200
            'code' => 'INVITEE',
2201
            'title' => 'Invitee',
2202
            'roles' => ['ROLE_INVITEE'],
2203
        ],
2204
    ];
2205
    $repo = $manager->getRepository('ChamiloCoreBundle:Group');
2206
    foreach ($groups as $groupData) {
2207
        $criteria = ['code' => $groupData['code']];
2208
        $groupExists = $repo->findOneBy($criteria);
2209
        if (!$groupExists) {
2210
            $group = new Group($groupData['title']);
2211
            $group
2212
                ->setCode($groupData['code']);
2213
2214
            foreach ($groupData['roles'] as $role) {
2215
                $group->addRole($role);
2216
            }
2217
            $manager->persist($group);
2218
        }
2219
    }
2220
    $manager->flush();
2221
}
2222
2223
function installTools($container, $manager, $upgrade = false)
2224
{
2225
    error_log('installTools');
2226
    // Install course tools (table "tool")
2227
    $toolChain = $container->get(ToolChain::class);
2228
    $toolChain->createTools($manager);
2229
}
2230
2231
/**
2232
 * @param SymfonyContainer $container
2233
 * @param EntityManager    $manager
2234
 * @param bool             $upgrade
2235
 */
2236
function installSchemas($container, $manager, $upgrade = false)
2237
{
2238
    error_log('installSchemas');
2239
    $settingsManager = $container->get('chamilo.settings.manager');
2240
2241
    $urlRepo = $container->get('Chamilo\CoreBundle\Repository\AccessUrlRepository');
2242
    $accessUrl = $urlRepo->find(1);
2243
    if (!$accessUrl) {
2244
        $em = $urlRepo->getEntityManager();
2245
2246
        // Creating AccessUrl
2247
        $accessUrl = new AccessUrl();
2248
        $accessUrl
2249
            ->setUrl('http://localhost/')
2250
            ->setDescription('')
2251
            ->setActive(1)
2252
            ->setCreatedBy(1)
2253
        ;
2254
        $em->persist($accessUrl);
2255
        $em->flush();
2256
2257
        error_log('AccessUrl created');
2258
    }
2259
2260
    if ($upgrade) {
2261
        error_log('Upgrade settings');
2262
        $settingsManager->updateSchemas($accessUrl);
2263
    } else {
2264
        error_log('Install settings');
2265
        // Installing schemas (filling settings_current table)
2266
        $settingsManager->installSchemas($accessUrl);
2267
    }
2268
}
2269
2270
/**
2271
 * @param SymfonyContainer $container
2272
 */
2273
function upgradeWithContainer($container)
2274
{
2275
    Container::setContainer($container);
2276
    Container::setLegacyServices($container, false);
2277
    error_log('setLegacyServices');
2278
    $manager = Database::getManager();
2279
    installGroups($manager);
2280
    // @todo check if adminId = 1
2281
    installTools($container, $manager, true);
2282
    installSchemas($container, $manager, true);
2283
}
2284
2285
/**
2286
 * After the schema was created (table creation), the function adds
2287
 * admin/platform information.
2288
 *
2289
 * @param \Psr\Container\ContainerInterface $container
2290
 * @param string                            $sysPath
2291
 * @param string                            $encryptPassForm
2292
 * @param string                            $passForm
2293
 * @param string                            $adminLastName
2294
 * @param string                            $adminFirstName
2295
 * @param string                            $loginForm
2296
 * @param string                            $emailForm
2297
 * @param string                            $adminPhoneForm
2298
 * @param string                            $languageForm
2299
 * @param string                            $institutionForm
2300
 * @param string                            $institutionUrlForm
2301
 * @param string                            $siteName
2302
 * @param string                            $allowSelfReg
2303
 * @param string                            $allowSelfRegProf
2304
 * @param string                            $installationProfile Installation profile, if any was provided
2305
 */
2306
function finishInstallationWithContainer(
2307
    $container,
2308
    $sysPath,
2309
    $encryptPassForm,
2310
    $passForm,
2311
    $adminLastName,
2312
    $adminFirstName,
2313
    $loginForm,
2314
    $emailForm,
2315
    $adminPhoneForm,
2316
    $languageForm,
2317
    $institutionForm,
2318
    $institutionUrlForm,
2319
    $siteName,
2320
    $allowSelfReg,
2321
    $allowSelfRegProf,
2322
    $installationProfile = ''
2323
) {
2324
    error_log('finishInstallationWithContainer');
2325
    $sysPath = !empty($sysPath) ? $sysPath : api_get_path(SYMFONY_SYS_PATH);
2326
    Container::setContainer($container);
2327
    Container::setLegacyServices($container, false);
2328
    error_log('setLegacyServices');
2329
2330
    $manager = Database::getManager();
2331
    $connection = $manager->getConnection();
2332
    $trans = $container->get('translator');
2333
2334
    // Add version table
2335
    $connection->executeQuery($sql);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $sql seems to be never defined.
Loading history...
2336
2337
    error_log("Create $sql ");
2338
2339
    // Add tickets defaults
2340
    $ticketProject = new TicketProject();
2341
    $ticketProject
2342
        ->setId(1)
2343
        ->setName('Ticket System')
2344
        ->setInsertUserId(1);
2345
2346
    $manager->persist($ticketProject);
2347
2348
    $categories = [
2349
        $trans->trans('Enrollment') => $trans->trans('Tickets about enrollment'),
2350
        $trans->trans('General information') => $trans->trans('Tickets about general information'),
2351
        $trans->trans('Requests and paperwork') => $trans->trans('Tickets about requests and paperwork'),
2352
        $trans->trans('Academic Incidents') => $trans->trans('Tickets about academic incidents, like exams, practices, tasks, etc.'),
2353
        $trans->trans('Virtual campus') => $trans->trans('Tickets about virtual campus'),
2354
        $trans->trans('Online evaluation') => $trans->trans('Tickets about online evaluation'),
2355
    ];
2356
2357
    $i = 1;
2358
    foreach ($categories as $category => $description) {
2359
        // Online evaluation requires a course
2360
        $ticketCategory = new TicketCategory();
2361
        $ticketCategory
2362
            ->setId($i)
2363
            ->setName($category)
2364
            ->setDescription($description)
2365
            ->setProject($ticketProject)
2366
            ->setInsertUserId(1);
2367
2368
        $isRequired = 6 == $i;
2369
        $ticketCategory->setCourseRequired($isRequired);
2370
2371
        $manager->persist($ticketCategory);
2372
        $i++;
2373
    }
2374
2375
    // Default Priorities
2376
    $defaultPriorities = [
2377
        TicketManager::PRIORITY_NORMAL => $trans->trans('Normal'),
2378
        TicketManager::PRIORITY_HIGH => $trans->trans('High'),
2379
        TicketManager::PRIORITY_LOW => $trans->trans('Low'),
2380
    ];
2381
2382
    $i = 1;
2383
    foreach ($defaultPriorities as $code => $priority) {
2384
        $ticketPriority = new TicketPriority();
2385
        $ticketPriority
2386
            ->setId($i)
2387
            ->setName($priority)
2388
            ->setCode($code)
2389
            ->setInsertUserId(1);
2390
2391
        $manager->persist($ticketPriority);
2392
        $i++;
2393
    }
2394
    error_log('Save ticket data');
2395
    $manager->flush();
2396
2397
    $table = Database::get_main_table(TABLE_TICKET_STATUS);
2398
2399
    // Default status
2400
    $defaultStatus = [
2401
        TicketManager::STATUS_NEW => $trans->trans('New'),
2402
        TicketManager::STATUS_PENDING => $trans->trans('Pending'),
2403
        TicketManager::STATUS_UNCONFIRMED => $trans->trans('Unconfirmed'),
2404
        TicketManager::STATUS_CLOSE => $trans->trans('Close'),
2405
        TicketManager::STATUS_FORWARDED => $trans->trans('Forwarded'),
2406
    ];
2407
2408
    $i = 1;
2409
    foreach ($defaultStatus as $code => $status) {
2410
        $attributes = [
2411
            'id' => $i,
2412
            'code' => $code,
2413
            'name' => $status,
2414
        ];
2415
        Database::insert($table, $attributes);
2416
        $i++;
2417
    }
2418
2419
    installGroups($manager);
2420
2421
    error_log('Inserting data.sql');
2422
    // Inserting default data
2423
    $data = file_get_contents($sysPath.'public/main/install/data.sql');
2424
    $result = $manager->getConnection()->prepare($data);
2425
    $executeResult = $result->execute();
2426
2427
    if ($executeResult) {
2428
        error_log('data.sql Ok');
2429
    }
2430
    $result->closeCursor();
2431
2432
    UserManager::setPasswordEncryption($encryptPassForm);
2433
2434
    error_log('user creation - admin');
2435
2436
    // Create admin user.
2437
    $adminId = UserManager::create_user(
2438
        $adminFirstName,
2439
        $adminLastName,
2440
        1,
2441
        $emailForm,
2442
        $loginForm,
2443
        $passForm,
2444
        'ADMIN',
2445
        $languageForm,
2446
        $adminPhoneForm,
2447
        '',
2448
        PLATFORM_AUTH_SOURCE,
2449
        '',
2450
        1,
2451
        0,
2452
        null,
2453
        '',
2454
        false,
2455
        true,
2456
        '',
2457
        false,
2458
        '',
2459
        0,
2460
        [],
2461
        '',
2462
        false,
2463
        false
2464
    );
2465
    error_log('user creation - anon');
2466
    // Create anonymous user.
2467
    $anonId = UserManager::create_user(
2468
        'Joe',
2469
        'Anonymous',
2470
        6,
2471
        'anonymous@localhost',
2472
        'anon',
2473
        'anon',
2474
        'anonymous',
2475
        $languageForm,
2476
        '',
2477
        '',
2478
        PLATFORM_AUTH_SOURCE,
2479
        '',
2480
        1,
2481
        0,
2482
        null,
2483
        '',
2484
        false,
2485
        false,
2486
        '',
2487
        false,
2488
        '',
2489
        $adminId,
2490
        [],
2491
        '',
2492
        false,
2493
        false
2494
    );
2495
    $userManager = $container->get('Chamilo\CoreBundle\Repository\UserRepository');
2496
    $urlRepo = $container->get('Chamilo\CoreBundle\Repository\AccessUrlRepository');
2497
2498
    installTools($container, $manager, false);
2499
2500
    /** @var User $admin */
2501
    $admin = $userManager->find($adminId);
2502
    $admin->addRole('ROLE_GLOBAL_ADMIN');
2503
    $manager->persist($admin);
2504
2505
    // Login as admin
2506
    $token = new UsernamePasswordToken(
2507
        $admin,
2508
        $admin->getPassword(),
2509
        'public',
2510
        $admin->getRoles()
2511
    );
2512
    $container->get('security.token_storage')->setToken($token);
2513
2514
    $userManager->addUserToResourceNode($adminId, $adminId);
2515
    $userManager->addUserToResourceNode($anonId, $adminId);
2516
    $manager->flush();
2517
2518
    installSchemas($container, $manager, false);
2519
    $accessUrl = $urlRepo->find(1);
2520
2521
    UrlManager::add_user_to_url($adminId, $adminId);
2522
    UrlManager::add_user_to_url($anonId, $adminId);
2523
2524
    $branch = new BranchSync();
2525
    $branch->setBranchName('localhost');
2526
    $branch->setUrl($accessUrl);
2527
    $manager->persist($branch);
2528
    $manager->flush();
2529
2530
    // Set default language
2531
    Database::update(
2532
        Database::get_main_table(TABLE_MAIN_LANGUAGE),
2533
        ['available' => 1],
2534
        ['english_name = ?' => $languageForm]
2535
    );
2536
2537
    // Install settings
2538
    installSettings(
2539
        $institutionForm,
2540
        $institutionUrlForm,
2541
        $siteName,
2542
        $emailForm,
2543
        $adminLastName,
2544
        $adminFirstName,
2545
        $languageForm,
2546
        $allowSelfReg,
2547
        $allowSelfRegProf,
2548
        $installationProfile
2549
    );
2550
2551
    lockSettings();
2552
    updateDirAndFilesPermissions();
2553
}
2554
2555
/**
2556
 * Update settings based on installation profile defined in a JSON file.
2557
 *
2558
 * @param string $installationProfile The name of the JSON file in main/install/profiles/ folder
2559
 *
2560
 * @return bool false on failure (no bad consequences anyway, just ignoring profile)
2561
 */
2562
function installProfileSettings($installationProfile = '')
2563
{
2564
    error_log('installProfileSettings');
2565
    if (empty($installationProfile)) {
2566
        return false;
2567
    }
2568
    $jsonPath = api_get_path(SYS_PATH).'main/install/profiles/'.$installationProfile.'.json';
2569
    // Make sure the path to the profile is not hacked
2570
    if (!Security::check_abs_path($jsonPath, api_get_path(SYS_PATH).'main/install/profiles/')) {
2571
        return false;
2572
    }
2573
    if (!is_file($jsonPath)) {
2574
        return false;
2575
    }
2576
    if (!is_readable($jsonPath)) {
2577
        return false;
2578
    }
2579
    if (!function_exists('json_decode')) {
2580
        // The php-json extension is not available. Ignore profile.
2581
        return false;
2582
    }
2583
    $json = file_get_contents($jsonPath);
2584
    $params = json_decode($json);
2585
    if (false === $params or null === $params) {
2586
        return false;
2587
    }
2588
    $settings = $params->params;
2589
    if (!empty($params->parent)) {
2590
        installProfileSettings($params->parent);
2591
    }
2592
2593
    $tblSettings = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
2594
2595
    foreach ($settings as $id => $param) {
2596
        $conditions = ['variable = ? ' => $param->variable];
2597
2598
        if (!empty($param->subkey)) {
2599
            $conditions['AND subkey = ? '] = $param->subkey;
2600
        }
2601
2602
        Database::update(
2603
            $tblSettings,
2604
            ['selected_value' => $param->selected_value],
2605
            $conditions
2606
        );
2607
    }
2608
2609
    return true;
2610
}
2611
2612
/**
2613
 * Quick function to remove a directory with its subdirectories.
2614
 *
2615
 * @param $dir
2616
 */
2617
function rrmdir($dir)
2618
{
2619
    if (is_dir($dir)) {
2620
        $objects = scandir($dir);
2621
        foreach ($objects as $object) {
2622
            if ("." != $object && ".." != $object) {
2623
                if ("dir" == filetype($dir."/".$object)) {
2624
                    @rrmdir($dir."/".$object);
0 ignored issues
show
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

2624
                    /** @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...
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...
2625
                } else {
2626
                    @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

2626
                    /** @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...
2627
                }
2628
            }
2629
        }
2630
        reset($objects);
2631
        rmdir($dir);
2632
    }
2633
}
2634
2635
/**
2636
 * Control the different steps of the migration through a big switch.
2637
 *
2638
 * @param string        $fromVersion
2639
 * @param EntityManager $manager
2640
 * @param bool          $processFiles
2641
 *
2642
 * @return bool Always returns true except if the process is broken
2643
 *
2644
 */
2645
function migrateSwitch($fromVersion, $manager, $processFiles = true)
2646
{
2647
    error_log('Starting migration process from '.$fromVersion.' ('.date('Y-m-d H:i:s').')');
2648
    //echo '<a class="btn btn-secondary" href="javascript:void(0)" id="details_button">'.get_lang('Details').'</a><br />';
2649
    //echo '<div id="details" style="display:none">';
2650
    $connection = $manager->getConnection();
2651
    $database = new Database();
2652
    $database->setManager($manager);
2653
2654
    switch ($fromVersion) {
2655
        case '1.11.0':
2656
        case '1.11.1':
2657
        case '1.11.2':
2658
        case '1.11.4':
2659
        case '1.11.6':
2660
        case '1.11.8':
2661
        case '1.11.10':
2662
        case '1.11.12':
2663
        case '1.11.14':
2664
            $database = new Database();
2665
            $database->setManager($manager);
2666
            // Migrate using the migration files located in:
2667
            // /srv/http/chamilo2/src/CoreBundle/Migrations/Schema/V200
2668
            $result = migrate( $manager);
2669
2670
            if ($result) {
2671
                error_log('Migrations files were executed ('.date('Y-m-d H:i:s').')');
2672
                $sql = "UPDATE settings_current SET selected_value = '2.0.0' WHERE variable = 'chamilo_database_version'";
2673
                $connection->executeQuery($sql);
2674
                if ($processFiles) {
2675
                    error_log('Update config files');
2676
                    include __DIR__.'/update-files-1.11.0-2.0.0.inc.php';
2677
                    // Only updates the configuration.inc.php with the new version
2678
                    include __DIR__.'/update-configuration.inc.php';
2679
                }
2680
                error_log('Upgrade 2.0.0 process concluded!  ('.date('Y-m-d H:i:s').')');
2681
            } else {
2682
                error_log('There was an error during running migrations. Check error.log');
2683
            }
2684
            break;
2685
        default:
2686
            break;
2687
    }
2688
2689
    //echo '</div>';
2690
2691
    return true;
2692
}
2693
2694
/**
2695
 * @return string
2696
 */
2697
function generateRandomToken()
2698
{
2699
    return hash('sha1', uniqid(mt_rand(), true));
2700
}
2701
2702
/**
2703
 * This function checks if the given file can be created or overwritten.
2704
 *
2705
 * @param string $file Full path to a file
2706
 *
2707
 * @return string An HTML coloured label showing success or failure
2708
 */
2709
function checkCanCreateFile($file)
2710
{
2711
    if (file_exists($file)) {
2712
        if (is_writable($file)) {
2713
            return Display::label(get_lang('Writable'), 'success');
2714
        } else {
2715
            return Display::label(get_lang('Not writable'), 'important');
2716
        }
2717
    } else {
2718
        $write = @file_put_contents($file, '');
2719
        if ($write) {
2720
            unlink($file);
2721
2722
            return Display::label(get_lang('Writable'), 'success');
2723
        } else {
2724
            return Display::label(get_lang('Not writable'), 'important');
2725
        }
2726
    }
2727
}
2728