Completed
Pull Request — master (#2349)
by Julito
31:02 queued 07:14
created

finishInstallationWithContainer()   B

Complexity

Conditions 6

Size

Total Lines 218
Code Lines 136

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
eloc 136
nop 17
dl 0
loc 218
rs 7.0769
c 0
b 0
f 0

How to fix   Long Method    Many Parameters   

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:

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
/* For licensing terms, see /license.txt */
3
4
use Chamilo\CoreBundle\Entity\ExtraField;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, ExtraField. Consider defining an alias.

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

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

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

// Bar.php
namespace OtherDir;

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

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

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

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

// Bar.php
namespace OtherDir;

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

109
    /** @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...
110
) {
111
    $currentPhpValue = getPhpSetting($phpSetting);
112
    if ($currentPhpValue == $recommendedValue) {
113
        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

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

330
    $buffer = fread(/** @scrutinizer ignore-type */ $fp, filesize($filename));
Loading history...
331
    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

331
    fclose(/** @scrutinizer ignore-type */ $fp);
Loading history...
332
333
    return explode('<br />', nl2br($buffer));
334
}
335
336
/**
337
 * We assume this function is called from install scripts that reside inside the install folder.
338
 */
339
function set_file_folder_permissions()
340
{
341
    @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

341
    /** @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...
342
    @chmod('..', 0755); //set permissions on parent dir of install dir
343
}
344
345
/**
346
 * Write the main system config file
347
 * @param string $path Path to the config file
348
 */
349
function write_system_config_file($path)
350
{
351
    global $dbHostForm;
352
    global $dbPortForm;
353
    global $dbUsernameForm;
354
    global $dbPassForm;
355
    global $dbNameForm;
356
    global $urlForm;
357
    global $pathForm;
358
    global $urlAppendPath;
359
    global $languageForm;
360
    global $encryptPassForm;
361
    global $session_lifetime;
362
    global $new_version;
363
    global $new_version_stable;
364
365
    $root_sys = api_add_trailing_slash(str_replace('\\', '/', realpath($pathForm)));
366
    $content = file_get_contents(__DIR__.'/'.SYSTEM_CONFIG_FILENAME);
367
368
    $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...
369
    $config['{DATABASE_HOST}'] = $dbHostForm;
370
    $config['{DATABASE_PORT}'] = $dbPortForm;
371
    $config['{DATABASE_USER}'] = $dbUsernameForm;
372
    $config['{DATABASE_PASSWORD}'] = $dbPassForm;
373
    $config['{DATABASE_MAIN}'] = $dbNameForm;
374
    $config['{ROOT_WEB}'] = $urlForm;
375
    $config['{ROOT_SYS}'] = $root_sys;
376
    $config['{URL_APPEND_PATH}'] = $urlAppendPath;
377
    $config['{PLATFORM_LANGUAGE}'] = $languageForm;
378
    $config['{SECURITY_KEY}'] = md5(uniqid(rand().time()));
379
    $config['{ENCRYPT_PASSWORD}'] = $encryptPassForm;
380
381
    $config['SESSION_LIFETIME'] = $session_lifetime;
382
    $config['{NEW_VERSION}'] = $new_version;
383
    $config['NEW_VERSION_STABLE'] = trueFalse($new_version_stable);
384
385
    foreach ($config as $key => $value) {
386
        $content = str_replace($key, $value, $content);
387
    }
388
    $fp = @ fopen($path, 'w');
389
390
    if (!$fp) {
391
        echo '<strong><font color="red">Your script doesn\'t have write access to the config directory</font></strong><br />
392
                        <em>('.str_replace('\\', '/', realpath($path)).')</em><br /><br />
393
                        You probably do not have write access on Chamilo root directory,
394
                        i.e. you should <em>CHMOD 777</em> or <em>755</em> or <em>775</em>.<br /><br />
395
                        Your problems can be related on two possible causes:<br />
396
                        <ul>
397
                          <li>Permission problems.<br />Try initially with <em>chmod -R 777</em> and increase restrictions gradually.</li>
398
                          <li>PHP is running in <a href="http://www.php.net/manual/en/features.safe-mode.php" target="_blank">Safe-Mode</a>. If possible, try to switch it off.</li>
399
                        </ul>
400
                        <a href="http://forum.chamilo.org/" target="_blank">Read about this problem in Support Forum</a><br /><br />
401
                        Please go back to step 5.
402
                        <p><input type="submit" name="step5" value="&lt; Back" /></p>
403
                        </td></tr></table></form></body></html>';
404
        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...
405
    }
406
407
    fwrite($fp, $content);
408
    fclose($fp);
409
}
410
411
/**
412
 * Returns a list of language directories.
413
 */
414
function & get_language_folder_list()
415
{
416
    static $result;
417
    if (!is_array($result)) {
418
        $result = [];
419
        $exceptions = ['.', '..', 'CVS', '.svn'];
420
        $search       = ['_latin', '_unicode', '_corporate', '_org', '_KM', '_'];
421
        $replace_with = [' (Latin)', ' (unicode)', ' (corporate)', ' (org)', ' (KM)', ' '];
422
        $dirname = api_get_path(SYS_LANG_PATH);
423
        $handle = opendir($dirname);
424
        while ($entries = readdir($handle)) {
0 ignored issues
show
Bug introduced by
It seems like $handle can also be of type false; however, parameter $dir_handle of readdir() 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

424
        while ($entries = readdir(/** @scrutinizer ignore-type */ $handle)) {
Loading history...
425
            if (in_array($entries, $exceptions)) {
426
                continue;
427
            }
428
            if (is_dir($dirname.$entries)) {
429
                if (is_file($dirname.$entries.'/install_disabled')) {
430
                    // Skip all languages that have this file present, just for
431
                    // the install process (languages incomplete)
432
                    continue;
433
                }
434
                $result[$entries] = ucwords(str_replace($search, $replace_with, $entries));
435
            }
436
        }
437
        closedir($handle);
0 ignored issues
show
Bug introduced by
It seems like $handle can also be of type false; however, parameter $dir_handle of closedir() 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

437
        closedir(/** @scrutinizer ignore-type */ $handle);
Loading history...
438
        asort($result);
439
    }
440
441
    return $result;
442
}
443
444
/**
445
 * This function returns the value of a parameter from the configuration file
446
 *
447
 * WARNING - this function relies heavily on global variables $updateFromConfigFile
448
 * and $configFile, and also changes these globals. This can be rewritten.
449
 *
450
 * @param   string  $param  the parameter of which the value is returned
451
 * @param   string  If we want to give the path rather than take it from POST
452
 * @return  string  the value of the parameter
453
 * @author Olivier Brouckaert
454
 * @author Reworked by Ivan Tcholakov, 2010
455
 */
456
function get_config_param($param, $updatePath = '')
457
{
458
    global $configFile, $updateFromConfigFile;
459
460
    // Look if we already have the queried parameter.
461
    if (is_array($configFile) && isset($configFile[$param])) {
462
        return $configFile[$param];
463
    }
464
    if (empty($updatePath) && !empty($_POST['updatePath'])) {
465
        $updatePath = $_POST['updatePath'];
466
    }
467
468
    if (empty($updatePath)) {
469
        $updatePath = api_get_path(SYS_PATH);
470
    }
471
    $updatePath = api_add_trailing_slash(str_replace('\\', '/', realpath($updatePath)));
472
    $updateFromInstalledVersionFile = '';
473
474
    if (empty($updateFromConfigFile)) {
475
        // If update from previous install was requested,
476
        // try to recover config file from Chamilo 1.9.x
477
        if (file_exists($updatePath.'main/inc/conf/configuration.php')) {
478
            $updateFromConfigFile = 'main/inc/conf/configuration.php';
479
        } elseif (file_exists($updatePath.'app/config/configuration.php')) {
480
            $updateFromConfigFile = 'app/config/configuration.php';
481
        } else {
482
            // Give up recovering.
483
            //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);
484
            return null;
485
        }
486
    }
487
488
    if (file_exists($updatePath.$updateFromConfigFile) &&
489
        !is_dir($updatePath.$updateFromConfigFile)
490
    ) {
491
        require $updatePath.$updateFromConfigFile;
492
        $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...
493
        return $config->get($param);
494
    }
495
496
    error_log('Config array could not be found in get_config_param()', 0);
497
    return null;
498
}
499
500
/*      DATABASE RELATED FUNCTIONS */
501
502
/**
503
 * Gets a configuration parameter from the database. Returns returns null on failure.
504
 * @param   string  $param Name of param we want
505
 * @return  mixed   The parameter value or null if not found
506
 */
507
function get_config_param_from_db($param = '')
508
{
509
    if (($res = Database::query("SELECT * FROM settings_current WHERE variable = '$param'")) !== false) {
510
        if (Database::num_rows($res) > 0) {
511
            $row = Database::fetch_array($res);
512
            return $row['selected_value'];
513
        }
514
    }
515
    return null;
516
}
517
518
/**
519
 * Connect to the database and returns the entity manager
520
 * @param string  $dbHostForm DB host
521
 * @param string  $dbUsernameForm DB username
522
 * @param string  $dbPassForm DB password
523
 * @param string  $dbNameForm DB name
524
 * @param int     $dbPortForm DB port
525
 *
526
 * @return Database
527
 */
528
function connectToDatabase(
529
    $dbHostForm,
530
    $dbUsernameForm,
531
    $dbPassForm,
532
    $dbNameForm,
533
    $dbPortForm = 3306
534
) {
535
    $dbParams = [
536
        'driver' => 'pdo_mysql',
537
        'host' => $dbHostForm,
538
        'port' => $dbPortForm,
539
        'user' => $dbUsernameForm,
540
        'password' => $dbPassForm,
541
        'dbname' => $dbNameForm
542
    ];
543
544
    $database = new \Database();
545
    $database->connect($dbParams);
546
547
    return $database;
548
}
549
550
/*      DISPLAY FUNCTIONS */
551
552
/**
553
 * This function prints class=active_step $current_step=$param
554
 * @param   int $param  A step in the installer process
555
 * @author Patrick Cool <[email protected]>, Ghent University
556
 */
557
function step_active($param)
558
{
559
    global $current_step;
560
    if ($param == $current_step) {
561
        echo 'class="current-step" ';
562
    }
563
}
564
565
/**
566
 * This function displays the Step X of Y -
567
 * @return  string  String that says 'Step X of Y' with the right values
568
 */
569
function display_step_sequence()
570
{
571
    global $current_step;
572
    return get_lang('Step'.$current_step).' &ndash; ';
573
}
574
575
/**
576
 * Displays a drop down box for selection the preferred language.
577
 */
578
function display_language_selection_box(
579
    $name = 'language_list',
580
    $default_language = 'english'
581
) {
582
    // Reading language list.
583
    $language_list = get_language_folder_list();
584
585
    /*
586
    // Reduction of the number of languages shown. Enable this fragment of code for customization purposes.
587
    // Modify the language list according to your preference. Don't exclude the 'english' item.
588
    $language_to_display = array('asturian', 'bulgarian', 'english', 'italian', 'french', 'slovenian', 'slovenian_unicode', 'spanish');
589
    foreach ($language_list as $key => & $value) {
590
        if (!in_array($key, $language_to_display)) {
591
            unset($language_list[$key]);
592
        }
593
    }
594
    */
595
596
    // Sanity checks due to the possibility for customizations.
597
    if (!is_array($language_list) || empty($language_list)) {
598
        $language_list = ['english' => 'English'];
599
    }
600
601
    // Sorting again, if it is necessary.
602
    //asort($language_list);
603
604
    // More sanity checks.
605
    if (!array_key_exists($default_language, $language_list)) {
606
        if (array_key_exists('english', $language_list)) {
607
            $default_language = 'english';
608
        } else {
609
            $language_keys = array_keys($language_list);
610
            $default_language = $language_keys[0];
611
        }
612
    }
613
614
    // Displaying the box.
615
    $html = '';
616
    $html .= "\t\t<select class='selectpicker show-tick' name=\"$name\">\n";
617
    foreach ($language_list as $key => $value) {
618
        if ($key == $default_language) {
619
            $option_end = ' selected="selected">';
620
        } else {
621
            $option_end = '>';
622
        }
623
        $html .= "\t\t\t<option value=\"$key\"$option_end";
624
        $html .= $value;
625
        $html .= "</option>\n";
626
    }
627
    $html .= "\t\t</select>\n";
628
    return $html;
629
}
630
631
/**
632
 * This function displays a language dropdown box so that the installatioin
633
 * can be done in the language of the user
634
 */
635
function display_language_selection()
636
{
637
    ?>
638
    <h2><?php get_lang('WelcomeToTheChamiloInstaller'); ?></h2>
639
    <div class="RequirementHeading">
640
        <h2><?php echo display_step_sequence(); ?>
641
            <?php echo get_lang('InstallationLanguage'); ?>
642
        </h2>
643
        <p><?php echo get_lang('PleaseSelectInstallationProcessLanguage'); ?>:</p>
644
        <form id="lang_form" method="post" action="<?php echo api_get_self(); ?>">
645
        <div class="form-group">
646
            <div class="col-sm-4">
647
                <?php echo display_language_selection_box('language_list', api_get_interface_language()); ?>
648
            </div>
649
            <div class="col-sm-6">
650
                <button type="submit" name="step1" class="btn btn-success" value="<?php echo get_lang('Next'); ?>">
651
                    <em class="fa fa-forward"> </em>
652
                    <?php echo get_lang('Next'); ?></button>
653
            </div>
654
        </div>
655
656
        <input type="hidden" name="is_executable" id="is_executable" value="-" />
657
        </form>
658
659
    </div>
660
    <div class="RequirementHeading">
661
        <?php echo get_lang('YourLanguageNotThereContactUs'); ?>
662
    </div>
663
<?php
664
}
665
666
/**
667
 * This function displays the requirements for installing Chamilo.
668
 *
669
 * @param string $installType
670
 * @param boolean $badUpdatePath
671
 * @param boolean $badUpdatePath
672
 * @param string $updatePath The updatePath given (if given)
673
 * @param array $update_from_version_8 The different subversions from version 1.9
674
 *
675
 * @author unknow
676
 * @author Patrick Cool <[email protected]>, Ghent University
677
 */
678
function display_requirements(
679
    $installType,
680
    $badUpdatePath,
681
    $updatePath = '',
682
    $update_from_version_8 = []
683
) {
684
    global $_setting;
685
    echo '<div class="RequirementHeading"><h2>'.display_step_sequence().get_lang('Requirements')."</h2></div>";
686
    echo '<div class="RequirementText">';
687
    echo '<strong>'.get_lang('ReadThoroughly').'</strong><br />';
688
    echo get_lang('MoreDetails').' <a href="../../documentation/installation_guide.html" target="_blank">'.get_lang('ReadTheInstallationGuide').'</a>.<br />'."\n";
689
690
    if ($installType == 'update') {
691
        echo get_lang('IfYouPlanToUpgradeFromOlderVersionYouMightWantToHaveAlookAtTheChangelog').'<br />';
692
    }
693
    echo '</div>';
694
695
    $properlyAccessUrl = checkAccessUrl();
696
697
    if (!$properlyAccessUrl) {
698
        echo '
699
            <div class="alert alert-danger">
700
                ' . Display::return_icon('error.png', get_lang('Error'), [], ICON_SIZE_MEDIUM, true, false, true).
701
            ' '.
702
            sprintf(get_lang('InstallMultiURLDetectedNotMainURL'), api_get_configuration_value('root_web')).'
0 ignored issues
show
Bug introduced by
It seems like api_get_configuration_value('root_web') can also be of type false; however, parameter $args of sprintf() does only seem to accept string, 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

702
            sprintf(get_lang('InstallMultiURLDetectedNotMainURL'), /** @scrutinizer ignore-type */ api_get_configuration_value('root_web')).'
Loading history...
703
            </div>
704
        ';
705
    }
706
707
    //  SERVER REQUIREMENTS
708
    echo '<div class="RequirementHeading"><h4>'.get_lang('ServerRequirements').'</h4>';
709
710
    $timezone = checkPhpSettingExists("date.timezone");
711
    if (!$timezone) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $timezone of type false|string is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === false instead.

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

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
712
        echo "<div class='alert alert-warning'>".
713
            Display::return_icon(
714
                'warning.png',
715
                get_lang('Warning'),
716
                '',
717
                ICON_SIZE_MEDIUM,
718
                true,
719
                false,
720
                false
721
            ).
722
            get_lang("DateTimezoneSettingNotSet")."</div>";
723
    }
724
725
    echo '<div class="RequirementText">'.get_lang('ServerRequirementsInfo').'</div>';
726
    echo '<div class="RequirementContent">';
727
    echo '<table class="table">
728
            <tr>
729
                <td class="requirements-item">'.get_lang('PHPVersion').' >= '.REQUIRED_PHP_VERSION.'</td>
730
                <td class="requirements-value">';
731
    if (version_compare(phpversion(), REQUIRED_PHP_VERSION, '>=') > 1) {
732
        echo '<strong><font color="red">'.get_lang('PHPVersionError').'</font></strong>';
733
    } else {
734
        echo '<strong><font color="green">'.get_lang('PHPVersionOK').' '.phpversion().'</font></strong>';
735
    }
736
    echo '</td>
737
            </tr>
738
            <tr>
739
                <td class="requirements-item"><a href="http://php.net/manual/en/book.session.php" target="_blank">Session</a> '.get_lang('Support').'</td>
740
                <td class="requirements-value">'.checkExtension('session', get_lang('Yes'), get_lang('ExtensionSessionsNotAvailable')).'</td>
741
            </tr>
742
            <tr>
743
                <td class="requirements-item"><a href="http://php.net/manual/en/book.mysql.php" target="_blank">pdo_mysql</a> '.get_lang('Support').'</td>
744
                <td class="requirements-value">'.checkExtension('pdo_mysql', get_lang('Yes'), get_lang('ExtensionMySQLNotAvailable')).'</td>
745
            </tr>
746
            <tr>
747
                <td class="requirements-item"><a href="http://php.net/manual/en/book.zip.php" target="_blank">Zip</a> '.get_lang('Support').'</td>
748
                <td class="requirements-value">'.checkExtension('zip', get_lang('Yes'), get_lang('ExtensionNotAvailable')).'</td>
749
            </tr>
750
            <tr>
751
                <td class="requirements-item"><a href="http://php.net/manual/en/book.zlib.php" target="_blank">Zlib</a> '.get_lang('Support').'</td>
752
                <td class="requirements-value">'.checkExtension('zlib', get_lang('Yes'), get_lang('ExtensionZlibNotAvailable')).'</td>
753
            </tr>
754
            <tr>
755
                <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>
756
                <td class="requirements-value">'.checkExtension('pcre', get_lang('Yes'), get_lang('ExtensionPCRENotAvailable')).'</td>
757
            </tr>
758
            <tr>
759
                <td class="requirements-item"><a href="http://php.net/manual/en/book.xml.php" target="_blank">XML</a> '.get_lang('Support').'</td>
760
                <td class="requirements-value">'.checkExtension('xml', get_lang('Yes'), get_lang('No')).'</td>
761
            </tr>
762
            <tr>
763
                <td class="requirements-item"><a href="http://php.net/manual/en/book.intl.php" target="_blank">Internationalization</a> '.get_lang('Support').'</td>
764
                <td class="requirements-value">'.checkExtension('intl', get_lang('Yes'), get_lang('No')).'</td>
765
            </tr>
766
               <tr>
767
                <td class="requirements-item"><a href="http://php.net/manual/en/book.json.php" target="_blank">JSON</a> '.get_lang('Support').'</td>
768
                <td class="requirements-value">'.checkExtension('json', get_lang('Yes'), get_lang('No')).'</td>
769
            </tr>
770
             <tr>
771
                <td class="requirements-item"><a href="http://php.net/manual/en/book.image.php" target="_blank">GD</a> '.get_lang('Support').'</td>
772
                <td class="requirements-value">'.checkExtension('gd', get_lang('Yes'), get_lang('ExtensionGDNotAvailable')).'</td>
773
            </tr>
774
            <tr>
775
                <td class="requirements-item"><a href="http://php.net/manual/en/book.curl.php" target="_blank">cURL</a>'.get_lang('Support').'</td>
776
                <td class="requirements-value">'.checkExtension('curl', get_lang('Yes'), get_lang('No')).'</td>
777
            </tr>
778
779
            <tr>
780
                <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>
781
                <td class="requirements-value">'.checkExtension('mbstring', get_lang('Yes'), get_lang('ExtensionMBStringNotAvailable'), true).'</td>
782
            </tr>
783
            <tr>
784
                <td class="requirements-item"><a href="http://php.net/opcache" target="_blank">Zend OpCache</a> '.get_lang('Support').' ('.get_lang('Optional').')</td>
785
                <td class="requirements-value">'.checkExtension('Zend OPcache', get_lang('Yes'), get_lang('No'), true, 'opcache.enable').'</td>
786
            </tr>
787
            <tr>
788
                <td class="requirements-item"><a href="http://php.net/apcu" target="_blank">APCu</a> '.get_lang('Support').' ('.get_lang('Optional').')</td>
789
                <td class="requirements-value">'.checkExtension('apcu', get_lang('Yes'), get_lang('No'), true, 'apc.enabled').'</td>
790
            </tr>
791
            <tr>
792
                <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>
793
                <td class="requirements-value">'.checkExtension('iconv', get_lang('Yes'), get_lang('No'), true).'</td>
794
            </tr>
795
            <tr>
796
                <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>
797
                <td class="requirements-value">'.checkExtension('ldap', get_lang('Yes'), get_lang('ExtensionLDAPNotAvailable'), true).'</td>
798
            </tr>
799
            <tr>
800
                <td class="requirements-item"><a href="http://xapian.org/" target="_blank">Xapian</a> '.get_lang('Support').' ('.get_lang('Optional').')</td>
801
                <td class="requirements-value">'.checkExtension('xapian', get_lang('Yes'), get_lang('No'), true).'</td>
802
            </tr>
803
        </table>';
804
    echo '</div>';
805
    echo '</div>';
806
807
    // RECOMMENDED SETTINGS
808
    // Note: these are the settings for Joomla, does this also apply for Chamilo?
809
    // Note: also add upload_max_filesize here so that large uploads are possible
810
    echo '<div class="RequirementHeading"><h4>'.get_lang('RecommendedSettings').'</h4>';
811
    echo '<div class="RequirementText">'.get_lang('RecommendedSettingsInfo').'</div>';
812
    echo '<div class="RequirementContent">';
813
    echo '<table class="table">
814
            <tr>
815
                <th>'.get_lang('Setting').'</th>
816
                <th>'.get_lang('Recommended').'</th>
817
                <th>'.get_lang('Actual').'</th>
818
            </tr>
819
            <tr>
820
                <td class="requirements-item"><a href="http://php.net/manual/features.safe-mode.php">Safe Mode</a></td>
821
                <td class="requirements-recommended">'.Display::label('OFF', 'success').'</td>
822
                <td class="requirements-value">'.checkPhpSetting('safe_mode', 'OFF').'</td>
823
            </tr>
824
            <tr>
825
                <td class="requirements-item"><a href="http://php.net/manual/ref.errorfunc.php#ini.display-errors">Display Errors</a></td>
826
                <td class="requirements-recommended">'.Display::label('OFF', 'success').'</td>
827
                <td class="requirements-value">'.checkPhpSetting('display_errors', 'OFF').'</td>
828
            </tr>
829
            <tr>
830
                <td class="requirements-item"><a href="http://php.net/manual/ini.core.php#ini.file-uploads">File Uploads</a></td>
831
                <td class="requirements-recommended">'.Display::label('ON', 'success').'</td>
832
                <td class="requirements-value">'.checkPhpSetting('file_uploads', 'ON').'</td>
833
            </tr>
834
            <tr>
835
                <td class="requirements-item"><a href="http://php.net/manual/ref.info.php#ini.magic-quotes-gpc">Magic Quotes GPC</a></td>
836
                <td class="requirements-recommended">'.Display::label('OFF', 'success').'</td>
837
                <td class="requirements-value">'.checkPhpSetting('magic_quotes_gpc', 'OFF').'</td>
838
            </tr>
839
            <tr>
840
                <td class="requirements-item"><a href="http://php.net/manual/ref.info.php#ini.magic-quotes-runtime">Magic Quotes Runtime</a></td>
841
                <td class="requirements-recommended">'.Display::label('OFF', 'success').'</td>
842
                <td class="requirements-value">'.checkPhpSetting('magic_quotes_runtime', 'OFF').'</td>
843
            </tr>
844
            <tr>
845
                <td class="requirements-item"><a href="http://php.net/manual/security.globals.php">Register Globals</a></td>
846
                <td class="requirements-recommended">'.Display::label('OFF', 'success').'</td>
847
                <td class="requirements-value">'.checkPhpSetting('register_globals', 'OFF').'</td>
848
            </tr>
849
            <tr>
850
                <td class="requirements-item"><a href="http://php.net/manual/ref.session.php#ini.session.auto-start">Session auto start</a></td>
851
                <td class="requirements-recommended">'.Display::label('OFF', 'success').'</td>
852
                <td class="requirements-value">'.checkPhpSetting('session.auto_start', 'OFF').'</td>
853
            </tr>
854
            <tr>
855
                <td class="requirements-item"><a href="http://php.net/manual/ini.core.php#ini.short-open-tag">Short Open Tag</a></td>
856
                <td class="requirements-recommended">'.Display::label('OFF', 'success').'</td>
857
                <td class="requirements-value">'.checkPhpSetting('short_open_tag', 'OFF').'</td>
858
            </tr>
859
            <tr>
860
                <td class="requirements-item"><a href="http://www.php.net/manual/en/session.configuration.php#ini.session.cookie-httponly">Cookie HTTP Only</a></td>
861
                <td class="requirements-recommended">'.Display::label('ON', 'success').'</td>
862
                <td class="requirements-value">'.checkPhpSetting('session.cookie_httponly', 'ON').'</td>
863
            </tr>
864
            <tr>
865
                <td class="requirements-item"><a href="http://php.net/manual/ini.core.php#ini.upload-max-filesize">Maximum upload file size</a></td>
866
                <td class="requirements-recommended">'.Display::label('>= '.REQUIRED_MIN_UPLOAD_MAX_FILESIZE.'M', 'success').'</td>
867
                <td class="requirements-value">'.compare_setting_values(ini_get('upload_max_filesize'), REQUIRED_MIN_UPLOAD_MAX_FILESIZE).'</td>
868
            </tr>
869
            <tr>
870
                <td class="requirements-item"><a href="http://php.net/manual/ini.core.php#ini.post-max-size">Maximum post size</a></td>
871
                <td class="requirements-recommended">'.Display::label('>= '.REQUIRED_MIN_POST_MAX_SIZE.'M', 'success').'</td>
872
                <td class="requirements-value">'.compare_setting_values(ini_get('post_max_size'), REQUIRED_MIN_POST_MAX_SIZE).'</td>
873
            </tr>
874
            <tr>
875
                <td class="requirements-item"><a href="http://www.php.net/manual/en/ini.core.php#ini.memory-limit">Memory Limit</a></td>
876
                <td class="requirements-recommended">'.Display::label('>= '.REQUIRED_MIN_MEMORY_LIMIT.'M', 'success').'</td>
877
                <td class="requirements-value">'.compare_setting_values(ini_get('memory_limit'), REQUIRED_MIN_MEMORY_LIMIT).'</td>
878
            </tr>
879
          </table>';
880
    echo '  </div>';
881
    echo '</div>';
882
883
    // DIRECTORY AND FILE PERMISSIONS
884
    echo '<div class="RequirementHeading"><h4>'.get_lang('DirectoryAndFilePermissions').'</h4>';
885
    echo '<div class="RequirementText">'.get_lang('DirectoryAndFilePermissionsInfo').'</div>';
886
    echo '<div class="RequirementContent">';
887
888
    $course_attempt_name = '__XxTestxX__';
889
    $course_dir = api_get_path(SYS_COURSE_PATH).$course_attempt_name;
890
891
    //Just in case
892
    @unlink($course_dir.'/test.php');
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

892
    /** @scrutinizer ignore-unhandled */ @unlink($course_dir.'/test.php');

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...
893
    @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

893
    /** @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...
894
895
    $perms_dir = [0777, 0755, 0775, 0770, 0750, 0700];
896
    $perms_fil = [0666, 0644, 0664, 0660, 0640, 0600];
897
    $course_test_was_created = false;
898
    $dir_perm_verified = 0777;
899
    foreach ($perms_dir as $perm) {
900
        $r = @mkdir($course_dir, $perm);
901
        if ($r === true) {
902
            $dir_perm_verified = $perm;
903
            $course_test_was_created = true;
904
            break;
905
        }
906
    }
907
908
    $fil_perm_verified = 0666;
909
    $file_course_test_was_created = false;
910
    if (is_dir($course_dir)) {
911
        foreach ($perms_fil as $perm) {
912
            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...
913
                break;
914
            }
915
            $r = @touch($course_dir.'/test.php', $perm);
916
            if ($r === true) {
917
                $fil_perm_verified = $perm;
918
                if (check_course_script_interpretation($course_dir, $course_attempt_name, 'test.php')) {
919
                    $file_course_test_was_created = true;
920
                }
921
            }
922
        }
923
    }
924
925
    @unlink($course_dir.'/test.php');
926
    @rmdir($course_dir);
927
928
    $_SESSION['permissions_for_new_directories'] = $_setting['permissions_for_new_directories'] = $dir_perm_verified;
929
    $_SESSION['permissions_for_new_files'] = $_setting['permissions_for_new_files'] = $fil_perm_verified;
930
931
    $dir_perm = Display::label('0'.decoct($dir_perm_verified), 'info');
932
    $file_perm = Display::label('0'.decoct($fil_perm_verified), 'info');
933
934
    $courseTestLabel = Display::label(get_lang('No'), 'important');
935
    if ($course_test_was_created && $file_course_test_was_created) {
936
        $courseTestLabel = Display::label(get_lang('Yes'), 'success');
937
    }
938
939
    if ($course_test_was_created && !$file_course_test_was_created) {
940
        $courseTestLabel = Display::label(get_lang('Warning'), 'warning');
941
        $courseTestLabel .= '<br />'.sprintf(
942
            get_lang('InstallWarningCouldNotInterpretPHP'),
943
            api_get_path(WEB_COURSE_PATH).$course_attempt_name.'/test.php'
944
        );
945
    }
946
947
    if (!$course_test_was_created && !$file_course_test_was_created) {
948
        $courseTestLabel = Display::label(get_lang('No'), 'important');
949
    }
950
951
    $oldConf = '';
952
    if (file_exists(api_get_path(SYS_CODE_PATH).'inc/conf/configuration.php')) {
953
        $oldConf = '<tr>
954
            <td class="requirements-item">'.api_get_path(SYS_CODE_PATH).'inc/conf</td>
955
            <td class="requirements-value">'.check_writable(api_get_path(SYS_CODE_PATH).'inc/conf').'</td>
956
        </tr>';
957
    }
958
959
    echo '<table class="table">
960
            '.$oldConf.'
961
            <tr>
962
                <td class="requirements-item">'.api_get_path(SYS_APP_PATH).'</td>
963
                <td class="requirements-value">'.check_writable(api_get_path(SYS_APP_PATH)).'</td>
964
            </tr>
965
            <tr>
966
                <td class="requirements-item">'.api_get_path(SYS_CODE_PATH).'default_course_document/images/</td>
967
                <td class="requirements-value">'.check_writable(api_get_path(SYS_CODE_PATH).'default_course_document/images/').'</td>
968
            </tr>
969
            <tr>
970
                <td class="requirements-item">'.api_get_path(SYS_CODE_PATH).'lang/</td>
971
                <td class="requirements-value">'.check_writable(api_get_path(SYS_CODE_PATH).'lang/', true).' <br />('.get_lang('SuggestionOnlyToEnableSubLanguageFeatureOrUpgradeProcess').')</td>
972
            </tr>
973
            <tr>
974
                <td class="requirements-item">'.api_get_path(SYS_PATH).'vendor/</td>
975
                <td class="requirements-value">'.checkReadable(api_get_path(SYS_PATH).'vendor').'</td>
976
            </tr>
977
            <tr>
978
                <td class="requirements-item">'.api_get_path(SYS_PUBLIC_PATH).'</td>
979
                <td class="requirements-value">'.check_writable(api_get_path(SYS_PUBLIC_PATH)).'</td>
980
            </tr>
981
            <tr>
982
                <td class="requirements-item">'.get_lang('CourseTestWasCreated').'</td>
983
                <td class="requirements-value">'.$courseTestLabel.' </td>
984
            </tr>
985
            <tr>
986
                <td class="requirements-item">'.get_lang('PermissionsForNewDirs').'</td>
987
                <td class="requirements-value">'.$dir_perm.' </td>
988
            </tr>
989
            <tr>
990
                <td class="requirements-item">'.get_lang('PermissionsForNewFiles').'</td>
991
                <td class="requirements-value">'.$file_perm.' </td>
992
            </tr>
993
        </table>';
994
    echo '  </div>';
995
    echo '</div>';
996
997
    if ($installType == 'update' && (empty($updatePath) || $badUpdatePath)) {
998
        if ($badUpdatePath) {
999
            ?>
1000
            <div class="alert alert-warning">
1001
                <?php echo get_lang('Error'); ?>!<br />
1002
                Chamilo <?php echo implode('|', $update_from_version_8).' '.get_lang('HasNotBeenFoundInThatDir'); ?>.
1003
            </div>
1004
        <?php
1005
        } else {
1006
            echo '<br />';
1007
        } ?>
1008
            <div class="row">
1009
                <div class="col-md-12">
1010
                    <p><?php echo get_lang('OldVersionRootPath'); ?>:
1011
                        <input type="text" name="updatePath" size="50" value="<?php echo ($badUpdatePath && !empty($updatePath)) ? htmlentities($updatePath) : ''; ?>" />
1012
                    </p>
1013
                    <p>
1014
                        <button type="submit" class="btn btn-default" name="step1" value="<?php echo get_lang('Back'); ?>" >
1015
                            <em class="fa fa-backward"> <?php echo get_lang('Back'); ?></em>
1016
                        </button>
1017
                        <input type="hidden" name="is_executable" id="is_executable" value="-" />
1018
                        <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;" >
1019
                            <em class="fa fa-forward"> </em> <?php echo get_lang('Next'); ?>
1020
                        </button>
1021
                    </p>
1022
                </div>
1023
            </div>
1024
1025
        <?php
1026
    } else {
1027
        $error = false;
1028
        // First, attempt to set writing permissions if we don't have them yet
1029
        $perm = api_get_permissions_for_new_directories();
1030
        $perm_file = api_get_permissions_for_new_files();
1031
        $notWritable = [];
1032
1033
        $checked_writable = api_get_path(SYS_APP_PATH);
1034
        if (!is_writable($checked_writable)) {
1035
            $notWritable[] = $checked_writable;
1036
            @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

1036
            /** @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...
1037
        }
1038
1039
        $checked_writable = api_get_path(SYS_PUBLIC_PATH);
1040
        if (!is_writable($checked_writable)) {
1041
            $notWritable[] = $checked_writable;
1042
            @chmod($checked_writable, $perm);
1043
        }
1044
1045
        $checked_writable = api_get_path(SYS_CODE_PATH).'default_course_document/images/';
1046
        if (!is_writable($checked_writable)) {
1047
            $notWritable[] = $checked_writable;
1048
            @chmod($checked_writable, $perm);
1049
        }
1050
1051
        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...
1052
            $error = true;
1053
        }
1054
1055
        $checked_writable = api_get_path(CONFIGURATION_PATH).'configuration.php';
1056
        if (file_exists($checked_writable) && !is_writable($checked_writable)) {
1057
            $notWritable[] = $checked_writable;
1058
            @chmod($checked_writable, $perm_file);
1059
        }
1060
1061
        // Second, if this fails, report an error
1062
1063
        //--> The user would have to adjust the permissions manually
1064
        if (count($notWritable) > 0) {
1065
            $error = true; ?>
1066
            <div class="text-danger">
1067
                <h3 class="text-center"><?php echo get_lang('Warning') ?></h3>
1068
                <p>
1069
                    <?php printf(get_lang('NoWritePermissionPleaseReadInstallGuide'), '<a href="../../documentation/installation_guide.html" target="blank">', '</a>'); ?>
1070
                </p>
1071
            </div>
1072
            <?php
1073
            echo '<ul>';
1074
            foreach ($notWritable as $value) {
1075
                echo '<li class="text-danger">'.$value.'</li>';
1076
            }
1077
            echo '</ul>';
1078
        } elseif (file_exists(api_get_path(CONFIGURATION_PATH).'configuration.php')) {
1079
            // Check wether a Chamilo configuration file already exists.
1080
            echo '<div class="alert alert-warning"><h4><center>';
1081
            echo get_lang('WarningExistingLMSInstallationDetected');
1082
            echo '</center></h4></div>';
1083
        }
1084
1085
        $deprecated = [
1086
            api_get_path(SYS_CODE_PATH).'exercice/',
1087
            api_get_path(SYS_CODE_PATH).'newscorm/',
1088
            api_get_path(SYS_PLUGIN_PATH).'ticket/',
1089
            api_get_path(SYS_PLUGIN_PATH).'skype/'
1090
        ];
1091
        $deprecatedToRemove = [];
1092
1093
        foreach ($deprecated as $deprecatedDirectory) {
1094
            if (!is_dir($deprecatedDirectory)) {
1095
                continue;
1096
            }
1097
1098
            $deprecatedToRemove[] = $deprecatedDirectory;
1099
        }
1100
1101
        if (count($deprecatedToRemove) > 0) {
1102
            $error = true; ?>
1103
            <p class="text-danger"><?php echo get_lang('WarningForDeprecatedDirectoriesForUpgrade') ?></p>
1104
            <ul>
1105
                <?php foreach ($deprecatedToRemove as $deprecatedDirectory) {
1106
                ?>
1107
                    <li class="text-danger"><?php echo $deprecatedDirectory ?></li>
1108
                <?php
1109
            } ?>
1110
            </ul>
1111
            <?php
1112
        }
1113
1114
        if (!$properlyAccessUrl) {
1115
            $error = true;
1116
        }
1117
1118
        // And now display the choice buttons (go back or install)?>
1119
        <p align="center" style="padding-top:15px">
1120
        <button type="submit" name="step1" class="btn btn-default" onclick="javascript: window.location='index.php'; return false;" value="<?php echo get_lang('Previous'); ?>" >
1121
            <em class="fa fa-backward"> </em> <?php echo get_lang('Previous'); ?>
1122
        </button>
1123
        <button type="submit" name="step2_install" class="btn btn-success" value="<?php echo get_lang("NewInstallation"); ?>" <?php if ($error) {
1124
            echo 'disabled="disabled"';
1125
        } ?> >
1126
            <em class="fa fa-forward"> </em> <?php echo get_lang('NewInstallation'); ?>
1127
        </button>
1128
        <input type="hidden" name="is_executable" id="is_executable" value="-" />
1129
            <button type="submit" class="btn btn-default" <?php echo !$error ?: 'disabled="disabled"' ?> name="step2_update_8" value="Upgrade from Chamilo 1.9.x">
1130
                <em class="fa fa-forward" aria-hidden="true"></em> <?php echo get_lang('UpgradeVersion') ?>
1131
            </button>
1132
            </p>
1133
        <?php
1134
    }
1135
}
1136
1137
/**
1138
 * Displays the license (GNU GPL) as step 2, with
1139
 * - an "I accept" button named step3 to proceed to step 3;
1140
 * - a "Back" button named step1 to go back to the first step.
1141
 */
1142
1143
function display_license_agreement()
1144
{
1145
    echo '<div class="RequirementHeading"><h2>'.display_step_sequence().get_lang('Licence').'</h2>';
1146
    echo '<p>'.get_lang('LMSLicenseInfo').'</p>';
1147
    echo '<p><a href="../../documentation/license.html" target="_blank">'.get_lang('PrintVers').'</a></p>';
1148
    echo '</div>'; ?>
1149
    <div class="row">
1150
        <div class="col-md-12">
1151
            <pre style="overflow: auto; height: 200px; margin-top: 5px;">
1152
                <?php echo api_htmlentities(@file_get_contents(api_get_path(SYS_PATH).'documentation/license.txt')); ?>
1153
            </pre>
1154
            <div class="checkbox">
1155
                <label>
1156
                    <input type="checkbox" name="accept" id="accept_licence" value="1" />
1157
                    <?php echo get_lang('IAccept'); ?>
1158
                </label>
1159
            </div>
1160
        </div>
1161
    </div>
1162
    <div class="row">
1163
        <div class="col-md-12">
1164
            <p class="alert alert-info"><?php echo get_lang('LMSMediaLicense'); ?></p>
1165
        </div>
1166
    </div>
1167
1168
    <!-- Contact information form -->
1169
    <div class="section-parameters">
1170
        <a href="javascript://" class = "advanced_parameters" >
1171
        <span id="img_plus_and_minus">&nbsp;<i class="fa fa-eye" aria-hidden="true"></i>&nbsp;<?php echo get_lang('ContactInformation') ?></span>
1172
        </a>
1173
    </div>
1174
1175
    <div id="id_contact_form" style="display:block">
1176
        <div class="normal-message"><?php echo get_lang('ContactInformationDescription') ?></div>
1177
        <div id="contact_registration">
1178
            <p><?php echo get_contact_registration_form() ?></p><br />
1179
        </div>
1180
    </div>
1181
    <div class="text-center">
1182
    <button type="submit" class="btn btn-default" name="step1" value="&lt; <?php echo get_lang('Previous'); ?>" >
1183
        <em class="fa fa-backward"> </em> <?php echo get_lang('Previous'); ?>
1184
    </button>
1185
    <input type="hidden" name="is_executable" id="is_executable" value="-" />
1186
    <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;" >
1187
        <em class="fa fa-forward"> </em> <?php echo get_lang('Next'); ?>
1188
    </button>
1189
    </div>
1190
    <?php
1191
}
1192
1193
/**
1194
 * Get contact registration form
1195
 */
1196
function get_contact_registration_form()
1197
{
1198
    $html = '
1199
   <div class="form-horizontal">
1200
    <div class="panel panel-default">
1201
    <div class="panel-body">
1202
    <div id="div_sent_information"></div>
1203
    <div class="form-group">
1204
            <label class="col-sm-3"><span class="form_required">*</span>'.get_lang('Name').'</label>
1205
            <div class="col-sm-9"><input id="person_name" class="form-control" type="text" name="person_name" size="30" /></div>
1206
    </div>
1207
    <div class="form-group">
1208
            <label class="col-sm-3"><span class="form_required">*</span>'.get_lang('Email').'</label>
1209
            <div class="col-sm-9"><input id="person_email" class="form-control" type="text" name="person_email" size="30" /></div>
1210
    </div>
1211
    <div class="form-group">
1212
            <label class="col-sm-3"><span class="form_required">*</span>'.get_lang('CompanyName').'</label>
1213
            <div class="col-sm-9"><input id="company_name" class="form-control" type="text" name="company_name" size="30" /></div>
1214
    </div>
1215
    <div class="form-group">
1216
        <label class="col-sm-3"><span class="form_required">*</span>'.get_lang('CompanyActivity').'</label>
1217
        <div class="col-sm-9">
1218
            <select class="selectpicker show-tick" name="company_activity" id="company_activity" >
1219
                <option value="">--- '.get_lang('SelectOne').' ---</option>
1220
                <Option value="Advertising/Marketing/PR">Advertising/Marketing/PR</Option><Option value="Agriculture/Forestry">Agriculture/Forestry</Option>
1221
                <Option value="Architecture">Architecture</Option><Option value="Banking/Finance">Banking/Finance</Option>
1222
                <Option value="Biotech/Pharmaceuticals">Biotech/Pharmaceuticals</Option><Option value="Business Equipment">Business Equipment</Option>
1223
                <Option value="Business Services">Business Services</Option><Option value="Construction">Construction</Option>
1224
                <Option value="Consulting/Research">Consulting/Research</Option><Option value="Education">Education</Option>
1225
                <Option value="Engineering">Engineering</Option><Option value="Environmental">Environmental</Option>
1226
                <Option value="Government">Government</Option><Option value="Healthcare">Health Care</Option>
1227
                <Option value="Hospitality/Lodging/Travel">Hospitality/Lodging/Travel</Option><Option value="Insurance">Insurance</Option>
1228
                <Option value="Legal">Legal</Option><Option value="Manufacturing">Manufacturing</Option>
1229
                <Option value="Media/Entertainment">Media/Entertainment</Option><Option value="Mortgage">Mortgage</Option>
1230
                <Option value="Non-Profit">Non-Profit</Option><Option value="Real Estate">Real Estate</Option>
1231
                <Option value="Restaurant">Restaurant</Option><Option value="Retail">Retail</Option>
1232
                <Option value="Shipping/Transportation">Shipping/Transportation</Option>
1233
                <Option value="Technology">Technology</Option><Option value="Telecommunications">Telecommunications</Option>
1234
                <Option value="Other">Other</Option>
1235
            </select>
1236
        </div>
1237
    </div>
1238
1239
    <div class="form-group">
1240
        <label class="col-sm-3"><span class="form_required">*</span>'.get_lang('PersonRole').'</label>
1241
        <div class="col-sm-9">
1242
            <select class="selectpicker show-tick" name="person_role" id="person_role" >
1243
                <option value="">--- '.get_lang('SelectOne').' ---</option>
1244
                <Option value="Administration">Administration</Option><Option value="CEO/President/ Owner">CEO/President/ Owner</Option>
1245
                <Option value="CFO">CFO</Option><Option value="CIO/CTO">CIO/CTO</Option>
1246
                <Option value="Consultant">Consultant</Option><Option value="Customer Service">Customer Service</Option>
1247
                <Option value="Engineer/Programmer">Engineer/Programmer</Option><Option value="Facilities/Operations">Facilities/Operations</Option>
1248
                <Option value="Finance/ Accounting Manager">Finance/ Accounting Manager</Option><Option value="Finance/ Accounting Staff">Finance/ Accounting Staff</Option>
1249
                <Option value="General Manager">General Manager</Option><Option value="Human Resources">Human Resources</Option>
1250
                <Option value="IS/IT Management">IS/IT Management</Option><Option value="IS/ IT Staff">IS/ IT Staff</Option>
1251
                <Option value="Marketing Manager">Marketing Manager</Option><Option value="Marketing Staff">Marketing Staff</Option>
1252
                <Option value="Partner/Principal">Partner/Principal</Option><Option value="Purchasing Manager">Purchasing Manager</Option>
1253
                <Option value="Sales/ Business Dev. Manager">Sales/ Business Dev. Manager</Option><Option value="Sales/ Business Dev.">Sales/ Business Dev.</Option>
1254
                <Option value="Vice President/Senior Manager">Vice President/Senior Manager</Option><Option value="Other">Other</Option>
1255
            </select>
1256
        </div>
1257
    </div>
1258
1259
    <div class="form-group">
1260
        <label class="col-sm-3"><span class="form_required">*</span>'.get_lang('CompanyCountry').'</label>
1261
        <div class="col-sm-9">'.get_countries_list_from_array(true).'</div>
1262
    </div>
1263
    <div class="form-group">
1264
        <label class="col-sm-3">'.get_lang('CompanyCity').'</label>
1265
        <div class="col-sm-9">
1266
                <input type="text" class="form-control" id="company_city" name="company_city" size="30" />
1267
        </div>
1268
    </div>
1269
    <div class="form-group">
1270
        <label class="col-sm-3">'.get_lang('WhichLanguageWouldYouLikeToUseWhenContactingYou').'</label>
1271
        <div class="col-sm-9">
1272
            <select class="selectpicker show-tick" id="language" name="language">
1273
                <option value="bulgarian">Bulgarian</option>
1274
                <option value="indonesian">Bahasa Indonesia</option>
1275
                <option value="bosnian">Bosanski</option>
1276
                <option value="german">Deutsch</option>
1277
                <option selected="selected" value="english">English</option>
1278
                <option value="spanish">Spanish</option>
1279
                <option value="french">Français</option>
1280
                <option value="italian">Italian</option>
1281
                <option value="hungarian">Magyar</option>
1282
                <option value="dutch">Nederlands</option>
1283
                <option value="brazilian">Português do Brasil</option>
1284
                <option value="portuguese">Português europeu</option>
1285
                <option value="slovenian">Slovenčina</option>
1286
            </select>
1287
        </div>
1288
    </div>
1289
1290
    <div class="form-group">
1291
        <label class="col-sm-3">'.get_lang('HaveYouThePowerToTakeFinancialDecisions').'</label>
1292
        <div class="col-sm-9">
1293
            <div class="radio">
1294
                <label>
1295
                    <input type="radio" name="financial_decision" id="financial_decision1" value="1" checked /> ' . get_lang('Yes').'
1296
                </label>
1297
            </div>
1298
            <div class="radio">
1299
                <label>
1300
                    <input type="radio" name="financial_decision" id="financial_decision2" value="0" /> '.get_lang('No').'
1301
                </label>
1302
            </div>
1303
        </div>
1304
    </div>
1305
    <div class="clear"></div>
1306
    <div class="form-group">
1307
            <div class="col-sm-3">&nbsp;</div>
1308
            <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>
1309
    </div>
1310
    <div class="form-group">
1311
            <div class="col-sm-3">&nbsp;</div>
1312
            <div class="col-sm-9"><span class="form_required">*</span><small>'.get_lang('FieldRequired').'</small></div>
1313
    </div></div></div>
1314
    </div>';
1315
1316
    return $html;
1317
}
1318
1319
/**
1320
 * Displays a parameter in a table row.
1321
 * Used by the display_database_settings_form function.
1322
 * @param   string  Type of install
1323
 * @param   string  Name of parameter
1324
 * @param   string  Field name (in the HTML form)
1325
 * @param   string  Field value
1326
 * @param   string  Extra notice (to show on the right side)
1327
 * @param   boolean Whether to display in update mode
1328
 * @param   string  Additional attribute for the <tr> element
1329
 * @return  void    Direct output
1330
 */
1331
function displayDatabaseParameter(
1332
    $installType,
1333
    $parameterName,
1334
    $formFieldName,
1335
    $parameterValue,
1336
    $extra_notice,
1337
    $displayWhenUpdate = true,
1338
    $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

1338
    /** @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...
1339
) {
1340
    //echo "<tr ".$tr_attribute.">";
1341
    echo "<label class='col-sm-4'>$parameterName</label>";
1342
1343
    if ($installType == INSTALL_TYPE_UPDATE && $displayWhenUpdate) {
1344
        echo '<input type="hidden" name="'.$formFieldName.'" id="'.$formFieldName.'" value="'.api_htmlentities($parameterValue).'" />'.$parameterValue;
1345
    } else {
1346
        $inputType = $formFieldName == 'dbPassForm' ? 'password' : 'text';
1347
1348
        //Slightly limit the length of the database prefix to avoid having to cut down the databases names later on
1349
        $maxLength = $formFieldName == 'dbPrefixForm' ? '15' : MAX_FORM_FIELD_LENGTH;
1350
        if ($installType == INSTALL_TYPE_UPDATE) {
1351
            echo '<input type="hidden" name="'.$formFieldName.'" id="'.$formFieldName.'" value="'.api_htmlentities($parameterValue).'" />';
1352
            echo api_htmlentities($parameterValue);
1353
        } else {
1354
            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>";
1355
            echo '<div class="col-sm-3">'.$extra_notice.'</div>';
1356
        }
1357
    }
1358
}
1359
1360
/**
1361
 * Displays step 3 - a form where the user can enter the installation settings
1362
 * regarding the databases - login and password, names, prefixes, single
1363
 * or multiple databases, tracking or not...
1364
 * @param string $installType
1365
 * @param string $dbHostForm
1366
 * @param string $dbUsernameForm
1367
 * @param string $dbPassForm
1368
 * @param string $dbNameForm
1369
 * @param int    $dbPortForm
1370
 * @param string $installationProfile
1371
 */
1372
function display_database_settings_form(
1373
    $installType,
1374
    $dbHostForm,
1375
    $dbUsernameForm,
1376
    $dbPassForm,
1377
    $dbNameForm,
1378
    $dbPortForm = 3306,
1379
    $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

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

1798
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...
1799
{
1800
    echo '<div class="RequirementContent">'.get_lang('FirstUseTip').'</div>';
1801
    echo '<div class="alert alert-warning">';
1802
    echo '<strong>'.get_lang('SecurityAdvice').'</strong>';
1803
    echo ': ';
1804
    printf(get_lang('ToProtectYourSiteMakeXReadOnlyAndDeleteY'), 'app/config/', 'main/install/');
1805
    echo '</div>'; ?></form>
1806
    <br />
1807
    <a class="btn btn-success btn-block" href="../../index.php">
1808
        <?php echo get_lang('GoToYourNewlyCreatedPortal'); ?>
1809
    </a>
1810
    <?php
1811
}
1812
1813
/**
1814
 * This function return countries list from array (hardcoded)
1815
 * @param   bool  $combo  (Optional) True for returning countries list with select html
1816
 * @return  array|string countries list
1817
 */
1818
function get_countries_list_from_array($combo = false)
1819
{
1820
    $a_countries = [
1821
        "Afghanistan", "Albania", "Algeria", "Andorra", "Angola", "Antigua and Barbuda", "Argentina", "Armenia", "Australia", "Austria", "Azerbaijan",
1822
        "Bahamas", "Bahrain", "Bangladesh", "Barbados", "Belarus", "Belgium", "Belize", "Benin", "Bhutan", "Bolivia", "Bosnia and Herzegovina", "Botswana", "Brazil", "Brunei", "Bulgaria", "Burkina Faso", "Burundi",
1823
        "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",
1824
        "Denmark", "Djibouti", "Dominica", "Dominican Republic",
1825
        "East Timor (Timor Timur)", "Ecuador", "Egypt", "El Salvador", "Equatorial Guinea", "Eritrea", "Estonia", "Ethiopia",
1826
        "Fiji", "Finland", "France",
1827
        "Gabon", "Gambia, The", "Georgia", "Germany", "Ghana", "Greece", "Grenada", "Guatemala", "Guinea", "Guinea-Bissau", "Guyana",
1828
        "Haiti", "Honduras", "Hungary",
1829
        "Iceland", "India", "Indonesia", "Iran", "Iraq", "Ireland", "Israel", "Italy",
1830
        "Jamaica", "Japan", "Jordan",
1831
        "Kazakhstan", "Kenya", "Kiribati", "Korea, North", "Korea, South", "Kuwait", "Kyrgyzstan",
1832
        "Laos", "Latvia", "Lebanon", "Lesotho", "Liberia", "Libya", "Liechtenstein", "Lithuania", "Luxembourg",
1833
        "Macedonia", "Madagascar", "Malawi", "Malaysia", "Maldives", "Mali", "Malta", "Marshall Islands", "Mauritania", "Mauritius", "Mexico", "Micronesia", "Moldova", "Monaco", "Mongolia", "Morocco", "Mozambique", "Myanmar",
1834
        "Namibia", "Nauru", "Nepa", "Netherlands", "New Zealand", "Nicaragua", "Niger", "Nigeria", "Norway",
1835
        "Oman",
1836
        "Pakistan", "Palau", "Panama", "Papua New Guinea", "Paraguay", "Peru", "Philippines", "Poland", "Portugal",
1837
        "Qatar",
1838
        "Romania", "Russia", "Rwanda",
1839
        "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",
1840
        "Taiwan", "Tajikistan", "Tanzania", "Thailand", "Togo", "Tonga", "Trinidad and Tobago", "Tunisia", "Turkey", "Turkmenistan", "Tuvalu",
1841
        "Uganda", "Ukraine", "United Arab Emirates", "United Kingdom", "United States", "Uruguay", "Uzbekistan",
1842
        "Vanuatu", "Vatican City", "Venezuela", "Vietnam",
1843
        "Yemen",
1844
        "Zambia", "Zimbabwe"
1845
    ];
1846
1847
    $country_select = '';
1848
    if ($combo) {
1849
        $country_select = '<select class="selectpicker show-tick" id="country" name="country">';
1850
        $country_select .= '<option value="">--- '.get_lang('SelectOne').' ---</option>';
1851
        foreach ($a_countries as $country) {
1852
            $country_select .= '<option value="'.$country.'">'.$country.'</option>';
1853
        }
1854
        $country_select .= '</select>';
1855
        return $country_select;
1856
    }
1857
1858
    return $a_countries;
1859
}
1860
1861
/**
1862
 * Lock settings that can't be changed in other portals
1863
 */
1864
function lockSettings()
1865
{
1866
    $access_url_locked_settings = api_get_locked_settings();
1867
    $table = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
1868
    foreach ($access_url_locked_settings as $setting) {
1869
        $sql = "UPDATE $table SET access_url_locked = 1 WHERE variable  = '$setting'";
1870
        Database::query($sql);
1871
    }
1872
}
1873
1874
/**
1875
 * Update dir values
1876
 */
1877
function updateDirAndFilesPermissions()
1878
{
1879
    $table = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
1880
    $permissions_for_new_directories = isset($_SESSION['permissions_for_new_directories']) ? $_SESSION['permissions_for_new_directories'] : 0770;
1881
    $permissions_for_new_files = isset($_SESSION['permissions_for_new_files']) ? $_SESSION['permissions_for_new_files'] : 0660;
1882
    // use decoct() to store as string
1883
    $sql = "UPDATE $table SET selected_value = '0".decoct($permissions_for_new_directories)."'
1884
              WHERE variable  = 'permissions_for_new_directories'";
1885
    Database::query($sql);
1886
1887
    $sql = "UPDATE $table SET selected_value = '0".decoct($permissions_for_new_files)."' WHERE variable  = 'permissions_for_new_files'";
1888
    Database::query($sql);
1889
1890
    if (isset($_SESSION['permissions_for_new_directories'])) {
1891
        unset($_SESSION['permissions_for_new_directories']);
1892
    }
1893
1894
    if (isset($_SESSION['permissions_for_new_files'])) {
1895
        unset($_SESSION['permissions_for_new_files']);
1896
    }
1897
}
1898
1899
/**
1900
 * @param $current_value
1901
 * @param $wanted_value
1902
 * @return string
1903
 */
1904
function compare_setting_values($current_value, $wanted_value)
1905
{
1906
    $current_value_string = $current_value;
1907
    $current_value = (float) $current_value;
1908
    $wanted_value = (float) $wanted_value;
1909
1910
    if ($current_value >= $wanted_value) {
1911
        return Display::label($current_value_string, 'success');
1912
    } else {
1913
        return Display::label($current_value_string, 'important');
1914
    }
1915
}
1916
1917
/**
1918
 * @param $course_dir
1919
 * @param $course_attempt_name
1920
 * @param string $file
1921
 * @return bool
1922
 */
1923
function check_course_script_interpretation(
1924
    $course_dir,
1925
    $course_attempt_name,
1926
    $file = 'test.php'
1927
) {
1928
    $output = false;
1929
    //Write in file
1930
    $file_name = $course_dir.'/'.$file;
1931
    $content = '<?php echo "123"; exit;';
1932
1933
    if (is_writable($file_name)) {
1934
        if ($handler = @fopen($file_name, "w")) {
1935
            //write content
1936
            if (fwrite($handler, $content)) {
1937
                $sock_errno = '';
1938
                $sock_errmsg = '';
1939
                $url = api_get_path(WEB_PATH).'app/courses/'.$course_attempt_name.'/'.$file;
1940
1941
                $parsed_url = parse_url($url);
1942
                //$scheme = isset($parsedUrl['scheme']) ? $parsedUrl['scheme'] : ''; //http
1943
                $host = isset($parsed_url['host']) ? $parsed_url['host'] : '';
1944
                // Patch if the host is the default host and is used through
1945
                // the IP address (sometimes the host is not taken correctly
1946
                // in this case)
1947
                if (empty($host) && !empty($_SERVER['HTTP_HOST'])) {
1948
                    $host = $_SERVER['HTTP_HOST'];
1949
                    $url = preg_replace('#:///#', '://'.$host.'/', $url);
1950
                }
1951
                $path = isset($parsed_url['path']) ? $parsed_url['path'] : '/';
1952
                $port = '';
1953
                $scheme = '';
1954
                switch ($parsed_url['scheme']) {
1955
                    case 'https':
1956
                        $scheme = 'ssl://';
1957
                        $port = 443;
1958
                        break;
1959
                    case 'http':
1960
                    default:
1961
                        $scheme = '';
1962
                        $port = 80;
1963
                }
1964
1965
                //Check fsockopen (not sure it works with https). If that is your case, you might want to try the
1966
                // suggestion at https://support.chamilo.org/issues/8260#note-3 (although it ignores SSL peer checks)
1967
                if ($fp = @fsockopen(str_replace('http://', $scheme, $url), $port, $sock_errno, $sock_errmsg, 60)) {
1968
                    $out  = "GET $path HTTP/1.1\r\n";
1969
                    $out .= "Host: $host\r\n";
1970
                    $out .= "Connection: Close\r\n\r\n";
1971
1972
                    fwrite($fp, $out);
1973
                    while (!feof($fp)) {
1974
                        $result = str_replace("\r\n", '', fgets($fp, 128));
1975
                        if (!empty($result) && $result == '123') {
1976
                            $output = true;
1977
                        }
1978
                    }
1979
                    fclose($fp);
1980
                } elseif (ini_get('allow_url_fopen')) {
1981
                    // Check allow_url_fopen
1982
                    if ($fp = @fopen($url, 'r')) {
1983
                        while ($result = fgets($fp, 1024)) {
1984
                            if (!empty($result) && $result == '123') {
1985
                                $output = true;
1986
                            }
1987
                        }
1988
                        fclose($fp);
1989
                    }
1990
                } elseif (function_exists('curl_init')) {
1991
                    // Check if has support for cURL
1992
                    $ch = curl_init();
1993
                    curl_setopt($ch, CURLOPT_HEADER, 0);
1994
                    curl_setopt($ch, CURLOPT_URL, $url);
1995
                    //curl_setopt($ch, CURLOPT_TIMEOUT, 30);
1996
                    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
1997
                    $result = curl_exec($ch);
1998
                    if (!empty($result) && $result == '123') {
1999
                        $output = true;
2000
                    }
2001
                    curl_close($ch);
2002
                }
2003
            }
2004
            @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

2004
            /** @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...
2005
        }
2006
    }
2007
2008
    return $output;
2009
}
2010
2011
/**
2012
 * Save settings values
2013
 *
2014
 * @param string $organizationName
2015
 * @param string $organizationUrl
2016
 * @param string $siteName
2017
 * @param string $adminEmail
2018
 * @param string $adminLastName
2019
 * @param string $adminFirstName
2020
 * @param string $language
2021
 * @param string $allowRegistration
2022
 * @param string $allowTeacherSelfRegistration
2023
 * @param string $installationProfile The name of an installation profile file in main/install/profiles/
2024
 */
2025
function installSettings(
2026
    $organizationName,
2027
    $organizationUrl,
2028
    $siteName,
2029
    $adminEmail,
2030
    $adminLastName,
2031
    $adminFirstName,
2032
    $language,
2033
    $allowRegistration,
2034
    $allowTeacherSelfRegistration,
2035
    $installationProfile = ''
2036
) {
2037
    $allowTeacherSelfRegistration = $allowTeacherSelfRegistration ? 'true' : 'false';
2038
2039
    // Use PHP 5.3 to avoid issue with weird peripherical auto-installers like travis-ci
2040
    $settings = [
2041
        'Institution' => $organizationName,
2042
        'InstitutionUrl' => $organizationUrl,
2043
        'siteName' => $siteName,
2044
        'emailAdministrator' => $adminEmail,
2045
        'administratorSurname' => $adminLastName,
2046
        'administratorName' => $adminFirstName,
2047
        'platformLanguage' => $language,
2048
        'allow_registration' => $allowRegistration,
2049
        'allow_registration_as_teacher' => $allowTeacherSelfRegistration,
2050
    ];
2051
2052
    foreach ($settings as $variable => $value) {
2053
        $sql = "UPDATE settings_current
2054
                SET selected_value = '$value'
2055
                WHERE variable = '$variable'";
2056
        Database::query($sql);
2057
    }
2058
    installProfileSettings($installationProfile);
2059
}
2060
2061
/**
2062
 * Executes DB changes based in the classes defined in
2063
 * src/Chamilo/CoreBundle/Migrations/Schema/*
2064
 *
2065
 * @param string $chamiloVersion
2066
 * @param EntityManager $manager
2067
 * @throws \Doctrine\DBAL\DBALException
2068
 * @return bool
2069
 */
2070
function migrate($chamiloVersion, EntityManager $manager)
2071
{
2072
    $debug = true;
2073
    $connection = $manager->getConnection();
2074
2075
    $config = new \Doctrine\DBAL\Migrations\Configuration\Configuration($connection);
2076
2077
    // Table name that will store migrations log (will be created automatically,
2078
    // default name is: doctrine_migration_versions)
2079
    $config->setMigrationsTableName('version');
2080
    // Namespace of your migration classes, do not forget escape slashes, do not add last slash
2081
    $config->setMigrationsNamespace('Application\Migrations\Schema\V'.$chamiloVersion);
2082
    // Directory where your migrations are located
2083
    $config->setMigrationsDirectory(api_get_path(SYS_PATH).'app/Migrations/Schema/V'.$chamiloVersion);
2084
    // Load your migrations
2085
    $config->registerMigrationsFromDirectory($config->getMigrationsDirectory());
2086
2087
    $migration = new \Doctrine\DBAL\Migrations\Migration($config);
2088
    $versions = $config->getMigrations();
2089
2090
    /** @var Doctrine\DBAL\Migrations\Version $migrationItem */
2091
    foreach ($versions as $version) {
2092
        $version->getMigration()->setEntityManager($manager);
0 ignored issues
show
Bug introduced by
The method setEntityManager() does not exist on Doctrine\DBAL\Migrations\AbstractMigration. It seems like you code against a sub-type of Doctrine\DBAL\Migrations\AbstractMigration such as Application\Migrations\AbstractMigrationChamilo. ( Ignorable by Annotation )

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

2092
        $version->getMigration()->/** @scrutinizer ignore-call */ setEntityManager($manager);
Loading history...
2093
    }
2094
2095
    $to = null; // if $to == null then schema will be migrated to latest version
2096
2097
    echo "<pre>";
2098
    try {
2099
        // Execute migration!
2100
        $migratedSQL = $migration->migrate($to);
2101
2102
        if ($debug) {
2103
            foreach ($migratedSQL as $version => $sqlList) {
2104
                echo "VERSION: $version<br>";
2105
                echo "----------------------------------------------<br>";
2106
                $total = count($sqlList);
2107
                error_log("VERSION: $version");
2108
                error_log("# queries: ".$total);
2109
                $counter = 1;
2110
                foreach ($sqlList as $sql) {
2111
                    echo "<code>$sql</code><br>";
2112
                    error_log("$counter/$total : $sql");
2113
                    $counter++;
2114
                }
2115
            }
2116
2117
            echo "<br>DONE!<br>";
2118
        }
2119
2120
        return true;
2121
    } catch (Exception $ex) {
2122
        if ($debug) {
2123
            echo "ERROR: {$ex->getMessage()}<br>";
2124
            return false;
2125
        }
2126
    }
2127
2128
    echo "</pre>";
2129
2130
    return false;
2131
}
2132
2133
/**
2134
* @param EntityManager $em
2135
 *
2136
* @throws \Doctrine\DBAL\DBALException
2137
 */
2138
function fixIds(EntityManager $em)
2139
{
2140
    $connection = $em->getConnection();
2141
    $database = new Database();
2142
    $database->setManager($em);
2143
    $debug = true;
2144
    if ($debug) {
2145
        error_log('fixIds');
2146
    }
2147
2148
    // Create temporary indexes to increase speed of the following operations
2149
    // Adding and removing indexes will usually take much less time than
2150
    // the execution without indexes of the queries in this function, particularly
2151
    // for large tables
2152
    $sql = "ALTER TABLE c_document ADD INDEX tmpidx_doc(c_id, id)";
2153
    $connection->executeQuery($sql);
2154
    $sql = "ALTER TABLE c_student_publication ADD INDEX tmpidx_stud (c_id, id)";
2155
    $connection->executeQuery($sql);
2156
    $sql = "ALTER TABLE c_quiz ADD INDEX tmpidx_quiz (c_id, id)";
2157
    $connection->executeQuery($sql);
2158
    $sql = "ALTER TABLE c_item_property ADD INDEX tmpidx_ip (to_group_id)";
2159
    $connection->executeQuery($sql);
2160
2161
    $sql = "SELECT * FROM c_lp_item";
2162
    $result = $connection->fetchAll($sql);
2163
    foreach ($result as $item) {
2164
        $courseId = $item['c_id'];
2165
        $iid = isset($item['iid']) ? intval($item['iid']) : 0;
2166
        $ref = isset($item['ref']) ? intval($item['ref']) : 0;
2167
        $sql = null;
2168
2169
        $newId = '';
2170
2171
        switch ($item['item_type']) {
2172
            case TOOL_LINK:
2173
                $sql = "SELECT * FROM c_link WHERE c_id = $courseId AND id = $ref";
2174
                $data = $connection->fetchAssoc($sql);
2175
                if ($data) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $data of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
2176
                    $newId = $data['iid'];
2177
                }
2178
                break;
2179
            case TOOL_STUDENTPUBLICATION:
2180
                $sql = "SELECT * FROM c_student_publication WHERE c_id = $courseId AND id = $ref";
2181
                $data = $connection->fetchAssoc($sql);
2182
                if ($data) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $data of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
2183
                    $newId = $data['iid'];
2184
                }
2185
                break;
2186
            case TOOL_QUIZ:
2187
                $sql = "SELECT * FROM c_quiz WHERE c_id = $courseId AND id = $ref";
2188
                $data = $connection->fetchAssoc($sql);
2189
                if ($data) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $data of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
2190
                    $newId = $data['iid'];
2191
                }
2192
                break;
2193
            case TOOL_DOCUMENT:
2194
                $sql = "SELECT * FROM c_document WHERE c_id = $courseId AND id = $ref";
2195
                $data = $connection->fetchAssoc($sql);
2196
                if ($data) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $data of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
2197
                    $newId = $data['iid'];
2198
                }
2199
                break;
2200
            case TOOL_FORUM:
2201
                $sql = "SELECT * FROM c_forum_forum WHERE c_id = $courseId AND forum_id = $ref";
2202
                $data = $connection->fetchAssoc($sql);
2203
                if ($data) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $data of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
2204
                    $newId = $data['iid'];
2205
                }
2206
                break;
2207
            case 'thread':
2208
                $sql = "SELECT * FROM c_forum_thread WHERE c_id = $courseId AND thread_id = $ref";
2209
                $data = $connection->fetchAssoc($sql);
2210
                if ($data) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $data of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
2211
                    $newId = $data['iid'];
2212
                }
2213
                break;
2214
        }
2215
2216
        if (!empty($sql) && !empty($newId) && !empty($iid)) {
2217
            $sql = "UPDATE c_lp_item SET ref = $newId WHERE iid = $iid";
2218
2219
            $connection->executeQuery($sql);
2220
        }
2221
    }
2222
2223
    // Set NULL if session = 0
2224
    $sql = "UPDATE c_item_property SET session_id = NULL WHERE session_id = 0";
2225
    $connection->executeQuery($sql);
2226
2227
    // Set NULL if group = 0
2228
    $sql = "UPDATE c_item_property SET to_group_id = NULL WHERE to_group_id = 0";
2229
    $connection->executeQuery($sql);
2230
2231
    // Set NULL if insert_user_id = 0
2232
    $sql = "UPDATE c_item_property SET insert_user_id = NULL WHERE insert_user_id = 0";
2233
    $connection->executeQuery($sql);
2234
2235
    // Delete session data of sessions that don't exist.
2236
    $sql = "DELETE FROM c_item_property
2237
            WHERE session_id IS NOT NULL AND session_id NOT IN (SELECT id FROM session)";
2238
    $connection->executeQuery($sql);
2239
2240
    // Delete group data of groups that don't exist.
2241
    $sql = "DELETE FROM c_item_property
2242
            WHERE to_group_id IS NOT NULL AND to_group_id NOT IN (SELECT DISTINCT id FROM c_group_info)";
2243
    $connection->executeQuery($sql);
2244
2245
    // This updates the group_id with c_group_info.iid instead of c_group_info.id
2246
2247
    if ($debug) {
2248
        error_log('update iids');
2249
    }
2250
2251
    $groupTableToFix = [
2252
        'c_group_rel_user',
2253
        'c_group_rel_tutor',
2254
        'c_permission_group',
2255
        'c_role_group',
2256
        'c_survey_invitation',
2257
        'c_attendance_calendar_rel_group'
2258
    ];
2259
2260
    foreach ($groupTableToFix as $table) {
2261
        $sql = "SELECT * FROM $table";
2262
        $result = $connection->fetchAll($sql);
2263
        foreach ($result as $item) {
2264
            $iid = $item['iid'];
2265
            $courseId = $item['c_id'];
2266
            $groupId = intval($item['group_id']);
2267
2268
            // Fix group id
2269
            if (!empty($groupId)) {
2270
                $sql = "SELECT * FROM c_group_info
2271
                        WHERE c_id = $courseId AND id = $groupId
2272
                        LIMIT 1";
2273
                $data = $connection->fetchAssoc($sql);
2274
                if (!empty($data)) {
2275
                    $newGroupId = $data['iid'];
2276
                    $sql = "UPDATE $table SET group_id = $newGroupId
2277
                            WHERE iid = $iid";
2278
                    $connection->executeQuery($sql);
2279
                } else {
2280
                    // The group does not exists clean this record
2281
                    $sql = "DELETE FROM $table WHERE iid = $iid";
2282
                    $connection->executeQuery($sql);
2283
                }
2284
            }
2285
        }
2286
    }
2287
2288
    // Fix c_item_property
2289
    if ($debug) {
2290
        error_log('update c_item_property');
2291
    }
2292
2293
    $sql = "SELECT * FROM course";
2294
    $courseList = $connection->fetchAll($sql);
2295
    if ($debug) {
2296
        error_log('Getting course list');
2297
    }
2298
2299
    $totalCourse = count($courseList);
2300
    $counter = 0;
2301
2302
    foreach ($courseList as $courseData) {
2303
        $courseId = $courseData['id'];
2304
        if ($debug) {
2305
            error_log('Updating course: '.$courseData['code']);
2306
        }
2307
2308
        $sql = "SELECT * FROM c_item_property WHERE c_id = $courseId";
2309
        $result = $connection->fetchAll($sql);
2310
        foreach ($result as $item) {
2311
            $sessionId = intval($item['session_id']);
2312
            $groupId = intval($item['to_group_id']);
2313
            $iid = $item['iid'];
2314
            $ref = $item['ref'];
2315
2316
            // Fix group id
2317
            if (!empty($groupId)) {
2318
                $sql = "SELECT * FROM c_group_info
2319
                        WHERE c_id = $courseId AND id = $groupId";
2320
                $data = $connection->fetchAssoc($sql);
2321
                if (!empty($data)) {
2322
                    $newGroupId = $data['iid'];
2323
                    $sql = "UPDATE c_item_property SET to_group_id = $newGroupId
2324
                            WHERE iid = $iid";
2325
                    $connection->executeQuery($sql);
2326
                } else {
2327
                    // The group does not exists clean this record
2328
                    $sql = "DELETE FROM c_item_property WHERE iid = $iid";
2329
                    $connection->executeQuery($sql);
2330
                }
2331
            }
2332
2333
            $sql = '';
2334
            $newId = '';
2335
            switch ($item['tool']) {
2336
                case TOOL_LINK:
2337
                    $sql = "SELECT * FROM c_link WHERE c_id = $courseId AND id = $ref ";
2338
                    break;
2339
                case TOOL_STUDENTPUBLICATION:
2340
                    $sql = "SELECT * FROM c_student_publication WHERE c_id = $courseId AND id = $ref";
2341
                    break;
2342
                case TOOL_QUIZ:
2343
                    $sql = "SELECT * FROM c_quiz WHERE c_id = $courseId AND id = $ref";
2344
                    break;
2345
                case TOOL_DOCUMENT:
2346
                    $sql = "SELECT * FROM c_document WHERE c_id = $courseId AND id = $ref";
2347
                    break;
2348
                case TOOL_FORUM:
2349
                    $sql = "SELECT * FROM c_forum_forum WHERE c_id = $courseId AND id = $ref";
2350
                    break;
2351
                case 'thread':
2352
                    $sql = "SELECT * FROM c_forum_thread WHERE c_id = $courseId AND id = $ref";
2353
                    break;
2354
            }
2355
2356
            if (!empty($sql) && !empty($newId)) {
2357
                $data = $connection->fetchAssoc($sql);
2358
                if (isset($data['iid'])) {
2359
                    $newId = $data['iid'];
2360
                }
2361
                $sql = "UPDATE c_item_property SET ref = $newId WHERE iid = $iid";
2362
                error_log($sql);
2363
                $connection->executeQuery($sql);
2364
            }
2365
        }
2366
2367
        if ($debug) {
2368
            // Print a status in the log once in a while
2369
            error_log("Course process #$counter/$totalCourse");
2370
        }
2371
        $counter++;
2372
    }
2373
2374
    if ($debug) {
2375
        error_log('update gradebook_link');
2376
    }
2377
2378
    // Fix gradebook_link
2379
    $sql = "SELECT * FROM gradebook_link";
2380
    $result = $connection->fetchAll($sql);
2381
    foreach ($result as $item) {
2382
        $courseCode = $item['course_code'];
2383
2384
        $sql = "SELECT * FROM course WHERE code = '$courseCode'";
2385
        $courseInfo = $connection->fetchAssoc($sql);
2386
        if (empty($courseInfo)) {
2387
            continue;
2388
        }
2389
2390
        $courseId = $courseInfo['id'];
2391
2392
        $ref = $item['ref_id'];
2393
        $iid = $item['id'];
2394
2395
        $sql = '';
2396
        switch ($item['type']) {
2397
            case LINK_LEARNPATH:
2398
                $sql = "SELECT * FROM c_link WHERE c_id = $courseId AND id = $ref ";
2399
                break;
2400
            case LINK_STUDENTPUBLICATION:
2401
                $sql = "SELECT * FROM c_student_publication WHERE c_id = $courseId AND id = $ref";
2402
                break;
2403
            case LINK_EXERCISE:
2404
                $sql = "SELECT * FROM c_quiz WHERE c_id = $courseId AND id = $ref";
2405
                break;
2406
            case LINK_ATTENDANCE:
2407
                //$sql = "SELECT * FROM c_document WHERE c_id = $courseId AND id = $ref";
2408
                break;
2409
            case LINK_FORUM_THREAD:
2410
                $sql = "SELECT * FROM c_forum_thread WHERE c_id = $courseId AND thread_id = $ref";
2411
                break;
2412
        }
2413
2414
        if (!empty($sql)) {
2415
            $data = $connection->fetchAssoc($sql);
2416
            if (isset($data) && isset($data['iid'])) {
2417
                $newId = $data['iid'];
2418
                $sql = "UPDATE gradebook_link SET ref_id = $newId
2419
                        WHERE id = $iid";
2420
                $connection->executeQuery($sql);
2421
            }
2422
        }
2423
    }
2424
2425
    if ($debug) {
2426
        error_log('update groups');
2427
    }
2428
2429
    $sql = "SELECT * FROM groups";
2430
    $result = $connection->executeQuery($sql);
2431
    $groups = $result->fetchAll();
2432
2433
    $oldGroups = [];
2434
2435
    if (!empty($groups)) {
2436
        foreach ($groups as $group) {
2437
            if (empty($group['name'])) {
2438
                continue;
2439
            }
2440
2441
            $params = [
2442
                'name' => $group['name'],
2443
                'description' => $group['description'],
2444
                'group_type' => 1,
2445
                'picture' => $group['picture_uri'],
2446
                'url' => $group['url'],
2447
                'visibility' => $group['visibility'],
2448
                'updated_at' => $group['updated_on'],
2449
                'created_at' => $group['created_on']
2450
            ];
2451
            $connection->insert('usergroup', $params);
2452
            $id = $connection->lastInsertId('id');
2453
            $oldGroups[$group['id']] = $id;
2454
        }
2455
    }
2456
2457
    if (!empty($oldGroups)) {
2458
        error_log('Moving group files');
2459
        foreach ($oldGroups as $oldId => $newId) {
2460
            $path = get_group_picture_path_by_id(
2461
                $oldId,
2462
                'system'
2463
            );
2464
2465
            if (!empty($path)) {
2466
                $newPath = str_replace(
2467
                    "groups/$oldId/",
2468
                    "groups/$newId/",
2469
                    $path['dir']
2470
                );
2471
                $command = "mv {$path['dir']} $newPath ";
2472
                error_log("Executing $command");
2473
                system($command);
2474
            }
2475
        }
2476
2477
        $sql = "SELECT * FROM group_rel_user";
2478
        $result = $connection->executeQuery($sql);
2479
        $dataList = $result->fetchAll();
2480
2481
        if (!empty($dataList)) {
2482
            foreach ($dataList as $data) {
2483
                if (isset($oldGroups[$data['group_id']])) {
2484
                    $data['group_id'] = $oldGroups[$data['group_id']];
2485
                    $userId = $data['user_id'];
2486
2487
                    $sql = "SELECT id FROM user WHERE user_id = $userId";
2488
                    $userResult = $connection->executeQuery($sql);
2489
                    $userInfo = $userResult->fetch();
2490
                    if (empty($userInfo)) {
2491
                        continue;
2492
                    }
2493
2494
                    $sql = "INSERT INTO usergroup_rel_user (usergroup_id, user_id, relation_type)
2495
                            VALUES ('{$data['group_id']}', '{$userId}', '{$data['relation_type']}')";
2496
                    $connection->executeQuery($sql);
2497
                }
2498
            }
2499
        }
2500
2501
        $sql = "SELECT * FROM group_rel_group";
2502
        $result = $connection->executeQuery($sql);
2503
        $dataList = $result->fetchAll();
2504
2505
        if (!empty($dataList)) {
2506
            foreach ($dataList as $data) {
2507
                if (isset($oldGroups[$data['group_id']]) && isset($oldGroups[$data['subgroup_id']])) {
2508
                    $data['group_id'] = $oldGroups[$data['group_id']];
2509
                    $data['subgroup_id'] = $oldGroups[$data['subgroup_id']];
2510
                    $sql = "INSERT INTO usergroup_rel_usergroup (group_id, subgroup_id, relation_type)
2511
                            VALUES ('{$data['group_id']}', '{$data['subgroup_id']}', '{$data['relation_type']}')";
2512
                    $connection->executeQuery($sql);
2513
                }
2514
            }
2515
        }
2516
2517
        $sql = "SELECT * FROM announcement_rel_group";
2518
        $result = $connection->executeQuery($sql);
2519
        $dataList = $result->fetchAll();
2520
2521
        if (!empty($dataList)) {
2522
            foreach ($dataList as $data) {
2523
                if (isset($oldGroups[$data['group_id']])) {
2524
                    // Deleting relation
2525
                    $sql = "DELETE FROM announcement_rel_group WHERE group_id = {$data['group_id']}";
2526
                    $connection->executeQuery($sql);
2527
2528
                    // Add new relation
2529
                    $data['group_id'] = $oldGroups[$data['group_id']];
2530
                    $sql = "INSERT INTO announcement_rel_group(group_id, announcement_id)
2531
                            VALUES ('{$data['group_id']}', '{$data['announcement_id']}')";
2532
                    $connection->executeQuery($sql);
2533
                }
2534
            }
2535
        }
2536
2537
        $sql = "SELECT * FROM group_rel_tag";
2538
        $result = $connection->executeQuery($sql);
2539
        $dataList = $result->fetchAll();
2540
        if (!empty($dataList)) {
2541
            foreach ($dataList as $data) {
2542
                if (isset($oldGroups[$data['group_id']])) {
2543
                    $data['group_id'] = $oldGroups[$data['group_id']];
2544
                    $sql = "INSERT INTO usergroup_rel_tag (tag_id, usergroup_id)
2545
                            VALUES ('{$data['tag_id']}', '{$data['group_id']}')";
2546
                    $connection->executeQuery($sql);
2547
                }
2548
            }
2549
        }
2550
    }
2551
2552
    if ($debug) {
2553
        error_log('update extra fields');
2554
    }
2555
2556
    // Extra fields
2557
    $extraFieldTables = [
2558
        ExtraField::USER_FIELD_TYPE => Database::get_main_table(TABLE_MAIN_USER_FIELD),
2559
        ExtraField::COURSE_FIELD_TYPE => Database::get_main_table(TABLE_MAIN_COURSE_FIELD),
2560
        //ExtraField::LP_FIELD_TYPE => Database::get_main_table(TABLE_MAIN_LP_FIELD),
2561
        ExtraField::SESSION_FIELD_TYPE => Database::get_main_table(TABLE_MAIN_SESSION_FIELD),
2562
        //ExtraField::CALENDAR_FIELD_TYPE => Database::get_main_table(TABLE_MAIN_CALENDAR_EVENT_FIELD),
2563
        //ExtraField::QUESTION_FIELD_TYPE => Database::get_main_table(TABLE_MAIN_CALENDAR_EVENT_FIELD),
2564
        //ExtraField::USER_FIELD_TYPE => //Database::get_main_table(TABLE_MAIN_SPECIFIC_FIELD),
2565
    ];
2566
2567
    foreach ($extraFieldTables as $type => $table) {
2568
        $sql = "SELECT * FROM $table ";
2569
        if ($debug) {
2570
            error_log($sql);
2571
        }
2572
        $result = $connection->query($sql);
2573
        $fields = $result->fetchAll();
2574
2575
        foreach ($fields as $field) {
2576
            if ($debug) {
2577
                error_log("Loading field: ".$field['field_variable']);
2578
            }
2579
            $originalId = $field['id'];
2580
2581
            $params = [
2582
                'extra_field_type' => $type,
2583
                'variable' => $field['field_variable'],
2584
                'field_type' => $field['field_type'],
2585
                'display_text' => $field['field_display_text'],
2586
                'default_value' => $field['field_default_value'],
2587
                'field_order' => $field['field_order'],
2588
                'visible' => $field['field_visible'],
2589
                'changeable' => $field['field_changeable'],
2590
                'filter' => $field['field_filter']
2591
            ];
2592
2593
            $connection->insert('extra_field', $params);
2594
            $newExtraFieldId = $connection->lastInsertId();
2595
2596
            $values = [];
2597
            $handlerId = null;
2598
            switch ($type) {
2599
                case ExtraField::USER_FIELD_TYPE:
2600
                    $optionTable = Database::get_main_table(
2601
                        TABLE_MAIN_USER_FIELD_OPTIONS
2602
                    );
2603
                    $valueTable = Database::get_main_table(
2604
                        TABLE_MAIN_USER_FIELD_VALUES
2605
                    );
2606
                    $handlerId = 'user_id';
2607
                    break;
2608
                case ExtraField::COURSE_FIELD_TYPE:
2609
                    $optionTable = Database::get_main_table(
2610
                        TABLE_MAIN_COURSE_FIELD_OPTIONS
2611
                    );
2612
                    $valueTable = Database::get_main_table(
2613
                        TABLE_MAIN_COURSE_FIELD_VALUES
2614
                    );
2615
                    $handlerId = 'c_id';
2616
                    break;
2617
                case ExtraField::SESSION_FIELD_TYPE:
2618
                    $optionTable = Database::get_main_table(
2619
                        TABLE_MAIN_SESSION_FIELD_OPTIONS
2620
                    );
2621
                    $valueTable = Database::get_main_table(
2622
                        TABLE_MAIN_SESSION_FIELD_VALUES
2623
                    );
2624
                    $handlerId = 'session_id';
2625
                    break;
2626
            }
2627
2628
            if (!empty($optionTable)) {
2629
                $sql = "SELECT * FROM $optionTable WHERE field_id = $originalId ";
2630
                $result = $connection->query($sql);
2631
                $options = $result->fetchAll();
2632
2633
                foreach ($options as $option) {
2634
                    $params = [
2635
                        'display_text' => $option['option_display_text'],
2636
                        'field_id' => $newExtraFieldId,
2637
                        'option_order' => $option['option_order'],
2638
                        'option_value' => $option['option_value']
2639
                    ];
2640
                    $connection->insert('extra_field_options', $params);
2641
                }
2642
2643
                $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...
2644
                $result = $connection->query($sql);
2645
                $values = $result->fetchAll();
2646
                if ($debug) {
2647
                    error_log("Fetch all values for field");
2648
                }
2649
            }
2650
2651
            if (!empty($values)) {
2652
                if ($debug) {
2653
                    error_log("Saving field value in new table");
2654
                }
2655
                $k = 0;
2656
                foreach ($values as $value) {
2657
                    if (isset($value[$handlerId])) {
2658
                        // Insert without the use of the entity as it reduces
2659
                        // speed to 2 records per second (much too slow)
2660
                        $params = [
2661
                            'field_id' => $newExtraFieldId,
2662
                            'value' => $value['field_value'],
2663
                            'item_id' => $value[$handlerId]
2664
                        ];
2665
                        $connection->insert('extra_field_values', $params);
2666
                        if ($debug && ($k % 10000 == 0)) {
2667
                            error_log("Saving field $k");
2668
                        }
2669
                        $k++;
2670
                    }
2671
                }
2672
            }
2673
        }
2674
    }
2675
2676
    if ($debug) {
2677
        error_log('Remove index');
2678
    }
2679
2680
    // Drop temporary indexes added to increase speed of this function's queries
2681
    $sql = "ALTER TABLE c_document DROP INDEX tmpidx_doc";
2682
    $connection->executeQuery($sql);
2683
    $sql = "ALTER TABLE c_student_publication DROP INDEX tmpidx_stud";
2684
    $connection->executeQuery($sql);
2685
    $sql = "ALTER TABLE c_quiz DROP INDEX tmpidx_quiz";
2686
    $connection->executeQuery($sql);
2687
    $sql = "ALTER TABLE c_item_property DROP INDEX tmpidx_ip";
2688
    $connection->executeQuery($sql);
2689
2690
    if ($debug) {
2691
        error_log('Finish fixId function');
2692
    }
2693
}
2694
2695
/**
2696
 * @param string $distFile
2697
 * @param string $envFile
2698
 * @param array $params
2699
 */
2700
function updateEnvFile($distFile, $envFile, $params)
2701
{
2702
    $contents = file_get_contents($distFile);
2703
    $contents = str_replace(array_keys($params), array_values($params), $contents);
2704
    file_put_contents($envFile, $contents);
2705
}
2706
2707
/**
2708
 *
2709
 * After the schema was created (table creation), the function adds
2710
 * admin/platform information.
2711
 * @param \Chamilo\CoreBundle\Framework\Container $container
2712
 * @param EntityManager $manager
2713
 * @param string $sysPath
2714
 * @param string $encryptPassForm
2715
 * @param string $passForm
2716
 * @param string $adminLastName
2717
 * @param string $adminFirstName
2718
 * @param string $loginForm
2719
 * @param string $emailForm
2720
 * @param string $adminPhoneForm
2721
 * @param string $languageForm
2722
 * @param string $institutionForm
2723
 * @param string $institutionUrlForm
2724
 * @param string $siteName
2725
 * @param string $allowSelfReg
2726
 * @param string $allowSelfRegProf
2727
 * @param string $installationProfile Installation profile, if any was provided
2728
 */
2729
function finishInstallationWithContainer(
2730
    $container,
0 ignored issues
show
Unused Code introduced by
The parameter $container 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

2730
    /** @scrutinizer ignore-unused */ $container,

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...
2731
    $manager,
2732
    $sysPath,
2733
    $encryptPassForm,
2734
    $passForm,
2735
    $adminLastName,
2736
    $adminFirstName,
2737
    $loginForm,
2738
    $emailForm,
2739
    $adminPhoneForm,
2740
    $languageForm,
2741
    $institutionForm,
2742
    $institutionUrlForm,
2743
    $siteName,
2744
    $allowSelfReg,
2745
    $allowSelfRegProf,
2746
    $installationProfile = ''
2747
) {
2748
    $sysPath = !empty($sysPath) ? $sysPath : api_get_path(SYS_PATH);
2749
    $connection = $manager->getConnection();
2750
2751
    Database::setConnection($connection);
2752
    Database::setManager($manager);
2753
2754
    $sql = getVersionTable();
2755
    // Add version table
2756
    $connection->executeQuery($sql);
2757
2758
    // Add tickets defaults
2759
    $ticketProject = new TicketProject();
2760
    $ticketProject
2761
        ->setId(1)
2762
        ->setName('Ticket System')
2763
        ->setInsertUserId(1);
2764
2765
    $manager->persist($ticketProject);
2766
    $manager->flush();
2767
2768
    $categories = [
2769
        get_lang('TicketEnrollment') => get_lang('TicketsAboutEnrollment'),
2770
        get_lang('TicketGeneralInformation') => get_lang('TicketsAboutGeneralInformation'),
2771
        get_lang('TicketRequestAndPapework') => get_lang('TicketsAboutRequestAndPapework'),
2772
        get_lang('TicketAcademicIncidence') => get_lang('TicketsAboutAcademicIncidence'),
2773
        get_lang('TicketVirtualCampus') => get_lang('TicketsAboutVirtualCampus'),
2774
        get_lang('TicketOnlineEvaluation') => get_lang('TicketsAboutOnlineEvaluation')
2775
    ];
2776
2777
    $i = 1;
2778
    foreach ($categories as $category => $description) {
2779
        // Online evaluation requires a course
2780
        $ticketCategory = new TicketCategory();
2781
        $ticketCategory
2782
            ->setId($i)
2783
            ->setName($category)
2784
            ->setDescription($description)
2785
            ->setProject($ticketProject)
2786
            ->setInsertUserId(1);
2787
2788
        $isRequired = $i == 6;
2789
        $ticketCategory->setCourseRequired($isRequired);
2790
2791
        $manager->persist($ticketCategory);
2792
        $manager->flush();
2793
2794
        $i++;
2795
    }
2796
2797
    // Default Priorities
2798
    $defaultPriorities = [
2799
        TicketManager::PRIORITY_NORMAL => get_lang('PriorityNormal'),
2800
        TicketManager::PRIORITY_HIGH => get_lang('PriorityHigh'),
2801
        TicketManager::PRIORITY_LOW => get_lang('PriorityLow')
2802
    ];
2803
2804
    $i = 1;
2805
    foreach ($defaultPriorities as $code => $priority) {
2806
        $ticketPriority = new TicketPriority();
2807
        $ticketPriority
2808
            ->setId($i)
2809
            ->setName($priority)
2810
            ->setCode($code)
2811
            ->setInsertUserId(1);
2812
2813
        $manager->persist($ticketPriority);
2814
        $manager->flush();
2815
        $i++;
2816
    }
2817
2818
    $table = Database::get_main_table(TABLE_TICKET_STATUS);
2819
2820
    // Default status
2821
    $defaultStatus = [
2822
        TicketManager::STATUS_NEW => get_lang('StatusNew'),
2823
        TicketManager::STATUS_PENDING => get_lang('StatusPending'),
2824
        TicketManager::STATUS_UNCONFIRMED => get_lang('StatusUnconfirmed'),
2825
        TicketManager::STATUS_CLOSE => get_lang('StatusClose'),
2826
        TicketManager::STATUS_FORWARDED => get_lang('StatusForwarded')
2827
    ];
2828
2829
    $i = 1;
2830
    foreach ($defaultStatus as $code => $status) {
2831
        $attributes = [
2832
            'id' => $i,
2833
            'code' => $code,
2834
            'name' => $status
2835
        ];
2836
        Database::insert($table, $attributes);
2837
        $i++;
2838
    }
2839
2840
    $accessUrl = new \Chamilo\CoreBundle\Entity\AccessUrl();
2841
    $accessUrl
2842
        ->setUrl('http://localhost/')
2843
        ->setDescription('')
2844
        ->setActive(1)
2845
    ;
2846
    $manager->persist($accessUrl);
2847
    $manager->flush();
2848
2849
    $container = \Chamilo\CoreBundle\Framework\Container::$container;
2850
    $settingsManager = $container->get('chamilo.settings.manager');
2851
    $settingsManager->installSchemas($accessUrl);
2852
2853
    /*
2854
    // Inserting data.sql replaced with new settings schema
2855
    $data = file_get_contents($sysPath.'main/install/data.sql');
2856
    $result = $manager->getConnection()->prepare($data);
2857
    $result->execute();
2858
    $result->closeCursor();*/
2859
2860
    UserManager::setPasswordEncryption($encryptPassForm);
2861
2862
    // Create admin user.
2863
    @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

2863
    /** @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...
2864
        $adminFirstName,
2865
        $adminLastName,
2866
        1,
2867
        $emailForm,
2868
        $loginForm,
2869
        $passForm,
2870
        'ADMIN', //$official_code = '',
2871
        $languageForm,
2872
        $adminPhoneForm,
2873
        '', //$picture_uri = '',
2874
        PLATFORM_AUTH_SOURCE,
2875
        '', //$expirationDate,
2876
        1,
2877
        0,
2878
        null,
2879
        '',
2880
        false, //$send_mail = false,
2881
        true, //$isAdmin = false
2882
            '',
2883
        false,
2884
        '',
2885
        1
2886
    );
2887
2888
    // Create anonymous user.
2889
    @UserManager::create_user(
2890
        'Joe',
2891
        'Anonymous',
2892
        6,
2893
        'anonymous@localhost',
2894
        'anon',
2895
        'anon',
2896
        'anonymous', //$official_code = '',
2897
        $languageForm,
2898
        '',
2899
        '', //$picture_uri = '',
2900
        PLATFORM_AUTH_SOURCE,
2901
        '',
2902
        1,
2903
        0,
2904
        null,
2905
        '',
2906
        false, //$send_mail = false,
2907
        false, //$isAdmin = false
2908
        '',
2909
        false,
2910
        '',
2911
        1
2912
    );
2913
2914
    // Set default language
2915
    $sql = "UPDATE language SET available = 1 WHERE dokeos_folder = '$languageForm'";
2916
    Database::query($sql);
2917
2918
    // Install settings
2919
    installSettings(
2920
        $institutionForm,
2921
        $institutionUrlForm,
2922
        $siteName,
2923
        $emailForm,
2924
        $adminLastName,
2925
        $adminFirstName,
2926
        $languageForm,
2927
        $allowSelfReg,
2928
        $allowSelfRegProf,
2929
        $installationProfile
2930
    );
2931
2932
    lockSettings();
2933
    updateDirAndFilesPermissions();
2934
2935
    // Set the latest version
2936
    $path = $sysPath.'app/Migrations/Schema/V111/';
2937
    $finder = new \Symfony\Component\Finder\Finder();
2938
    $files = $finder->files()->in($path);
2939
2940
    // Needed for chash
2941
    createVersionTable();
2942
2943
    foreach ($files as $version) {
2944
        $version = str_replace(['Version', '.php'], '', $version->getFilename());
2945
        $sql = "INSERT INTO version (version) VALUES ('$version')";
2946
        Database::query($sql);
2947
    }
2948
}
2949
2950
/**
2951
 * Creates 'version' table
2952
 */
2953
function createVersionTable()
2954
{
2955
    $sql = getVersionTable();
2956
    Database::query($sql);
2957
}
2958
2959
/**
2960
 * Get version creation table query
2961
 * @return string
2962
 */
2963
function getVersionTable()
2964
{
2965
    return 'CREATE TABLE IF NOT EXISTS version (id int unsigned NOT NULL AUTO_INCREMENT, version varchar(20), PRIMARY KEY(id), UNIQUE(version));';
2966
}
2967
2968
/**
2969
 * Update settings based on installation profile defined in a JSON file
2970
 * @param string $installationProfile The name of the JSON file in main/install/profiles/ folder
2971
 *
2972
 * @return bool false on failure (no bad consequences anyway, just ignoring profile)
2973
 */
2974
function installProfileSettings($installationProfile = '')
2975
{
2976
    if (empty($installationProfile)) {
2977
        return false;
2978
    }
2979
    $jsonPath = api_get_path(SYS_PATH).'main/install/profiles/'.$installationProfile.'.json';
2980
    // Make sure the path to the profile is not hacked
2981
    if (!Security::check_abs_path($jsonPath, api_get_path(SYS_PATH).'main/install/profiles/')) {
2982
        return false;
2983
    }
2984
    if (!is_file($jsonPath)) {
2985
        return false;
2986
    }
2987
    if (!is_readable($jsonPath)) {
2988
        return false;
2989
    }
2990
    if (!function_exists('json_decode')) {
2991
        // The php-json extension is not available. Ignore profile.
2992
        return false;
2993
    }
2994
    $json = file_get_contents($jsonPath);
2995
    $params = json_decode($json);
2996
    if ($params === false or $params === null) {
2997
        return false;
2998
    }
2999
    $settings = $params->params;
3000
    if (!empty($params->parent)) {
3001
        installProfileSettings($params->parent);
3002
    }
3003
    foreach ($settings as $id => $param) {
3004
        $sql = "UPDATE settings_current
3005
                SET selected_value = '".$param->selected_value."'
3006
                WHERE variable = '".$param->variable."'";
3007
        if (!empty($param->subkey)) {
3008
            $sql .= " AND subkey='".$param->subkey."'";
3009
        }
3010
        Database::query($sql);
3011
    }
3012
3013
    return true;
3014
}
3015
3016
/**
3017
 * Quick function to remove a directory with its subdirectories
3018
 * @param $dir
3019
 */
3020
function rrmdir($dir)
3021
{
3022
    if (is_dir($dir)) {
3023
        $objects = scandir($dir);
3024
        foreach ($objects as $object) {
3025
            if ($object != "." && $object != "..") {
3026
                if (filetype($dir."/".$object) == "dir") {
3027
                    @rrmdir($dir."/".$object);
0 ignored issues
show
Bug introduced by
Are you sure the usage of rrmdir($dir . '/' . $object) is correct as it seems to always return null.

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

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

}

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

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

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

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

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

3027
                    /** @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...
3028
                } else {
3029
                    @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

3029
                    /** @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...
3030
                }
3031
            }
3032
        }
3033
        reset($objects);
3034
        rmdir($dir);
3035
    }
3036
}
3037
3038
function get_group_picture_path_by_id($id, $type = 'web', $preview = false, $anonymous = false)
3039
{
3040
    switch ($type) {
3041
        case 'system': // Base: absolute system path.
3042
            $base = api_get_path(SYS_UPLOAD_PATH);
3043
            break;
3044
        case 'web': // Base: absolute web path.
3045
        default:
3046
            $base = api_get_path(WEB_UPLOAD_PATH);
3047
            break;
3048
    }
3049
3050
    $noPicturePath = ['dir' => $base.'img/', 'file' => 'unknown.jpg'];
3051
3052
    if (empty($id) || empty($type)) {
3053
        return $anonymous ? $noPicturePath : ['dir' => '', 'file' => ''];
3054
    }
3055
3056
    $id = intval($id);
3057
3058
    //$group_table = Database::get_main_table(TABLE_MAIN_GROUP);
3059
    $group_table = 'groups';
3060
    $sql = "SELECT picture_uri FROM $group_table WHERE id=".$id;
3061
    $res = Database::query($sql);
3062
3063
    if (!Database::num_rows($res)) {
3064
        return $anonymous ? $noPicturePath : ['dir' => '', 'file' => ''];
3065
    }
3066
3067
    $user = Database::fetch_array($res);
3068
    $picture_filename = trim($user['picture_uri']);
3069
3070
    if (api_get_setting('split_users_upload_directory') === 'true') {
3071
        if (!empty($picture_filename)) {
3072
            $dir = $base.'groups/'.substr($picture_filename, 0, 1).'/'.$id.'/';
3073
        } elseif ($preview) {
3074
            $dir = $base.'groups/'.substr((string) $id, 0, 1).'/'.$id.'/';
3075
        } else {
3076
            $dir = $base.'groups/'.$id.'/';
3077
        }
3078
    } else {
3079
        $dir = $base.'groups/'.$id.'/';
3080
    }
3081
3082
    if (empty($picture_filename) && $anonymous) {
3083
        return $noPicturePath;
3084
    }
3085
3086
    return ['dir' => $dir, 'file' => $picture_filename];
3087
}
3088
3089
/**
3090
 * Control the different steps of the migration through a big switch
3091
 * @param string $fromVersion
3092
 * @param EntityManager $manager
3093
 * @param bool $processFiles
3094
 * @return bool Always returns true except if the process is broken
3095
 */
3096
function migrateSwitch($fromVersion, $manager, $processFiles = true)
3097
{
3098
    error_log('Starting migration process from '.$fromVersion.' ('.date('Y-m-d H:i:s').')');
3099
3100
    echo '<a class="btn btn-default" href="javascript:void(0)" id="details_button">'.get_lang('Details').'</a><br />';
3101
    echo '<div id="details" style="display:none">';
3102
3103
    $connection = $manager->getConnection();
3104
3105
    $database = new Database();
3106
    $database->setManager($manager);
3107
3108
    switch ($fromVersion) {
3109
        case '1.9.0':
3110
        case '1.9.2':
3111
        case '1.9.4':
3112
        case '1.9.6':
3113
        case '1.9.6.1':
3114
        case '1.9.8':
3115
        case '1.9.8.1':
3116
        case '1.9.8.2':
3117
        case '1.9.10':
3118
        case '1.9.10.2':
3119
        case '1.9.10.4':
3120
        case '1.9.10.6':
3121
            $database = new Database();
3122
            $database->setManager($manager);
3123
3124
            // Fix type "enum" before running the migration with Doctrine
3125
            $connection->executeQuery("ALTER TABLE course_category MODIFY COLUMN auth_course_child VARCHAR(40) DEFAULT 'TRUE'");
3126
            $connection->executeQuery("ALTER TABLE course_category MODIFY COLUMN auth_cat_child VARCHAR(40) DEFAULT 'TRUE'");
3127
            $connection->executeQuery("ALTER TABLE c_quiz_answer MODIFY COLUMN hotspot_type varchar(40) default NULL");
3128
            $connection->executeQuery("ALTER TABLE c_tool MODIFY COLUMN target varchar(20) NOT NULL default '_self'");
3129
            $connection->executeQuery("ALTER TABLE c_link MODIFY COLUMN on_homepage char(10) NOT NULL default '0'");
3130
            $connection->executeQuery("ALTER TABLE c_blog_rating MODIFY COLUMN rating_type char(40) NOT NULL default 'post'");
3131
            $connection->executeQuery("ALTER TABLE c_survey MODIFY COLUMN anonymous char(10) NOT NULL default '0'");
3132
            $connection->executeQuery("ALTER TABLE c_document MODIFY COLUMN filetype char(10) NOT NULL default 'file'");
3133
            $connection->executeQuery("ALTER TABLE c_student_publication MODIFY COLUMN filetype char(10) NOT NULL default 'file'");
3134
3135
            // Migrate using the migration files located in:
3136
            // src/Chamilo/CoreBundle/Migrations/Schema/V110
3137
            $result = migrate(
3138
                110,
3139
                $manager
3140
            );
3141
3142
            if ($result) {
3143
                error_log('Migrations files were executed ('.date('Y-m-d H:i:s').')');
3144
                fixIds($manager);
3145
                error_log('fixIds finished ('.date('Y-m-d H:i:s').')');
3146
3147
                $connection->executeQuery("UPDATE settings_current SET selected_value = '1.10.0' WHERE variable = 'chamilo_database_version'");
3148
3149
                if ($processFiles) {
3150
                    $fromVersionShort = '1.9';
3151
                    include __DIR__.'/update-files-1.9.0-1.10.0.inc.php';
3152
                    // Only updates the configuration.inc.php with the new version
3153
                    include __DIR__.'/update-configuration.inc.php';
3154
3155
                    $configurationFiles = [
3156
                        'mail.conf.php',
3157
                        'profile.conf.php',
3158
                        'course_info.conf.php',
3159
                        'add_course.conf.php',
3160
                        'events.conf.php',
3161
                        'auth.conf.php'
3162
                    ];
3163
3164
                    error_log('Copy conf files');
3165
3166
                    foreach ($configurationFiles as $file) {
3167
                        if (file_exists(api_get_path(SYS_CODE_PATH).'inc/conf/'.$file)) {
3168
                            copy(
3169
                                api_get_path(SYS_CODE_PATH).'inc/conf/'.$file,
3170
                                api_get_path(CONFIGURATION_PATH).$file
3171
                            );
3172
                        }
3173
                    }
3174
                }
3175
3176
                error_log('Upgrade 1.10.x process concluded! ('.date('Y-m-d H:i:s').')');
3177
            } else {
3178
                error_log('There was an error during running migrations. Check error.log');
3179
                break;
3180
            }
3181
            // no break
3182
        case '1.10.0':
3183
        case '1.10.2':
3184
        case '1.10.4':
3185
        case '1.10.6':
3186
        case '1.10.8':
3187
            $database = new Database();
3188
            $database->setManager($manager);
3189
            // Migrate using the migration files located in:
3190
            // src/Chamilo/CoreBundle/Migrations/Schema/V111
3191
            $result = migrate(
3192
                111,
3193
                $manager
3194
            );
3195
3196
            if ($result) {
3197
                error_log('Migrations files were executed ('.date('Y-m-d H:i:s').')');
3198
3199
                fixPostGroupIds($connection);
3200
3201
                $sql = "UPDATE settings_current SET selected_value = '1.11.0' WHERE variable = 'chamilo_database_version'";
3202
                $connection->executeQuery($sql);
3203
                if ($processFiles) {
3204
                    error_log('Update config files');
3205
                    $fromVersionShort = '1.10';
3206
                    include __DIR__.'/update-files-1.10.0-1.11.0.inc.php';
3207
                    // Only updates the configuration.inc.php with the new version
3208
                    include __DIR__.'/update-configuration.inc.php';
3209
                }
3210
                error_log('Upgrade 1.11.x process concluded!  ('.date('Y-m-d H:i:s').')');
3211
            } else {
3212
                error_log('There was an error during running migrations. Check error.log');
3213
            }
3214
            break;
3215
        default:
3216
            break;
3217
    }
3218
3219
    echo '</div>';
3220
3221
    return true;
3222
}
3223
3224
/**
3225
 * @param \Doctrine\DBAL\Connection $connection
3226
 */
3227
function fixPostGroupIds($connection)
3228
{
3229
    $connection->executeQuery("ALTER TABLE course_category MODIFY COLUMN auth_course_child VARCHAR(40) DEFAULT 'TRUE'");
3230
    error_log('Fix c_student_publication.post_group_id');
3231
3232
    // Fix post_group_id
3233
    $sql = "SELECT * FROM c_student_publication 
3234
            WHERE (post_group_id <> 0 AND post_group_id is not null)";
3235
    $statement = $connection->executeQuery($sql);
3236
    $result = $statement->fetchAll();
3237
3238
    foreach ($result as $row) {
3239
        $groupId = $row['post_group_id'];
3240
        $courseId = $row['c_id'];
3241
        $workIid = $row['iid'];
3242
        $sql = "SELECT iid from c_group_info 
3243
                WHERE c_id = $courseId AND id = $groupId";
3244
        $statement = $connection->executeQuery($sql);
3245
        $count = $statement->rowCount();
3246
        if ($count > 0) {
3247
            $rowGroup = $statement->fetch();
3248
            $newGroupId = $rowGroup['iid'];
3249
            if ($newGroupId == $groupId) {
3250
                continue;
3251
            }
3252
            if ($newGroupId) {
3253
                $sql = "UPDATE c_student_publication 
3254
                        SET post_group_id = $newGroupId 
3255
                        WHERE 
3256
                            c_id = $courseId AND
3257
                            iid = $workIid
3258
                        ";
3259
                $connection->executeQuery($sql);
3260
            }
3261
        }
3262
    }
3263
3264
    error_log('End - Fix c_student_publication.post_group_id');
3265
3266
    // Delete c_student_publication from any session that doesn't exist anymore
3267
    $sql = "DELETE FROM c_student_publication 
3268
            WHERE session_id NOT IN (SELECT id FROM session) AND (session_id <> 0 AND session_id is not null)";
3269
    $connection->executeQuery($sql);
3270
3271
    error_log('Fix work documents');
3272
    // Fix work documents that don't have c_item_property value
3273
    $sql = "SELECT * FROM c_student_publication WHERE parent_id IS NOT NULL";
3274
    $statement = $connection->executeQuery($sql);
3275
    $result = $statement->fetchAll();
3276
    foreach ($result as $row) {
3277
        $groupId = $row['post_group_id'];
3278
        $courseId = $row['c_id'];
3279
        $sessionId = $row['session_id'];
3280
        $workId = $row['id'];
3281
        $itemInfo = api_get_item_property_info(
3282
            $courseId,
3283
            'work',
3284
            $workId,
3285
            $sessionId
3286
        );
3287
        $courseInfo = api_get_course_info_by_id($courseId);
3288
        if (empty($itemInfo)) {
3289
            api_item_property_update(
3290
                $courseInfo,
3291
                'work',
3292
                $workId,
3293
                'visible',
3294
                1,
3295
                $groupId,
3296
                null,
3297
                null,
3298
                null,
3299
                $sessionId
3300
            );
3301
        }
3302
    }
3303
    error_log('End - Fix work documents');
3304
}
3305