Completed
Push — master ( cccadf...20b4d3 )
by Julito
09:33
created

checkCourseScriptCreation()   F

Complexity

Conditions 22
Paths 147

Size

Total Lines 86
Code Lines 53

Duplication

Lines 0
Ratio 0 %

Importance

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

How to fix   Long Method    Complexity   

Long Method

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

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

Commonly applied refactorings include:

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

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

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

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

// Bar.php
namespace OtherDir;

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

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

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

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

// Bar.php
namespace OtherDir;

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

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

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

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

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

373
    /** @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...
374
    @chmod('..', 0755); //set permissions on parent dir of install dir
375
}
376
377
/**
378
 * Write the main system config file.
379
 *
380
 * @param string $path Path to the config file
381
 */
382
function write_system_config_file($path)
383
{
384
    global $dbHostForm;
385
    global $dbPortForm;
386
    global $dbUsernameForm;
387
    global $dbPassForm;
388
    global $dbNameForm;
389
    global $urlForm;
390
    global $pathForm;
391
    global $urlAppendPath;
392
    global $languageForm;
393
    global $encryptPassForm;
394
    global $session_lifetime;
395
    global $new_version;
396
    global $new_version_stable;
397
398
    $root_sys = api_add_trailing_slash(str_replace('\\', '/', realpath($pathForm)));
399
    $content = file_get_contents(__DIR__.'/'.SYSTEM_CONFIG_FILENAME);
400
401
    $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...
402
    $config['{DATABASE_HOST}'] = $dbHostForm;
403
    $config['{DATABASE_PORT}'] = $dbPortForm;
404
    $config['{DATABASE_USER}'] = $dbUsernameForm;
405
    $config['{DATABASE_PASSWORD}'] = $dbPassForm;
406
    $config['{DATABASE_MAIN}'] = $dbNameForm;
407
    $config['{ROOT_WEB}'] = $urlForm;
408
    $config['{ROOT_SYS}'] = $root_sys;
409
    $config['{URL_APPEND_PATH}'] = $urlAppendPath;
410
    $config['{PLATFORM_LANGUAGE}'] = $languageForm;
411
    $config['{SECURITY_KEY}'] = md5(uniqid(rand().time()));
412
    $config['{ENCRYPT_PASSWORD}'] = $encryptPassForm;
413
414
    $config['SESSION_LIFETIME'] = $session_lifetime;
415
    $config['{NEW_VERSION}'] = $new_version;
416
    $config['NEW_VERSION_STABLE'] = trueFalse($new_version_stable);
417
418
    foreach ($config as $key => $value) {
419
        $content = str_replace($key, $value, $content);
420
    }
421
    $fp = @fopen($path, 'w');
422
423
    if (!$fp) {
0 ignored issues
show
introduced by
$fp is of type false|resource, thus it always evaluated to false.
Loading history...
424
        echo '<strong>
425
                <font color="red">Your script doesn\'t have write access to the config directory</font></strong><br />
426
                <em>('.str_replace('\\', '/', realpath($path)).')</em><br /><br />
427
                You probably do not have write access on Chamilo root directory,
428
                i.e. you should <em>CHMOD 777</em> or <em>755</em> or <em>775</em>.<br /><br />
429
                Your problems can be related on two possible causes:<br />
430
                <ul>
431
                  <li>Permission problems.<br />Try initially with <em>chmod -R 777</em> and increase restrictions gradually.</li>
432
                  <li>PHP is running in <a href="http://www.php.net/manual/en/features.safe-mode.php" target="_blank">Safe-Mode</a>. 
433
                  If possible, try to switch it off.</li>
434
                </ul>
435
                <a href="http://forum.chamilo.org/" target="_blank">Read about this problem in Support Forum</a><br /><br />
436
                Please go back to step 5.
437
                <p><input type="submit" name="step5" value="&lt; Back" /></p>
438
                </td></tr></table></form></body></html>';
439
        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...
440
    }
441
442
    fwrite($fp, $content);
443
    fclose($fp);
444
}
445
446
/**
447
 * Returns a list of language directories.
448
 */
449
function get_language_folder_list()
450
{
451
    return [
452
        'ar' => 'arabic',
453
        'ast' => 'asturian',
454
        'bg' => 'bulgarian',
455
        'bs' => 'bosnian',
456
        'ca' => 'catalan',
457
        'zh' => 'simpl_chinese',
458
        'zh-tw' => 'trad_chinese',
459
        'cs' => 'czech',
460
        'da' => 'danish',
461
        'prs' => 'dari',
462
        'de' => 'german',
463
        'el' => 'greek',
464
        'en' => 'english',
465
        'es' => 'spanish',
466
        'eo' => 'esperanto',
467
        'eu' => 'basque',
468
        'fa' => 'persian',
469
        'fr' => 'french',
470
        'fur' => 'friulian',
471
        'gl' => 'galician',
472
        'ka' => 'georgian',
473
        'hr' => 'croatian',
474
        'he' => 'hebrew',
475
        'hi' => 'hindi',
476
        'id' => 'indonesian',
477
        'it' => 'italian',
478
        'ko' => 'korean',
479
        'lv' => 'latvian',
480
        'lt' => 'lithuanian',
481
        'mk' => 'macedonian',
482
        'hu' => 'hungarian',
483
        'ms' => 'malay',
484
        'nl' => 'dutch',
485
        'ja' => 'japanese',
486
        'no' => 'norwegian',
487
        'oc' => 'occitan',
488
        'ps' => 'pashto',
489
        'pl' => 'polish',
490
        'pt' => 'portuguese',
491
        'pt-br' => 'brazilian',
492
        'ro' => 'romanian',
493
        'qu' => 'quechua_cusco',
494
        'ru' => 'russian',
495
        'sk' => 'slovak',
496
        'sl' => 'slovenian',
497
        'sr' => 'serbian',
498
        'fi' => 'finnish',
499
        'sv' => 'swedish',
500
        'th' => 'thai',
501
        'tr' => 'turkish',
502
        'uk' => 'ukrainian',
503
        'vi' => 'vietnamese',
504
        'sw' => 'swahili',
505
        'yo' => 'yoruba',
506
    ];
507
}
508
509
/**
510
 * This function returns the value of a parameter from the configuration file.
511
 *
512
 * WARNING - this function relies heavily on global variables $updateFromConfigFile
513
 * and $configFile, and also changes these globals. This can be rewritten.
514
 *
515
 * @param string $param      the parameter of which the value is returned
516
 * @param string $updatePath If we want to give the path rather than take it from POST
517
 *
518
 * @return string the value of the parameter
519
 *
520
 * @author Olivier Brouckaert
521
 * @author Reworked by Ivan Tcholakov, 2010
522
 */
523
function get_config_param($param, $updatePath = '')
524
{
525
    global $configFile, $updateFromConfigFile;
526
527
    // Look if we already have the queried parameter.
528
    if (is_array($configFile) && isset($configFile[$param])) {
529
        return $configFile[$param];
530
    }
531
    if (empty($updatePath) && !empty($_POST['updatePath'])) {
532
        $updatePath = $_POST['updatePath'];
533
    }
534
535
    if (empty($updatePath)) {
536
        $updatePath = api_get_path(SYS_PATH);
537
    }
538
    $updatePath = api_add_trailing_slash(str_replace('\\', '/', realpath($updatePath)));
539
    $updateFromInstalledVersionFile = '';
540
541
    if (empty($updateFromConfigFile)) {
542
        // If update from previous install was requested,
543
        // try to recover config file from Chamilo 1.9.x
544
        if (file_exists($updatePath.'main/inc/conf/configuration.php')) {
545
            $updateFromConfigFile = 'main/inc/conf/configuration.php';
546
        } elseif (file_exists($updatePath.'app/config/configuration.php')) {
547
            $updateFromConfigFile = 'app/config/configuration.php';
548
        } elseif (file_exists($updatePath.'config/configuration.php')) {
549
            $updateFromConfigFile = 'config/configuration.php';
550
        } else {
551
            // Give up recovering.
552
            //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);
553
            return null;
554
        }
555
    }
556
557
    if (file_exists($updatePath.$updateFromConfigFile) &&
558
        !is_dir($updatePath.$updateFromConfigFile)
559
    ) {
560
        require $updatePath.$updateFromConfigFile;
561
        $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...
562
563
        return $config->get($param);
564
    }
565
566
    error_log('Config array could not be found in get_config_param()', 0);
567
568
    return null;
569
}
570
571
/*      DATABASE RELATED FUNCTIONS */
572
573
/**
574
 * Gets a configuration parameter from the database. Returns returns null on failure.
575
 *
576
 * @param string $param Name of param we want
577
 *
578
 * @return mixed The parameter value or null if not found
579
 */
580
function get_config_param_from_db($param = '')
581
{
582
    $param = Database::escape_string($param);
583
584
    if (($res = Database::query("SELECT * FROM settings_current WHERE variable = '$param'")) !== false) {
585
        if (Database::num_rows($res) > 0) {
586
            $row = Database::fetch_array($res);
587
588
            return $row['selected_value'];
589
        }
590
    }
591
592
    return null;
593
}
594
595
/**
596
 * Connect to the database and returns the entity manager.
597
 *
598
 * @param string $dbHostForm     DB host
599
 * @param string $dbUsernameForm DB username
600
 * @param string $dbPassForm     DB password
601
 * @param string $dbNameForm     DB name
602
 * @param int    $dbPortForm     DB port
603
 *
604
 * @return \Database
605
 */
606
function connectToDatabase(
607
    $dbHostForm,
608
    $dbUsernameForm,
609
    $dbPassForm,
610
    $dbNameForm,
611
    $dbPortForm = 3306
612
) {
613
    $dbParams = [
614
        'driver' => 'pdo_mysql',
615
        'host' => $dbHostForm,
616
        'port' => $dbPortForm,
617
        'user' => $dbUsernameForm,
618
        'password' => $dbPassForm,
619
        'dbname' => $dbNameForm,
620
    ];
621
622
    $database = new \Database();
623
    $database->connect($dbParams);
624
625
    return $database;
626
}
627
628
/*      DISPLAY FUNCTIONS */
629
630
/**
631
 * This function prints class=active_step $current_step=$param.
632
 *
633
 * @param int $param A step in the installer process
634
 *
635
 * @author Patrick Cool <[email protected]>, Ghent University
636
 */
637
function step_active($param)
638
{
639
    global $current_step;
640
    if ($param == $current_step) {
641
        echo 'active';
642
    }
643
}
644
645
/**
646
 * This function displays the Step X of Y -.
647
 *
648
 * @return string String that says 'Step X of Y' with the right values
649
 */
650
function display_step_sequence()
651
{
652
    global $current_step;
653
654
    return get_lang('Step'.$current_step).' &ndash; ';
655
}
656
657
/**
658
 * Displays a drop down box for selection the preferred language.
659
 */
660
function display_language_selection_box(
661
    $name = 'language_list',
0 ignored issues
show
Unused Code introduced by
The parameter $name 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

661
    /** @scrutinizer ignore-unused */ $name = 'language_list',

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...
662
    $default_language = 'english'
663
) {
664
    // Reading language list.
665
    $language_list = get_language_folder_list();
666
667
    // Sanity checks due to the possibility for customizations.
668
    if (!is_array($language_list) || empty($language_list)) {
669
        $language_list = ['en' => 'English'];
670
    }
671
672
    // Sorting again, if it is necessary.
673
    //asort($language_list);
674
675
    // More sanity checks.
676
    if (!array_key_exists($default_language, $language_list)) {
677
        if (array_key_exists('en', $language_list)) {
678
            $default_language = 'en';
679
        } else {
680
            $language_keys = array_keys($language_list);
681
            $default_language = $language_keys[0];
682
        }
683
    }
684
685
    // Displaying the box.
686
687
    $html = Display::select(
688
        'language_list',
689
        $language_list,
690
        $default_language,
691
        ['class' => 'form-control selectpicker show-tick form-control'],
692
        false
693
    );
694
695
    return $html;
696
}
697
698
/**
699
 * This function displays a language dropdown box so that the installatioin
700
 * can be done in the language of the user.
701
 */
702
function display_language_selection()
703
{
704
    ?>
705
        <div class="install-icon">
706
            <img width="150px;" src="chamilo-install.svg"/>
707
        </div>
708
        <h2 class="install-title">
709
            <?php echo display_step_sequence(); ?>
710
            <?php echo get_lang('InstallationLanguage'); ?>
711
        </h2>
712
        <label for="language_list"><?php echo get_lang('Please select installation language'); ?></label>
713
        <div class="form-group">
714
            <?php echo display_language_selection_box('language_list', api_get_interface_language()); ?>
715
        </div>
716
        <button type="submit" name="step1" class="btn btn-success" value="<?php echo get_lang('Next'); ?>">
717
            <em class="fa fa-forward"> </em>
718
            <?php echo get_lang('Next'); ?>
719
        </button>
720
        <input type="hidden" name="is_executable" id="is_executable" value="-" />
721
        <div class="RequirementHeading">
722
            <?php echo get_lang('YourLanguageNotThereContactUs'); ?>
723
        </div>
724
<?php
725
}
726
727
/**
728
 * This function displays the requirements for installing Chamilo.
729
 *
730
 * @param string $installType
731
 * @param bool   $badUpdatePath
732
 * @param bool   $badUpdatePath
733
 * @param string $updatePath            The updatePath given (if given)
734
 * @param array  $update_from_version_8 The different subversions from version 1.9
735
 *
736
 * @author unknow
737
 * @author Patrick Cool <[email protected]>, Ghent University
738
 */
739
function display_requirements(
740
    $installType,
741
    $badUpdatePath,
742
    $updatePath = '',
743
    $update_from_version_8 = []
744
) {
745
    global $_setting, $originalMemoryLimit;
746
747
    $dir = api_get_path(SYS_ARCHIVE_PATH).'temp/';
748
    $fileToCreate = 'test';
749
750
    $perms_dir = [0777, 0755, 0775, 0770, 0750, 0700];
751
    $perms_fil = [0666, 0644, 0664, 0660, 0640, 0600];
752
    $course_test_was_created = false;
753
    $dir_perm_verified = 0777;
754
755
    foreach ($perms_dir as $perm) {
756
        $r = @mkdir($dir, $perm);
757
        if ($r === true) {
758
            $dir_perm_verified = $perm;
759
            $course_test_was_created = true;
760
            break;
761
        }
762
    }
763
764
    $fil_perm_verified = 0666;
765
    $file_course_test_was_created = false;
766
    if (is_dir($dir)) {
767
        foreach ($perms_fil as $perm) {
768
            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...
769
                break;
770
            }
771
            $r = @touch($dir.'/'.$fileToCreate, $perm);
772
            if ($r === true) {
773
                $fil_perm_verified = $perm;
774
                $file_course_test_was_created = true;
775
            }
776
        }
777
    }
778
779
    @unlink($dir.'/'.$fileToCreate);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for unlink(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

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

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

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

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

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

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

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

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

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

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
781
782
    echo '<h2 class="install-title">'.display_step_sequence().get_lang('Requirements')."</h2>";
783
    echo '<div class="RequirementText">';
784
    echo '<strong>'.get_lang('ReadThoroughly').'</strong><br />';
785
    echo get_lang('MoreDetails').' <a href="../../documentation/installation_guide.html" target="_blank">'.get_lang('ReadTheInstallationGuide').'</a>.<br />'."\n";
786
787
    if ($installType == 'update') {
788
        echo get_lang('IfYouPlanToUpgradeFromOlderVersionYouMightWantToHaveAlookAtTheChangelog').'<br />';
789
    }
790
    echo '</div>';
791
792
    $properlyAccessUrl = checkAccessUrl();
793
    if (!$properlyAccessUrl) {
794
        echo '
795
            <div class="alert alert-danger">
796
            <i class="fa fa-exclamation-triangle" aria-hidden="true"></i>&nbsp;'.
797
            sprintf(get_lang('InstallMultiURLDetectedNotMainURL'), api_get_configuration_value('root_web')).'
798
            </div>
799
        ';
800
    }
801
802
    //  SERVER REQUIREMENTS
803
    echo '<h4 class="install-subtitle">'.get_lang('ServerRequirements').'</h4>';
804
    $timezone = checkPhpSettingExists('date.timezone');
805
    if (!$timezone) {
806
        echo "<div class='alert alert-warning'>
807
            <i class=\"fa fa-exclamation-triangle\" aria-hidden=\"true\"></i>&nbsp;".
808
            get_lang('DateTimezoneSettingNotSet')."</div>";
809
    }
810
811
    echo '<div class="install-requirement">'.get_lang('ServerRequirementsInfo').'</div>';
812
    echo '<div class="table-responsive">';
813
    echo '<table class="table table-bordered">
814
            <tr>
815
                <td class="requirements-item">'.get_lang('PHPVersion').' >= '.REQUIRED_PHP_VERSION.'</td>
816
                <td class="requirements-value">';
817
    if (version_compare(phpversion(), REQUIRED_PHP_VERSION, '>=') > 1) {
818
        echo '<strong class="text-danger">'.get_lang('PHPVersionError').'</strong>';
819
    } else {
820
        echo '<strong class="text-success">'.get_lang('PHPVersionOK').' '.phpversion().'</strong>';
821
    }
822
    echo '</td>
823
            </tr>
824
            <tr>
825
                <td class="requirements-item"><a href="http://php.net/manual/en/book.session.php" target="_blank">Session</a> '.get_lang('Support').'</td>
826
                <td class="requirements-value">'.checkExtension('session', get_lang('Yes'), get_lang('ExtensionSessionsNotAvailable')).'</td>
827
            </tr>
828
            <tr>
829
                <td class="requirements-item"><a href="http://php.net/manual/en/book.mysql.php" target="_blank">pdo_mysql</a> '.get_lang('Support').'</td>
830
                <td class="requirements-value">'.checkExtension('pdo_mysql', get_lang('Yes'), get_lang('ExtensionMySQLNotAvailable')).'</td>
831
            </tr>
832
            <tr>
833
                <td class="requirements-item"><a href="http://php.net/manual/en/book.zip.php" target="_blank">Zip</a> '.get_lang('Support').'</td>
834
                <td class="requirements-value">'.checkExtension('zip', get_lang('Yes'), get_lang('ExtensionNotAvailable')).'</td>
835
            </tr>
836
            <tr>
837
                <td class="requirements-item"><a href="http://php.net/manual/en/book.zlib.php" target="_blank">Zlib</a> '.get_lang('Support').'</td>
838
                <td class="requirements-value">'.checkExtension('zlib', get_lang('Yes'), get_lang('ExtensionZlibNotAvailable')).'</td>
839
            </tr>
840
            <tr>
841
                <td class="requirements-item"><a href="http://php.net/manual/en/book.pcre.php" target="_blank">Perl-compatible regular expressions</a> '.get_lang('Support').'</td>
842
                <td class="requirements-value">'.checkExtension('pcre', get_lang('Yes'), get_lang('ExtensionPCRENotAvailable')).'</td>
843
            </tr>
844
            <tr>
845
                <td class="requirements-item"><a href="http://php.net/manual/en/book.xml.php" target="_blank">XML</a> '.get_lang('Support').'</td>
846
                <td class="requirements-value">'.checkExtension('xml', get_lang('Yes'), get_lang('No')).'</td>
847
            </tr>
848
            <tr>
849
                <td class="requirements-item"><a href="http://php.net/manual/en/book.intl.php" target="_blank">Internationalization</a> '.get_lang('Support').'</td>
850
                <td class="requirements-value">'.checkExtension('intl', get_lang('Yes'), get_lang('No')).'</td>
851
            </tr>
852
               <tr>
853
                <td class="requirements-item"><a href="http://php.net/manual/en/book.json.php" target="_blank">JSON</a> '.get_lang('Support').'</td>
854
                <td class="requirements-value">'.checkExtension('json', get_lang('Yes'), get_lang('No')).'</td>
855
            </tr>
856
             <tr>
857
                <td class="requirements-item"><a href="http://php.net/manual/en/book.image.php" target="_blank">GD</a> '.get_lang('Support').'</td>
858
                <td class="requirements-value">'.checkExtension('gd', get_lang('Yes'), get_lang('ExtensionGDNotAvailable')).'</td>
859
            </tr>
860
            <tr>
861
                <td class="requirements-item"><a href="http://php.net/manual/en/book.curl.php" target="_blank">cURL</a>'.get_lang('Support').'</td>
862
                <td class="requirements-value">'.checkExtension('curl', get_lang('Yes'), get_lang('No')).'</td>
863
            </tr>
864
865
            <tr>
866
                <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>
867
                <td class="requirements-value">'.checkExtension('mbstring', get_lang('Yes'), get_lang('ExtensionMBStringNotAvailable'), true).'</td>
868
            </tr>
869
            <tr>
870
                <td class="requirements-item"><a href="http://php.net/opcache" target="_blank">Zend OpCache</a> '.get_lang('Support').' ('.get_lang('Optional').')</td>
871
                <td class="requirements-value">'.checkExtension('Zend OPcache', get_lang('Yes'), get_lang('No'), true, 'opcache.enable').'</td>
872
            </tr>
873
            <tr>
874
                <td class="requirements-item"><a href="http://php.net/apcu" target="_blank">APCu</a> '.get_lang('Support').' ('.get_lang('Optional').')</td>
875
                <td class="requirements-value">'.checkExtension('apcu', get_lang('Yes'), get_lang('No'), true, 'apc.enabled').'</td>
876
            </tr>
877
            <tr>
878
                <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>
879
                <td class="requirements-value">'.checkExtension('iconv', get_lang('Yes'), get_lang('No'), true).'</td>
880
            </tr>
881
            <tr>
882
                <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>
883
                <td class="requirements-value">'.checkExtension('ldap', get_lang('Yes'), get_lang('ExtensionLDAPNotAvailable'), true).'</td>
884
            </tr>
885
            <tr>
886
                <td class="requirements-item"><a href="http://xapian.org/" target="_blank">Xapian</a> '.get_lang('Support').' ('.get_lang('Optional').')</td>
887
                <td class="requirements-value">'.checkExtension('xapian', get_lang('Yes'), get_lang('No'), true).'</td>
888
            </tr>
889
        </table>';
890
    echo '</div>';
891
892
    // RECOMMENDED SETTINGS
893
    // Note: these are the settings for Joomla, does this also apply for Chamilo?
894
    // Note: also add upload_max_filesize here so that large uploads are possible
895
    echo '<h4 class="install-subtitle">'.get_lang('RecommendedSettings').'</h4>';
896
    echo '<div class="install-requirement">'.get_lang('RecommendedSettingsInfo').'</div>';
897
    echo '<div class="table-responsive">';
898
    echo '<table class="table table-bordered">
899
            <tr>
900
                <th>'.get_lang('Setting').'</th>
901
                <th>'.get_lang('Recommended').'</th>
902
                <th>'.get_lang('Actual').'</th>
903
            </tr>
904
            
905
            <tr>
906
                <td class="requirements-item"><a href="http://php.net/manual/ref.errorfunc.php#ini.display-errors">Display Errors</a></td>
907
                <td class="requirements-recommended">'.Display::label('OFF', 'success').'</td>
908
                <td class="requirements-value">'.checkPhpSetting('display_errors', 'OFF').'</td>
909
            </tr>
910
            <tr>
911
                <td class="requirements-item"><a href="http://php.net/manual/ini.core.php#ini.file-uploads">File Uploads</a></td>
912
                <td class="requirements-recommended">'.Display::label('ON', 'success').'</td>
913
                <td class="requirements-value">'.checkPhpSetting('file_uploads', 'ON').'</td>
914
            </tr>
915
            <tr>
916
                <td class="requirements-item"><a href="http://php.net/manual/ref.session.php#ini.session.auto-start">Session auto start</a></td>
917
                <td class="requirements-recommended">'.Display::label('OFF', 'success').'</td>
918
                <td class="requirements-value">'.checkPhpSetting('session.auto_start', 'OFF').'</td>
919
            </tr>
920
            <tr>
921
                <td class="requirements-item"><a href="http://php.net/manual/ini.core.php#ini.short-open-tag">Short Open Tag</a></td>
922
                <td class="requirements-recommended">'.Display::label('OFF', 'success').'</td>
923
                <td class="requirements-value">'.checkPhpSetting('short_open_tag', 'OFF').'</td>
924
            </tr>
925
            <tr>
926
                <td class="requirements-item"><a href="http://www.php.net/manual/en/session.configuration.php#ini.session.cookie-httponly">Cookie HTTP Only</a></td>
927
                <td class="requirements-recommended">'.Display::label('ON', 'success').'</td>
928
                <td class="requirements-value">'.checkPhpSetting('session.cookie_httponly', 'ON').'</td>
929
            </tr>
930
            <tr>
931
                <td class="requirements-item"><a href="http://php.net/manual/ini.core.php#ini.upload-max-filesize">Maximum upload file size</a></td>
932
                <td class="requirements-recommended">'.Display::label('>= '.REQUIRED_MIN_UPLOAD_MAX_FILESIZE.'M', 'success').'</td>
933
                <td class="requirements-value">'.compare_setting_values(ini_get('upload_max_filesize'), REQUIRED_MIN_UPLOAD_MAX_FILESIZE).'</td>
934
            </tr>
935
            <tr>
936
                <td class="requirements-item"><a href="http://php.net/manual/ini.core.php#ini.post-max-size">Maximum post size</a></td>
937
                <td class="requirements-recommended">'.Display::label('>= '.REQUIRED_MIN_POST_MAX_SIZE.'M', 'success').'</td>
938
                <td class="requirements-value">'.compare_setting_values(ini_get('post_max_size'), REQUIRED_MIN_POST_MAX_SIZE).'</td>
939
            </tr>
940
            <tr>
941
                <td class="requirements-item"><a href="http://www.php.net/manual/en/ini.core.php#ini.memory-limit">Memory Limit</a></td>
942
                <td class="requirements-recommended">'.Display::label('>= '.REQUIRED_MIN_MEMORY_LIMIT.'M', 'success').'</td>
943
                <td class="requirements-value">'.compare_setting_values($originalMemoryLimit, REQUIRED_MIN_MEMORY_LIMIT).'</td>
944
            </tr>
945
          </table>';
946
    echo '</div>';
947
948
    // DIRECTORY AND FILE PERMISSIONS
949
    echo '<h4 class="install-subtitle">'.get_lang('DirectoryAndFilePermissions').'</h4>';
950
    echo '<div class="install-requirement">'.get_lang('DirectoryAndFilePermissionsInfo').'</div>';
951
    echo '<div class="table-responsive">';
952
953
    $_SESSION['permissions_for_new_directories'] = $_setting['permissions_for_new_directories'] = $dir_perm_verified;
954
    $_SESSION['permissions_for_new_files'] = $_setting['permissions_for_new_files'] = $fil_perm_verified;
955
956
    $dir_perm = Display::label('0'.decoct($dir_perm_verified), 'info');
957
    $file_perm = Display::label('0'.decoct($fil_perm_verified), 'info');
958
959
    $oldConf = '';
960
    if (file_exists(api_get_path(SYS_CODE_PATH).'inc/conf/configuration.php')) {
961
        $oldConf = '<tr>
962
            <td class="requirements-item">'.api_get_path(SYS_CODE_PATH).'inc/conf</td>
963
            <td class="requirements-value">'.check_writable(api_get_path(SYS_CODE_PATH).'inc/conf').'</td>
964
        </tr>';
965
    }
966
967
    echo '<table class="table table-bordered">
968
            '.$oldConf.'
969
            <tr>
970
                <td class="requirements-item">'.api_get_path(SYS_APP_PATH).'</td>
971
                <td class="requirements-value">'.check_writable(api_get_path(SYS_APP_PATH)).'</td>
972
            </tr>
973
            <tr>
974
                <td class="requirements-item">'.api_get_path(SYS_PATH).'config</td>
975
                <td class="requirements-value">'.check_writable(api_get_path(SYS_PATH).'config').'</td>
976
            </tr>
977
            <tr>
978
                <td class="requirements-item">'.api_get_path(SYS_PATH).'vendor/</td>
979
                <td class="requirements-value">'.checkReadable(api_get_path(SYS_PATH).'vendor').'</td>
980
            </tr>
981
            <tr>
982
                <td class="requirements-item">'.api_get_path(SYS_PUBLIC_PATH).'</td>
983
                <td class="requirements-value">'.check_writable(api_get_path(SYS_PUBLIC_PATH)).'</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
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
                        <div class="btn-group">
1015
                            <button type="submit" class="btn btn-secondary" name="step1" value="<?php echo get_lang('Back'); ?>" >
1016
                                <em class="fa fa-backward"> <?php echo get_lang('Back'); ?></em>
1017
                            </button>
1018
                            <input type="hidden" name="is_executable" id="is_executable" value="-" />
1019
                            <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;" >
1020
                                <em class="fa fa-forward"> </em> <?php echo get_lang('Next'); ?>
1021
                            </button>
1022
                        </div>
1023
                    </p>
1024
                </div>
1025
            </div>
1026
        <?php
1027
    } else {
1028
        $error = false;
1029
        // First, attempt to set writing permissions if we don't have them yet
1030
        $perm = api_get_permissions_for_new_directories();
1031
        $perm_file = api_get_permissions_for_new_files();
1032
        $notWritable = [];
1033
1034
        $checked_writable = api_get_path(SYS_APP_PATH);
1035
        if (!is_writable($checked_writable)) {
1036
            $notWritable[] = $checked_writable;
1037
            @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

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

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

1366
    /** @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...
1367
) {
1368
    if ($installType == 'update') {
1369
        global $_configuration;
1370
        $dbHostForm = $_configuration['db_host'];
1371
        $dbUsernameForm = $_configuration['db_user'];
1372
        $dbPassForm = $_configuration['db_password'];
1373
        $dbNameForm = $_configuration['main_database'];
1374
        $dbPortForm = isset($_configuration['db_port']) ? $_configuration['db_port'] : '';
1375
1376
        echo '<div class="RequirementHeading"><h2>'.display_step_sequence().get_lang('Database settings').'</h2></div>';
1377
        echo '<div class="RequirementContent">';
1378
        echo get_lang('DBSettingUpgradeIntro');
1379
        echo '</div>';
1380
    } else {
1381
        echo '<div class="RequirementHeading"><h2>'.display_step_sequence().get_lang('Database settings').'</h2></div>';
1382
        echo '<div class="RequirementContent">';
1383
        echo get_lang('DBSettingIntro');
1384
        echo '</div>';
1385
    } ?>
1386
    <div class="panel panel-default">
1387
        <div class="panel-body">
1388
        <div class="form-group row">
1389
            <label class="col-sm-4"><?php echo get_lang('DBHost'); ?> </label>
1390
            <?php if ($installType == 'update') {
1391
        ?>
1392
            <div class="col-sm-5">
1393
                <input type="hidden" name="dbHostForm" value="<?php echo htmlentities($dbHostForm); ?>" /><?php echo $dbHostForm; ?>
1394
            </div>
1395
            <div class="col-sm-3"></div>
1396
            <?php
1397
    } else {
1398
        ?>
1399
            <div class="col-sm-5">
1400
                <input type="text" class="form-control" size="25" maxlength="50" name="dbHostForm" value="<?php echo htmlentities($dbHostForm); ?>" />
1401
            </div>
1402
            <div class="col-sm-3"><?php echo get_lang('EG').' localhost'; ?></div>
1403
            <?php
1404
    } ?>
1405
        </div>
1406
        <div class="form-group row">
1407
            <label class="col-sm-4"><?php echo get_lang('DBPort'); ?> </label>
1408
            <?php if ($installType == 'update') {
1409
        ?>
1410
            <div class="col-sm-5">
1411
                <input type="hidden" name="dbPortForm" value="<?php echo htmlentities($dbPortForm); ?>" /><?php echo $dbPortForm; ?>
1412
            </div>
1413
            <div class="col-sm-3"></div>
1414
            <?php
1415
    } else {
1416
        ?>
1417
            <div class="col-sm-5">
1418
                <input type="text" class="form-control" size="25" maxlength="50" name="dbPortForm" value="<?php echo htmlentities($dbPortForm); ?>" />
1419
            </div>
1420
            <div class="col-sm-3"><?php echo get_lang('EG').' 3306'; ?></div>
1421
            <?php
1422
    } ?>
1423
        </div>
1424
        <div class="form-group row">
1425
            <?php
1426
                //database user username
1427
                $example_login = get_lang('EG').' root';
1428
    displayDatabaseParameter($installType, get_lang('DBLogin'), 'dbUsernameForm', $dbUsernameForm, $example_login); ?>
1429
        </div>
1430
        <div class="form-group row">
1431
            <?php
1432
            //database user password
1433
            $example_password = get_lang('EG').' '.api_generate_password();
1434
    displayDatabaseParameter($installType, get_lang('DBPassword'), 'dbPassForm', $dbPassForm, $example_password); ?>
1435
        </div>
1436
        <div class="form-group row">
1437
            <?php
1438
            //Database Name fix replace weird chars
1439
            if ($installType != INSTALL_TYPE_UPDATE) {
1440
                $dbNameForm = str_replace(['-', '*', '$', ' ', '.'], '', $dbNameForm);
1441
            }
1442
1443
    displayDatabaseParameter(
1444
                $installType,
1445
                get_lang('MainDB'),
1446
                'dbNameForm',
1447
                $dbNameForm,
1448
                '&nbsp;',
1449
                null,
1450
                'id="optional_param1"'
1451
                ); ?>
1452
        </div>
1453
       <?php if ($installType != INSTALL_TYPE_UPDATE) {
1454
                    ?>
1455
        <div class="form-group row">
1456
            <div class="col-sm-4"></div>
1457
            <div class="col-sm-8">
1458
            <button type="submit" class="btn btn-primary" name="step3" value="step3">
1459
                <em class="fa fa-refresh"> </em>
1460
                <?php echo get_lang('CheckDatabaseConnection'); ?>
1461
            </button>
1462
            </div>
1463
        </div>
1464
        <?php
1465
                } ?>
1466
1467
        </div>
1468
    </div>
1469
    <?php
1470
        $database_exists_text = '';
1471
    $manager = null;
1472
    try {
1473
        if ($installType === 'update') {
1474
            /** @var \Database $manager */
1475
            $manager = connectToDatabase(
1476
                $dbHostForm,
1477
                $dbUsernameForm,
1478
                $dbPassForm,
1479
                $dbNameForm,
1480
                $dbPortForm
1481
            );
1482
1483
            $connection = $manager->getConnection();
1484
            $connection->connect();
1485
            $schemaManager = $connection->getSchemaManager();
1486
1487
            // Test create/alter/drop table
1488
            $table = 'zXxTESTxX_'.mt_rand(0, 1000);
1489
            $sql = "CREATE TABLE $table (id INT AUTO_INCREMENT NOT NULL, name varchar(255), PRIMARY KEY(id))";
1490
            $connection->query($sql);
1491
            $tableCreationWorks = false;
1492
            $tableDropWorks = false;
1493
            if ($schemaManager->tablesExist($table)) {
1494
                $tableCreationWorks = true;
1495
                $sql = "ALTER TABLE $table ADD COLUMN name2 varchar(140) ";
1496
                $connection->query($sql);
1497
                $schemaManager->dropTable($table);
1498
                $tableDropWorks = $schemaManager->tablesExist($table) === false;
1499
            }
1500
        } else {
1501
            $manager = connectToDatabase(
1502
                $dbHostForm,
1503
                $dbUsernameForm,
1504
                $dbPassForm,
1505
                null,
1506
                $dbPortForm
1507
            );
1508
1509
            $schemaManager = $manager->getConnection()->getSchemaManager();
1510
            $databases = $schemaManager->listDatabases();
1511
            if (in_array($dbNameForm, $databases)) {
1512
                $database_exists_text = '<div class="alert alert-warning">'.get_lang('ADatabaseWithTheSameNameAlreadyExists').'</div>';
1513
            }
1514
        }
1515
    } catch (Exception $e) {
1516
        $database_exists_text = $e->getMessage();
1517
        $manager = false;
1518
    }
1519
1520
    if ($manager && $manager->getConnection()->isConnected()): ?>
1521
        <?php echo $database_exists_text; ?>
1522
        <div id="db_status" class="alert alert-success">
1523
            Database host: <strong><?php echo $manager->getConnection()->getHost(); ?></strong><br/>
1524
            Database port: <strong><?php echo $manager->getConnection()->getPort(); ?></strong><br/>
1525
            Database driver: <strong><?php echo $manager->getConnection()->getDriver()->getName(); ?></strong><br/>
1526
            <?php
1527
                if ($installType === 'update') {
1528
                    echo get_lang('CreateTableWorks').' <strong>Ok</strong>';
1529
                    echo '<br/ >';
1530
                    echo get_lang('AlterTableWorks').' <strong>Ok</strong>';
1531
                    echo '<br/ >';
1532
                    echo get_lang('DropColumnWorks').' <strong>Ok</strong>';
1533
                } ?>
1534
        </div>
1535
    <?php else: ?>
1536
        <div id="db_status" class="alert alert-danger">
1537
            <p><?php echo get_lang('FailedConectionDatabase'); ?></strong></p>
1538
            <code><?php echo $database_exists_text; ?></code>
1539
        </div>
1540
    <?php endif; ?>
1541
1542
   <div class="btn-group" role="group">
1543
       <button type="submit" name="step2"
1544
               class="btn btn-secondary float-right" value="&lt; <?php echo get_lang('Previous'); ?>" >
1545
           <em class="fa fa-backward"> </em> <?php echo get_lang('Previous'); ?>
1546
       </button>
1547
       <input type="hidden" name="is_executable" id="is_executable" value="-" />
1548
       <?php if ($manager) {
1549
                    ?>
1550
           <button type="submit" class="btn btn-success" name="step4" value="<?php echo get_lang('Next'); ?> &gt;" >
1551
               <em class="fa fa-forward"> </em> <?php echo get_lang('Next'); ?>
1552
           </button>
1553
       <?php
1554
                } else {
1555
                    ?>
1556
           <button
1557
                   disabled="disabled"
1558
                   type="submit" class="btn btn-success disabled" name="step4" value="<?php echo get_lang('Next'); ?> &gt;" >
1559
               <em class="fa fa-forward"> </em> <?php echo get_lang('Next'); ?>
1560
           </button>
1561
       <?php
1562
                } ?>
1563
   </div>
1564
    <?php
1565
}
1566
1567
function panel($content = null, $title = null, $id = null, $style = null)
1568
{
1569
    $html = '';
1570
    if (empty($style)) {
1571
        $style = 'default';
1572
    }
1573
    if (!empty($title)) {
1574
        $panelTitle = Display::div($title, ['class' => 'panel-heading']);
1575
        $panelBody = Display::div($content, ['class' => 'panel-body']);
1576
        $panelParent = Display::div($panelTitle.$panelBody, ['id' => $id, 'class' => 'panel panel-'.$style]);
1577
    } else {
1578
        $panelBody = Display::div($html, ['class' => 'panel-body']);
1579
        $panelParent = Display::div($panelBody, ['id' => $id, 'class' => 'panel panel-'.$style]);
1580
    }
1581
    $html .= $panelParent;
1582
1583
    return $html;
1584
}
1585
1586
/**
1587
 * Displays a parameter in a table row.
1588
 * Used by the display_configuration_settings_form function.
1589
 *
1590
 * @param string $installType
1591
 * @param string $parameterName
1592
 * @param string $formFieldName
1593
 * @param string $parameterValue
1594
 * @param string $displayWhenUpdate
1595
 *
1596
 * @return string
1597
 */
1598
function display_configuration_parameter(
1599
    $installType,
1600
    $parameterName,
1601
    $formFieldName,
1602
    $parameterValue,
1603
    $displayWhenUpdate = 'true'
1604
) {
1605
    $html = '<div class="form-group row">';
1606
    $html .= '<label class="col-sm-6 control-label">'.$parameterName.'</label>';
1607
    if ($installType == INSTALL_TYPE_UPDATE && $displayWhenUpdate) {
1608
        $html .= '<input type="hidden" name="'.$formFieldName.'" value="'.api_htmlentities($parameterValue, ENT_QUOTES).'" />'.$parameterValue;
1609
    } else {
1610
        $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>";
1611
    }
1612
    $html .= "</div>";
1613
1614
    return $html;
1615
}
1616
1617
/**
1618
 * Displays step 4 of the installation - configuration settings about Chamilo itself.
1619
 *
1620
 * @param string $installType
1621
 * @param string $urlForm
1622
 * @param string $languageForm
1623
 * @param string $emailForm
1624
 * @param string $adminFirstName
1625
 * @param string $adminLastName
1626
 * @param string $adminPhoneForm
1627
 * @param string $campusForm
1628
 * @param string $institutionForm
1629
 * @param string $institutionUrlForm
1630
 * @param string $encryptPassForm
1631
 * @param bool   $allowSelfReg
1632
 * @param bool   $allowSelfRegProf
1633
 * @param string $loginForm
1634
 * @param string $passForm
1635
 */
1636
function display_configuration_settings_form(
1637
    $installType,
1638
    $urlForm,
1639
    $languageForm,
1640
    $emailForm,
1641
    $adminFirstName,
1642
    $adminLastName,
1643
    $adminPhoneForm,
1644
    $campusForm,
1645
    $institutionForm,
1646
    $institutionUrlForm,
1647
    $encryptPassForm,
1648
    $allowSelfReg,
1649
    $allowSelfRegProf,
1650
    $loginForm,
1651
    $passForm
1652
) {
1653
    if ($installType != 'update' && empty($languageForm)) {
1654
        $languageForm = $_SESSION['install_language'];
1655
    }
1656
    echo '<div class="RequirementHeading">';
1657
    echo "<h2>".display_step_sequence().get_lang("ConfigurationSettings")."</h2>";
1658
    echo '</div>';
1659
1660
    // Parameter 1: administrator's login
1661
    $html = '';
1662
    $html .= display_configuration_parameter(
1663
        $installType,
1664
        get_lang('AdminLogin'),
1665
        'loginForm',
1666
        $loginForm,
1667
        $installType == 'update'
1668
    );
1669
1670
    // Parameter 2: administrator's password
1671
    if ($installType != 'update') {
1672
        $html .= display_configuration_parameter($installType, get_lang('AdminPass'), 'passForm', $passForm, false);
1673
    }
1674
1675
    // Parameters 3 and 4: administrator's names
1676
1677
    $html .= display_configuration_parameter(
1678
        $installType,
1679
        get_lang('AdminFirstName'),
1680
        'adminFirstName',
1681
        $adminFirstName
1682
    );
1683
    $html .= display_configuration_parameter($installType, get_lang('AdminLastName'), 'adminLastName', $adminLastName);
1684
1685
    //Parameter 3: administrator's email
1686
    $html .= display_configuration_parameter($installType, get_lang('AdminEmail'), 'emailForm', $emailForm);
1687
1688
    //Parameter 6: administrator's telephone
1689
    $html .= display_configuration_parameter($installType, get_lang('AdminPhone'), 'adminPhoneForm', $adminPhoneForm);
1690
    echo panel($html, get_lang('Administrator'), 'administrator');
1691
1692
    //First parameter: language
1693
    $html = '<div class="form-group row">';
1694
    $html .= '<label class="col-sm-6 control-label">'.get_lang('MainLang')."</label>";
1695
    if ($installType == 'update') {
1696
        $html .= '<input type="hidden" name="languageForm" value="'.api_htmlentities($languageForm, ENT_QUOTES).'" />'.$languageForm;
1697
    } else { // new installation
1698
        $html .= '<div class="col-sm-6">';
1699
        $html .= display_language_selection_box('languageForm', $languageForm);
1700
        $html .= '</div>';
1701
    }
1702
    $html .= "</div>";
1703
1704
    //Second parameter: Chamilo URL
1705
    $html .= '<div class="form-group row">';
1706
    $html .= '<label class="col-sm-6 control-label">'.get_lang('ChamiloURL').get_lang('ThisFieldIsRequired').'</label>';
1707
1708
    if ($installType == 'update') {
1709
        $html .= api_htmlentities($urlForm, ENT_QUOTES)."\n";
1710
    } else {
1711
        $html .= '<div class="col-sm-6">';
1712
        $html .= '<input class="form-control" type="text" size="40" maxlength="100" name="urlForm" value="'.api_htmlentities($urlForm, ENT_QUOTES).'" />';
1713
        $html .= '</div>';
1714
    }
1715
    $html .= '</div>';
1716
1717
    //Parameter 9: campus name
1718
    $html .= display_configuration_parameter(
1719
        $installType,
1720
        get_lang('CampusName'),
1721
        'campusForm',
1722
        $campusForm
1723
    );
1724
1725
    //Parameter 10: institute (short) name
1726
    $html .= display_configuration_parameter(
1727
        $installType,
1728
        get_lang('InstituteShortName'),
1729
        'institutionForm',
1730
        $institutionForm
1731
    );
1732
1733
    //Parameter 11: institute (short) name
1734
    $html .= display_configuration_parameter(
1735
        $installType,
1736
        get_lang('InstituteURL'),
1737
        'institutionUrlForm',
1738
        $institutionUrlForm
1739
    );
1740
1741
    $html .= '<div class="form-group row">
1742
            <label class="col-sm-6 control-label">'.get_lang("EncryptMethodUserPass").'</label>
1743
        <div class="col-sm-6">';
1744
    if ($installType == 'update') {
1745
        $html .= '<input type="hidden" name="encryptPassForm" value="'.$encryptPassForm.'" />'.$encryptPassForm;
1746
    } else {
1747
        $html .= '<div class="checkbox">
1748
                    <label>
1749
                        <input  type="radio" name="encryptPassForm" value="bcrypt" id="encryptPass1" '.($encryptPassForm == 'bcrypt' ? 'checked="checked" ' : '').'/> bcrypt
1750
                    </label>';
1751
1752
        $html .= '<label>
1753
                        <input  type="radio" name="encryptPassForm" value="sha1" id="encryptPass1" '.($encryptPassForm == 'sha1' ? 'checked="checked" ' : '').'/> sha1
1754
                    </label>';
1755
1756
        $html .= '<label>
1757
                        <input type="radio" name="encryptPassForm" value="md5" id="encryptPass0" '.($encryptPassForm == 'md5' ? 'checked="checked" ' : '').'/> md5
1758
                    </label>';
1759
1760
        $html .= '<label>
1761
                        <input type="radio" name="encryptPassForm" value="none" id="encryptPass2" '.($encryptPassForm == 'none' ? 'checked="checked" ' : '').'/>'.get_lang('None').'
1762
                    </label>';
1763
        $html .= '</div>';
1764
    }
1765
    $html .= '</div></div>';
1766
1767
    $html .= '<div class="form-group row">
1768
            <label class="col-sm-6 control-label">'.get_lang('AllowSelfReg').'</label>
1769
            <div class="col-sm-6">';
1770
    if ($installType == 'update') {
1771
        if ($allowSelfReg == 'true') {
1772
            $label = get_lang('Yes');
1773
        } elseif ($allowSelfReg == 'false') {
1774
            $label = get_lang('No');
1775
        } else {
1776
            $label = get_lang('AfterApproval');
1777
        }
1778
        $html .= '<input type="hidden" name="allowSelfReg" value="'.$allowSelfReg.'" />'.$label;
1779
    } else {
1780
        $html .= '<div class="control-group">';
1781
        $html .= '<label class="checkbox-inline">
1782
                        <input type="radio" name="allowSelfReg" value="true" id="allowSelfReg1" '.($allowSelfReg == 'true' ? 'checked="checked" ' : '').' /> '.get_lang('Yes').'
1783
                    </label>';
1784
        $html .= '<label class="checkbox-inline">
1785
                        <input type="radio" name="allowSelfReg" value="false" id="allowSelfReg0" '.($allowSelfReg == 'false' ? '' : 'checked="checked" ').' /> '.get_lang('No').'
1786
                    </label>';
1787
        $html .= '<label class="checkbox-inline">
1788
                    <input type="radio" name="allowSelfReg" value="approval" id="allowSelfReg2" '.($allowSelfReg == 'approval' ? '' : 'checked="checked" ').' /> '.get_lang('AfterApproval').'
1789
                </label>';
1790
        $html .= '</div>';
1791
    }
1792
    $html .= '</div>';
1793
    $html .= '</div>';
1794
1795
    $html .= '<div class="form-group row">';
1796
    $html .= '<label class="col-sm-6 control-label">'.get_lang('AllowSelfRegProf').'</label>
1797
        <div class="col-sm-6">';
1798
    if ($installType == 'update') {
1799
        if ($allowSelfRegProf == 'true') {
1800
            $label = get_lang('Yes');
1801
        } else {
1802
            $label = get_lang('No');
1803
        }
1804
        $html .= '<input type="hidden" name="allowSelfRegProf" value="'.$allowSelfRegProf.'" />'.$label;
1805
    } else {
1806
        $html .= '<div class="control-group">
1807
                <label class="checkbox-inline">
1808
                    <input type="radio" name="allowSelfRegProf" value="1" id="allowSelfRegProf1" '.($allowSelfRegProf ? 'checked="checked" ' : '').'/>
1809
                '.get_lang('Yes').'
1810
                </label>';
1811
        $html .= '<label class="checkbox-inline">
1812
                    <input type="radio" name="allowSelfRegProf" value="0" id="allowSelfRegProf0" '.($allowSelfRegProf ? '' : 'checked="checked" ').' />
1813
                   '.get_lang('No').'
1814
                </label>';
1815
        $html .= '</div>';
1816
    }
1817
    $html .= '</div>
1818
    </div>';
1819
1820
    echo panel($html, get_lang('Platform'), 'platform'); ?>
1821
    <div class='btn-group'>
1822
        <button type="submit" class="btn btn-secondary pull-right" name="step3" value="&lt; <?php echo get_lang('Previous'); ?>" ><em class="fa fa-backward"> </em> <?php echo get_lang('Previous'); ?></button>
1823
        <input type="hidden" name="is_executable" id="is_executable" value="-" />
1824
        <button class="btn btn-success" type="submit" name="step5">
1825
            <em class="fa fa-forward"> </em> <?php echo get_lang('Next'); ?>
1826
        </button>
1827
    </div>
1828
    <?php
1829
}
1830
1831
/**
1832
 * After installation is completed (step 6), this message is displayed.
1833
 */
1834
function display_after_install_message()
1835
{
1836
    $html = '<div class="RequirementContent">'.get_lang('FirstUseTip').'</div>';
1837
    $html .= '<div class="alert alert-warning">';
1838
    $html .= '<strong>'.get_lang('SecurityAdvice').'</strong>';
1839
    $html .= ': ';
1840
    $html .= sprintf(get_lang('ToProtectYourSiteMakeXReadOnlyAndDeleteY'), 'app/config/', 'main/install/');
1841
    $html .= '</div></form>
1842
    <br />
1843
    <a class="btn btn-success btn-block" href="../../index.php">
1844
        '.get_lang('GoToYourNewlyCreatedPortal').'
1845
    </a>';
1846
1847
    return $html;
1848
}
1849
1850
/**
1851
 * This function return countries list from array (hardcoded).
1852
 *
1853
 * @param bool $combo (Optional) True for returning countries list with select html
1854
 *
1855
 * @return array|string countries list
1856
 */
1857
function get_countries_list_from_array($combo = false)
1858
{
1859
    $a_countries = [
1860
        "Afghanistan", "Albania", "Algeria", "Andorra", "Angola", "Antigua and Barbuda", "Argentina", "Armenia", "Australia", "Austria", "Azerbaijan",
1861
        "Bahamas", "Bahrain", "Bangladesh", "Barbados", "Belarus", "Belgium", "Belize", "Benin", "Bhutan", "Bolivia", "Bosnia and Herzegovina", "Botswana", "Brazil", "Brunei", "Bulgaria", "Burkina Faso", "Burundi",
1862
        "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",
1863
        "Denmark", "Djibouti", "Dominica", "Dominican Republic",
1864
        "East Timor (Timor Timur)", "Ecuador", "Egypt", "El Salvador", "Equatorial Guinea", "Eritrea", "Estonia", "Ethiopia",
1865
        "Fiji", "Finland", "France",
1866
        "Gabon", "Gambia, The", "Georgia", "Germany", "Ghana", "Greece", "Grenada", "Guatemala", "Guinea", "Guinea-Bissau", "Guyana",
1867
        "Haiti", "Honduras", "Hungary",
1868
        "Iceland", "India", "Indonesia", "Iran", "Iraq", "Ireland", "Israel", "Italy",
1869
        "Jamaica", "Japan", "Jordan",
1870
        "Kazakhstan", "Kenya", "Kiribati", "Korea, North", "Korea, South", "Kuwait", "Kyrgyzstan",
1871
        "Laos", "Latvia", "Lebanon", "Lesotho", "Liberia", "Libya", "Liechtenstein", "Lithuania", "Luxembourg",
1872
        "Macedonia", "Madagascar", "Malawi", "Malaysia", "Maldives", "Mali", "Malta", "Marshall Islands", "Mauritania", "Mauritius", "Mexico", "Micronesia", "Moldova", "Monaco", "Mongolia", "Morocco", "Mozambique", "Myanmar",
1873
        "Namibia", "Nauru", "Nepa", "Netherlands", "New Zealand", "Nicaragua", "Niger", "Nigeria", "Norway",
1874
        "Oman",
1875
        "Pakistan", "Palau", "Panama", "Papua New Guinea", "Paraguay", "Peru", "Philippines", "Poland", "Portugal",
1876
        "Qatar",
1877
        "Romania", "Russia", "Rwanda",
1878
        "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",
1879
        "Taiwan", "Tajikistan", "Tanzania", "Thailand", "Togo", "Tonga", "Trinidad and Tobago", "Tunisia", "Turkey", "Turkmenistan", "Tuvalu",
1880
        "Uganda", "Ukraine", "United Arab Emirates", "United Kingdom", "United States", "Uruguay", "Uzbekistan",
1881
        "Vanuatu", "Vatican City", "Venezuela", "Vietnam",
1882
        "Yemen",
1883
        "Zambia", "Zimbabwe",
1884
    ];
1885
    if ($combo) {
1886
        $country_select = '<select class="selectpicker show-tick" id="country" name="country">';
1887
        $country_select .= '<option value="">--- '.get_lang('SelectOne').' ---</option>';
1888
        foreach ($a_countries as $country) {
1889
            $country_select .= '<option value="'.$country.'">'.$country.'</option>';
1890
        }
1891
        $country_select .= '</select>';
1892
1893
        return $country_select;
1894
    }
1895
1896
    return $a_countries;
1897
}
1898
1899
/**
1900
 * Lock settings that can't be changed in other portals.
1901
 */
1902
function lockSettings()
1903
{
1904
    $settings = api_get_locked_settings();
1905
    $table = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
1906
    foreach ($settings as $setting) {
1907
        $sql = "UPDATE $table SET access_url_locked = 1 WHERE variable  = '$setting'";
1908
        Database::query($sql);
1909
    }
1910
}
1911
1912
/**
1913
 * Update dir values.
1914
 */
1915
function updateDirAndFilesPermissions()
1916
{
1917
    $table = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
1918
    $permissions_for_new_directories = isset($_SESSION['permissions_for_new_directories']) ? $_SESSION['permissions_for_new_directories'] : 0770;
1919
    $permissions_for_new_files = isset($_SESSION['permissions_for_new_files']) ? $_SESSION['permissions_for_new_files'] : 0660;
1920
    // use decoct() to store as string
1921
    Database::update(
1922
        $table,
1923
        ['selected_value' => '0'.decoct($permissions_for_new_directories)],
1924
        ['variable = ?' => 'permissions_for_new_directories']
1925
    );
1926
1927
    Database::update(
1928
        $table,
1929
        ['selected_value' => '0'.decoct($permissions_for_new_files)],
1930
        ['variable = ?' => 'permissions_for_new_files']
1931
    );
1932
1933
    if (isset($_SESSION['permissions_for_new_directories'])) {
1934
        unset($_SESSION['permissions_for_new_directories']);
1935
    }
1936
1937
    if (isset($_SESSION['permissions_for_new_files'])) {
1938
        unset($_SESSION['permissions_for_new_files']);
1939
    }
1940
}
1941
1942
/**
1943
 * @param $current_value
1944
 * @param $wanted_value
1945
 *
1946
 * @return string
1947
 */
1948
function compare_setting_values($current_value, $wanted_value)
1949
{
1950
    $current_value_string = $current_value;
1951
    $current_value = (float) $current_value;
1952
    $wanted_value = (float) $wanted_value;
1953
1954
    if ($current_value >= $wanted_value) {
1955
        return Display::label($current_value_string, 'success');
1956
    } else {
1957
        return Display::label($current_value_string, 'important');
1958
    }
1959
}
1960
1961
/**
1962
 * Save settings values.
1963
 *
1964
 * @param string $organizationName
1965
 * @param string $organizationUrl
1966
 * @param string $siteName
1967
 * @param string $adminEmail
1968
 * @param string $adminLastName
1969
 * @param string $adminFirstName
1970
 * @param string $language
1971
 * @param string $allowRegistration
1972
 * @param string $allowTeacherSelfRegistration
1973
 * @param string $installationProfile          The name of an installation profile file in main/install/profiles/
1974
 */
1975
function installSettings(
1976
    $organizationName,
1977
    $organizationUrl,
1978
    $siteName,
1979
    $adminEmail,
1980
    $adminLastName,
1981
    $adminFirstName,
1982
    $language,
1983
    $allowRegistration,
1984
    $allowTeacherSelfRegistration,
1985
    $installationProfile = ''
1986
) {
1987
    $allowTeacherSelfRegistration = $allowTeacherSelfRegistration ? 'true' : 'false';
1988
1989
    $settings = [
1990
        'institution' => $organizationName,
1991
        'institution_url' => $organizationUrl,
1992
        'site_name' => $siteName,
1993
        'administrator_email' => $adminEmail,
1994
        'administrator_surname' => $adminLastName,
1995
        'administrator_name' => $adminFirstName,
1996
        'platform_language' => $language,
1997
        'allow_registration' => $allowRegistration,
1998
        'allow_registration_as_teacher' => $allowTeacherSelfRegistration,
1999
    ];
2000
2001
    foreach ($settings as $variable => $value) {
2002
        $sql = "UPDATE settings_current
2003
                SET selected_value = '$value'
2004
                WHERE variable = '$variable'";
2005
        Database::query($sql);
2006
    }
2007
    installProfileSettings($installationProfile);
2008
}
2009
2010
/**
2011
 * Executes DB changes based in the classes defined in
2012
 * src/CoreBundle/Migrations/Schema/*.
2013
 *
2014
 * @param string        $chamiloVersion
2015
 * @param EntityManager $manager
2016
 *
2017
 * @throws \Doctrine\DBAL\DBALException
2018
 *
2019
 * @return bool
2020
 */
2021
function migrate($chamiloVersion, EntityManager $manager)
2022
{
2023
    $debug = true;
2024
    $connection = $manager->getConnection();
2025
2026
    $config = new \Doctrine\DBAL\Migrations\Configuration\Configuration($connection);
2027
2028
    // Table name that will store migrations log (will be created automatically,
2029
    // default name is: doctrine_migration_versions)
2030
    $config->setMigrationsTableName('version');
2031
    // Namespace of your migration classes, do not forget escape slashes, do not add last slash
2032
    $config->setMigrationsNamespace('Chamilo\CoreBundle\Migrations\Schema\V'.$chamiloVersion);
2033
    // Directory where your migrations are located
2034
    $versionPath = api_get_path(SYS_PATH).'src/CoreBundle/Migrations/Schema/V'.$chamiloVersion;
2035
    error_log("Reading files from dir: $versionPath");
2036
    $config->setMigrationsDirectory($versionPath);
2037
    // Load your migrations
2038
    $config->registerMigrationsFromDirectory($config->getMigrationsDirectory());
2039
2040
    $migration = new \Doctrine\DBAL\Migrations\Migration($config);
2041
    $versions = $config->getMigrations();
2042
2043
    /** @var Doctrine\DBAL\Migrations\Version $migrationItem */
2044
    foreach ($versions as $version) {
2045
        $version->getMigration()->setEntityManager($manager);
2046
    }
2047
2048
    $to = null; // if $to == null then schema will be migrated to latest version
2049
    echo '<pre>';
2050
    try {
2051
        // Execute migration!
2052
        $migratedSQL = $migration->migrate($to);
2053
2054
        if ($debug) {
2055
            foreach ($migratedSQL as $version => $sqlList) {
2056
                echo "VERSION: $version<br>";
2057
                echo '----------------------------------------------<br />';
2058
                $total = count($sqlList);
2059
                error_log("VERSION: $version");
2060
                error_log("# queries: $total");
2061
                $counter = 1;
2062
                foreach ($sqlList as $sql) {
2063
                    echo "<code>$sql</code><br>";
2064
                    error_log("$counter/$total : $sql");
2065
                    $counter++;
2066
                }
2067
            }
2068
2069
            echo "<br>DONE!<br>";
2070
        }
2071
2072
        return true;
2073
    } catch (Exception $ex) {
2074
        if ($debug) {
2075
            echo "ERROR: {$ex->getMessage()}<br>";
2076
2077
            return false;
2078
        }
2079
    }
2080
2081
    echo '</pre>';
2082
2083
    return false;
2084
}
2085
2086
/**
2087
 * @param EntityManager $em
2088
 *
2089
 * @throws \Doctrine\DBAL\DBALException
2090
 */
2091
function fixIds(EntityManager $em)
2092
{
2093
    $connection = $em->getConnection();
2094
    $database = new Database();
2095
    $database->setManager($em);
2096
    $debug = true;
2097
    if ($debug) {
2098
        error_log('fixIds');
2099
    }
2100
2101
    // Create temporary indexes to increase speed of the following operations
2102
    // Adding and removing indexes will usually take much less time than
2103
    // the execution without indexes of the queries in this function, particularly
2104
    // for large tables
2105
    $sql = "ALTER TABLE c_document ADD INDEX tmpidx_doc(c_id, id)";
2106
    $connection->executeQuery($sql);
2107
    $sql = "ALTER TABLE c_student_publication ADD INDEX tmpidx_stud (c_id, id)";
2108
    $connection->executeQuery($sql);
2109
    $sql = "ALTER TABLE c_quiz ADD INDEX tmpidx_quiz (c_id, id)";
2110
    $connection->executeQuery($sql);
2111
    $sql = "ALTER TABLE c_item_property ADD INDEX tmpidx_ip (to_group_id)";
2112
    $connection->executeQuery($sql);
2113
2114
    $sql = "SELECT * FROM c_lp_item";
2115
    $result = $connection->fetchAll($sql);
2116
    foreach ($result as $item) {
2117
        $courseId = $item['c_id'];
2118
        $iid = isset($item['iid']) ? intval($item['iid']) : 0;
2119
        $ref = isset($item['ref']) ? intval($item['ref']) : 0;
2120
        $sql = null;
2121
2122
        $newId = '';
2123
2124
        switch ($item['item_type']) {
2125
            case TOOL_LINK:
2126
                $sql = "SELECT * FROM c_link WHERE c_id = $courseId AND id = $ref";
2127
                $data = $connection->fetchAssoc($sql);
2128
                if ($data) {
2129
                    $newId = $data['iid'];
2130
                }
2131
                break;
2132
            case TOOL_STUDENTPUBLICATION:
2133
                $sql = "SELECT * FROM c_student_publication WHERE c_id = $courseId AND id = $ref";
2134
                $data = $connection->fetchAssoc($sql);
2135
                if ($data) {
2136
                    $newId = $data['iid'];
2137
                }
2138
                break;
2139
            case TOOL_QUIZ:
2140
                $sql = "SELECT * FROM c_quiz WHERE c_id = $courseId AND id = $ref";
2141
                $data = $connection->fetchAssoc($sql);
2142
                if ($data) {
2143
                    $newId = $data['iid'];
2144
                }
2145
                break;
2146
            case TOOL_DOCUMENT:
2147
                $sql = "SELECT * FROM c_document WHERE c_id = $courseId AND id = $ref";
2148
                $data = $connection->fetchAssoc($sql);
2149
                if ($data) {
2150
                    $newId = $data['iid'];
2151
                }
2152
                break;
2153
            case TOOL_FORUM:
2154
                $sql = "SELECT * FROM c_forum_forum WHERE c_id = $courseId AND forum_id = $ref";
2155
                $data = $connection->fetchAssoc($sql);
2156
                if ($data) {
2157
                    $newId = $data['iid'];
2158
                }
2159
                break;
2160
            case 'thread':
2161
                $sql = "SELECT * FROM c_forum_thread WHERE c_id = $courseId AND thread_id = $ref";
2162
                $data = $connection->fetchAssoc($sql);
2163
                if ($data) {
2164
                    $newId = $data['iid'];
2165
                }
2166
                break;
2167
        }
2168
2169
        if (!empty($sql) && !empty($newId) && !empty($iid)) {
2170
            $sql = "UPDATE c_lp_item SET ref = $newId WHERE iid = $iid";
2171
            $connection->executeQuery($sql);
2172
        }
2173
    }
2174
2175
    // Set NULL if session = 0
2176
    $sql = "UPDATE c_item_property SET session_id = NULL WHERE session_id = 0";
2177
    $connection->executeQuery($sql);
2178
2179
    // Set NULL if group = 0
2180
    $sql = "UPDATE c_item_property SET to_group_id = NULL WHERE to_group_id = 0";
2181
    $connection->executeQuery($sql);
2182
2183
    // Set NULL if insert_user_id = 0
2184
    $sql = "UPDATE c_item_property SET insert_user_id = NULL WHERE insert_user_id = 0";
2185
    $connection->executeQuery($sql);
2186
2187
    // Delete session data of sessions that don't exist.
2188
    $sql = "DELETE FROM c_item_property
2189
            WHERE session_id IS NOT NULL AND session_id NOT IN (SELECT id FROM session)";
2190
    $connection->executeQuery($sql);
2191
2192
    // Delete group data of groups that don't exist.
2193
    $sql = "DELETE FROM c_item_property
2194
            WHERE to_group_id <> 0 AND to_group_id IS NOT NULL AND to_group_id NOT IN (SELECT DISTINCT iid FROM c_group_info)";
2195
    $connection->executeQuery($sql);
2196
    // This updates the group_id with c_group_info.iid instead of c_group_info.id
2197
2198
    if ($debug) {
2199
        error_log('update iids');
2200
    }
2201
2202
    $groupTableToFix = [
2203
        'c_group_rel_user',
2204
        'c_group_rel_tutor',
2205
        'c_permission_group',
2206
        'c_role_group',
2207
        'c_survey_invitation',
2208
        'c_attendance_calendar_rel_group',
2209
    ];
2210
2211
    foreach ($groupTableToFix as $table) {
2212
        $sql = "SELECT * FROM $table";
2213
        $result = $connection->fetchAll($sql);
2214
        foreach ($result as $item) {
2215
            $iid = $item['iid'];
2216
            $courseId = $item['c_id'];
2217
            $groupId = intval($item['group_id']);
2218
2219
            // Fix group id
2220
            if (!empty($groupId)) {
2221
                $sql = "SELECT * FROM c_group_info
2222
                        WHERE c_id = $courseId AND id = $groupId
2223
                        LIMIT 1";
2224
                $data = $connection->fetchAssoc($sql);
2225
                if (!empty($data)) {
2226
                    $newGroupId = $data['iid'];
2227
                    $sql = "UPDATE $table SET group_id = $newGroupId
2228
                            WHERE iid = $iid";
2229
                    $connection->executeQuery($sql);
2230
                } else {
2231
                    // The group does not exists clean this record
2232
                    $sql = "DELETE FROM $table WHERE iid = $iid";
2233
                    $connection->executeQuery($sql);
2234
                }
2235
            }
2236
        }
2237
    }
2238
2239
    // Fix c_item_property
2240
    if ($debug) {
2241
        error_log('update c_item_property');
2242
    }
2243
2244
    $sql = "SELECT * FROM course";
2245
    $courseList = $connection->fetchAll($sql);
2246
    if ($debug) {
2247
        error_log('Getting course list');
2248
    }
2249
2250
    $totalCourse = count($courseList);
2251
    $counter = 0;
2252
2253
    foreach ($courseList as $courseData) {
2254
        $courseId = $courseData['id'];
2255
        if ($debug) {
2256
            error_log('Updating course: '.$courseData['code']);
2257
        }
2258
2259
        $sql = "SELECT * FROM c_item_property WHERE c_id = $courseId";
2260
        $result = $connection->fetchAll($sql);
2261
        foreach ($result as $item) {
2262
            $sessionId = intval($item['session_id']);
2263
            $groupId = intval($item['to_group_id']);
2264
            $iid = $item['iid'];
2265
            $ref = $item['ref'];
2266
2267
            // Fix group id
2268
            // Commented group id is already fixed in Version20150603181728.php
2269
            /*if (!empty($groupId)) {
2270
                $sql = "SELECT * FROM c_group_info
2271
                        WHERE c_id = $courseId AND id = $groupId";
2272
                $data = $connection->fetchAssoc($sql);
2273
                if (!empty($data)) {
2274
                    $newGroupId = $data['iid'];
2275
                    $sql = "UPDATE c_item_property SET to_group_id = $newGroupId
2276
                            WHERE iid = $iid";
2277
                    $connection->executeQuery($sql);
2278
                } else {
2279
                    // The group does not exists clean this record
2280
                    $sql = "DELETE FROM c_item_property WHERE iid = $iid";
2281
                    $connection->executeQuery($sql);
2282
                }
2283
            }*/
2284
2285
            $sql = '';
2286
            $newId = '';
2287
            switch ($item['tool']) {
2288
                case TOOL_LINK:
2289
                    $sql = "SELECT * FROM c_link WHERE c_id = $courseId AND id = $ref ";
2290
                    break;
2291
                case TOOL_STUDENTPUBLICATION:
2292
                    $sql = "SELECT * FROM c_student_publication WHERE c_id = $courseId AND id = $ref";
2293
                    break;
2294
                case TOOL_QUIZ:
2295
                    $sql = "SELECT * FROM c_quiz WHERE c_id = $courseId AND id = $ref";
2296
                    break;
2297
                case TOOL_DOCUMENT:
2298
                    $sql = "SELECT * FROM c_document WHERE c_id = $courseId AND id = $ref";
2299
                    break;
2300
                case TOOL_FORUM:
2301
                    $sql = "SELECT * FROM c_forum_forum WHERE c_id = $courseId AND id = $ref";
2302
                    break;
2303
                case 'thread':
2304
                    $sql = "SELECT * FROM c_forum_thread WHERE c_id = $courseId AND id = $ref";
2305
                    break;
2306
            }
2307
2308
            if (!empty($sql) && !empty($newId)) {
2309
                $data = $connection->fetchAssoc($sql);
2310
                if (isset($data['iid'])) {
2311
                    $newId = $data['iid'];
2312
                }
2313
                $sql = "UPDATE c_item_property SET ref = $newId WHERE iid = $iid";
2314
                error_log($sql);
2315
                $connection->executeQuery($sql);
2316
            }
2317
        }
2318
2319
        if ($debug) {
2320
            // Print a status in the log once in a while
2321
            error_log("Course process #$counter/$totalCourse");
2322
        }
2323
        $counter++;
2324
    }
2325
2326
    if ($debug) {
2327
        error_log('update gradebook_link');
2328
    }
2329
2330
    // Fix gradebook_link
2331
    $sql = "SELECT * FROM gradebook_link";
2332
    $result = $connection->fetchAll($sql);
2333
    foreach ($result as $item) {
2334
        $courseCode = $item['course_code'];
2335
        $categoryId = (int) $item['category_id'];
2336
2337
        $sql = "SELECT * FROM course WHERE code = '$courseCode'";
2338
        $courseInfo = $connection->fetchAssoc($sql);
2339
        if (empty($courseInfo)) {
2340
            continue;
2341
        }
2342
2343
        $courseId = $courseInfo['id'];
2344
2345
        $ref = $item['ref_id'];
2346
        $iid = $item['id'];
2347
2348
        $sql = '';
2349
        switch ($item['type']) {
2350
            case LINK_LEARNPATH:
2351
                $sql = "SELECT * FROM c_link WHERE c_id = $courseId AND id = $ref ";
2352
                break;
2353
            case LINK_STUDENTPUBLICATION:
2354
                $sql = "SELECT * FROM c_student_publication WHERE c_id = $courseId AND id = $ref";
2355
                break;
2356
            case LINK_EXERCISE:
2357
                $sql = "SELECT * FROM c_quiz WHERE c_id = $courseId AND id = $ref";
2358
                break;
2359
            case LINK_ATTENDANCE:
2360
                //$sql = "SELECT * FROM c_document WHERE c_id = $courseId AND id = $ref";
2361
                break;
2362
            case LINK_FORUM_THREAD:
2363
                $sql = "SELECT * FROM c_forum_thread WHERE c_id = $courseId AND thread_id = $ref";
2364
                break;
2365
        }
2366
2367
        if (!empty($sql)) {
2368
            $data = $connection->fetchAssoc($sql);
2369
            if (isset($data) && isset($data['iid'])) {
2370
                $newId = $data['iid'];
2371
                $sql = "UPDATE gradebook_link SET ref_id = $newId
2372
                        WHERE id = $iid AND course_code = '$courseCode' AND category_id = $categoryId ";
2373
                $connection->executeQuery($sql);
2374
            }
2375
        }
2376
    }
2377
2378
    if ($debug) {
2379
        error_log('update groups');
2380
    }
2381
2382
    $sql = 'SELECT * FROM groups';
2383
    $result = $connection->executeQuery($sql);
2384
    $groups = $result->fetchAll();
2385
    $oldGroups = [];
2386
    if (!empty($groups)) {
2387
        foreach ($groups as $group) {
2388
            if (empty($group['name'])) {
2389
                continue;
2390
            }
2391
2392
            $params = [
2393
                'name' => $group['name'],
2394
                'description' => $group['description'],
2395
                'group_type' => 1,
2396
                'picture' => $group['picture_uri'],
2397
                'url' => $group['url'],
2398
                'visibility' => $group['visibility'],
2399
                'updated_at' => $group['updated_on'],
2400
                'created_at' => $group['created_on'],
2401
            ];
2402
            $connection->insert('usergroup', $params);
2403
            $id = $connection->lastInsertId('id');
2404
            $oldGroups[$group['id']] = $id;
2405
        }
2406
    }
2407
2408
    if (!empty($oldGroups)) {
2409
        error_log('Moving group files');
2410
        foreach ($oldGroups as $oldId => $newId) {
2411
            $path = get_group_picture_path_by_id(
2412
                $oldId,
2413
                'system'
2414
            );
2415
2416
            if (!empty($path)) {
2417
                $newPath = str_replace(
2418
                    "groups/$oldId/",
2419
                    "groups/$newId/",
2420
                    $path['dir']
2421
                );
2422
                $command = "mv {$path['dir']} $newPath ";
2423
                error_log("Executing $command");
2424
                system($command);
2425
            }
2426
        }
2427
2428
        $sql = "SELECT * FROM group_rel_user";
2429
        $result = $connection->executeQuery($sql);
2430
        $dataList = $result->fetchAll();
2431
2432
        if (!empty($dataList)) {
2433
            foreach ($dataList as $data) {
2434
                if (isset($oldGroups[$data['group_id']])) {
2435
                    $data['group_id'] = $oldGroups[$data['group_id']];
2436
                    $userId = $data['user_id'];
2437
2438
                    $sql = "SELECT id FROM user WHERE user_id = $userId";
2439
                    $userResult = $connection->executeQuery($sql);
2440
                    $userInfo = $userResult->fetch();
2441
                    if (empty($userInfo)) {
2442
                        continue;
2443
                    }
2444
2445
                    $sql = "INSERT INTO usergroup_rel_user (usergroup_id, user_id, relation_type)
2446
                            VALUES ('{$data['group_id']}', '{$userId}', '{$data['relation_type']}')";
2447
                    $connection->executeQuery($sql);
2448
                }
2449
            }
2450
        }
2451
2452
        $sql = "SELECT * FROM group_rel_group";
2453
        $result = $connection->executeQuery($sql);
2454
        $dataList = $result->fetchAll();
2455
2456
        if (!empty($dataList)) {
2457
            foreach ($dataList as $data) {
2458
                if (isset($oldGroups[$data['group_id']]) && isset($oldGroups[$data['subgroup_id']])) {
2459
                    $data['group_id'] = $oldGroups[$data['group_id']];
2460
                    $data['subgroup_id'] = $oldGroups[$data['subgroup_id']];
2461
                    $sql = "INSERT INTO usergroup_rel_usergroup (group_id, subgroup_id, relation_type)
2462
                            VALUES ('{$data['group_id']}', '{$data['subgroup_id']}', '{$data['relation_type']}')";
2463
                    $connection->executeQuery($sql);
2464
                }
2465
            }
2466
        }
2467
2468
        $sql = "SELECT * FROM announcement_rel_group";
2469
        $result = $connection->executeQuery($sql);
2470
        $dataList = $result->fetchAll();
2471
2472
        if (!empty($dataList)) {
2473
            foreach ($dataList as $data) {
2474
                if (isset($oldGroups[$data['group_id']])) {
2475
                    // Deleting relation
2476
                    $sql = "DELETE FROM announcement_rel_group WHERE group_id = {$data['group_id']}";
2477
                    $connection->executeQuery($sql);
2478
2479
                    // Add new relation
2480
                    $data['group_id'] = $oldGroups[$data['group_id']];
2481
                    $sql = "INSERT INTO announcement_rel_group(group_id, announcement_id)
2482
                            VALUES ('{$data['group_id']}', '{$data['announcement_id']}')";
2483
                    $connection->executeQuery($sql);
2484
                }
2485
            }
2486
        }
2487
2488
        $sql = "SELECT * FROM group_rel_tag";
2489
        $result = $connection->executeQuery($sql);
2490
        $dataList = $result->fetchAll();
2491
        if (!empty($dataList)) {
2492
            foreach ($dataList as $data) {
2493
                if (isset($oldGroups[$data['group_id']])) {
2494
                    $data['group_id'] = $oldGroups[$data['group_id']];
2495
                    $sql = "INSERT INTO usergroup_rel_tag (tag_id, usergroup_id)
2496
                            VALUES ('{$data['tag_id']}', '{$data['group_id']}')";
2497
                    $connection->executeQuery($sql);
2498
                }
2499
            }
2500
        }
2501
    }
2502
2503
    if ($debug) {
2504
        error_log('update extra fields');
2505
    }
2506
2507
    // Extra fields
2508
    $extraFieldTables = [
2509
        ExtraField::USER_FIELD_TYPE => Database::get_main_table(TABLE_MAIN_USER_FIELD),
2510
        ExtraField::COURSE_FIELD_TYPE => Database::get_main_table(TABLE_MAIN_COURSE_FIELD),
2511
        //ExtraField::LP_FIELD_TYPE => Database::get_main_table(TABLE_MAIN_LP_FIELD),
2512
        ExtraField::SESSION_FIELD_TYPE => Database::get_main_table(TABLE_MAIN_SESSION_FIELD),
2513
        //ExtraField::CALENDAR_FIELD_TYPE => Database::get_main_table(TABLE_MAIN_CALENDAR_EVENT_FIELD),
2514
        //ExtraField::QUESTION_FIELD_TYPE => Database::get_main_table(TABLE_MAIN_CALENDAR_EVENT_FIELD),
2515
        //ExtraField::USER_FIELD_TYPE => //Database::get_main_table(TABLE_MAIN_SPECIFIC_FIELD),
2516
    ];
2517
2518
    foreach ($extraFieldTables as $type => $table) {
2519
        $sql = "SELECT * FROM $table ";
2520
        if ($debug) {
2521
            error_log($sql);
2522
        }
2523
        $result = $connection->query($sql);
2524
        $fields = $result->fetchAll();
2525
2526
        foreach ($fields as $field) {
2527
            if ($debug) {
2528
                error_log("Loading field: ".$field['field_variable']);
2529
            }
2530
            $originalId = $field['id'];
2531
2532
            $params = [
2533
                'extra_field_type' => $type,
2534
                'variable' => $field['field_variable'],
2535
                'field_type' => $field['field_type'],
2536
                'display_text' => $field['field_display_text'],
2537
                'default_value' => $field['field_default_value'],
2538
                'field_order' => $field['field_order'],
2539
                'visible' => $field['field_visible'],
2540
                'changeable' => $field['field_changeable'],
2541
                'filter' => $field['field_filter'],
2542
            ];
2543
2544
            $connection->insert('extra_field', $params);
2545
            $newExtraFieldId = $connection->lastInsertId();
2546
2547
            $values = [];
2548
            $handlerId = null;
2549
            switch ($type) {
2550
                case ExtraField::USER_FIELD_TYPE:
2551
                    $optionTable = Database::get_main_table(
2552
                        TABLE_MAIN_USER_FIELD_OPTIONS
2553
                    );
2554
                    $valueTable = Database::get_main_table(
2555
                        TABLE_MAIN_USER_FIELD_VALUES
2556
                    );
2557
                    $handlerId = 'user_id';
2558
                    break;
2559
                case ExtraField::COURSE_FIELD_TYPE:
2560
                    $optionTable = Database::get_main_table(
2561
                        TABLE_MAIN_COURSE_FIELD_OPTIONS
2562
                    );
2563
                    $valueTable = Database::get_main_table(
2564
                        TABLE_MAIN_COURSE_FIELD_VALUES
2565
                    );
2566
                    $handlerId = 'c_id';
2567
                    break;
2568
                case ExtraField::SESSION_FIELD_TYPE:
2569
                    $optionTable = Database::get_main_table(
2570
                        TABLE_MAIN_SESSION_FIELD_OPTIONS
2571
                    );
2572
                    $valueTable = Database::get_main_table(
2573
                        TABLE_MAIN_SESSION_FIELD_VALUES
2574
                    );
2575
                    $handlerId = 'session_id';
2576
                    break;
2577
            }
2578
2579
            if (!empty($optionTable)) {
2580
                $sql = "SELECT * FROM $optionTable WHERE field_id = $originalId ";
2581
                $result = $connection->query($sql);
2582
                $options = $result->fetchAll();
2583
2584
                foreach ($options as $option) {
2585
                    $params = [
2586
                        'display_text' => $option['option_display_text'],
2587
                        'field_id' => $newExtraFieldId,
2588
                        'option_order' => $option['option_order'],
2589
                        'option_value' => $option['option_value'],
2590
                    ];
2591
                    $connection->insert('extra_field_options', $params);
2592
                }
2593
2594
                $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...
2595
                $result = $connection->query($sql);
2596
                $values = $result->fetchAll();
2597
                if ($debug) {
2598
                    error_log("Fetch all values for field");
2599
                }
2600
            }
2601
2602
            if (!empty($values)) {
2603
                if ($debug) {
2604
                    error_log("Saving field value in new table");
2605
                }
2606
                $k = 0;
2607
                foreach ($values as $value) {
2608
                    if (isset($value[$handlerId])) {
2609
                        // Insert without the use of the entity as it reduces
2610
                        // speed to 2 records per second (much too slow)
2611
                        $params = [
2612
                            'field_id' => $newExtraFieldId,
2613
                            'value' => $value['field_value'],
2614
                            'item_id' => $value[$handlerId],
2615
                        ];
2616
                        $connection->insert('extra_field_values', $params);
2617
                        if ($debug && ($k % 10000 == 0)) {
2618
                            error_log("Saving field $k");
2619
                        }
2620
                        $k++;
2621
                    }
2622
                }
2623
            }
2624
        }
2625
    }
2626
2627
    if ($debug) {
0 ignored issues
show
introduced by
$debug is of type mixed, thus it always evaluated to true.
Loading history...
2628
        error_log('Remove index');
2629
    }
2630
2631
    // Drop temporary indexes added to increase speed of this function's queries
2632
    $sql = "ALTER TABLE c_document DROP INDEX tmpidx_doc";
2633
    $connection->executeQuery($sql);
2634
    $sql = "ALTER TABLE c_student_publication DROP INDEX tmpidx_stud";
2635
    $connection->executeQuery($sql);
2636
    $sql = "ALTER TABLE c_quiz DROP INDEX tmpidx_quiz";
2637
    $connection->executeQuery($sql);
2638
    $sql = "ALTER TABLE c_item_property DROP INDEX tmpidx_ip";
2639
    $connection->executeQuery($sql);
2640
2641
    if ($debug) {
2642
        error_log('Finish fixId function');
2643
    }
2644
2645
    fixLpId($connection, true);
2646
}
2647
2648
/**
2649
 * @param \Doctrine\DBAL\Connection $connection
2650
 * @param $debug
2651
 *
2652
 * @throws \Doctrine\DBAL\DBALException
2653
 */
2654
function fixLpId($connection, $debug)
2655
{
2656
    if ($debug) {
2657
        error_log('Fix lp.id lp.iids');
2658
    }
2659
2660
    $sql = 'SELECT id, title, code FROM course';
2661
    $result = $connection->query($sql);
2662
    $courses = $result->fetchAll();
2663
2664
    $sql = 'SELECT id FROM session';
2665
    $result = $connection->query($sql);
2666
    $sessions = $result->fetchAll();
2667
2668
    $tblCLp = Database::get_course_table(TABLE_LP_MAIN);
2669
    $tblCLpItem = Database::get_course_table(TABLE_LP_ITEM);
2670
    $toolTable = Database::get_course_table(TABLE_TOOL_LIST);
2671
2672
    if (!empty($sessions)) {
2673
        $sessions = array_column($sessions, 'id');
2674
        $sessions[] = 0;
2675
    } else {
2676
        $sessions = [0];
2677
    }
2678
2679
    foreach ($courses as $course) {
2680
        $courseId = $course['id'];
2681
        $sql = "SELECT * FROM $tblCLp WHERE c_id = $courseId AND iid <> id ORDER by iid";
2682
        $result = $connection->query($sql);
2683
        if ($debug) {
2684
            error_log('-------------');
2685
            error_log("Entering Lps in course #$courseId");
2686
            error_log($sql);
2687
        }
2688
        $lpList = $result->fetchAll();
2689
        $myOnlyLpList = [];
2690
        if (!empty($lpList)) {
2691
            foreach ($lpList as $lpInfo) {
2692
                $oldId = $lpInfo['id'];
2693
                $sql = "SELECT * FROM $tblCLpItem WHERE c_id = $courseId AND lp_id = $oldId ORDER by iid";
2694
                $result = $connection->query($sql);
2695
                $items = $result->fetchAll();
2696
                $lpInfo['lp_list'] = $items;
2697
                $myOnlyLpList[] = $lpInfo;
2698
            }
2699
        }
2700
2701
        if (!empty($myOnlyLpList)) {
2702
            foreach ($myOnlyLpList as $lpInfo) {
2703
                $lpIid = $lpInfo['iid'];
2704
                $oldId = $lpInfo['id'];
2705
                $items = $lpInfo['lp_list'];
2706
2707
                if (empty($items)) {
2708
                    continue;
2709
                }
2710
                $itemList = [];
2711
                foreach ($items as $subItem) {
2712
                    $itemList[$subItem['id']] = $subItem['iid'];
2713
                }
2714
                $variablesToFix = [
2715
                    'parent_item_id',
2716
                    'next_item_id',
2717
                    'prerequisite',
2718
                    'previous_item_id',
2719
                ];
2720
2721
                foreach ($sessions as $sessionId) {
2722
                    $correctLink = "lp/lp_controller.php?action=view&lp_id=$lpIid&id_session=$sessionId";
2723
                    $link = "newscorm/lp_controller.php?action=view&lp_id=$oldId&id_session=$sessionId";
2724
                    $secondLink = "lp/lp_controller.php?action=view&lp_id=$oldId&id_session=$sessionId";
2725
                    $sql = "UPDATE $toolTable 
2726
                        SET link = '$correctLink'
2727
                        WHERE c_id = $courseId AND (link = '$link' OR link ='$secondLink')";
2728
                    $connection->query($sql);
2729
                }
2730
2731
                foreach ($items as $item) {
2732
                    $itemIid = $item['iid'];
2733
                    $itemId = $item['id'];
2734
                    foreach ($variablesToFix as $variable) {
2735
                        if (!empty($item[$variable]) && isset($itemList[$item[$variable]])) {
2736
                            $newId = $itemList[$item[$variable]];
2737
                            $sql = "UPDATE $tblCLpItem SET $variable = $newId 
2738
                                    WHERE iid = $itemIid AND c_id = $courseId AND lp_id = $oldId";
2739
                            $connection->query($sql);
2740
                        }
2741
                    }
2742
2743
                    if ($item['item_type'] == 'document' && !empty($item['path'])) {
2744
                        $oldDocumentId = $item['path'];
2745
                        $sql = "SELECT * FROM c_document WHERE c_id = $courseId AND id = $oldDocumentId";
2746
                        $result = $connection->query($sql);
2747
                        $document = $result->fetch();
2748
                        if (!empty($document)) {
2749
                            $newDocumentId = $document['iid'];
2750
                            if (!empty($newDocumentId)) {
2751
                                $sql = "UPDATE $tblCLpItem SET path = $newDocumentId 
2752
                                    WHERE iid = $itemIid AND c_id = $courseId";
2753
                                $connection->query($sql);
2754
                                if ($debug) {
2755
                                    //error_log("Fix document: ");
2756
                                    //error_log($sql);
2757
                                }
2758
                            }
2759
                        }
2760
                    }
2761
2762
                    // c_lp_view
2763
                    $sql = "UPDATE c_lp_view SET last_item = $itemIid 
2764
                            WHERE c_id = $courseId AND last_item = $itemId AND lp_id = $oldId";
2765
                    $connection->query($sql);
2766
2767
                    // c_lp_item_view
2768
                    $sql = "UPDATE c_lp_item_view SET lp_item_id = $itemIid 
2769
                            WHERE c_id = $courseId AND lp_item_id = $itemId";
2770
                    $connection->query($sql);
2771
2772
                    // Update track_exercises
2773
                    $sql = "UPDATE track_e_exercises SET orig_lp_item_id = $itemIid 
2774
                            WHERE c_id = $courseId AND orig_lp_id = $oldId AND orig_lp_item_id = $itemId";
2775
                    $connection->query($sql);
2776
2777
                    // c_forum_thread
2778
                    $sql = "UPDATE c_forum_thread SET lp_item_id = $itemIid 
2779
                            WHERE c_id = $courseId AND lp_item_id = $itemId";
2780
                    $connection->query($sql);
2781
2782
                    // orig_lp_item_view_id
2783
                    $sql = "SELECT * FROM c_lp_view
2784
                            WHERE c_id = $courseId AND lp_id = $oldId";
2785
                    $result = $connection->query($sql);
2786
                    $itemViewList = $result->fetchAll();
2787
                    if ($itemViewList) {
2788
                        foreach ($itemViewList as $itemView) {
2789
                            $userId = $itemView['user_id'];
2790
                            $oldItemViewId = $itemView['id'];
2791
                            $newItemView = $itemView['iid'];
2792
2793
                            if (empty($oldItemViewId)) {
2794
                                continue;
2795
                            }
2796
2797
                            $sql = "UPDATE track_e_exercises 
2798
                                SET orig_lp_item_view_id = $newItemView 
2799
                                WHERE 
2800
                                  c_id = $courseId AND 
2801
                                  orig_lp_id = $oldId AND 
2802
                                  orig_lp_item_id = $itemIid AND 
2803
                                  orig_lp_item_view_id = $oldItemViewId AND 
2804
                                  exe_user_id = $userId                                       
2805
                                  ";
2806
                            $connection->query($sql);
2807
2808
                            /*$sql = "UPDATE c_lp_item_view
2809
                                    SET lp_view_id = $newItemView
2810
                                    WHERE
2811
                                      lp_view_id = $oldItemViewId AND
2812
                                      c_id = $courseId
2813
                                  ";
2814
                            $connection->query($sql);*/
2815
                        }
2816
                    }
2817
2818
                    $sql = "UPDATE $tblCLpItem SET lp_id = $lpIid 
2819
                            WHERE c_id = $courseId AND lp_id = $oldId AND id = $itemId";
2820
                    $connection->query($sql);
2821
2822
                    $sql = "UPDATE $tblCLpItem SET id = iid 
2823
                            WHERE c_id = $courseId AND lp_id = $oldId AND id = $itemId";
2824
                    $connection->query($sql);
2825
                }
2826
2827
                $sql = "UPDATE c_lp_view SET lp_id = $lpIid WHERE c_id = $courseId AND lp_id = $oldId";
2828
                $connection->query($sql);
2829
2830
                $sql = "UPDATE c_forum_forum SET lp_id = $lpIid WHERE c_id = $courseId AND lp_id = $oldId";
2831
                $connection->query($sql);
2832
2833
                // Update track_exercises.
2834
                $sql = "UPDATE track_e_exercises SET orig_lp_id = $lpIid 
2835
                        WHERE c_id = $courseId AND orig_lp_id = $oldId";
2836
                $connection->query($sql);
2837
2838
                $sql = "UPDATE $tblCLp SET id = iid WHERE c_id = $courseId AND id = $oldId ";
2839
                $connection->query($sql);
2840
            }
2841
        }
2842
    }
2843
2844
    if ($debug) {
2845
        error_log('END Fix lp.id lp.iids');
2846
    }
2847
}
2848
2849
/**
2850
 * @param string $distFile
2851
 * @param string $envFile
2852
 * @param array  $params
2853
 */
2854
function updateEnvFile($distFile, $envFile, $params)
2855
{
2856
    $requirements = [
2857
        'DATABASE_HOST',
2858
        'DATABASE_PORT',
2859
        'DATABASE_NAME',
2860
        'DATABASE_USER',
2861
        'DATABASE_PASSWORD',
2862
        'APP_INSTALLED',
2863
        'APP_ENCRYPT_METHOD',
2864
        'APP_URL_APPEND',
2865
    ];
2866
2867
    foreach ($requirements as $requirement) {
2868
        if (!isset($params['{{'.$requirement.'}}'])) {
2869
            throw new \Exception("The parameter $requirement is needed in order to edit the .env.local file");
2870
        }
2871
    }
2872
2873
    $contents = file_get_contents($distFile);
2874
    $contents = str_replace(array_keys($params), array_values($params), $contents);
2875
    file_put_contents($envFile, $contents);
2876
}
2877
2878
/**
2879
 * @param SymfonyContainer $container
2880
 * @param EntityManager    $manager
2881
 */
2882
function installGroups($container, $manager)
2883
{
2884
    // Creating fos_group (groups and roles)
2885
    $groupManager = $container->get('fos_user.group_manager');
2886
    $groups = [
2887
        [
2888
            'code' => 'ADMIN',
2889
            'title' => 'Administrators',
2890
            'roles' => ['ROLE_ADMIN'],
2891
        ],
2892
        [
2893
            'code' => 'STUDENT',
2894
            'title' => 'Students',
2895
            'roles' => ['ROLE_STUDENT'],
2896
        ],
2897
        [
2898
            'code' => 'TEACHER',
2899
            'title' => 'Teachers',
2900
            'roles' => ['ROLE_TEACHER'],
2901
        ],
2902
        [
2903
            'code' => 'RRHH',
2904
            'title' => 'Human resources manager',
2905
            'roles' => ['ROLE_RRHH'],
2906
        ],
2907
        [
2908
            'code' => 'SESSION_MANAGER',
2909
            'title' => 'Session',
2910
            'roles' => ['ROLE_SESSION_MANAGER'],
2911
        ],
2912
        [
2913
            'code' => 'QUESTION_MANAGER',
2914
            'title' => 'Question manager',
2915
            'roles' => ['ROLE_QUESTION_MANAGER'],
2916
        ],
2917
        [
2918
            'code' => 'STUDENT_BOSS',
2919
            'title' => 'Student boss',
2920
            'roles' => ['ROLE_STUDENT_BOSS'],
2921
        ],
2922
        [
2923
            'code' => 'INVITEE',
2924
            'title' => 'Invitee',
2925
            'roles' => ['ROLE_INVITEE'],
2926
        ],
2927
    ];
2928
2929
    foreach ($groups as $groupData) {
2930
        $criteria = ['code' => $groupData['code']];
2931
        $groupExists = $groupManager->findGroupBy($criteria);
2932
        if (!$groupExists) {
2933
            $group = $groupManager->createGroup($groupData['title']);
2934
            $group->setCode($groupData['code']);
2935
            foreach ($groupData['roles'] as $role) {
2936
                $group->addRole($role);
2937
            }
2938
            $manager->persist($group);
2939
            $groupManager->updateGroup($group, true);
2940
        }
2941
    }
2942
}
2943
2944
/**
2945
 * @param SymfonyContainer $container
2946
 */
2947
function installPages($container)
2948
{
2949
    error_log('installPages');
2950
2951
    $siteManager = Container::getSiteManager();
2952
2953
    // Create site
2954
    /** @var Chamilo\PageBundle\Entity\Site $site */
2955
    $site = $siteManager->create();
2956
    $site->setHost('localhost');
2957
    $site->setEnabled(true);
2958
    $site->setName('localhost');
2959
    $site->setEnabledFrom(new \DateTime('now'));
2960
    $site->setEnabledTo(new \DateTime('+20 years'));
2961
    $site->setRelativePath('');
2962
    $site->setIsDefault(true);
2963
    $site->setLocale('en');
2964
    $siteManager->save($site);
2965
2966
    // Create home page
2967
    /** @var PageManager $pageManager */
2968
    $pageManager = $container->get('sonata.page.manager.page');
2969
    /** @var \Sonata\PageBundle\Model\Page $page */
2970
    $page = $pageManager->create();
2971
    $page->setSlug('homepage');
2972
    $page->setUrl('/');
2973
    $page->setName('homepage');
2974
    $page->setTitle('home');
2975
    $page->setEnabled(true);
2976
    $page->setDecorate(1);
2977
    $page->setRequestMethod('GET|POST|HEAD|DELETE|PUT');
2978
    $page->setTemplateCode('default');
2979
    $page->setRouteName('homepage');
2980
    //$page->setParent($this->getReference('page-homepage'));
2981
    $page->setSite($site);
2982
    $pageManager->save($page);
2983
2984
    // Create welcome page
2985
    $pageWelcome = $pageManager->create();
2986
    $pageWelcome->setSlug('welcome');
2987
    $pageWelcome->setUrl('/welcome');
2988
    $pageWelcome->setName('welcome');
2989
    $pageWelcome->setTitle('welcome');
2990
    $pageWelcome->setEnabled(true);
2991
    $pageWelcome->setDecorate(1);
2992
    $pageWelcome->setRequestMethod('GET');
2993
    $pageWelcome->setTemplateCode('default');
2994
    $pageWelcome->setRouteName('welcome');
2995
    $pageWelcome->setParent($page);
2996
    $pageWelcome->setSite($site);
2997
    $pageManager->save($pageWelcome);
2998
2999
    // Creating page blocks
3000
    $templateManager = $container->get('sonata.page.template_manager');
3001
    $template = $templateManager->get('default');
3002
    $templateContainers = $template->getContainers();
3003
3004
    $containers = [];
3005
    foreach ($templateContainers as $id => $area) {
3006
        $containers[$id] = [
3007
            'area' => $area,
3008
            'block' => false,
3009
        ];
3010
    }
3011
3012
    // Create blocks for this page
3013
    $blockInteractor = $container->get('sonata.page.block_interactor');
3014
    $parentBlock = null;
3015
    foreach ($containers as $id => $area) {
3016
        if (false === $area['block'] && $templateContainers[$id]['shared'] === false) {
3017
            $block = $blockInteractor->createNewContainer(
3018
                [
3019
                    'page' => $pageWelcome,
3020
                    'name' => $templateContainers[$id]['name'],
3021
                    'code' => $id,
3022
                ]
3023
            );
3024
3025
            if ($id === 'content' && $templateContainers[$id]['name'] == 'Main content') {
3026
                $parentBlock = $block;
3027
            }
3028
        }
3029
    }
3030
3031
    // Create block in main content
3032
    $block = $container->get('sonata.page.manager.block');
3033
    /** @var \Sonata\BlockBundle\Model\Block $myBlock */
3034
    $myBlock = $block->create();
3035
    $myBlock->setType('sonata.formatter.block.formatter');
3036
    $myBlock->setSetting('format', 'richhtml');
3037
    $myBlock->setSetting('content', '');
3038
    $myBlock->setSetting('rawContent', '');
3039
    $myBlock->setSetting('template', '@SonataFormatter/Block/block_formatter.html.twig');
3040
    $myBlock->setParent($parentBlock);
3041
    $pageWelcome->addBlocks($myBlock);
3042
    $pageManager->save($pageWelcome);
3043
}
3044
3045
/**
3046
 * @param SymfonyContainer $container
3047
 * @param EntityManager    $manager
3048
 * @param bool             $upgrade
3049
 */
3050
function installSchemas($container, $manager, $upgrade = false)
3051
{
3052
    error_log('installSchemas');
3053
    $settingsManager = Container::getSettingsManager();
3054
3055
    $accessUrl = $manager->getRepository('ChamiloCoreBundle:AccessUrl')->find(1);
3056
    if (!$accessUrl) {
3057
        // Creating AccessUrl
3058
        $accessUrl = new AccessUrl();
3059
        $accessUrl
3060
            ->setUrl('http://localhost/')
3061
            ->setDescription('')
3062
            ->setActive(1)
3063
        ;
3064
        $manager->persist($accessUrl);
3065
        $manager->flush();
3066
    }
3067
3068
    // Install course tools (table "tool")
3069
    $toolChain = $container->get('chamilo_course.tool_chain');
3070
    $toolChain->createTools($manager);
3071
3072
    if ($upgrade) {
3073
        $settingsManager->updateSchemas($accessUrl);
3074
    } else {
3075
        // Installing schemas (filling settings_current table)
3076
        $settingsManager->installSchemas($accessUrl);
3077
    }
3078
}
3079
3080
/**
3081
 * @param SymfonyContainer $container
3082
 */
3083
function upgradeWithContainer($container)
3084
{
3085
    Container::setContainer($container);
3086
    Container::setLegacyServices($container, false);
3087
    error_log('setLegacyServices');
3088
    $manager = Database::getManager();
3089
    installGroups($container, $manager);
3090
    error_log('installGroups');
3091
    installSchemas($container, $manager, true);
3092
    installPages($container);
3093
    fixMedia($container);
3094
}
3095
3096
function fixMedia($container)
3097
{
3098
    error_log('fix medias');
3099
    $pool = $container->get('sonata.media.pool');
3100
    $contextManager = $container->get('sonata.classification.manager.context');
3101
    $categoryManager = $container->get('sonata.media.manager.category');
3102
3103
    foreach ($pool->getContexts() as $context => $contextAttrs) {
3104
        /** @var ContextInterface $defaultContext */
3105
        $defaultContext = $contextManager->findOneBy([
3106
            'id' => $context,
3107
        ]);
3108
3109
        if (!$defaultContext) {
3110
            $defaultContext = $contextManager->create();
3111
            $defaultContext->setId($context);
3112
            $defaultContext->setName(ucfirst($context));
3113
            $defaultContext->setEnabled(true);
3114
3115
            $contextManager->save($defaultContext);
3116
        }
3117
3118
        $defaultCategory = $categoryManager->getRootCategory($defaultContext);
3119
3120
        if (!$defaultCategory) {
3121
            $defaultCategory = $categoryManager->create();
3122
            $defaultCategory->setContext($defaultContext);
3123
            $defaultCategory->setName(ucfirst($context));
3124
            $defaultCategory->setEnabled(true);
3125
            $defaultCategory->setPosition(0);
3126
3127
            $categoryManager->save($defaultCategory);
3128
        }
3129
    }
3130
}
3131
3132
/**
3133
 * After the schema was created (table creation), the function adds
3134
 * admin/platform information.
3135
 *
3136
 * @param \Psr\Container\ContainerInterface $container
3137
 * @param string                            $sysPath
3138
 * @param string                            $encryptPassForm
3139
 * @param string                            $passForm
3140
 * @param string                            $adminLastName
3141
 * @param string                            $adminFirstName
3142
 * @param string                            $loginForm
3143
 * @param string                            $emailForm
3144
 * @param string                            $adminPhoneForm
3145
 * @param string                            $languageForm
3146
 * @param string                            $institutionForm
3147
 * @param string                            $institutionUrlForm
3148
 * @param string                            $siteName
3149
 * @param string                            $allowSelfReg
3150
 * @param string                            $allowSelfRegProf
3151
 * @param string                            $installationProfile Installation profile, if any was provided
3152
 */
3153
function finishInstallationWithContainer(
3154
    $container,
3155
    $sysPath,
3156
    $encryptPassForm,
3157
    $passForm,
3158
    $adminLastName,
3159
    $adminFirstName,
3160
    $loginForm,
3161
    $emailForm,
3162
    $adminPhoneForm,
3163
    $languageForm,
3164
    $institutionForm,
3165
    $institutionUrlForm,
3166
    $siteName,
3167
    $allowSelfReg,
3168
    $allowSelfRegProf,
3169
    $installationProfile = ''
3170
) {
3171
    $sysPath = !empty($sysPath) ? $sysPath : api_get_path(SYS_PATH);
3172
    Container::setContainer($container);
3173
    Container::setLegacyServices($container, false);
3174
3175
    $manager = Database::getManager();
3176
    $connection = $manager->getConnection();
3177
    $sql = getVersionTable();
3178
    // Add version table
3179
    $connection->executeQuery($sql);
3180
3181
    // Add tickets defaults
3182
    $ticketProject = new TicketProject();
3183
    $ticketProject
3184
        ->setId(1)
3185
        ->setName('Ticket System')
3186
        ->setInsertUserId(1);
3187
3188
    $manager->persist($ticketProject);
3189
    $manager->flush();
3190
3191
    $categories = [
3192
        get_lang('TicketEnrollment') => get_lang('TicketsAboutEnrollment'),
3193
        get_lang('TicketGeneralInformation') => get_lang('TicketsAboutGeneralInformation'),
3194
        get_lang('TicketRequestAndPapework') => get_lang('TicketsAboutRequestAndPapework'),
3195
        get_lang('TicketAcademicIncidence') => get_lang('TicketsAboutAcademicIncidence'),
3196
        get_lang('TicketVirtualCampus') => get_lang('TicketsAboutVirtualCampus'),
3197
        get_lang('TicketOnlineEvaluation') => get_lang('TicketsAboutOnlineEvaluation'),
3198
    ];
3199
3200
    $i = 1;
3201
    foreach ($categories as $category => $description) {
3202
        // Online evaluation requires a course
3203
        $ticketCategory = new TicketCategory();
3204
        $ticketCategory
3205
            ->setId($i)
3206
            ->setName($category)
3207
            ->setDescription($description)
3208
            ->setProject($ticketProject)
3209
            ->setInsertUserId(1);
3210
3211
        $isRequired = $i == 6;
3212
        $ticketCategory->setCourseRequired($isRequired);
3213
3214
        $manager->persist($ticketCategory);
3215
        $manager->flush();
3216
3217
        $i++;
3218
    }
3219
3220
    // Default Priorities
3221
    $defaultPriorities = [
3222
        TicketManager::PRIORITY_NORMAL => get_lang('PriorityNormal'),
3223
        TicketManager::PRIORITY_HIGH => get_lang('PriorityHigh'),
3224
        TicketManager::PRIORITY_LOW => get_lang('PriorityLow'),
3225
    ];
3226
3227
    $i = 1;
3228
    foreach ($defaultPriorities as $code => $priority) {
3229
        $ticketPriority = new TicketPriority();
3230
        $ticketPriority
3231
            ->setId($i)
3232
            ->setName($priority)
3233
            ->setCode($code)
3234
            ->setInsertUserId(1);
3235
3236
        $manager->persist($ticketPriority);
3237
        $manager->flush();
3238
        $i++;
3239
    }
3240
3241
    $table = Database::get_main_table(TABLE_TICKET_STATUS);
3242
3243
    // Default status
3244
    $defaultStatus = [
3245
        TicketManager::STATUS_NEW => get_lang('StatusNew'),
3246
        TicketManager::STATUS_PENDING => get_lang('StatusPending'),
3247
        TicketManager::STATUS_UNCONFIRMED => get_lang('StatusUnconfirmed'),
3248
        TicketManager::STATUS_CLOSE => get_lang('StatusClose'),
3249
        TicketManager::STATUS_FORWARDED => get_lang('StatusForwarded'),
3250
    ];
3251
3252
    $i = 1;
3253
    foreach ($defaultStatus as $code => $status) {
3254
        $attributes = [
3255
            'id' => $i,
3256
            'code' => $code,
3257
            'name' => $status,
3258
        ];
3259
        Database::insert($table, $attributes);
3260
        $i++;
3261
    }
3262
3263
    installGroups($container, $manager);
3264
    installSchemas($container, $manager);
3265
    installPages($container);
3266
3267
    // Inserting default data
3268
    $data = file_get_contents($sysPath.'main/install/data.sql');
3269
    $result = $manager->getConnection()->prepare($data);
3270
    $result->execute();
3271
    $result->closeCursor();
3272
3273
    UserManager::setPasswordEncryption($encryptPassForm);
3274
3275
    // Create admin user.
3276
    @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

3276
    /** @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...
3277
        $adminFirstName,
3278
        $adminLastName,
3279
        1,
3280
        $emailForm,
3281
        $loginForm,
3282
        $passForm,
3283
        'ADMIN', //$official_code = '',
3284
        $languageForm,
3285
        $adminPhoneForm,
3286
        '', //$picture_uri = '',
3287
        PLATFORM_AUTH_SOURCE,
3288
        '', //$expirationDate,
3289
        1,
3290
        0,
3291
        null,
3292
        '',
3293
        false, //$send_mail = false,
3294
        true, //$isAdmin = false
3295
        '',
3296
        false,
3297
        '',
3298
        1
3299
    );
3300
3301
    // Create anonymous user.
3302
    @UserManager::create_user(
3303
        'Joe',
3304
        'Anonymous',
3305
        6,
3306
        'anonymous@localhost',
3307
        'anon',
3308
        'anon',
3309
        'anonymous', //$official_code = '',
3310
        $languageForm,
3311
        '',
3312
        '', //$picture_uri = '',
3313
        PLATFORM_AUTH_SOURCE,
3314
        '',
3315
        1,
3316
        0,
3317
        null,
3318
        '',
3319
        false, //$send_mail = false,
3320
        false, //$isAdmin = false
3321
        '',
3322
        false,
3323
        '',
3324
        1
3325
    );
3326
3327
    // Set default language
3328
    Database::update(
3329
        Database::get_main_table(TABLE_MAIN_LANGUAGE),
3330
        ['available' => 1],
3331
        ['dokeos_folder = ?' => $languageForm]
3332
    );
3333
3334
    // Install settings
3335
    installSettings(
3336
        $institutionForm,
3337
        $institutionUrlForm,
3338
        $siteName,
3339
        $emailForm,
3340
        $adminLastName,
3341
        $adminFirstName,
3342
        $languageForm,
3343
        $allowSelfReg,
3344
        $allowSelfRegProf,
3345
        $installationProfile
3346
    );
3347
3348
    lockSettings();
3349
    updateDirAndFilesPermissions();
3350
    fixMedia($container);
3351
3352
    // Set the latest version
3353
    /*$path = $sysPath.'app/Migrations/Schema/V111/';
3354
    $finder = new \Symfony\Component\Finder\Finder();
3355
    $files = $finder->files()->in($path);
3356
3357
    // Needed for chash
3358
    createVersionTable();
3359
3360
    foreach ($files as $version) {
3361
        $version = str_replace(['Version', '.php'], '', $version->getFilename());
3362
        $sql = "INSERT INTO version (version) VALUES ('$version')";
3363
        Database::query($sql);
3364
    }*/
3365
}
3366
3367
/**
3368
 * Creates 'version' table.
3369
 */
3370
function createVersionTable()
3371
{
3372
    $sql = getVersionTable();
3373
    Database::query($sql);
3374
}
3375
3376
/**
3377
 * Get version creation table query.
3378
 *
3379
 * @return string
3380
 */
3381
function getVersionTable()
3382
{
3383
    return 'CREATE TABLE IF NOT EXISTS version (id int unsigned NOT NULL AUTO_INCREMENT, version varchar(20), PRIMARY KEY(id), UNIQUE(version));';
3384
}
3385
3386
/**
3387
 * Update settings based on installation profile defined in a JSON file.
3388
 *
3389
 * @param string $installationProfile The name of the JSON file in main/install/profiles/ folder
3390
 *
3391
 * @return bool false on failure (no bad consequences anyway, just ignoring profile)
3392
 */
3393
function installProfileSettings($installationProfile = '')
3394
{
3395
    if (empty($installationProfile)) {
3396
        return false;
3397
    }
3398
    $jsonPath = api_get_path(SYS_PATH).'main/install/profiles/'.$installationProfile.'.json';
3399
    // Make sure the path to the profile is not hacked
3400
    if (!Security::check_abs_path($jsonPath, api_get_path(SYS_PATH).'main/install/profiles/')) {
3401
        return false;
3402
    }
3403
    if (!is_file($jsonPath)) {
3404
        return false;
3405
    }
3406
    if (!is_readable($jsonPath)) {
3407
        return false;
3408
    }
3409
    if (!function_exists('json_decode')) {
3410
        // The php-json extension is not available. Ignore profile.
3411
        return false;
3412
    }
3413
    $json = file_get_contents($jsonPath);
3414
    $params = json_decode($json);
3415
    if ($params === false or $params === null) {
3416
        return false;
3417
    }
3418
    $settings = $params->params;
3419
    if (!empty($params->parent)) {
3420
        installProfileSettings($params->parent);
3421
    }
3422
3423
    $tblSettings = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
3424
3425
    foreach ($settings as $id => $param) {
3426
        $conditions = ['variable = ? ' => $param->variable];
3427
3428
        if (!empty($param->subkey)) {
3429
            $conditions['AND subkey = ? '] = $param->subkey;
3430
        }
3431
3432
        Database::update(
3433
            $tblSettings,
3434
            ['selected_value' => $param->selected_value],
3435
            $conditions
3436
        );
3437
    }
3438
3439
    return true;
3440
}
3441
3442
/**
3443
 * Quick function to remove a directory with its subdirectories.
3444
 *
3445
 * @param $dir
3446
 */
3447
function rrmdir($dir)
3448
{
3449
    if (is_dir($dir)) {
3450
        $objects = scandir($dir);
3451
        foreach ($objects as $object) {
3452
            if ($object != "." && $object != "..") {
3453
                if (filetype($dir."/".$object) == "dir") {
3454
                    @rrmdir($dir."/".$object);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for rrmdir(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

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

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

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

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

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
Bug introduced by
Are you sure the usage of rrmdir($dir . '/' . $object) is correct as it seems to always return null.

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

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

}

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

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

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

Loading history...
3455
                } else {
3456
                    @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

3456
                    /** @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...
3457
                }
3458
            }
3459
        }
3460
        reset($objects);
0 ignored issues
show
Bug introduced by
It seems like $objects can also be of type false; however, parameter $array of reset() does only seem to accept array, 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

3460
        reset(/** @scrutinizer ignore-type */ $objects);
Loading history...
3461
        rmdir($dir);
3462
    }
3463
}
3464
3465
/**
3466
 * @param        $id
3467
 * @param string $type
3468
 * @param bool   $preview
3469
 * @param bool   $anonymous
3470
 *
3471
 * @throws \Doctrine\DBAL\DBALException
3472
 *
3473
 * @return array
3474
 */
3475
function get_group_picture_path_by_id($id, $type = 'web', $preview = false, $anonymous = false)
3476
{
3477
    switch ($type) {
3478
        case 'system': // Base: absolute system path.
3479
            $base = api_get_path(SYS_UPLOAD_PATH);
3480
            break;
3481
        case 'web': // Base: absolute web path.
3482
        default:
3483
            $base = api_get_path(WEB_UPLOAD_PATH);
3484
            break;
3485
    }
3486
3487
    $noPicturePath = ['dir' => $base.'img/', 'file' => 'unknown.jpg'];
3488
3489
    if (empty($id) || empty($type)) {
3490
        return $anonymous ? $noPicturePath : ['dir' => '', 'file' => ''];
3491
    }
3492
3493
    $id = intval($id);
3494
3495
    //$group_table = Database::get_main_table(TABLE_MAIN_GROUP);
3496
    $group_table = 'groups';
3497
    $sql = "SELECT picture_uri FROM $group_table WHERE id=".$id;
3498
    $res = Database::query($sql);
3499
3500
    if (!Database::num_rows($res)) {
3501
        return $anonymous ? $noPicturePath : ['dir' => '', 'file' => ''];
3502
    }
3503
3504
    $user = Database::fetch_array($res);
3505
    $picture_filename = trim($user['picture_uri']);
3506
3507
    if (api_get_setting('split_users_upload_directory') === 'true') {
3508
        if (!empty($picture_filename)) {
3509
            $dir = $base.'groups/'.substr($picture_filename, 0, 1).'/'.$id.'/';
3510
        } elseif ($preview) {
3511
            $dir = $base.'groups/'.substr((string) $id, 0, 1).'/'.$id.'/';
3512
        } else {
3513
            $dir = $base.'groups/'.$id.'/';
3514
        }
3515
    } else {
3516
        $dir = $base.'groups/'.$id.'/';
3517
    }
3518
3519
    if (empty($picture_filename) && $anonymous) {
3520
        return $noPicturePath;
3521
    }
3522
3523
    return ['dir' => $dir, 'file' => $picture_filename];
3524
}
3525
3526
/**
3527
 * Control the different steps of the migration through a big switch.
3528
 *
3529
 * @param string        $fromVersion
3530
 * @param EntityManager $manager
3531
 * @param bool          $processFiles
3532
 *
3533
 * @throws \Doctrine\DBAL\DBALException
3534
 *
3535
 * @return bool Always returns true except if the process is broken
3536
 */
3537
function migrateSwitch($fromVersion, $manager, $processFiles = true)
3538
{
3539
    error_log('Starting migration process from '.$fromVersion.' ('.date('Y-m-d H:i:s').')');
3540
3541
    echo '<a class="btn btn-secondary" href="javascript:void(0)" id="details_button">'.get_lang('Details').'</a><br />';
3542
    echo '<div id="details" style="display:none">';
3543
3544
    $connection = $manager->getConnection();
3545
3546
    $database = new Database();
3547
    $database->setManager($manager);
3548
3549
    switch ($fromVersion) {
3550
        case '1.9.0':
3551
        case '1.9.2':
3552
        case '1.9.4':
3553
        case '1.9.6':
3554
        case '1.9.6.1':
3555
        case '1.9.8':
3556
        case '1.9.8.1':
3557
        case '1.9.8.2':
3558
        case '1.9.10':
3559
        case '1.9.10.2':
3560
        case '1.9.10.4':
3561
        case '1.9.10.6':
3562
            $database = new Database();
3563
            $database->setManager($manager);
3564
3565
            // Fix type "enum" before running the migration with Doctrine
3566
            $connection->executeQuery("ALTER TABLE course_category MODIFY COLUMN auth_course_child VARCHAR(40) DEFAULT 'TRUE'");
3567
            $connection->executeQuery("ALTER TABLE course_category MODIFY COLUMN auth_cat_child VARCHAR(40) DEFAULT 'TRUE'");
3568
            $connection->executeQuery('ALTER TABLE c_quiz_answer MODIFY COLUMN hotspot_type varchar(40) default NULL');
3569
            $connection->executeQuery("ALTER TABLE c_tool MODIFY COLUMN target varchar(20) NOT NULL default '_self'");
3570
            $connection->executeQuery("ALTER TABLE c_link MODIFY COLUMN on_homepage char(10) NOT NULL default '0'");
3571
            $connection->executeQuery("ALTER TABLE c_blog_rating MODIFY COLUMN rating_type char(40) NOT NULL default 'post'");
3572
            $connection->executeQuery("ALTER TABLE c_survey MODIFY COLUMN anonymous char(10) NOT NULL default '0'");
3573
            $connection->executeQuery("ALTER TABLE c_document MODIFY COLUMN filetype char(10) NOT NULL default 'file'");
3574
            $connection->executeQuery("ALTER TABLE c_student_publication MODIFY COLUMN filetype char(10) NOT NULL default 'file'");
3575
3576
            // Migrate using the migration files located in:
3577
            // src/Chamilo/CoreBundle/Migrations/Schema/V110
3578
            $result = migrate(
3579
                110,
3580
                $manager
3581
            );
3582
3583
            if ($result) {
3584
                error_log('Migrations files were executed ('.date('Y-m-d H:i:s').')');
3585
                fixIds($manager);
3586
                error_log('fixIds finished ('.date('Y-m-d H:i:s').')');
3587
3588
                $connection->executeQuery("UPDATE settings_current SET selected_value = '1.10.0' WHERE variable = 'chamilo_database_version'");
3589
3590
                if ($processFiles) {
3591
                    $fromVersionShort = '1.9';
3592
                    include __DIR__.'/update-files-1.9.0-1.10.0.inc.php';
3593
                    // Only updates the configuration.inc.php with the new version
3594
                    include __DIR__.'/update-configuration.inc.php';
3595
                }
3596
3597
                error_log('Upgrade 1.10.x process concluded! ('.date('Y-m-d H:i:s').')');
3598
            } else {
3599
                error_log('There was an error during running migrations. Check error.log');
3600
                break;
3601
            }
3602
            // no break
3603
        case '1.10.0':
3604
        case '1.10.2':
3605
        case '1.10.4':
3606
        case '1.10.6':
3607
        case '1.10.8':
3608
            $database = new Database();
3609
            $database->setManager($manager);
3610
            // Migrate using the migration files located in:
3611
            // src/Chamilo/CoreBundle/Migrations/Schema/V111
3612
            $result = migrate(111, $manager);
3613
3614
            if ($result) {
3615
                error_log('Migrations files were executed ('.date('Y-m-d H:i:s').')');
3616
3617
                fixPostGroupIds($connection);
3618
3619
                $sql = "UPDATE settings_current SET selected_value = '1.11.0' WHERE variable = 'chamilo_database_version'";
3620
                $connection->executeQuery($sql);
3621
                if ($processFiles) {
3622
                    error_log('Update config files');
3623
                    $fromVersionShort = '1.10';
3624
                    include __DIR__.'/update-files-1.10.0-1.11.0.inc.php';
3625
                    // Only updates the configuration.inc.php with the new version
3626
                    include __DIR__.'/update-configuration.inc.php';
3627
                }
3628
                error_log('Upgrade 1.11.x process concluded!  ('.date('Y-m-d H:i:s').')');
3629
            } else {
3630
                error_log('There was an error during running migrations. Check error.log');
3631
            }
3632
            // no break
3633
        case '1.11.0':
3634
        case '1.11.1':
3635
        case '1.11.2':
3636
        case '1.11.4':
3637
        case '1.11.6':
3638
        case '1.11.8':
3639
        case '1.11.10':
3640
            $database = new Database();
3641
            $database->setManager($manager);
3642
            // Migrate using the migration files located in:
3643
            // src/Chamilo/CoreBundle/Migrations/Schema/V111
3644
            $result = migrate(200, $manager);
3645
3646
            if ($result) {
3647
                error_log('Migrations files were executed ('.date('Y-m-d H:i:s').')');
3648
                $sql = "UPDATE settings_current SET selected_value = '2.0.0' WHERE variable = 'chamilo_database_version'";
3649
                $connection->executeQuery($sql);
3650
                if ($processFiles) {
3651
                    error_log('Update config files');
3652
                    $fromVersionShort = '1.11';
3653
                    include __DIR__.'/update-files-1.11.0-2.0.0.inc.php';
3654
                    // Only updates the configuration.inc.php with the new version
3655
                    include __DIR__.'/update-configuration.inc.php';
3656
                }
3657
                error_log('Upgrade 2.0.0 process concluded!  ('.date('Y-m-d H:i:s').')');
3658
            } else {
3659
                error_log('There was an error during running migrations. Check error.log');
3660
            }
3661
            break;
3662
        default:
3663
            break;
3664
    }
3665
3666
    echo '</div>';
3667
3668
    return true;
3669
}
3670
3671
/**
3672
 * @param \Doctrine\DBAL\Connection $connection
3673
 *
3674
 * @throws \Doctrine\DBAL\DBALException
3675
 */
3676
function fixPostGroupIds($connection)
3677
{
3678
    $connection->executeQuery("ALTER TABLE course_category MODIFY COLUMN auth_course_child VARCHAR(40) DEFAULT 'TRUE'");
3679
    error_log('Fix c_student_publication.post_group_id');
3680
3681
    // Fix post_group_id
3682
    $sql = "SELECT * FROM c_student_publication 
3683
            WHERE (post_group_id <> 0 AND post_group_id is not null)";
3684
    $statement = $connection->executeQuery($sql);
3685
    $result = $statement->fetchAll();
3686
3687
    foreach ($result as $row) {
3688
        $groupId = $row['post_group_id'];
3689
        $courseId = $row['c_id'];
3690
        $workIid = $row['iid'];
3691
        $sql = "SELECT iid from c_group_info 
3692
                WHERE c_id = $courseId AND id = $groupId";
3693
        $statement = $connection->executeQuery($sql);
3694
        $count = $statement->rowCount();
3695
        if ($count > 0) {
3696
            $rowGroup = $statement->fetch();
3697
            $newGroupId = $rowGroup['iid'];
3698
            if ($newGroupId == $groupId) {
3699
                continue;
3700
            }
3701
            if ($newGroupId) {
3702
                $sql = "UPDATE c_student_publication 
3703
                        SET post_group_id = $newGroupId 
3704
                        WHERE 
3705
                            c_id = $courseId AND
3706
                            iid = $workIid
3707
                        ";
3708
                $connection->executeQuery($sql);
3709
            }
3710
        }
3711
    }
3712
3713
    error_log('End - Fix c_student_publication.post_group_id');
3714
3715
    // Delete c_student_publication from any session that doesn't exist anymore
3716
    $sql = "DELETE FROM c_student_publication 
3717
            WHERE session_id NOT IN (SELECT id FROM session) AND (session_id <> 0 AND session_id is not null)";
3718
    $connection->executeQuery($sql);
3719
3720
    error_log('Fix work documents');
3721
    // Fix work documents that don't have c_item_property value
3722
    $sql = "SELECT * FROM c_student_publication WHERE parent_id IS NOT NULL";
3723
    $statement = $connection->executeQuery($sql);
3724
    $result = $statement->fetchAll();
3725
    foreach ($result as $row) {
3726
        $groupId = $row['post_group_id'];
3727
        $courseId = $row['c_id'];
3728
        $sessionId = $row['session_id'];
3729
        $workId = $row['id'];
3730
        $sessionCondition = " session_id = $sessionId";
3731
        if (empty($sessionId)) {
3732
            $sessionCondition = ' (session_id = 0 OR session_id IS NULL) ';
3733
        }
3734
        $sql = "SELECT * FROM c_item_property
3735
                WHERE
3736
                    c_id = $courseId AND
3737
                    tool = 'work' AND
3738
                    ref = $workId AND
3739
                    $sessionCondition ";
3740
        $itemInfo = $connection->fetchAssoc($sql);
3741
        if (empty($itemInfo)) {
3742
            $params = [
3743
                'c_id' => $courseId,
3744
                'to_group_id' => $groupId,
3745
                //'to_user_id' => null,
3746
                'insert_user_id' => 1,
3747
                'session_id' => $sessionId,
3748
                'tool' => 'work',
3749
                'insert_date' => api_get_utc_datetime(),
3750
                'lastedit_date' => api_get_utc_datetime(),
3751
                'ref' => $workId,
3752
                'lastedit_type' => 'visible',
3753
                'lastedit_user_id' => 1,
3754
                'visibility' => 1,
3755
            ];
3756
            $connection->insert('c_item_property', $params);
3757
            $id = $connection->lastInsertId();
3758
            $sql = "UPDATE c_item_property SET id = iid WHERE iid = $id";
3759
            $connection->executeQuery($sql);
3760
        }
3761
    }
3762
    error_log('End - Fix work documents');
3763
}
3764