Completed
Push — master ( af42cb...3888f0 )
by Julito
13:17
created

checkCourseScriptCreation()   F

Complexity

Conditions 22
Paths 147

Size

Total Lines 86
Code Lines 53

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 22
eloc 53
c 0
b 0
f 0
nc 147
nop 3
dl 0
loc 86
rs 3.775

How to fix   Long Method    Complexity   

Long Method

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

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

Commonly applied refactorings include:

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

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

120
    /** @scrutinizer ignore-unused */ $returnFailure = false

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
121
) {
122
    $currentPhpValue = getPhpSetting($phpSetting);
123
    if ($currentPhpValue == $recommendedValue) {
124
        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

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

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

361
    $buffer = fread(/** @scrutinizer ignore-type */ $fp, filesize($filename));
Loading history...
362
    fclose($fp);
0 ignored issues
show
Bug introduced by
It seems like $fp can also be of type false; however, parameter $handle of fclose() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

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

362
    fclose(/** @scrutinizer ignore-type */ $fp);
Loading history...
363
364
    return explode('<br />', nl2br($buffer));
365
}
366
367
/**
368
 * We assume this function is called from install scripts that reside inside the install folder.
369
 */
370
function set_file_folder_permissions()
371
{
372
    @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

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

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

948
    /** @scrutinizer ignore-unhandled */ @unlink($course_dir.'/'.$fileToCreate);

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

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

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

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

949
    /** @scrutinizer ignore-unhandled */ @rmdir($course_dir);

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

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

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
950
951
    $perms_dir = [0777, 0755, 0775, 0770, 0750, 0700];
952
    $perms_fil = [0666, 0644, 0664, 0660, 0640, 0600];
953
    $course_test_was_created = false;
954
    $dir_perm_verified = 0777;
955
    foreach ($perms_dir as $perm) {
956
        $r = @mkdir($course_dir, $perm);
957
        if ($r === true) {
958
            $dir_perm_verified = $perm;
959
            $course_test_was_created = true;
960
            break;
961
        }
962
    }
963
964
    $fil_perm_verified = 0666;
965
    $file_course_test_was_created = false;
966
    if (is_dir($course_dir)) {
967
        foreach ($perms_fil as $perm) {
968
            if ($file_course_test_was_created == true) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

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

Loading history...
969
                break;
970
            }
971
            $r = @touch($course_dir.'/'.$fileToCreate, $perm);
972
            if ($r === true) {
973
                $fil_perm_verified = $perm;
974
                if (checkCourseScriptCreation($course_dir, $course_attempt_name, $fileToCreate)) {
975
                    $file_course_test_was_created = true;
976
                }
977
            }
978
        }
979
    }
980
981
    @unlink($course_dir.'/'.$fileToCreate);
982
    @rmdir($course_dir);
983
984
    $_SESSION['permissions_for_new_directories'] = $_setting['permissions_for_new_directories'] = $dir_perm_verified;
985
    $_SESSION['permissions_for_new_files'] = $_setting['permissions_for_new_files'] = $fil_perm_verified;
986
987
    $dir_perm = Display::label('0'.decoct($dir_perm_verified), 'info');
988
    $file_perm = Display::label('0'.decoct($fil_perm_verified), 'info');
989
990
    $courseTestLabel = Display::label(get_lang('No'), 'important');
991
    if ($course_test_was_created && $file_course_test_was_created) {
992
        $courseTestLabel = Display::label(get_lang('Yes'), 'success');
993
    }
994
995
    if ($course_test_was_created && !$file_course_test_was_created) {
996
        $courseTestLabel = Display::label(get_lang('Warning'), 'warning');
997
        $courseTestLabel .= '<br />'.sprintf(
998
            get_lang('InstallWarningCouldNotInterpretPHP'),
999
            api_get_path(WEB_COURSE_PATH).$course_attempt_name.'/'.$fileToCreate
1000
        );
1001
    }
1002
1003
    if (!$course_test_was_created && !$file_course_test_was_created) {
1004
        $courseTestLabel = Display::label(get_lang('No'), 'important');
1005
    }
1006
1007
    $oldConf = '';
1008
    if (file_exists(api_get_path(SYS_CODE_PATH).'inc/conf/configuration.php')) {
1009
        $oldConf = '<tr>
1010
            <td class="requirements-item">'.api_get_path(SYS_CODE_PATH).'inc/conf</td>
1011
            <td class="requirements-value">'.check_writable(api_get_path(SYS_CODE_PATH).'inc/conf').'</td>
1012
        </tr>';
1013
    }
1014
1015
    echo '<table class="table">
1016
            '.$oldConf.'
1017
            <tr>
1018
                <td class="requirements-item">'.api_get_path(SYS_APP_PATH).'</td>
1019
                <td class="requirements-value">'.check_writable(api_get_path(SYS_APP_PATH)).'</td>
1020
            </tr>
1021
            <tr>
1022
                <td class="requirements-item">'.api_get_path(SYS_CODE_PATH).'default_course_document/images/</td>
1023
                <td class="requirements-value">'.check_writable(api_get_path(SYS_CODE_PATH).'default_course_document/images/').'</td>
1024
            </tr>
1025
            <tr>
1026
                <td class="requirements-item">'.api_get_path(SYS_CODE_PATH).'lang/</td>
1027
                <td class="requirements-value">'.check_writable(api_get_path(SYS_CODE_PATH).'lang/', true).' <br />('.get_lang('SuggestionOnlyToEnableSubLanguageFeatureOrUpgradeProcess').')</td>
1028
            </tr>
1029
            <tr>
1030
                <td class="requirements-item">'.api_get_path(SYS_PATH).'vendor/</td>
1031
                <td class="requirements-value">'.checkReadable(api_get_path(SYS_PATH).'vendor').'</td>
1032
            </tr>
1033
            <tr>
1034
                <td class="requirements-item">'.api_get_path(SYS_PUBLIC_PATH).'</td>
1035
                <td class="requirements-value">'.check_writable(api_get_path(SYS_PUBLIC_PATH)).'</td>
1036
            </tr>
1037
            <tr>
1038
                <td class="requirements-item">'.get_lang('CourseTestWasCreated').'</td>
1039
                <td class="requirements-value">'.$courseTestLabel.' </td>
1040
            </tr>
1041
            <tr>
1042
                <td class="requirements-item">'.get_lang('PermissionsForNewDirs').'</td>
1043
                <td class="requirements-value">'.$dir_perm.' </td>
1044
            </tr>
1045
            <tr>
1046
                <td class="requirements-item">'.get_lang('PermissionsForNewFiles').'</td>
1047
                <td class="requirements-value">'.$file_perm.' </td>
1048
            </tr>
1049
        </table>';
1050
    echo '  </div>';
1051
    echo '</div>';
1052
1053
    if ($installType == 'update' && (empty($updatePath) || $badUpdatePath)) {
1054
        if ($badUpdatePath) {
1055
            ?>
1056
            <div class="alert alert-warning">
1057
                <?php echo get_lang('Error'); ?>!<br />
1058
                Chamilo <?php echo implode('|', $update_from_version_8).' '.get_lang('HasNotBeenFoundInThatDir'); ?>.
1059
            </div>
1060
        <?php
1061
        } else {
1062
            echo '<br />';
1063
        } ?>
1064
            <div class="row">
1065
                <div class="col-md-12">
1066
                    <p><?php echo get_lang('OldVersionRootPath'); ?>:
1067
                        <input type="text" name="updatePath" size="50" value="<?php echo ($badUpdatePath && !empty($updatePath)) ? htmlentities($updatePath) : ''; ?>" />
1068
                    </p>
1069
                    <p>
1070
                        <button type="submit" class="btn btn-default" name="step1" value="<?php echo get_lang('Back'); ?>" >
1071
                            <em class="fa fa-backward"> <?php echo get_lang('Back'); ?></em>
1072
                        </button>
1073
                        <input type="hidden" name="is_executable" id="is_executable" value="-" />
1074
                        <button type="submit" class="btn btn-success" name="<?php echo isset($_POST['step2_update_6']) ? 'step2_update_6' : 'step2_update_8'; ?>" value="<?php echo get_lang('Next'); ?> &gt;" >
1075
                            <em class="fa fa-forward"> </em> <?php echo get_lang('Next'); ?>
1076
                        </button>
1077
                    </p>
1078
                </div>
1079
            </div>
1080
1081
        <?php
1082
    } else {
1083
        $error = false;
1084
        // First, attempt to set writing permissions if we don't have them yet
1085
        $perm = api_get_permissions_for_new_directories();
1086
        $perm_file = api_get_permissions_for_new_files();
1087
        $notWritable = [];
1088
1089
        $checked_writable = api_get_path(SYS_APP_PATH);
1090
        if (!is_writable($checked_writable)) {
1091
            $notWritable[] = $checked_writable;
1092
            @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

1092
            /** @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...
1093
        }
1094
1095
        $checked_writable = api_get_path(SYS_PUBLIC_PATH);
1096
        if (!is_writable($checked_writable)) {
1097
            $notWritable[] = $checked_writable;
1098
            @chmod($checked_writable, $perm);
1099
        }
1100
1101
        $checked_writable = api_get_path(SYS_CODE_PATH).'default_course_document/images/';
1102
        if (!is_writable($checked_writable)) {
1103
            $notWritable[] = $checked_writable;
1104
            @chmod($checked_writable, $perm);
1105
        }
1106
1107
        if ($course_test_was_created == false) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

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

Loading history...
1108
            $error = true;
1109
        }
1110
1111
        $checked_writable = api_get_path(CONFIGURATION_PATH).'configuration.php';
1112
        if (file_exists($checked_writable) && !is_writable($checked_writable)) {
1113
            $notWritable[] = $checked_writable;
1114
            @chmod($checked_writable, $perm_file);
1115
        }
1116
1117
        // Second, if this fails, report an error
1118
1119
        //--> The user would have to adjust the permissions manually
1120
        if (count($notWritable) > 0) {
1121
            $error = true; ?>
1122
            <div class="text-danger">
1123
                <h3 class="text-center"><?php echo get_lang('Warning'); ?></h3>
1124
                <p>
1125
                    <?php printf(get_lang('NoWritePermissionPleaseReadInstallGuide'), '<a href="../../documentation/installation_guide.html" target="blank">', '</a>'); ?>
1126
                </p>
1127
            </div>
1128
            <?php
1129
            echo '<ul>';
1130
            foreach ($notWritable as $value) {
1131
                echo '<li class="text-danger">'.$value.'</li>';
1132
            }
1133
            echo '</ul>';
1134
        } elseif (file_exists(api_get_path(CONFIGURATION_PATH).'configuration.php')) {
1135
            // Check wether a Chamilo configuration file already exists.
1136
            echo '<div class="alert alert-warning"><h4><center>';
1137
            echo get_lang('WarningExistingLMSInstallationDetected');
1138
            echo '</center></h4></div>';
1139
        }
1140
1141
        $deprecated = [
1142
            api_get_path(SYS_CODE_PATH).'exercice/',
1143
            api_get_path(SYS_CODE_PATH).'newscorm/',
1144
            api_get_path(SYS_PLUGIN_PATH).'ticket/',
1145
            api_get_path(SYS_PLUGIN_PATH).'skype/',
1146
        ];
1147
        $deprecatedToRemove = [];
1148
        foreach ($deprecated as $deprecatedDirectory) {
1149
            if (!is_dir($deprecatedDirectory)) {
1150
                continue;
1151
            }
1152
            $deprecatedToRemove[] = $deprecatedDirectory;
1153
        }
1154
1155
        if (count($deprecatedToRemove) > 0) {
1156
            ?>
1157
            <p class="text-danger"><?php echo get_lang('WarningForDeprecatedDirectoriesForUpgrade'); ?></p>
1158
            <ul>
1159
                <?php foreach ($deprecatedToRemove as $deprecatedDirectory) {
1160
                ?>
1161
                    <li class="text-danger"><?php echo $deprecatedDirectory; ?></li>
1162
                <?php
1163
            } ?>
1164
            </ul>
1165
            <?php
1166
        }
1167
1168
        if (!$properlyAccessUrl) {
1169
            $error = true;
1170
        }
1171
1172
        // And now display the choice buttons (go back or install)?>
1173
        <p align="center" style="padding-top:15px">
1174
        <button type="submit" name="step1" class="btn btn-default" onclick="javascript: window.location='index.php'; return false;" value="<?php echo get_lang('Previous'); ?>" >
1175
            <em class="fa fa-backward"> </em> <?php echo get_lang('Previous'); ?>
1176
        </button>
1177
        <button type="submit" name="step2_install" class="btn btn-success" value="<?php echo get_lang("NewInstallation"); ?>" <?php if ($error) {
1178
            echo 'disabled="disabled"';
1179
        } ?> >
1180
            <em class="fa fa-forward"> </em> <?php echo get_lang('NewInstallation'); ?>
1181
        </button>
1182
        <input type="hidden" name="is_executable" id="is_executable" value="-" />
1183
            <button type="submit" class="btn btn-default" <?php echo !$error ?: 'disabled="disabled"'; ?> name="step2_update_8" value="Upgrade from Chamilo 1.9.x">
1184
                <em class="fa fa-forward" aria-hidden="true"></em> <?php echo get_lang('UpgradeVersion'); ?>
1185
            </button>
1186
            </p>
1187
        <?php
1188
    }
1189
}
1190
1191
/**
1192
 * Displays the license (GNU GPL) as step 2, with
1193
 * - an "I accept" button named step3 to proceed to step 3;
1194
 * - a "Back" button named step1 to go back to the first step.
1195
 */
1196
function display_license_agreement()
1197
{
1198
    echo '<div class="RequirementHeading"><h2>'.display_step_sequence().get_lang('Licence').'</h2>';
1199
    echo '<p>'.get_lang('LMSLicenseInfo').'</p>';
1200
    echo '<p><a href="../../documentation/license.html" target="_blank">'.get_lang('PrintVers').'</a></p>';
1201
    echo '</div>'; ?>
1202
    <div class="row">
1203
        <div class="col-md-12">
1204
            <pre style="overflow: auto; height: 200px; margin-top: 5px;">
1205
                <?php echo api_htmlentities(@file_get_contents(api_get_path(SYS_PATH).'documentation/license.txt')); ?>
1206
            </pre>
1207
            <div class="checkbox">
1208
                <label>
1209
                    <input type="checkbox" name="accept" id="accept_licence" value="1" />
1210
                    <?php echo get_lang('IAccept'); ?>
1211
                </label>
1212
            </div>
1213
        </div>
1214
    </div>
1215
    <div class="row">
1216
        <div class="col-md-12">
1217
            <p class="alert alert-info"><?php echo get_lang('LMSMediaLicense'); ?></p>
1218
        </div>
1219
    </div>
1220
1221
    <!-- Contact information form -->
1222
    <div class="section-parameters">
1223
        <a href="javascript://" class = "advanced_parameters" >
1224
        <span id="img_plus_and_minus">&nbsp;<i class="fa fa-eye" aria-hidden="true"></i>&nbsp;<?php echo get_lang('ContactInformation'); ?></span>
1225
        </a>
1226
    </div>
1227
1228
    <div id="id_contact_form" style="display:block">
1229
        <div class="normal-message"><?php echo get_lang('ContactInformationDescription'); ?></div>
1230
        <div id="contact_registration">
1231
            <p><?php echo get_contact_registration_form(); ?></p><br />
1232
        </div>
1233
    </div>
1234
    <div class="text-center">
1235
    <button type="submit" class="btn btn-default" name="step1" value="&lt; <?php echo get_lang('Previous'); ?>" >
1236
        <em class="fa fa-backward"> </em> <?php echo get_lang('Previous'); ?>
1237
    </button>
1238
    <input type="hidden" name="is_executable" id="is_executable" value="-" />
1239
    <button type="submit" id="license-next" class="btn btn-success" name="step3" onclick="javascript: if(!document.getElementById('accept_licence').checked) { alert('<?php echo get_lang('YouMustAcceptLicence'); ?>');return false;}" value="<?php echo get_lang('Next'); ?> &gt;" >
1240
        <em class="fa fa-forward"> </em> <?php echo get_lang('Next'); ?>
1241
    </button>
1242
    </div>
1243
    <?php
1244
}
1245
1246
/**
1247
 * Get contact registration form.
1248
 */
1249
function get_contact_registration_form()
1250
{
1251
    $html = '
1252
   <div class="form-horizontal">
1253
    <div class="panel panel-default">
1254
    <div class="panel-body">
1255
    <div id="div_sent_information"></div>
1256
    <div class="form-group">
1257
            <label class="col-sm-3"><span class="form_required">*</span>'.get_lang('Name').'</label>
1258
            <div class="col-sm-9"><input id="person_name" class="form-control" type="text" name="person_name" size="30" /></div>
1259
    </div>
1260
    <div class="form-group">
1261
            <label class="col-sm-3"><span class="form_required">*</span>'.get_lang('Email').'</label>
1262
            <div class="col-sm-9"><input id="person_email" class="form-control" type="text" name="person_email" size="30" /></div>
1263
    </div>
1264
    <div class="form-group">
1265
            <label class="col-sm-3"><span class="form_required">*</span>'.get_lang('CompanyName').'</label>
1266
            <div class="col-sm-9"><input id="company_name" class="form-control" type="text" name="company_name" size="30" /></div>
1267
    </div>
1268
    <div class="form-group">
1269
        <label class="col-sm-3"><span class="form_required">*</span>'.get_lang('CompanyActivity').'</label>
1270
        <div class="col-sm-9">
1271
            <select class="selectpicker show-tick" name="company_activity" id="company_activity" >
1272
                <option value="">--- '.get_lang('SelectOne').' ---</option>
1273
                <Option value="Advertising/Marketing/PR">Advertising/Marketing/PR</Option><Option value="Agriculture/Forestry">Agriculture/Forestry</Option>
1274
                <Option value="Architecture">Architecture</Option><Option value="Banking/Finance">Banking/Finance</Option>
1275
                <Option value="Biotech/Pharmaceuticals">Biotech/Pharmaceuticals</Option><Option value="Business Equipment">Business Equipment</Option>
1276
                <Option value="Business Services">Business Services</Option><Option value="Construction">Construction</Option>
1277
                <Option value="Consulting/Research">Consulting/Research</Option><Option value="Education">Education</Option>
1278
                <Option value="Engineering">Engineering</Option><Option value="Environmental">Environmental</Option>
1279
                <Option value="Government">Government</Option><Option value="Healthcare">Health Care</Option>
1280
                <Option value="Hospitality/Lodging/Travel">Hospitality/Lodging/Travel</Option><Option value="Insurance">Insurance</Option>
1281
                <Option value="Legal">Legal</Option><Option value="Manufacturing">Manufacturing</Option>
1282
                <Option value="Media/Entertainment">Media/Entertainment</Option><Option value="Mortgage">Mortgage</Option>
1283
                <Option value="Non-Profit">Non-Profit</Option><Option value="Real Estate">Real Estate</Option>
1284
                <Option value="Restaurant">Restaurant</Option><Option value="Retail">Retail</Option>
1285
                <Option value="Shipping/Transportation">Shipping/Transportation</Option>
1286
                <Option value="Technology">Technology</Option><Option value="Telecommunications">Telecommunications</Option>
1287
                <Option value="Other">Other</Option>
1288
            </select>
1289
        </div>
1290
    </div>
1291
1292
    <div class="form-group">
1293
        <label class="col-sm-3"><span class="form_required">*</span>'.get_lang('PersonRole').'</label>
1294
        <div class="col-sm-9">
1295
            <select class="selectpicker show-tick" name="person_role" id="person_role" >
1296
                <option value="">--- '.get_lang('SelectOne').' ---</option>
1297
                <Option value="Administration">Administration</Option><Option value="CEO/President/ Owner">CEO/President/ Owner</Option>
1298
                <Option value="CFO">CFO</Option><Option value="CIO/CTO">CIO/CTO</Option>
1299
                <Option value="Consultant">Consultant</Option><Option value="Customer Service">Customer Service</Option>
1300
                <Option value="Engineer/Programmer">Engineer/Programmer</Option><Option value="Facilities/Operations">Facilities/Operations</Option>
1301
                <Option value="Finance/ Accounting Manager">Finance/ Accounting Manager</Option><Option value="Finance/ Accounting Staff">Finance/ Accounting Staff</Option>
1302
                <Option value="General Manager">General Manager</Option><Option value="Human Resources">Human Resources</Option>
1303
                <Option value="IS/IT Management">IS/IT Management</Option><Option value="IS/ IT Staff">IS/ IT Staff</Option>
1304
                <Option value="Marketing Manager">Marketing Manager</Option><Option value="Marketing Staff">Marketing Staff</Option>
1305
                <Option value="Partner/Principal">Partner/Principal</Option><Option value="Purchasing Manager">Purchasing Manager</Option>
1306
                <Option value="Sales/ Business Dev. Manager">Sales/ Business Dev. Manager</Option><Option value="Sales/ Business Dev.">Sales/ Business Dev.</Option>
1307
                <Option value="Vice President/Senior Manager">Vice President/Senior Manager</Option><Option value="Other">Other</Option>
1308
            </select>
1309
        </div>
1310
    </div>
1311
1312
    <div class="form-group">
1313
        <label class="col-sm-3"><span class="form_required">*</span>'.get_lang('CompanyCountry').'</label>
1314
        <div class="col-sm-9">'.get_countries_list_from_array(true).'</div>
1315
    </div>
1316
    <div class="form-group">
1317
        <label class="col-sm-3">'.get_lang('CompanyCity').'</label>
1318
        <div class="col-sm-9">
1319
                <input type="text" class="form-control" id="company_city" name="company_city" size="30" />
1320
        </div>
1321
    </div>
1322
    <div class="form-group">
1323
        <label class="col-sm-3">'.get_lang('WhichLanguageWouldYouLikeToUseWhenContactingYou').'</label>
1324
        <div class="col-sm-9">
1325
            <select class="selectpicker show-tick" id="language" name="language">
1326
                <option value="bulgarian">Bulgarian</option>
1327
                <option value="indonesian">Bahasa Indonesia</option>
1328
                <option value="bosnian">Bosanski</option>
1329
                <option value="german">Deutsch</option>
1330
                <option selected="selected" value="english">English</option>
1331
                <option value="spanish">Spanish</option>
1332
                <option value="french">Français</option>
1333
                <option value="italian">Italian</option>
1334
                <option value="hungarian">Magyar</option>
1335
                <option value="dutch">Nederlands</option>
1336
                <option value="brazilian">Português do Brasil</option>
1337
                <option value="portuguese">Português europeu</option>
1338
                <option value="slovenian">Slovenčina</option>
1339
            </select>
1340
        </div>
1341
    </div>
1342
1343
    <div class="form-group">
1344
        <label class="col-sm-3">'.get_lang('HaveYouThePowerToTakeFinancialDecisions').'</label>
1345
        <div class="col-sm-9">
1346
            <div class="radio">
1347
                <label>
1348
                    <input type="radio" name="financial_decision" id="financial_decision1" value="1" checked /> '.get_lang('Yes').'
1349
                </label>
1350
            </div>
1351
            <div class="radio">
1352
                <label>
1353
                    <input type="radio" name="financial_decision" id="financial_decision2" value="0" /> '.get_lang('No').'
1354
                </label>
1355
            </div>
1356
        </div>
1357
    </div>
1358
    <div class="clear"></div>
1359
    <div class="form-group">
1360
            <div class="col-sm-3">&nbsp;</div>
1361
            <div class="col-sm-9"><button type="button" class="btn btn-default" onclick="javascript:send_contact_information();" value="'.get_lang('SendInformation').'" ><em class="fa fa-floppy-o"></em> '.get_lang('SendInformation').'</button> <span id="loader-button"></span></div>
1362
    </div>
1363
    <div class="form-group">
1364
            <div class="col-sm-3">&nbsp;</div>
1365
            <div class="col-sm-9"><span class="form_required">*</span><small>'.get_lang('FieldRequired').'</small></div>
1366
    </div></div></div>
1367
    </div>';
1368
1369
    return $html;
1370
}
1371
1372
/**
1373
 * Displays a parameter in a table row.
1374
 * Used by the display_database_settings_form function.
1375
 *
1376
 * @param   string  Type of install
1377
 * @param   string  Name of parameter
1378
 * @param   string  Field name (in the HTML form)
1379
 * @param   string  Field value
1380
 * @param   string  Extra notice (to show on the right side)
1381
 * @param   bool Whether to display in update mode
1382
 * @param   string  Additional attribute for the <tr> element
1383
 */
1384
function displayDatabaseParameter(
1385
    $installType,
1386
    $parameterName,
1387
    $formFieldName,
1388
    $parameterValue,
1389
    $extra_notice,
1390
    $displayWhenUpdate = true,
1391
    $tr_attribute = ''
0 ignored issues
show
Unused Code introduced by
The parameter $tr_attribute is not used and could be removed. ( Ignorable by Annotation )

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

1391
    /** @scrutinizer ignore-unused */ $tr_attribute = ''

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
1392
) {
1393
    //echo "<tr ".$tr_attribute.">";
1394
    echo "<label class='col-sm-4'>$parameterName</label>";
1395
1396
    if ($installType == INSTALL_TYPE_UPDATE && $displayWhenUpdate) {
1397
        echo '<input type="hidden" name="'.$formFieldName.'" id="'.$formFieldName.'" value="'.api_htmlentities($parameterValue).'" />'.$parameterValue;
1398
    } else {
1399
        $inputType = $formFieldName == 'dbPassForm' ? 'password' : 'text';
1400
1401
        //Slightly limit the length of the database prefix to avoid having to cut down the databases names later on
1402
        $maxLength = $formFieldName == 'dbPrefixForm' ? '15' : MAX_FORM_FIELD_LENGTH;
1403
        if ($installType == INSTALL_TYPE_UPDATE) {
1404
            echo '<input type="hidden" name="'.$formFieldName.'" id="'.$formFieldName.'" value="'.api_htmlentities($parameterValue).'" />';
1405
            echo api_htmlentities($parameterValue);
1406
        } else {
1407
            echo '<div class="col-sm-5"><input type="'.$inputType.'" class="form-control" size="'.DATABASE_FORM_FIELD_DISPLAY_LENGTH.'" maxlength="'.$maxLength.'" name="'.$formFieldName.'" id="'.$formFieldName.'" value="'.api_htmlentities($parameterValue).'" />'."</div>";
1408
            echo '<div class="col-sm-3">'.$extra_notice.'</div>';
1409
        }
1410
    }
1411
}
1412
1413
/**
1414
 * Displays step 3 - a form where the user can enter the installation settings
1415
 * regarding the databases - login and password, names, prefixes, single
1416
 * or multiple databases, tracking or not...
1417
 *
1418
 * @param string $installType
1419
 * @param string $dbHostForm
1420
 * @param string $dbUsernameForm
1421
 * @param string $dbPassForm
1422
 * @param string $dbNameForm
1423
 * @param int    $dbPortForm
1424
 * @param string $installationProfile
1425
 */
1426
function display_database_settings_form(
1427
    $installType,
1428
    $dbHostForm,
1429
    $dbUsernameForm,
1430
    $dbPassForm,
1431
    $dbNameForm,
1432
    $dbPortForm = 3306,
1433
    $installationProfile = ''
0 ignored issues
show
Unused Code introduced by
The parameter $installationProfile is not used and could be removed. ( Ignorable by Annotation )

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

1433
    /** @scrutinizer ignore-unused */ $installationProfile = ''

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
1434
) {
1435
    if ($installType == 'update') {
1436
        global $_configuration;
1437
        $dbHostForm = $_configuration['db_host'];
1438
        $dbUsernameForm = $_configuration['db_user'];
1439
        $dbPassForm = $_configuration['db_password'];
1440
        $dbNameForm = $_configuration['main_database'];
1441
        $dbPortForm = isset($_configuration['db_port']) ? $_configuration['db_port'] : '';
1442
1443
        echo '<div class="RequirementHeading"><h2>'.display_step_sequence().get_lang('DBSetting').'</h2></div>';
1444
        echo '<div class="RequirementContent">';
1445
        echo get_lang('DBSettingUpgradeIntro');
1446
        echo '</div>';
1447
    } else {
1448
        echo '<div class="RequirementHeading"><h2>'.display_step_sequence().get_lang('DBSetting').'</h2></div>';
1449
        echo '<div class="RequirementContent">';
1450
        echo get_lang('DBSettingIntro');
1451
        echo '</div>';
1452
    } ?>
1453
    <div class="panel panel-default">
1454
        <div class="panel-body">
1455
        <div class="form-group">
1456
            <label class="col-sm-4"><?php echo get_lang('DBHost'); ?> </label>
1457
            <?php if ($installType == 'update') {
1458
        ?>
1459
            <div class="col-sm-5">
1460
                <input type="hidden" name="dbHostForm" value="<?php echo htmlentities($dbHostForm); ?>" /><?php echo $dbHostForm; ?>
1461
            </div>
1462
            <div class="col-sm-3"></div>
1463
            <?php
1464
    } else {
1465
        ?>
1466
            <div class="col-sm-5">
1467
                <input type="text" class="form-control" size="25" maxlength="50" name="dbHostForm" value="<?php echo htmlentities($dbHostForm); ?>" />
1468
            </div>
1469
            <div class="col-sm-3"><?php echo get_lang('EG').' localhost'; ?></div>
1470
            <?php
1471
    } ?>
1472
        </div>
1473
        <div class="form-group">
1474
            <label class="col-sm-4"><?php echo get_lang('DBPort'); ?> </label>
1475
            <?php if ($installType == 'update') {
1476
        ?>
1477
            <div class="col-sm-5">
1478
                <input type="hidden" name="dbPortForm" value="<?php echo htmlentities($dbPortForm); ?>" /><?php echo $dbPortForm; ?>
1479
            </div>
1480
            <div class="col-sm-3"></div>
1481
            <?php
1482
    } else {
1483
        ?>
1484
            <div class="col-sm-5">
1485
                <input type="text" class="form-control" size="25" maxlength="50" name="dbPortForm" value="<?php echo htmlentities($dbPortForm); ?>" />
1486
            </div>
1487
            <div class="col-sm-3"><?php echo get_lang('EG').' 3306'; ?></div>
1488
            <?php
1489
    } ?>
1490
        </div>
1491
        <div class="form-group">
1492
            <?php
1493
                //database user username
1494
                $example_login = get_lang('EG').' root';
1495
    displayDatabaseParameter($installType, get_lang('DBLogin'), 'dbUsernameForm', $dbUsernameForm, $example_login); ?>
1496
        </div>
1497
        <div class="form-group">
1498
            <?php
1499
            //database user password
1500
            $example_password = get_lang('EG').' '.api_generate_password();
1501
    displayDatabaseParameter($installType, get_lang('DBPassword'), 'dbPassForm', $dbPassForm, $example_password); ?>
1502
        </div>
1503
        <div class="form-group">
1504
            <?php
1505
            //Database Name fix replace weird chars
1506
            if ($installType != INSTALL_TYPE_UPDATE) {
1507
                $dbNameForm = str_replace(['-', '*', '$', ' ', '.'], '', $dbNameForm);
1508
            }
1509
1510
    displayDatabaseParameter(
1511
                $installType,
1512
                get_lang('MainDB'),
1513
                'dbNameForm',
1514
                $dbNameForm,
1515
                '&nbsp;',
1516
                null,
1517
                'id="optional_param1"'
1518
                ); ?>
1519
        </div>
1520
       <?php if ($installType != INSTALL_TYPE_UPDATE) {
1521
                    ?>
1522
        <div class="form-group">
1523
            <div class="col-sm-3"></div>
1524
            <div class="col-sm-9">
1525
            <button type="submit" class="btn btn-primary" name="step3" value="step3">
1526
                <em class="fa fa-refresh"> </em>
1527
                <?php echo get_lang('CheckDatabaseConnection'); ?>
1528
            </button>
1529
            </div>
1530
        </div>
1531
        <?php
1532
                } ?>
1533
1534
        </div>
1535
    </div>
1536
    <?php
1537
        $database_exists_text = '';
1538
    $manager = null;
1539
    try {
1540
        $manager = connectToDatabase(
1541
                $dbHostForm,
1542
                $dbUsernameForm,
1543
                $dbPassForm,
1544
                null,
1545
                $dbPortForm
1546
            );
1547
        $databases = $manager->getConnection()->getSchemaManager()->listDatabases();
1548
        if (in_array($dbNameForm, $databases)) {
1549
            $database_exists_text = '<div class="alert alert-warning">'.get_lang('ADatabaseWithTheSameNameAlreadyExists').'</div>';
1550
        }
1551
    } catch (Exception $e) {
1552
        $database_exists_text = $e->getMessage();
1553
    }
1554
1555
    if ($manager && $manager->getConnection()->isConnected()): ?>
1556
        <?php echo $database_exists_text; ?>
1557
        <div id="db_status" class="alert alert-success">
1558
            Database host: <strong><?php echo $manager->getConnection()->getHost(); ?></strong><br/>
1559
            Database port: <strong><?php echo $manager->getConnection()->getPort(); ?></strong><br/>
1560
            Database driver: <strong><?php echo $manager->getConnection()->getDriver()->getName(); ?></strong><br/>
1561
        </div>
1562
    <?php else: ?>
1563
        <div id="db_status" class="alert alert-danger">
1564
            <p><?php echo get_lang('FailedConectionDatabase'); ?></strong></p>
1565
            <code><?php echo $database_exists_text; ?></code>
1566
        </div>
1567
    <?php endif; ?>
1568
   <div class="form-group">
1569
       <div class="col-sm-6">
1570
           <button type="submit" name="step2" class="btn btn-default pull-right" value="&lt; <?php echo get_lang('Previous'); ?>" >
1571
               <em class="fa fa-backward"> </em> <?php echo get_lang('Previous'); ?>
1572
           </button>
1573
       </div>
1574
      <div class="col-sm-6">
1575
       <input type="hidden" name="is_executable" id="is_executable" value="-" />
1576
       <?php if ($manager) {
0 ignored issues
show
introduced by
$manager is of type Database, thus it always evaluated to true.
Loading history...
1577
        ?>
1578
           <button type="submit"  class="btn btn-success" name="step4" value="<?php echo get_lang('Next'); ?> &gt;" >
1579
               <em class="fa fa-forward"> </em> <?php echo get_lang('Next'); ?>
1580
           </button>
1581
       <?php
1582
    } else {
1583
        ?>
1584
           <button disabled="disabled" type="submit" class="btn btn-success disabled" name="step4" value="<?php echo get_lang('Next'); ?> &gt;" >
1585
               <em class="fa fa-forward"> </em> <?php echo get_lang('Next'); ?>
1586
           </button>
1587
       <?php
1588
    } ?>
1589
      </div>
1590
   </div>
1591
1592
    <?php
1593
}
1594
1595
function panel($content = null, $title = null, $id = null, $style = null)
1596
{
1597
    $html = '';
1598
    if (empty($style)) {
1599
        $style = 'default';
1600
    }
1601
    if (!empty($title)) {
1602
        $panelTitle = Display::div($title, ['class' => 'panel-heading']);
1603
        $panelBody = Display::div($content, ['class' => 'panel-body']);
1604
        $panelParent = Display::div($panelTitle.$panelBody, ['id' => $id, 'class' => 'panel panel-'.$style]);
1605
    } else {
1606
        $panelBody = Display::div($html, ['class' => 'panel-body']);
1607
        $panelParent = Display::div($panelBody, ['id' => $id, 'class' => 'panel panel-'.$style]);
1608
    }
1609
    $html .= $panelParent;
1610
1611
    return $html;
1612
}
1613
1614
/**
1615
 * Displays a parameter in a table row.
1616
 * Used by the display_configuration_settings_form function.
1617
 *
1618
 * @param string $installType
1619
 * @param string $parameterName
1620
 * @param string $formFieldName
1621
 * @param string $parameterValue
1622
 * @param string $displayWhenUpdate
1623
 *
1624
 * @return string
1625
 */
1626
function display_configuration_parameter(
1627
    $installType,
1628
    $parameterName,
1629
    $formFieldName,
1630
    $parameterValue,
1631
    $displayWhenUpdate = 'true'
1632
) {
1633
    $html = '<div class="form-group">';
1634
    $html .= '<label class="col-sm-6 control-label">'.$parameterName.'</label>';
1635
    if ($installType == INSTALL_TYPE_UPDATE && $displayWhenUpdate) {
1636
        $html .= '<input type="hidden" name="'.$formFieldName.'" value="'.api_htmlentities($parameterValue, ENT_QUOTES).'" />'.$parameterValue;
1637
    } else {
1638
        $html .= '<div class="col-sm-6"><input class="form-control" type="text" size="'.FORM_FIELD_DISPLAY_LENGTH.'" maxlength="'.MAX_FORM_FIELD_LENGTH.'" name="'.$formFieldName.'" value="'.api_htmlentities($parameterValue, ENT_QUOTES).'" />'."</div>";
1639
    }
1640
    $html .= "</div>";
1641
1642
    return $html;
1643
}
1644
1645
/**
1646
 * Displays step 4 of the installation - configuration settings about Chamilo itself.
1647
 *
1648
 * @param string $installType
1649
 * @param string $urlForm
1650
 * @param string $languageForm
1651
 * @param string $emailForm
1652
 * @param string $adminFirstName
1653
 * @param string $adminLastName
1654
 * @param string $adminPhoneForm
1655
 * @param string $campusForm
1656
 * @param string $institutionForm
1657
 * @param string $institutionUrlForm
1658
 * @param string $encryptPassForm
1659
 * @param bool   $allowSelfReg
1660
 * @param bool   $allowSelfRegProf
1661
 * @param string $loginForm
1662
 * @param string $passForm
1663
 */
1664
function display_configuration_settings_form(
1665
    $installType,
1666
    $urlForm,
1667
    $languageForm,
1668
    $emailForm,
1669
    $adminFirstName,
1670
    $adminLastName,
1671
    $adminPhoneForm,
1672
    $campusForm,
1673
    $institutionForm,
1674
    $institutionUrlForm,
1675
    $encryptPassForm,
1676
    $allowSelfReg,
1677
    $allowSelfRegProf,
1678
    $loginForm,
1679
    $passForm
1680
) {
1681
    if ($installType != 'update' && empty($languageForm)) {
1682
        $languageForm = $_SESSION['install_language'];
1683
    }
1684
    echo '<div class="RequirementHeading">';
1685
    echo "<h2>".display_step_sequence().get_lang("CfgSetting")."</h2>";
1686
    echo '</div>';
1687
1688
    echo '<p>'.get_lang('ConfigSettingsInfo').' <strong>app/config/configuration.php</strong></p>';
1689
1690
    // Parameter 1: administrator's login
1691
    $html = '';
1692
    $html .= display_configuration_parameter(
1693
        $installType,
1694
        get_lang('AdminLogin'),
1695
        'loginForm',
1696
        $loginForm,
1697
        $installType == 'update'
1698
    );
1699
1700
    // Parameter 2: administrator's password
1701
    if ($installType != 'update') {
1702
        $html .= display_configuration_parameter($installType, get_lang('AdminPass'), 'passForm', $passForm, false);
1703
    }
1704
1705
    // Parameters 3 and 4: administrator's names
1706
1707
    $html .= display_configuration_parameter(
1708
        $installType,
1709
        get_lang('AdminFirstName'),
1710
        'adminFirstName',
1711
        $adminFirstName
1712
    );
1713
    $html .= display_configuration_parameter($installType, get_lang('AdminLastName'), 'adminLastName', $adminLastName);
1714
1715
    //Parameter 3: administrator's email
1716
    $html .= display_configuration_parameter($installType, get_lang('AdminEmail'), 'emailForm', $emailForm);
1717
1718
    //Parameter 6: administrator's telephone
1719
    $html .= display_configuration_parameter($installType, get_lang('AdminPhone'), 'adminPhoneForm', $adminPhoneForm);
1720
    echo panel($html, get_lang('Administrator'), 'administrator');
1721
1722
    //First parameter: language
1723
    $html = '<div class="form-group">';
1724
    $html .= '<label class="col-sm-6 control-label">'.get_lang('MainLang')."</label>";
1725
    if ($installType == 'update') {
1726
        $html .= '<input type="hidden" name="languageForm" value="'.api_htmlentities($languageForm, ENT_QUOTES).'" />'.$languageForm;
1727
    } else { // new installation
1728
        $html .= '<div class="col-sm-6">';
1729
        $html .= display_language_selection_box('languageForm', $languageForm);
1730
        $html .= '</div>';
1731
    }
1732
    $html .= "</div>";
1733
1734
    //Second parameter: Chamilo URL
1735
    $html .= '<div class="form-group">';
1736
    $html .= '<label class="col-sm-6 control-label">'.get_lang('ChamiloURL').get_lang('ThisFieldIsRequired').'</label>';
1737
1738
    if ($installType == 'update') {
1739
        $html .= api_htmlentities($urlForm, ENT_QUOTES)."\n";
1740
    } else {
1741
        $html .= '<div class="col-sm-6">';
1742
        $html .= '<input class="form-control" type="text" size="40" maxlength="100" name="urlForm" value="'.api_htmlentities($urlForm, ENT_QUOTES).'" />';
1743
        $html .= '</div>';
1744
    }
1745
    $html .= '</div>';
1746
1747
    //Parameter 9: campus name
1748
    $html .= display_configuration_parameter(
1749
        $installType,
1750
        get_lang('CampusName'),
1751
        'campusForm',
1752
        $campusForm
1753
    );
1754
1755
    //Parameter 10: institute (short) name
1756
    $html .= display_configuration_parameter(
1757
        $installType,
1758
        get_lang('InstituteShortName'),
1759
        'institutionForm',
1760
        $institutionForm
1761
    );
1762
1763
    //Parameter 11: institute (short) name
1764
    $html .= display_configuration_parameter(
1765
        $installType,
1766
        get_lang('InstituteURL'),
1767
        'institutionUrlForm',
1768
        $institutionUrlForm
1769
    );
1770
1771
    $html .= '<div class="form-group">
1772
            <label class="col-sm-6 control-label">'.get_lang("EncryptMethodUserPass").'</label>
1773
        <div class="col-sm-6">';
1774
    if ($installType == 'update') {
1775
        $html .= '<input type="hidden" name="encryptPassForm" value="'.$encryptPassForm.'" />'.$encryptPassForm;
1776
    } else {
1777
        $html .= '<div class="checkbox">
1778
                    <label>
1779
                        <input  type="radio" name="encryptPassForm" value="bcrypt" id="encryptPass1" '.($encryptPassForm == 'bcrypt' ? 'checked="checked" ' : '').'/> bcrypt
1780
                    </label>';
1781
1782
        $html .= '<label>
1783
                        <input  type="radio" name="encryptPassForm" value="sha1" id="encryptPass1" '.($encryptPassForm == 'sha1' ? 'checked="checked" ' : '').'/> sha1
1784
                    </label>';
1785
1786
        $html .= '<label>
1787
                        <input type="radio" name="encryptPassForm" value="md5" id="encryptPass0" '.($encryptPassForm == 'md5' ? 'checked="checked" ' : '').'/> md5
1788
                    </label>';
1789
1790
        $html .= '<label>
1791
                        <input type="radio" name="encryptPassForm" value="none" id="encryptPass2" '.($encryptPassForm == 'none' ? 'checked="checked" ' : '').'/>'.get_lang('None').'
1792
                    </label>';
1793
        $html .= '</div>';
1794
    }
1795
    $html .= '</div></div>';
1796
1797
    $html .= '<div class="form-group">
1798
            <label class="col-sm-6 control-label">'.get_lang('AllowSelfReg').'</label>
1799
            <div class="col-sm-6">';
1800
    if ($installType == 'update') {
1801
        if ($allowSelfReg == 'true') {
1802
            $label = get_lang('Yes');
1803
        } elseif ($allowSelfReg == 'false') {
1804
            $label = get_lang('No');
1805
        } else {
1806
            $label = get_lang('AfterApproval');
1807
        }
1808
        $html .= '<input type="hidden" name="allowSelfReg" value="'.$allowSelfReg.'" />'.$label;
1809
    } else {
1810
        $html .= '<div class="control-group">';
1811
        $html .= '<label class="checkbox-inline">
1812
                        <input type="radio" name="allowSelfReg" value="true" id="allowSelfReg1" '.($allowSelfReg == 'true' ? 'checked="checked" ' : '').' /> '.get_lang('Yes').'
1813
                    </label>';
1814
        $html .= '<label class="checkbox-inline">
1815
                        <input type="radio" name="allowSelfReg" value="false" id="allowSelfReg0" '.($allowSelfReg == 'false' ? '' : 'checked="checked" ').' /> '.get_lang('No').'
1816
                    </label>';
1817
        $html .= '<label class="checkbox-inline">
1818
                    <input type="radio" name="allowSelfReg" value="approval" id="allowSelfReg2" '.($allowSelfReg == 'approval' ? '' : 'checked="checked" ').' /> '.get_lang('AfterApproval').'
1819
                </label>';
1820
        $html .= '</div>';
1821
    }
1822
    $html .= '</div>';
1823
    $html .= '</div>';
1824
1825
    $html .= '<div class="form-group">';
1826
    $html .= '<label class="col-sm-6 control-label">'.get_lang('AllowSelfRegProf').'</label>
1827
        <div class="col-sm-6">';
1828
    if ($installType == 'update') {
1829
        if ($allowSelfRegProf == 'true') {
1830
            $label = get_lang('Yes');
1831
        } else {
1832
            $label = get_lang('No');
1833
        }
1834
        $html .= '<input type="hidden" name="allowSelfRegProf" value="'.$allowSelfRegProf.'" />'.$label;
1835
    } else {
1836
        $html .= '<div class="control-group">
1837
                <label class="checkbox-inline">
1838
                    <input type="radio" name="allowSelfRegProf" value="1" id="allowSelfRegProf1" '.($allowSelfRegProf ? 'checked="checked" ' : '').'/>
1839
                '.get_lang('Yes').'
1840
                </label>';
1841
        $html .= '<label class="checkbox-inline">
1842
                    <input type="radio" name="allowSelfRegProf" value="0" id="allowSelfRegProf0" '.($allowSelfRegProf ? '' : 'checked="checked" ').' />
1843
                   '.get_lang('No').'
1844
                </label>';
1845
        $html .= '</div>';
1846
    }
1847
    $html .= '</div>
1848
    </div>';
1849
1850
    echo panel($html, get_lang('Platform'), 'platform'); ?>
1851
    <div class='form-group'>
1852
        <div class="col-sm-6">
1853
            <button type="submit" class="btn btn-default pull-right" name="step3" value="&lt; <?php echo get_lang('Previous'); ?>" ><em class="fa fa-backward"> </em> <?php echo get_lang('Previous'); ?></button>
1854
            <input type="hidden" name="is_executable" id="is_executable" value="-" />
1855
        </div>
1856
        <div class="col-sm-6">
1857
            <button class="btn btn-success" type="submit" name="step5" value="<?php echo get_lang('Next'); ?> &gt;" ><em class="fa fa-forward"> </em> <?php echo get_lang('Next'); ?></button>
1858
        </div>
1859
    </div>
1860
1861
    <?php
1862
}
1863
1864
/**
1865
 * After installation is completed (step 6), this message is displayed.
1866
 *
1867
 * @param string $installType
1868
 */
1869
function display_after_install_message($installType)
0 ignored issues
show
Unused Code introduced by
The parameter $installType is not used and could be removed. ( Ignorable by Annotation )

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

1869
function display_after_install_message(/** @scrutinizer ignore-unused */ $installType)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
1870
{
1871
    echo '<div class="RequirementContent">'.get_lang('FirstUseTip').'</div>';
1872
    echo '<div class="alert alert-warning">';
1873
    echo '<strong>'.get_lang('SecurityAdvice').'</strong>';
1874
    echo ': ';
1875
    printf(get_lang('ToProtectYourSiteMakeXReadOnlyAndDeleteY'), 'app/config/', 'main/install/');
1876
    echo '</div>'; ?></form>
1877
    <br />
1878
    <a class="btn btn-success btn-block" href="../../index.php">
1879
        <?php echo get_lang('GoToYourNewlyCreatedPortal'); ?>
1880
    </a>
1881
    <?php
1882
}
1883
1884
/**
1885
 * This function return countries list from array (hardcoded).
1886
 *
1887
 * @param bool $combo (Optional) True for returning countries list with select html
1888
 *
1889
 * @return array|string countries list
1890
 */
1891
function get_countries_list_from_array($combo = false)
1892
{
1893
    $a_countries = [
1894
        "Afghanistan", "Albania", "Algeria", "Andorra", "Angola", "Antigua and Barbuda", "Argentina", "Armenia", "Australia", "Austria", "Azerbaijan",
1895
        "Bahamas", "Bahrain", "Bangladesh", "Barbados", "Belarus", "Belgium", "Belize", "Benin", "Bhutan", "Bolivia", "Bosnia and Herzegovina", "Botswana", "Brazil", "Brunei", "Bulgaria", "Burkina Faso", "Burundi",
1896
        "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",
1897
        "Denmark", "Djibouti", "Dominica", "Dominican Republic",
1898
        "East Timor (Timor Timur)", "Ecuador", "Egypt", "El Salvador", "Equatorial Guinea", "Eritrea", "Estonia", "Ethiopia",
1899
        "Fiji", "Finland", "France",
1900
        "Gabon", "Gambia, The", "Georgia", "Germany", "Ghana", "Greece", "Grenada", "Guatemala", "Guinea", "Guinea-Bissau", "Guyana",
1901
        "Haiti", "Honduras", "Hungary",
1902
        "Iceland", "India", "Indonesia", "Iran", "Iraq", "Ireland", "Israel", "Italy",
1903
        "Jamaica", "Japan", "Jordan",
1904
        "Kazakhstan", "Kenya", "Kiribati", "Korea, North", "Korea, South", "Kuwait", "Kyrgyzstan",
1905
        "Laos", "Latvia", "Lebanon", "Lesotho", "Liberia", "Libya", "Liechtenstein", "Lithuania", "Luxembourg",
1906
        "Macedonia", "Madagascar", "Malawi", "Malaysia", "Maldives", "Mali", "Malta", "Marshall Islands", "Mauritania", "Mauritius", "Mexico", "Micronesia", "Moldova", "Monaco", "Mongolia", "Morocco", "Mozambique", "Myanmar",
1907
        "Namibia", "Nauru", "Nepa", "Netherlands", "New Zealand", "Nicaragua", "Niger", "Nigeria", "Norway",
1908
        "Oman",
1909
        "Pakistan", "Palau", "Panama", "Papua New Guinea", "Paraguay", "Peru", "Philippines", "Poland", "Portugal",
1910
        "Qatar",
1911
        "Romania", "Russia", "Rwanda",
1912
        "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",
1913
        "Taiwan", "Tajikistan", "Tanzania", "Thailand", "Togo", "Tonga", "Trinidad and Tobago", "Tunisia", "Turkey", "Turkmenistan", "Tuvalu",
1914
        "Uganda", "Ukraine", "United Arab Emirates", "United Kingdom", "United States", "Uruguay", "Uzbekistan",
1915
        "Vanuatu", "Vatican City", "Venezuela", "Vietnam",
1916
        "Yemen",
1917
        "Zambia", "Zimbabwe",
1918
    ];
1919
    if ($combo) {
1920
        $country_select = '<select class="selectpicker show-tick" id="country" name="country">';
1921
        $country_select .= '<option value="">--- '.get_lang('SelectOne').' ---</option>';
1922
        foreach ($a_countries as $country) {
1923
            $country_select .= '<option value="'.$country.'">'.$country.'</option>';
1924
        }
1925
        $country_select .= '</select>';
1926
1927
        return $country_select;
1928
    }
1929
1930
    return $a_countries;
1931
}
1932
1933
/**
1934
 * Lock settings that can't be changed in other portals.
1935
 */
1936
function lockSettings()
1937
{
1938
    $settings = api_get_locked_settings();
1939
    $table = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
1940
    foreach ($settings as $setting) {
1941
        $sql = "UPDATE $table SET access_url_locked = 1 WHERE variable  = '$setting'";
1942
        Database::query($sql);
1943
    }
1944
}
1945
1946
/**
1947
 * Update dir values.
1948
 */
1949
function updateDirAndFilesPermissions()
1950
{
1951
    $table = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
1952
    $permissions_for_new_directories = isset($_SESSION['permissions_for_new_directories']) ? $_SESSION['permissions_for_new_directories'] : 0770;
1953
    $permissions_for_new_files = isset($_SESSION['permissions_for_new_files']) ? $_SESSION['permissions_for_new_files'] : 0660;
1954
    // use decoct() to store as string
1955
    $sql = "UPDATE $table SET selected_value = '0".decoct($permissions_for_new_directories)."'
1956
              WHERE variable  = 'permissions_for_new_directories'";
1957
    Database::query($sql);
1958
1959
    $sql = "UPDATE $table SET selected_value = '0".decoct($permissions_for_new_files)."' WHERE variable  = 'permissions_for_new_files'";
1960
    Database::query($sql);
1961
1962
    if (isset($_SESSION['permissions_for_new_directories'])) {
1963
        unset($_SESSION['permissions_for_new_directories']);
1964
    }
1965
1966
    if (isset($_SESSION['permissions_for_new_files'])) {
1967
        unset($_SESSION['permissions_for_new_files']);
1968
    }
1969
}
1970
1971
/**
1972
 * @param $current_value
1973
 * @param $wanted_value
1974
 *
1975
 * @return string
1976
 */
1977
function compare_setting_values($current_value, $wanted_value)
1978
{
1979
    $current_value_string = $current_value;
1980
    $current_value = (float) $current_value;
1981
    $wanted_value = (float) $wanted_value;
1982
1983
    if ($current_value >= $wanted_value) {
1984
        return Display::label($current_value_string, 'success');
1985
    } else {
1986
        return Display::label($current_value_string, 'important');
1987
    }
1988
}
1989
1990
/**
1991
 * @param string $course_dir
1992
 * @param string $course_attempt_name
1993
 * @param string $file
1994
 *
1995
 * @return bool
1996
 */
1997
function checkCourseScriptCreation(
1998
    $course_dir,
1999
    $course_attempt_name,
2000
    $file
2001
) {
2002
    $output = false;
2003
    //Write in file
2004
    $file_name = $course_dir.'/'.$file;
2005
    $content = '123';
2006
2007
    if (is_writable($file_name)) {
2008
        if ($handler = @fopen($file_name, 'w')) {
2009
            //write content
2010
            if (fwrite($handler, $content)) {
2011
                $sock_errno = '';
2012
                $sock_errmsg = '';
2013
                $url = api_get_path(WEB_PATH).'app/courses/'.$course_attempt_name.'/'.$file;
2014
2015
                $parsed_url = parse_url($url);
2016
                //$scheme = isset($parsedUrl['scheme']) ? $parsedUrl['scheme'] : ''; //http
2017
                $host = isset($parsed_url['host']) ? $parsed_url['host'] : '';
2018
                // Patch if the host is the default host and is used through
2019
                // the IP address (sometimes the host is not taken correctly
2020
                // in this case)
2021
                if (empty($host) && !empty($_SERVER['HTTP_HOST'])) {
2022
                    $host = $_SERVER['HTTP_HOST'];
2023
                    $url = preg_replace('#:///#', '://'.$host.'/', $url);
2024
                }
2025
                $path = isset($parsed_url['path']) ? $parsed_url['path'] : '/';
2026
                $port = '';
2027
                $scheme = '';
2028
                switch ($parsed_url['scheme']) {
2029
                    case 'https':
2030
                        $scheme = 'ssl://';
2031
                        $port = 443;
2032
                        break;
2033
                    case 'http':
2034
                    default:
2035
                        $scheme = '';
2036
                        $port = 80;
2037
                }
2038
2039
                //Check fsockopen (not sure it works with https). If that is your case, you might want to try the
2040
                // suggestion at https://support.chamilo.org/issues/8260#note-3 (although it ignores SSL peer checks)
2041
                if ($fp = @fsockopen(str_replace('http://', $scheme, $url), $port, $sock_errno, $sock_errmsg, 60)) {
2042
                    $out = "GET $path HTTP/1.1\r\n";
2043
                    $out .= "Host: $host\r\n";
2044
                    $out .= "Connection: Close\r\n\r\n";
2045
2046
                    fwrite($fp, $out);
2047
                    while (!feof($fp)) {
2048
                        $result = str_replace("\r\n", '', fgets($fp, 128));
2049
                        if (!empty($result) && $result == '123') {
2050
                            $output = true;
2051
                        }
2052
                    }
2053
                    fclose($fp);
2054
                } elseif (ini_get('allow_url_fopen')) {
2055
                    // Check allow_url_fopen
2056
                    if ($fp = @fopen($url, 'r')) {
2057
                        while ($result = fgets($fp, 1024)) {
2058
                            if (!empty($result) && $result == '123') {
2059
                                $output = true;
2060
                            }
2061
                        }
2062
                        fclose($fp);
2063
                    }
2064
                } elseif (function_exists('curl_init')) {
2065
                    // Check if has support for cURL
2066
                    $ch = curl_init();
2067
                    curl_setopt($ch, CURLOPT_HEADER, 0);
2068
                    curl_setopt($ch, CURLOPT_URL, $url);
2069
                    //curl_setopt($ch, CURLOPT_TIMEOUT, 30);
2070
                    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
2071
                    $result = curl_exec($ch);
2072
                    if (!empty($result) && $result == '123') {
2073
                        $output = true;
2074
                    }
2075
                    curl_close($ch);
2076
                }
2077
            }
2078
            @fclose($handler);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for fclose(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

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

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

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

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

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
2079
        }
2080
    }
2081
2082
    return $output;
2083
}
2084
2085
/**
2086
 * Save settings values.
2087
 *
2088
 * @param string $organizationName
2089
 * @param string $organizationUrl
2090
 * @param string $siteName
2091
 * @param string $adminEmail
2092
 * @param string $adminLastName
2093
 * @param string $adminFirstName
2094
 * @param string $language
2095
 * @param string $allowRegistration
2096
 * @param string $allowTeacherSelfRegistration
2097
 * @param string $installationProfile          The name of an installation profile file in main/install/profiles/
2098
 */
2099
function installSettings(
2100
    $organizationName,
2101
    $organizationUrl,
2102
    $siteName,
2103
    $adminEmail,
2104
    $adminLastName,
2105
    $adminFirstName,
2106
    $language,
2107
    $allowRegistration,
2108
    $allowTeacherSelfRegistration,
2109
    $installationProfile = ''
2110
) {
2111
    $allowTeacherSelfRegistration = $allowTeacherSelfRegistration ? 'true' : 'false';
2112
2113
    $settings = [
2114
        'institution' => $organizationName,
2115
        'institution_url' => $organizationUrl,
2116
        'site_name' => $siteName,
2117
        'administrator_email' => $adminEmail,
2118
        'administrator_surname' => $adminLastName,
2119
        'administrator_name' => $adminFirstName,
2120
        'platform_language' => $language,
2121
        'allow_registration' => $allowRegistration,
2122
        'allow_registration_as_teacher' => $allowTeacherSelfRegistration,
2123
    ];
2124
2125
    foreach ($settings as $variable => $value) {
2126
        $sql = "UPDATE settings_current
2127
                SET selected_value = '$value'
2128
                WHERE variable = '$variable'";
2129
        Database::query($sql);
2130
    }
2131
    installProfileSettings($installationProfile);
2132
}
2133
2134
/**
2135
 * Executes DB changes based in the classes defined in
2136
 * src/Chamilo/CoreBundle/Migrations/Schema/*.
2137
 *
2138
 * @param string        $chamiloVersion
2139
 * @param EntityManager $manager
2140
 *
2141
 * @throws \Doctrine\DBAL\DBALException
2142
 *
2143
 * @return bool
2144
 */
2145
function migrate($chamiloVersion, EntityManager $manager)
2146
{
2147
    $debug = true;
2148
    $connection = $manager->getConnection();
2149
2150
    $config = new \Doctrine\DBAL\Migrations\Configuration\Configuration($connection);
2151
2152
    // Table name that will store migrations log (will be created automatically,
2153
    // default name is: doctrine_migration_versions)
2154
    $config->setMigrationsTableName('version');
2155
    // Namespace of your migration classes, do not forget escape slashes, do not add last slash
2156
    $config->setMigrationsNamespace('Application\Migrations\Schema\V'.$chamiloVersion);
2157
    // Directory where your migrations are located
2158
    $config->setMigrationsDirectory(api_get_path(SYS_PATH).'app/Migrations/Schema/V'.$chamiloVersion);
2159
    // Load your migrations
2160
    $config->registerMigrationsFromDirectory($config->getMigrationsDirectory());
2161
2162
    $migration = new \Doctrine\DBAL\Migrations\Migration($config);
2163
    $versions = $config->getMigrations();
2164
2165
    /** @var Doctrine\DBAL\Migrations\Version $migrationItem */
2166
    foreach ($versions as $version) {
2167
        $version->getMigration()->setEntityManager($manager);
2168
    }
2169
2170
    $to = null; // if $to == null then schema will be migrated to latest version
2171
2172
    echo "<pre>";
2173
    try {
2174
        // Execute migration!
2175
        $migratedSQL = $migration->migrate($to);
2176
2177
        if ($debug) {
2178
            foreach ($migratedSQL as $version => $sqlList) {
2179
                echo "VERSION: $version<br>";
2180
                echo "----------------------------------------------<br>";
2181
                $total = count($sqlList);
2182
                error_log("VERSION: $version");
2183
                error_log("# queries: ".$total);
2184
                $counter = 1;
2185
                foreach ($sqlList as $sql) {
2186
                    echo "<code>$sql</code><br>";
2187
                    error_log("$counter/$total : $sql");
2188
                    $counter++;
2189
                }
2190
            }
2191
2192
            echo "<br>DONE!<br>";
2193
        }
2194
2195
        return true;
2196
    } catch (Exception $ex) {
2197
        if ($debug) {
2198
            echo "ERROR: {$ex->getMessage()}<br>";
2199
2200
            return false;
2201
        }
2202
    }
2203
2204
    echo "</pre>";
2205
2206
    return false;
2207
}
2208
2209
/**
2210
 * @param EntityManager $em
2211
 *
2212
 * @throws \Doctrine\DBAL\DBALException
2213
 */
2214
function fixIds(EntityManager $em)
2215
{
2216
    $connection = $em->getConnection();
2217
    $database = new Database();
2218
    $database->setManager($em);
2219
    $debug = true;
2220
    if ($debug) {
2221
        error_log('fixIds');
2222
    }
2223
2224
    // Create temporary indexes to increase speed of the following operations
2225
    // Adding and removing indexes will usually take much less time than
2226
    // the execution without indexes of the queries in this function, particularly
2227
    // for large tables
2228
    $sql = "ALTER TABLE c_document ADD INDEX tmpidx_doc(c_id, id)";
2229
    $connection->executeQuery($sql);
2230
    $sql = "ALTER TABLE c_student_publication ADD INDEX tmpidx_stud (c_id, id)";
2231
    $connection->executeQuery($sql);
2232
    $sql = "ALTER TABLE c_quiz ADD INDEX tmpidx_quiz (c_id, id)";
2233
    $connection->executeQuery($sql);
2234
    $sql = "ALTER TABLE c_item_property ADD INDEX tmpidx_ip (to_group_id)";
2235
    $connection->executeQuery($sql);
2236
2237
    $sql = "SELECT * FROM c_lp_item";
2238
    $result = $connection->fetchAll($sql);
2239
    foreach ($result as $item) {
2240
        $courseId = $item['c_id'];
2241
        $iid = isset($item['iid']) ? intval($item['iid']) : 0;
2242
        $ref = isset($item['ref']) ? intval($item['ref']) : 0;
2243
        $sql = null;
2244
2245
        $newId = '';
2246
2247
        switch ($item['item_type']) {
2248
            case TOOL_LINK:
2249
                $sql = "SELECT * FROM c_link WHERE c_id = $courseId AND id = $ref";
2250
                $data = $connection->fetchAssoc($sql);
2251
                if ($data) {
2252
                    $newId = $data['iid'];
2253
                }
2254
                break;
2255
            case TOOL_STUDENTPUBLICATION:
2256
                $sql = "SELECT * FROM c_student_publication WHERE c_id = $courseId AND id = $ref";
2257
                $data = $connection->fetchAssoc($sql);
2258
                if ($data) {
2259
                    $newId = $data['iid'];
2260
                }
2261
                break;
2262
            case TOOL_QUIZ:
2263
                $sql = "SELECT * FROM c_quiz WHERE c_id = $courseId AND id = $ref";
2264
                $data = $connection->fetchAssoc($sql);
2265
                if ($data) {
2266
                    $newId = $data['iid'];
2267
                }
2268
                break;
2269
            case TOOL_DOCUMENT:
2270
                $sql = "SELECT * FROM c_document WHERE c_id = $courseId AND id = $ref";
2271
                $data = $connection->fetchAssoc($sql);
2272
                if ($data) {
2273
                    $newId = $data['iid'];
2274
                }
2275
                break;
2276
            case TOOL_FORUM:
2277
                $sql = "SELECT * FROM c_forum_forum WHERE c_id = $courseId AND forum_id = $ref";
2278
                $data = $connection->fetchAssoc($sql);
2279
                if ($data) {
2280
                    $newId = $data['iid'];
2281
                }
2282
                break;
2283
            case 'thread':
2284
                $sql = "SELECT * FROM c_forum_thread WHERE c_id = $courseId AND thread_id = $ref";
2285
                $data = $connection->fetchAssoc($sql);
2286
                if ($data) {
2287
                    $newId = $data['iid'];
2288
                }
2289
                break;
2290
        }
2291
2292
        if (!empty($sql) && !empty($newId) && !empty($iid)) {
2293
            $sql = "UPDATE c_lp_item SET ref = $newId WHERE iid = $iid";
2294
            $connection->executeQuery($sql);
2295
        }
2296
    }
2297
2298
    // Set NULL if session = 0
2299
    $sql = "UPDATE c_item_property SET session_id = NULL WHERE session_id = 0";
2300
    $connection->executeQuery($sql);
2301
2302
    // Set NULL if group = 0
2303
    $sql = "UPDATE c_item_property SET to_group_id = NULL WHERE to_group_id = 0";
2304
    $connection->executeQuery($sql);
2305
2306
    // Set NULL if insert_user_id = 0
2307
    $sql = "UPDATE c_item_property SET insert_user_id = NULL WHERE insert_user_id = 0";
2308
    $connection->executeQuery($sql);
2309
2310
    // Delete session data of sessions that don't exist.
2311
    $sql = "DELETE FROM c_item_property
2312
            WHERE session_id IS NOT NULL AND session_id NOT IN (SELECT id FROM session)";
2313
    $connection->executeQuery($sql);
2314
2315
    // Delete group data of groups that don't exist.
2316
    $sql = "DELETE FROM c_item_property
2317
            WHERE to_group_id IS NOT NULL AND to_group_id NOT IN (SELECT DISTINCT id FROM c_group_info)";
2318
    $connection->executeQuery($sql);
2319
2320
    // This updates the group_id with c_group_info.iid instead of c_group_info.id
2321
2322
    if ($debug) {
2323
        error_log('update iids');
2324
    }
2325
2326
    $groupTableToFix = [
2327
        'c_group_rel_user',
2328
        'c_group_rel_tutor',
2329
        'c_permission_group',
2330
        'c_role_group',
2331
        'c_survey_invitation',
2332
        'c_attendance_calendar_rel_group',
2333
    ];
2334
2335
    foreach ($groupTableToFix as $table) {
2336
        $sql = "SELECT * FROM $table";
2337
        $result = $connection->fetchAll($sql);
2338
        foreach ($result as $item) {
2339
            $iid = $item['iid'];
2340
            $courseId = $item['c_id'];
2341
            $groupId = intval($item['group_id']);
2342
2343
            // Fix group id
2344
            if (!empty($groupId)) {
2345
                $sql = "SELECT * FROM c_group_info
2346
                        WHERE c_id = $courseId AND id = $groupId
2347
                        LIMIT 1";
2348
                $data = $connection->fetchAssoc($sql);
2349
                if (!empty($data)) {
2350
                    $newGroupId = $data['iid'];
2351
                    $sql = "UPDATE $table SET group_id = $newGroupId
2352
                            WHERE iid = $iid";
2353
                    $connection->executeQuery($sql);
2354
                } else {
2355
                    // The group does not exists clean this record
2356
                    $sql = "DELETE FROM $table WHERE iid = $iid";
2357
                    $connection->executeQuery($sql);
2358
                }
2359
            }
2360
        }
2361
    }
2362
2363
    // Fix c_item_property
2364
    if ($debug) {
2365
        error_log('update c_item_property');
2366
    }
2367
2368
    $sql = "SELECT * FROM course";
2369
    $courseList = $connection->fetchAll($sql);
2370
    if ($debug) {
2371
        error_log('Getting course list');
2372
    }
2373
2374
    $totalCourse = count($courseList);
2375
    $counter = 0;
2376
2377
    foreach ($courseList as $courseData) {
2378
        $courseId = $courseData['id'];
2379
        if ($debug) {
2380
            error_log('Updating course: '.$courseData['code']);
2381
        }
2382
2383
        $sql = "SELECT * FROM c_item_property WHERE c_id = $courseId";
2384
        $result = $connection->fetchAll($sql);
2385
        foreach ($result as $item) {
2386
            $sessionId = intval($item['session_id']);
2387
            $groupId = intval($item['to_group_id']);
2388
            $iid = $item['iid'];
2389
            $ref = $item['ref'];
2390
2391
            // Fix group id
2392
            if (!empty($groupId)) {
2393
                $sql = "SELECT * FROM c_group_info
2394
                        WHERE c_id = $courseId AND id = $groupId";
2395
                $data = $connection->fetchAssoc($sql);
2396
                if (!empty($data)) {
2397
                    $newGroupId = $data['iid'];
2398
                    $sql = "UPDATE c_item_property SET to_group_id = $newGroupId
2399
                            WHERE iid = $iid";
2400
                    $connection->executeQuery($sql);
2401
                } else {
2402
                    // The group does not exists clean this record
2403
                    $sql = "DELETE FROM c_item_property WHERE iid = $iid";
2404
                    $connection->executeQuery($sql);
2405
                }
2406
            }
2407
2408
            $sql = '';
2409
            $newId = '';
2410
            switch ($item['tool']) {
2411
                case TOOL_LINK:
2412
                    $sql = "SELECT * FROM c_link WHERE c_id = $courseId AND id = $ref ";
2413
                    break;
2414
                case TOOL_STUDENTPUBLICATION:
2415
                    $sql = "SELECT * FROM c_student_publication WHERE c_id = $courseId AND id = $ref";
2416
                    break;
2417
                case TOOL_QUIZ:
2418
                    $sql = "SELECT * FROM c_quiz WHERE c_id = $courseId AND id = $ref";
2419
                    break;
2420
                case TOOL_DOCUMENT:
2421
                    $sql = "SELECT * FROM c_document WHERE c_id = $courseId AND id = $ref";
2422
                    break;
2423
                case TOOL_FORUM:
2424
                    $sql = "SELECT * FROM c_forum_forum WHERE c_id = $courseId AND id = $ref";
2425
                    break;
2426
                case 'thread':
2427
                    $sql = "SELECT * FROM c_forum_thread WHERE c_id = $courseId AND id = $ref";
2428
                    break;
2429
            }
2430
2431
            if (!empty($sql) && !empty($newId)) {
2432
                $data = $connection->fetchAssoc($sql);
2433
                if (isset($data['iid'])) {
2434
                    $newId = $data['iid'];
2435
                }
2436
                $sql = "UPDATE c_item_property SET ref = $newId WHERE iid = $iid";
2437
                error_log($sql);
2438
                $connection->executeQuery($sql);
2439
            }
2440
        }
2441
2442
        if ($debug) {
2443
            // Print a status in the log once in a while
2444
            error_log("Course process #$counter/$totalCourse");
2445
        }
2446
        $counter++;
2447
    }
2448
2449
    if ($debug) {
2450
        error_log('update gradebook_link');
2451
    }
2452
2453
    // Fix gradebook_link
2454
    $sql = "SELECT * FROM gradebook_link";
2455
    $result = $connection->fetchAll($sql);
2456
    foreach ($result as $item) {
2457
        $courseCode = $item['course_code'];
2458
        $categoryId = (int) $item['category_id'];
2459
2460
        $sql = "SELECT * FROM course WHERE code = '$courseCode'";
2461
        $courseInfo = $connection->fetchAssoc($sql);
2462
        if (empty($courseInfo)) {
2463
            continue;
2464
        }
2465
2466
        $courseId = $courseInfo['id'];
2467
2468
        $ref = $item['ref_id'];
2469
        $iid = $item['id'];
2470
2471
        $sql = '';
2472
        switch ($item['type']) {
2473
            case LINK_LEARNPATH:
2474
                $sql = "SELECT * FROM c_link WHERE c_id = $courseId AND id = $ref ";
2475
                break;
2476
            case LINK_STUDENTPUBLICATION:
2477
                $sql = "SELECT * FROM c_student_publication WHERE c_id = $courseId AND id = $ref";
2478
                break;
2479
            case LINK_EXERCISE:
2480
                $sql = "SELECT * FROM c_quiz WHERE c_id = $courseId AND id = $ref";
2481
                break;
2482
            case LINK_ATTENDANCE:
2483
                //$sql = "SELECT * FROM c_document WHERE c_id = $courseId AND id = $ref";
2484
                break;
2485
            case LINK_FORUM_THREAD:
2486
                $sql = "SELECT * FROM c_forum_thread WHERE c_id = $courseId AND thread_id = $ref";
2487
                break;
2488
        }
2489
2490
        if (!empty($sql)) {
2491
            $data = $connection->fetchAssoc($sql);
2492
            if (isset($data) && isset($data['iid'])) {
2493
                $newId = $data['iid'];
2494
                $sql = "UPDATE gradebook_link SET ref_id = $newId
2495
                        WHERE id = $iid AND course_code = '$courseCode' AND category_id = $categoryId ";
2496
                $connection->executeQuery($sql);
2497
            }
2498
        }
2499
    }
2500
2501
    if ($debug) {
2502
        error_log('update groups');
2503
    }
2504
2505
    $sql = "SELECT * FROM groups";
2506
    $result = $connection->executeQuery($sql);
2507
    $groups = $result->fetchAll();
2508
    $oldGroups = [];
2509
    if (!empty($groups)) {
2510
        foreach ($groups as $group) {
2511
            if (empty($group['name'])) {
2512
                continue;
2513
            }
2514
2515
            $params = [
2516
                'name' => $group['name'],
2517
                'description' => $group['description'],
2518
                'group_type' => 1,
2519
                'picture' => $group['picture_uri'],
2520
                'url' => $group['url'],
2521
                'visibility' => $group['visibility'],
2522
                'updated_at' => $group['updated_on'],
2523
                'created_at' => $group['created_on'],
2524
            ];
2525
            $connection->insert('usergroup', $params);
2526
            $id = $connection->lastInsertId('id');
2527
            $oldGroups[$group['id']] = $id;
2528
        }
2529
    }
2530
2531
    if (!empty($oldGroups)) {
2532
        error_log('Moving group files');
2533
        foreach ($oldGroups as $oldId => $newId) {
2534
            $path = get_group_picture_path_by_id(
2535
                $oldId,
2536
                'system'
2537
            );
2538
2539
            if (!empty($path)) {
2540
                $newPath = str_replace(
2541
                    "groups/$oldId/",
2542
                    "groups/$newId/",
2543
                    $path['dir']
2544
                );
2545
                $command = "mv {$path['dir']} $newPath ";
2546
                error_log("Executing $command");
2547
                system($command);
2548
            }
2549
        }
2550
2551
        $sql = "SELECT * FROM group_rel_user";
2552
        $result = $connection->executeQuery($sql);
2553
        $dataList = $result->fetchAll();
2554
2555
        if (!empty($dataList)) {
2556
            foreach ($dataList as $data) {
2557
                if (isset($oldGroups[$data['group_id']])) {
2558
                    $data['group_id'] = $oldGroups[$data['group_id']];
2559
                    $userId = $data['user_id'];
2560
2561
                    $sql = "SELECT id FROM user WHERE user_id = $userId";
2562
                    $userResult = $connection->executeQuery($sql);
2563
                    $userInfo = $userResult->fetch();
2564
                    if (empty($userInfo)) {
2565
                        continue;
2566
                    }
2567
2568
                    $sql = "INSERT INTO usergroup_rel_user (usergroup_id, user_id, relation_type)
2569
                            VALUES ('{$data['group_id']}', '{$userId}', '{$data['relation_type']}')";
2570
                    $connection->executeQuery($sql);
2571
                }
2572
            }
2573
        }
2574
2575
        $sql = "SELECT * FROM group_rel_group";
2576
        $result = $connection->executeQuery($sql);
2577
        $dataList = $result->fetchAll();
2578
2579
        if (!empty($dataList)) {
2580
            foreach ($dataList as $data) {
2581
                if (isset($oldGroups[$data['group_id']]) && isset($oldGroups[$data['subgroup_id']])) {
2582
                    $data['group_id'] = $oldGroups[$data['group_id']];
2583
                    $data['subgroup_id'] = $oldGroups[$data['subgroup_id']];
2584
                    $sql = "INSERT INTO usergroup_rel_usergroup (group_id, subgroup_id, relation_type)
2585
                            VALUES ('{$data['group_id']}', '{$data['subgroup_id']}', '{$data['relation_type']}')";
2586
                    $connection->executeQuery($sql);
2587
                }
2588
            }
2589
        }
2590
2591
        $sql = "SELECT * FROM announcement_rel_group";
2592
        $result = $connection->executeQuery($sql);
2593
        $dataList = $result->fetchAll();
2594
2595
        if (!empty($dataList)) {
2596
            foreach ($dataList as $data) {
2597
                if (isset($oldGroups[$data['group_id']])) {
2598
                    // Deleting relation
2599
                    $sql = "DELETE FROM announcement_rel_group WHERE group_id = {$data['group_id']}";
2600
                    $connection->executeQuery($sql);
2601
2602
                    // Add new relation
2603
                    $data['group_id'] = $oldGroups[$data['group_id']];
2604
                    $sql = "INSERT INTO announcement_rel_group(group_id, announcement_id)
2605
                            VALUES ('{$data['group_id']}', '{$data['announcement_id']}')";
2606
                    $connection->executeQuery($sql);
2607
                }
2608
            }
2609
        }
2610
2611
        $sql = "SELECT * FROM group_rel_tag";
2612
        $result = $connection->executeQuery($sql);
2613
        $dataList = $result->fetchAll();
2614
        if (!empty($dataList)) {
2615
            foreach ($dataList as $data) {
2616
                if (isset($oldGroups[$data['group_id']])) {
2617
                    $data['group_id'] = $oldGroups[$data['group_id']];
2618
                    $sql = "INSERT INTO usergroup_rel_tag (tag_id, usergroup_id)
2619
                            VALUES ('{$data['tag_id']}', '{$data['group_id']}')";
2620
                    $connection->executeQuery($sql);
2621
                }
2622
            }
2623
        }
2624
    }
2625
2626
    if ($debug) {
2627
        error_log('update extra fields');
2628
    }
2629
2630
    // Extra fields
2631
    $extraFieldTables = [
2632
        ExtraField::USER_FIELD_TYPE => Database::get_main_table(TABLE_MAIN_USER_FIELD),
2633
        ExtraField::COURSE_FIELD_TYPE => Database::get_main_table(TABLE_MAIN_COURSE_FIELD),
2634
        //ExtraField::LP_FIELD_TYPE => Database::get_main_table(TABLE_MAIN_LP_FIELD),
2635
        ExtraField::SESSION_FIELD_TYPE => Database::get_main_table(TABLE_MAIN_SESSION_FIELD),
2636
        //ExtraField::CALENDAR_FIELD_TYPE => Database::get_main_table(TABLE_MAIN_CALENDAR_EVENT_FIELD),
2637
        //ExtraField::QUESTION_FIELD_TYPE => Database::get_main_table(TABLE_MAIN_CALENDAR_EVENT_FIELD),
2638
        //ExtraField::USER_FIELD_TYPE => //Database::get_main_table(TABLE_MAIN_SPECIFIC_FIELD),
2639
    ];
2640
2641
    foreach ($extraFieldTables as $type => $table) {
2642
        $sql = "SELECT * FROM $table ";
2643
        if ($debug) {
2644
            error_log($sql);
2645
        }
2646
        $result = $connection->query($sql);
2647
        $fields = $result->fetchAll();
2648
2649
        foreach ($fields as $field) {
2650
            if ($debug) {
2651
                error_log("Loading field: ".$field['field_variable']);
2652
            }
2653
            $originalId = $field['id'];
2654
2655
            $params = [
2656
                'extra_field_type' => $type,
2657
                'variable' => $field['field_variable'],
2658
                'field_type' => $field['field_type'],
2659
                'display_text' => $field['field_display_text'],
2660
                'default_value' => $field['field_default_value'],
2661
                'field_order' => $field['field_order'],
2662
                'visible' => $field['field_visible'],
2663
                'changeable' => $field['field_changeable'],
2664
                'filter' => $field['field_filter'],
2665
            ];
2666
2667
            $connection->insert('extra_field', $params);
2668
            $newExtraFieldId = $connection->lastInsertId();
2669
2670
            $values = [];
2671
            $handlerId = null;
2672
            switch ($type) {
2673
                case ExtraField::USER_FIELD_TYPE:
2674
                    $optionTable = Database::get_main_table(
2675
                        TABLE_MAIN_USER_FIELD_OPTIONS
2676
                    );
2677
                    $valueTable = Database::get_main_table(
2678
                        TABLE_MAIN_USER_FIELD_VALUES
2679
                    );
2680
                    $handlerId = 'user_id';
2681
                    break;
2682
                case ExtraField::COURSE_FIELD_TYPE:
2683
                    $optionTable = Database::get_main_table(
2684
                        TABLE_MAIN_COURSE_FIELD_OPTIONS
2685
                    );
2686
                    $valueTable = Database::get_main_table(
2687
                        TABLE_MAIN_COURSE_FIELD_VALUES
2688
                    );
2689
                    $handlerId = 'c_id';
2690
                    break;
2691
                case ExtraField::SESSION_FIELD_TYPE:
2692
                    $optionTable = Database::get_main_table(
2693
                        TABLE_MAIN_SESSION_FIELD_OPTIONS
2694
                    );
2695
                    $valueTable = Database::get_main_table(
2696
                        TABLE_MAIN_SESSION_FIELD_VALUES
2697
                    );
2698
                    $handlerId = 'session_id';
2699
                    break;
2700
            }
2701
2702
            if (!empty($optionTable)) {
2703
                $sql = "SELECT * FROM $optionTable WHERE field_id = $originalId ";
2704
                $result = $connection->query($sql);
2705
                $options = $result->fetchAll();
2706
2707
                foreach ($options as $option) {
2708
                    $params = [
2709
                        'display_text' => $option['option_display_text'],
2710
                        'field_id' => $newExtraFieldId,
2711
                        'option_order' => $option['option_order'],
2712
                        'option_value' => $option['option_value'],
2713
                    ];
2714
                    $connection->insert('extra_field_options', $params);
2715
                }
2716
2717
                $sql = "SELECT * FROM $valueTable WHERE field_id = $originalId ";
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $valueTable does not seem to be defined for all execution paths leading up to this point.
Loading history...
2718
                $result = $connection->query($sql);
2719
                $values = $result->fetchAll();
2720
                if ($debug) {
2721
                    error_log("Fetch all values for field");
2722
                }
2723
            }
2724
2725
            if (!empty($values)) {
2726
                if ($debug) {
2727
                    error_log("Saving field value in new table");
2728
                }
2729
                $k = 0;
2730
                foreach ($values as $value) {
2731
                    if (isset($value[$handlerId])) {
2732
                        // Insert without the use of the entity as it reduces
2733
                        // speed to 2 records per second (much too slow)
2734
                        $params = [
2735
                            'field_id' => $newExtraFieldId,
2736
                            'value' => $value['field_value'],
2737
                            'item_id' => $value[$handlerId],
2738
                        ];
2739
                        $connection->insert('extra_field_values', $params);
2740
                        if ($debug && ($k % 10000 == 0)) {
2741
                            error_log("Saving field $k");
2742
                        }
2743
                        $k++;
2744
                    }
2745
                }
2746
            }
2747
        }
2748
    }
2749
2750
    if ($debug) {
0 ignored issues
show
introduced by
$debug is of type mixed, thus it always evaluated to true.
Loading history...
2751
        error_log('Remove index');
2752
    }
2753
2754
    // Drop temporary indexes added to increase speed of this function's queries
2755
    $sql = "ALTER TABLE c_document DROP INDEX tmpidx_doc";
2756
    $connection->executeQuery($sql);
2757
    $sql = "ALTER TABLE c_student_publication DROP INDEX tmpidx_stud";
2758
    $connection->executeQuery($sql);
2759
    $sql = "ALTER TABLE c_quiz DROP INDEX tmpidx_quiz";
2760
    $connection->executeQuery($sql);
2761
    $sql = "ALTER TABLE c_item_property DROP INDEX tmpidx_ip";
2762
    $connection->executeQuery($sql);
2763
2764
    if ($debug) {
2765
        error_log('Finish fixId function');
2766
    }
2767
2768
    fixLpId($connection, true);
2769
}
2770
2771
/**
2772
 * @param \Doctrine\DBAL\Connection $connection
2773
 * @param $debug
2774
 *
2775
 * @throws \Doctrine\DBAL\DBALException
2776
 */
2777
function fixLpId($connection, $debug)
2778
{
2779
    if ($debug) {
2780
        error_log('Fix lp.id lp.iids');
2781
    }
2782
2783
    $sql = 'SELECT id, title, code FROM course';
2784
    $result = $connection->query($sql);
2785
    $courses = $result->fetchAll();
2786
2787
    $sql = 'SELECT id FROM session';
2788
    $result = $connection->query($sql);
2789
    $sessions = $result->fetchAll();
2790
2791
    $tblCLp = Database::get_course_table(TABLE_LP_MAIN);
2792
    $tblCLpItem = Database::get_course_table(TABLE_LP_ITEM);
2793
    $toolTable = Database::get_course_table(TABLE_TOOL_LIST);
2794
2795
    if (!empty($sessions)) {
2796
        $sessions = array_column($sessions, 'id');
2797
        $sessions[] = 0;
2798
    } else {
2799
        $sessions = [0];
2800
    }
2801
2802
    foreach ($courses as $course) {
2803
        $courseId = $course['id'];
2804
        $sql = "SELECT * FROM $tblCLp WHERE c_id = $courseId AND iid <> id ORDER by iid";
2805
        $result = $connection->query($sql);
2806
        if ($debug) {
2807
            error_log('-------------');
2808
            error_log("Entering Lps in course #$courseId");
2809
            error_log($sql);
2810
        }
2811
        $lpList = $result->fetchAll();
2812
        $myOnlyLpList = [];
2813
        if (!empty($lpList)) {
2814
            foreach ($lpList as $lpInfo) {
2815
                $oldId = $lpInfo['id'];
2816
                $sql = "SELECT * FROM $tblCLpItem WHERE c_id = $courseId AND lp_id = $oldId ORDER by iid";
2817
                $result = $connection->query($sql);
2818
                $items = $result->fetchAll();
2819
                $lpInfo['lp_list'] = $items;
2820
                $myOnlyLpList[] = $lpInfo;
2821
            }
2822
        }
2823
2824
        if (!empty($myOnlyLpList)) {
2825
            foreach ($myOnlyLpList as $lpInfo) {
2826
                $lpIid = $lpInfo['iid'];
2827
                $oldId = $lpInfo['id'];
2828
                $items = $lpInfo['lp_list'];
2829
2830
                if (empty($items)) {
2831
                    continue;
2832
                }
2833
                $itemList = [];
2834
                foreach ($items as $subItem) {
2835
                    $itemList[$subItem['id']] = $subItem['iid'];
2836
                }
2837
                $variablesToFix = [
2838
                    'parent_item_id',
2839
                    'next_item_id',
2840
                    'prerequisite',
2841
                    'previous_item_id',
2842
                ];
2843
2844
                foreach ($sessions as $sessionId) {
2845
                    $correctLink = "lp/lp_controller.php?action=view&lp_id=$lpIid&id_session=$sessionId";
2846
                    $link = "newscorm/lp_controller.php?action=view&lp_id=$oldId&id_session=$sessionId";
2847
                    $secondLink = "lp/lp_controller.php?action=view&lp_id=$oldId&id_session=$sessionId";
2848
                    $sql = "UPDATE $toolTable 
2849
                        SET link = '$correctLink'
2850
                        WHERE c_id = $courseId AND (link = '$link' OR link ='$secondLink')";
2851
                    $connection->query($sql);
2852
                    if ($debug) {
0 ignored issues
show
Unused Code introduced by
This if statement is empty and can be removed.

This check looks for the bodies of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These if bodies can be removed. If you have an empty if but statements in the else branch, consider inverting the condition.

if (rand(1, 6) > 3) {
//print "Check failed";
} else {
    print "Check succeeded";
}

could be turned into

if (rand(1, 6) <= 3) {
    print "Check succeeded";
}

This is much more concise to read.

Loading history...
2853
                        //error_log("Fix wrong c_tool links");
2854
                        //error_log($sql);
2855
                    }
2856
                }
2857
2858
                foreach ($items as $item) {
2859
                    $itemIid = $item['iid'];
2860
                    $itemId = $item['id'];
2861
                    foreach ($variablesToFix as $variable) {
2862
                        if (!empty($item[$variable]) && isset($itemList[$item[$variable]])) {
2863
                            $newId = $itemList[$item[$variable]];
2864
                            $sql = "UPDATE $tblCLpItem SET $variable = $newId 
2865
                                    WHERE iid = $itemIid AND c_id = $courseId AND lp_id = $oldId";
2866
                            $connection->query($sql);
2867
                            if ($debug) {
0 ignored issues
show
Unused Code introduced by
This if statement is empty and can be removed.

This check looks for the bodies of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These if bodies can be removed. If you have an empty if but statements in the else branch, consider inverting the condition.

if (rand(1, 6) > 3) {
//print "Check failed";
} else {
    print "Check succeeded";
}

could be turned into

if (rand(1, 6) <= 3) {
    print "Check succeeded";
}

This is much more concise to read.

Loading history...
2868
                                //error_log($sql);
2869
                            }
2870
                        }
2871
                    }
2872
2873
                    if ($item['item_type'] == 'document' && !empty($item['path'])) {
2874
                        $oldDocumentId = $item['path'];
2875
                        $sql = "SELECT * FROM c_document WHERE c_id = $courseId AND id = $oldDocumentId";
2876
                        $result = $connection->query($sql);
2877
                        $document = $result->fetch();
2878
                        if (!empty($document)) {
2879
                            $newDocumentId = $document['iid'];
2880
                            if (!empty($newDocumentId)) {
2881
                                $sql = "UPDATE $tblCLpItem SET path = $newDocumentId 
2882
                                    WHERE iid = $itemIid AND c_id = $courseId";
2883
                                $connection->query($sql);
2884
                                if ($debug) {
0 ignored issues
show
Unused Code introduced by
This if statement is empty and can be removed.

This check looks for the bodies of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These if bodies can be removed. If you have an empty if but statements in the else branch, consider inverting the condition.

if (rand(1, 6) > 3) {
//print "Check failed";
} else {
    print "Check succeeded";
}

could be turned into

if (rand(1, 6) <= 3) {
    print "Check succeeded";
}

This is much more concise to read.

Loading history...
2885
                                    //error_log("Fix document: ");
2886
                                    //error_log($sql);
2887
                                }
2888
                            }
2889
                        }
2890
                    }
2891
2892
                    // c_lp_view
2893
                    $sql = "UPDATE c_lp_view SET last_item = $itemIid 
2894
                            WHERE c_id = $courseId AND last_item = $itemId AND lp_id = $oldId";
2895
                    $connection->query($sql);
2896
2897
                    // c_lp_item_view
2898
                    $sql = "UPDATE c_lp_item_view SET lp_item_id = $itemIid 
2899
                            WHERE c_id = $courseId AND lp_item_id = $itemId";
2900
                    $connection->query($sql);
2901
2902
                    // Update track_exercises
2903
                    $sql = "UPDATE track_e_exercises SET orig_lp_item_id = $itemIid 
2904
                            WHERE c_id = $courseId AND orig_lp_id = $oldId AND orig_lp_item_id = $itemId";
2905
                    $connection->query($sql);
2906
2907
                    // c_forum_thread
2908
                    $sql = "UPDATE c_forum_thread SET lp_item_id = $itemIid 
2909
                            WHERE c_id = $courseId AND lp_item_id = $itemId";
2910
                    $connection->query($sql);
2911
2912
                    // orig_lp_item_view_id
2913
                    $sql = "SELECT * FROM c_lp_view
2914
                            WHERE c_id = $courseId AND lp_id = $oldId";
2915
                    $result = $connection->query($sql);
2916
                    $itemViewList = $result->fetchAll();
2917
                    if ($itemViewList) {
2918
                        foreach ($itemViewList as $itemView) {
2919
                            $userId = $itemView['user_id'];
2920
                            $oldItemViewId = $itemView['id'];
2921
                            $newItemView = $itemView['iid'];
2922
2923
                            if (empty($oldItemViewId)) {
2924
                                continue;
2925
                            }
2926
2927
                            $sql = "UPDATE track_e_exercises 
2928
                                SET orig_lp_item_view_id = $newItemView 
2929
                                WHERE 
2930
                                  c_id = $courseId AND 
2931
                                  orig_lp_id = $oldId AND 
2932
                                  orig_lp_item_id = $itemIid AND 
2933
                                  orig_lp_item_view_id = $oldItemViewId AND 
2934
                                  exe_user_id = $userId                                       
2935
                                  ";
2936
                            $connection->query($sql);
2937
2938
                            /*$sql = "UPDATE c_lp_item_view
2939
                                    SET lp_view_id = $newItemView
2940
                                    WHERE
2941
                                      lp_view_id = $oldItemViewId AND
2942
                                      c_id = $courseId
2943
                                  ";
2944
                            $connection->query($sql);*/
2945
                        }
2946
                    }
2947
2948
                    $sql = "UPDATE $tblCLpItem SET lp_id = $lpIid 
2949
                            WHERE c_id = $courseId AND lp_id = $oldId AND id = $itemId";
2950
                    $connection->query($sql);
2951
2952
                    $sql = "UPDATE $tblCLpItem SET id = iid 
2953
                            WHERE c_id = $courseId AND lp_id = $oldId AND id = $itemId";
2954
                    $connection->query($sql);
2955
                }
2956
2957
                $sql = "UPDATE c_lp_view SET lp_id = $lpIid WHERE c_id = $courseId AND lp_id = $oldId";
2958
                $connection->query($sql);
2959
2960
                $sql = "UPDATE c_forum_forum SET lp_id = $lpIid WHERE c_id = $courseId AND lp_id = $oldId";
2961
                $connection->query($sql);
2962
2963
                // Update track_exercises.
2964
                $sql = "UPDATE track_e_exercises SET orig_lp_id = $lpIid 
2965
                        WHERE c_id = $courseId AND orig_lp_id = $oldId";
2966
                $connection->query($sql);
2967
2968
                $sql = "UPDATE $tblCLp SET id = iid WHERE c_id = $courseId AND id = $oldId ";
2969
                $connection->query($sql);
2970
            }
2971
        }
2972
    }
2973
2974
    if ($debug) {
2975
        error_log('END Fix lp.id lp.iids');
2976
    }
2977
}
2978
2979
/**
2980
 * @param string $distFile
2981
 * @param string $envFile
2982
 * @param array  $params
2983
 */
2984
function updateEnvFile($distFile, $envFile, $params)
2985
{
2986
    $contents = file_get_contents($distFile);
2987
    $contents = str_replace(array_keys($params), array_values($params), $contents);
2988
    file_put_contents($envFile, $contents);
2989
}
2990
2991
/**
2992
 * After the schema was created (table creation), the function adds
2993
 * admin/platform information.
2994
 *
2995
 * @param \Psr\Container\ContainerInterface $container
2996
 * @param string                            $sysPath
2997
 * @param string                            $encryptPassForm
2998
 * @param string                            $passForm
2999
 * @param string                            $adminLastName
3000
 * @param string                            $adminFirstName
3001
 * @param string                            $loginForm
3002
 * @param string                            $emailForm
3003
 * @param string                            $adminPhoneForm
3004
 * @param string                            $languageForm
3005
 * @param string                            $institutionForm
3006
 * @param string                            $institutionUrlForm
3007
 * @param string                            $siteName
3008
 * @param string                            $allowSelfReg
3009
 * @param string                            $allowSelfRegProf
3010
 * @param string                            $installationProfile Installation profile, if any was provided
3011
 */
3012
function finishInstallationWithContainer(
3013
    $container,
3014
    $sysPath,
3015
    $encryptPassForm,
3016
    $passForm,
3017
    $adminLastName,
3018
    $adminFirstName,
3019
    $loginForm,
3020
    $emailForm,
3021
    $adminPhoneForm,
3022
    $languageForm,
3023
    $institutionForm,
3024
    $institutionUrlForm,
3025
    $siteName,
3026
    $allowSelfReg,
3027
    $allowSelfRegProf,
3028
    $installationProfile = ''
3029
) {
3030
    $sysPath = !empty($sysPath) ? $sysPath : api_get_path(SYS_PATH);
3031
    Container::setContainer($container);
3032
    Container::setLegacyServices($container);
3033
3034
    $manager = Database::getManager();
3035
    $connection = $manager->getConnection();
3036
    $siteManager = Container::getSiteManager();
3037
    $settingsManager = Container::getSettingsManager();
3038
3039
    $sql = getVersionTable();
3040
3041
    // Add version table
3042
    $connection->executeQuery($sql);
3043
3044
    // Add tickets defaults
3045
    $ticketProject = new TicketProject();
3046
    $ticketProject
3047
        ->setId(1)
3048
        ->setName('Ticket System')
3049
        ->setInsertUserId(1);
3050
3051
    $manager->persist($ticketProject);
3052
    $manager->flush();
3053
3054
    $categories = [
3055
        get_lang('TicketEnrollment') => get_lang('TicketsAboutEnrollment'),
3056
        get_lang('TicketGeneralInformation') => get_lang('TicketsAboutGeneralInformation'),
3057
        get_lang('TicketRequestAndPapework') => get_lang('TicketsAboutRequestAndPapework'),
3058
        get_lang('TicketAcademicIncidence') => get_lang('TicketsAboutAcademicIncidence'),
3059
        get_lang('TicketVirtualCampus') => get_lang('TicketsAboutVirtualCampus'),
3060
        get_lang('TicketOnlineEvaluation') => get_lang('TicketsAboutOnlineEvaluation'),
3061
    ];
3062
3063
    $i = 1;
3064
    foreach ($categories as $category => $description) {
3065
        // Online evaluation requires a course
3066
        $ticketCategory = new TicketCategory();
3067
        $ticketCategory
3068
            ->setId($i)
3069
            ->setName($category)
3070
            ->setDescription($description)
3071
            ->setProject($ticketProject)
3072
            ->setInsertUserId(1);
3073
3074
        $isRequired = $i == 6;
3075
        $ticketCategory->setCourseRequired($isRequired);
3076
3077
        $manager->persist($ticketCategory);
3078
        $manager->flush();
3079
3080
        $i++;
3081
    }
3082
3083
    // Default Priorities
3084
    $defaultPriorities = [
3085
        TicketManager::PRIORITY_NORMAL => get_lang('PriorityNormal'),
3086
        TicketManager::PRIORITY_HIGH => get_lang('PriorityHigh'),
3087
        TicketManager::PRIORITY_LOW => get_lang('PriorityLow'),
3088
    ];
3089
3090
    $i = 1;
3091
    foreach ($defaultPriorities as $code => $priority) {
3092
        $ticketPriority = new TicketPriority();
3093
        $ticketPriority
3094
            ->setId($i)
3095
            ->setName($priority)
3096
            ->setCode($code)
3097
            ->setInsertUserId(1);
3098
3099
        $manager->persist($ticketPriority);
3100
        $manager->flush();
3101
        $i++;
3102
    }
3103
3104
    $table = Database::get_main_table(TABLE_TICKET_STATUS);
3105
3106
    // Default status
3107
    $defaultStatus = [
3108
        TicketManager::STATUS_NEW => get_lang('StatusNew'),
3109
        TicketManager::STATUS_PENDING => get_lang('StatusPending'),
3110
        TicketManager::STATUS_UNCONFIRMED => get_lang('StatusUnconfirmed'),
3111
        TicketManager::STATUS_CLOSE => get_lang('StatusClose'),
3112
        TicketManager::STATUS_FORWARDED => get_lang('StatusForwarded'),
3113
    ];
3114
3115
    $i = 1;
3116
    foreach ($defaultStatus as $code => $status) {
3117
        $attributes = [
3118
            'id' => $i,
3119
            'code' => $code,
3120
            'name' => $status,
3121
        ];
3122
        Database::insert($table, $attributes);
3123
        $i++;
3124
    }
3125
3126
    // Creating AccessUrl
3127
    $accessUrl = new AccessUrl();
3128
    $accessUrl
3129
        ->setUrl('http://localhost/')
3130
        ->setDescription('')
3131
        ->setActive(1)
3132
    ;
3133
    $manager->persist($accessUrl);
3134
    $manager->flush();
3135
3136
    // Creating settings
3137
    $settingsManager->installSchemas($accessUrl);
3138
3139
    // Inserting data
3140
    $data = file_get_contents($sysPath.'main/install/data.sql');
3141
    $result = $manager->getConnection()->prepare($data);
3142
    $result->execute();
3143
    $result->closeCursor();
3144
3145
    // Create site
3146
3147
    /** @var Chamilo\PageBundle\Entity\Site $site */
3148
    $site = $siteManager->create();
3149
    $site->setHost('localhost');
3150
    $site->setEnabled(true);
3151
    $site->setName('localhost');
3152
    $site->setEnabledFrom(new \DateTime('now'));
3153
    $site->setEnabledTo(new \DateTime('+20 years'));
3154
    $site->setRelativePath('');
3155
    $site->setIsDefault(true);
3156
    $siteManager->save($site);
3157
3158
    // Create home page
3159
    /** @var PageManager $pageManager */
3160
    $pageManager = $container->get('sonata.page.manager.page');
3161
    /** @var \Sonata\PageBundle\Model\Page $page */
3162
    $page = $pageManager->create();
3163
    $page->setSlug('homepage');
3164
    $page->setUrl('/');
3165
    $page->setName('homepage');
3166
    $page->setTitle('home');
3167
    $page->setEnabled(true);
3168
    $page->setDecorate(1);
3169
    $page->setRequestMethod('GET|POST|HEAD|DELETE|PUT');
3170
    $page->setTemplateCode('default');
3171
    $page->setRouteName('homepage');
3172
    //$page->setParent($this->getReference('page-homepage'));
3173
    $page->setSite($site);
3174
    $pageManager->save($page);
3175
3176
    // Create welcome page
3177
    $pageWelcome = $pageManager->create();
3178
    $pageWelcome->setSlug('welcome');
3179
    $pageWelcome->setUrl('/welcome');
3180
    $pageWelcome->setName('welcome');
3181
    $pageWelcome->setTitle('welcome');
3182
    $pageWelcome->setEnabled(true);
3183
    $pageWelcome->setDecorate(1);
3184
    $pageWelcome->setRequestMethod('GET');
3185
    $pageWelcome->setTemplateCode('default');
3186
    $pageWelcome->setRouteName('welcome');
3187
    $pageWelcome->setParent($page);
3188
    $pageWelcome->setSite($site);
3189
3190
    $pageManager->save($pageWelcome);
3191
3192
    $templateManager = $container->get('sonata.page.template_manager');
3193
    $template = $templateManager->get('default');
3194
    $templateContainers = $template->getContainers();
3195
3196
    $containers = [];
3197
    foreach ($templateContainers as $id => $area) {
3198
        $containers[$id] = [
3199
            'area' => $area,
3200
            'block' => false,
3201
        ];
3202
    }
3203
3204
    // Create blocks for this page
3205
    $blockInteractor = $container->get('sonata.page.block_interactor');
3206
    $parentBlock = null;
3207
    foreach ($containers as $id => $area) {
3208
        if (false === $area['block'] && $templateContainers[$id]['shared'] === false) {
3209
            $block = $blockInteractor->createNewContainer(
3210
                [
3211
                    'page' => $pageWelcome,
3212
                    'name' => $templateContainers[$id]['name'],
3213
                    'code' => $id,
3214
                ]
3215
            );
3216
3217
            if ($id === 'content' && $templateContainers[$id]['name'] == 'Main content') {
3218
                $parentBlock = $block;
3219
            }
3220
        }
3221
    }
3222
3223
    // Create block in main content
3224
    $block = $container->get('sonata.page.manager.block');
3225
    /** @var \Sonata\BlockBundle\Model\Block $myBlock */
3226
    $myBlock = $block->create();
3227
    $myBlock->setType('sonata.formatter.block.formatter');
3228
    $myBlock->setSetting('format', 'richhtml');
3229
    $myBlock->setSetting('content', '');
3230
    $myBlock->setSetting('rawContent', '');
3231
    $myBlock->setSetting('template', '@SonataFormatter/Block/block_formatter.html.twig');
3232
    $myBlock->setParent($parentBlock);
3233
    $pageWelcome->addBlocks($myBlock);
3234
    $pageManager->save($pageWelcome);
3235
3236
    UserManager::setPasswordEncryption($encryptPassForm);
3237
3238
    // Create admin user.
3239
    @UserManager::create_user(
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for create_user(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

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

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

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

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

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
3240
        $adminFirstName,
3241
        $adminLastName,
3242
        1,
3243
        $emailForm,
3244
        $loginForm,
3245
        $passForm,
3246
        'ADMIN', //$official_code = '',
3247
        $languageForm,
3248
        $adminPhoneForm,
3249
        '', //$picture_uri = '',
3250
        PLATFORM_AUTH_SOURCE,
3251
        '', //$expirationDate,
3252
        1,
3253
        0,
3254
        null,
3255
        '',
3256
        false, //$send_mail = false,
3257
        true, //$isAdmin = false
3258
            '',
3259
        false,
3260
        '',
3261
        1
3262
    );
3263
3264
    // Create anonymous user.
3265
    @UserManager::create_user(
3266
        'Joe',
3267
        'Anonymous',
3268
        6,
3269
        'anonymous@localhost',
3270
        'anon',
3271
        'anon',
3272
        'anonymous', //$official_code = '',
3273
        $languageForm,
3274
        '',
3275
        '', //$picture_uri = '',
3276
        PLATFORM_AUTH_SOURCE,
3277
        '',
3278
        1,
3279
        0,
3280
        null,
3281
        '',
3282
        false, //$send_mail = false,
3283
        false, //$isAdmin = false
3284
        '',
3285
        false,
3286
        '',
3287
        1
3288
    );
3289
3290
    // Set default language
3291
    $sql = "UPDATE language SET available = 1 WHERE dokeos_folder = '$languageForm'";
3292
    Database::query($sql);
3293
3294
    // Install settings
3295
    installSettings(
3296
        $institutionForm,
3297
        $institutionUrlForm,
3298
        $siteName,
3299
        $emailForm,
3300
        $adminLastName,
3301
        $adminFirstName,
3302
        $languageForm,
3303
        $allowSelfReg,
3304
        $allowSelfRegProf,
3305
        $installationProfile
3306
    );
3307
3308
    lockSettings();
3309
    updateDirAndFilesPermissions();
3310
3311
    // Set the latest version
3312
    /*$path = $sysPath.'app/Migrations/Schema/V111/';
3313
    $finder = new \Symfony\Component\Finder\Finder();
3314
    $files = $finder->files()->in($path);
3315
3316
    // Needed for chash
3317
    createVersionTable();
3318
3319
    foreach ($files as $version) {
3320
        $version = str_replace(['Version', '.php'], '', $version->getFilename());
3321
        $sql = "INSERT INTO version (version) VALUES ('$version')";
3322
        Database::query($sql);
3323
    }*/
3324
}
3325
3326
/**
3327
 * Creates 'version' table.
3328
 */
3329
function createVersionTable()
3330
{
3331
    $sql = getVersionTable();
3332
    Database::query($sql);
3333
}
3334
3335
/**
3336
 * Get version creation table query.
3337
 *
3338
 * @return string
3339
 */
3340
function getVersionTable()
3341
{
3342
    return 'CREATE TABLE IF NOT EXISTS version (id int unsigned NOT NULL AUTO_INCREMENT, version varchar(20), PRIMARY KEY(id), UNIQUE(version));';
3343
}
3344
3345
/**
3346
 * Update settings based on installation profile defined in a JSON file.
3347
 *
3348
 * @param string $installationProfile The name of the JSON file in main/install/profiles/ folder
3349
 *
3350
 * @return bool false on failure (no bad consequences anyway, just ignoring profile)
3351
 */
3352
function installProfileSettings($installationProfile = '')
3353
{
3354
    if (empty($installationProfile)) {
3355
        return false;
3356
    }
3357
    $jsonPath = api_get_path(SYS_PATH).'main/install/profiles/'.$installationProfile.'.json';
3358
    // Make sure the path to the profile is not hacked
3359
    if (!Security::check_abs_path($jsonPath, api_get_path(SYS_PATH).'main/install/profiles/')) {
3360
        return false;
3361
    }
3362
    if (!is_file($jsonPath)) {
3363
        return false;
3364
    }
3365
    if (!is_readable($jsonPath)) {
3366
        return false;
3367
    }
3368
    if (!function_exists('json_decode')) {
3369
        // The php-json extension is not available. Ignore profile.
3370
        return false;
3371
    }
3372
    $json = file_get_contents($jsonPath);
3373
    $params = json_decode($json);
3374
    if ($params === false or $params === null) {
3375
        return false;
3376
    }
3377
    $settings = $params->params;
3378
    if (!empty($params->parent)) {
3379
        installProfileSettings($params->parent);
3380
    }
3381
    foreach ($settings as $id => $param) {
3382
        $sql = "UPDATE settings_current
3383
                SET selected_value = '".$param->selected_value."'
3384
                WHERE variable = '".$param->variable."'";
3385
        if (!empty($param->subkey)) {
3386
            $sql .= " AND subkey='".$param->subkey."'";
3387
        }
3388
        Database::query($sql);
3389
    }
3390
3391
    return true;
3392
}
3393
3394
/**
3395
 * Quick function to remove a directory with its subdirectories.
3396
 *
3397
 * @param $dir
3398
 */
3399
function rrmdir($dir)
3400
{
3401
    if (is_dir($dir)) {
3402
        $objects = scandir($dir);
3403
        foreach ($objects as $object) {
3404
            if ($object != "." && $object != "..") {
3405
                if (filetype($dir."/".$object) == "dir") {
3406
                    @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

3406
                    /** @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...
3407
                } else {
3408
                    @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

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