Completed
Push — master ( 792ce7...e487ad )
by Julito
21:06 queued 10s
created

migrateSwitch()   C

Complexity

Conditions 12
Paths 28

Size

Total Lines 51
Code Lines 36

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 12
eloc 36
c 0
b 0
f 0
nc 28
nop 3
dl 0
loc 51
rs 6.9666

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\BranchSync;
6
use Chamilo\CoreBundle\Entity\ExtraField;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, ExtraField. Consider defining an alias.

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

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

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

// Bar.php
namespace OtherDir;

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

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

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

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

// Bar.php
namespace OtherDir;

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

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

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

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

349
    fclose(/** @scrutinizer ignore-type */ $fp);
Loading history...
350
351
    return explode('<br />', nl2br($buffer));
352
}
353
354
/**
355
 * We assume this function is called from install scripts that reside inside the install folder.
356
 */
357
function set_file_folder_permissions()
358
{
359
    @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

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

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

763
    /** @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...
764
    @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

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

1010
            /** @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...
1011
        }
1012
1013
        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...
1014
            $error = true;
1015
        }
1016
1017
        $checked_writable = api_get_path(CONFIGURATION_PATH).'configuration.php';
1018
        if (file_exists($checked_writable) && !is_writable($checked_writable)) {
1019
            $notWritable[] = $checked_writable;
1020
            @chmod($checked_writable, $perm_file);
1021
        }
1022
1023
        // Second, if this fails, report an error
1024
        //--> The user would have to adjust the permissions manually
1025
        if (count($notWritable) > 0) {
1026
            $error = true; ?>
1027
            <div class="text-danger">
1028
                <h3 class="text-center"><?php echo get_lang('Warning !'); ?></h3>
1029
                <p>
1030
                    <?php printf(get_lang('Some files or folders don\'t have writing permission. To be able to install Chamilo you should first change their permissions (using CHMOD). Please read the %s installation guide %s'), '<a href="../../documentation/installation_guide.html" target="blank">', '</a>'); ?>
1031
                </p>
1032
            </div>
1033
            <?php
1034
            echo '<ul>';
1035
            foreach ($notWritable as $value) {
1036
                echo '<li class="text-danger">'.$value.'</li>';
1037
            }
1038
            echo '</ul>';
1039
        } elseif (file_exists(api_get_path(CONFIGURATION_PATH).'configuration.php')) {
1040
            // Check wether a Chamilo configuration file already exists.
1041
            echo '<div class="alert alert-warning"><h4><center>';
1042
            echo get_lang('Warning !ExistingLMSInstallationDetected');
1043
            echo '</center></h4></div>';
1044
        }
1045
1046
        $deprecated = [
1047
            api_get_path(SYS_CODE_PATH).'exercice/',
1048
            api_get_path(SYS_CODE_PATH).'newscorm/',
1049
            api_get_path(SYS_PLUGIN_PATH).'ticket/',
1050
            api_get_path(SYS_PLUGIN_PATH).'skype/',
1051
        ];
1052
        $deprecatedToRemove = [];
1053
        foreach ($deprecated as $deprecatedDirectory) {
1054
            if (!is_dir($deprecatedDirectory)) {
1055
                continue;
1056
            }
1057
            $deprecatedToRemove[] = $deprecatedDirectory;
1058
        }
1059
1060
        if (count($deprecatedToRemove) > 0) {
1061
            ?>
1062
            <p class="text-danger"><?php echo get_lang('Warning !ForDeprecatedDirectoriesForUpgrade'); ?></p>
1063
            <ul>
1064
                <?php foreach ($deprecatedToRemove as $deprecatedDirectory) {
1065
                ?>
1066
                    <li class="text-danger"><?php echo $deprecatedDirectory; ?></li>
1067
                <?php
1068
            } ?>
1069
            </ul>
1070
            <?php
1071
        }
1072
1073
        // And now display the choice buttons (go back or install)?>
1074
        <p align="center" style="padding-top:15px">
1075
            <button type="submit" name="step1" class="btn btn-default" onclick="javascript: window.location='index.php'; return false;" value="<?php echo get_lang('Previous'); ?>" >
1076
                <em class="fa fa-backward"> </em> <?php echo get_lang('Previous'); ?>
1077
            </button>
1078
            <button type="submit" name="step2_install" class="btn btn-success" value="<?php echo get_lang("New installation"); ?>" <?php if ($error) {
1079
            echo 'disabled="disabled"';
1080
        } ?> >
1081
                <em class="fa fa-forward"> </em> <?php echo get_lang('New installation'); ?>
1082
            </button>
1083
        <input type="hidden" name="is_executable" id="is_executable" value="-" />
1084
            <button type="submit" class="btn btn-default" <?php echo !$error ?: 'disabled="disabled"'; ?> name="step2_update_8" value="Upgrade from Chamilo 1.9.x">
1085
                <em class="fa fa-forward" aria-hidden="true"></em> <?php echo get_lang('Upgrade Chamilo LMS version'); ?>
1086
            </button>
1087
            </p>
1088
        <?php
1089
    }
1090
}
1091
1092
/**
1093
 * Displays the license (GNU GPL) as step 2, with
1094
 * - an "I accept" button named step3 to proceed to step 3;
1095
 * - a "Back" button named step1 to go back to the first step.
1096
 */
1097
function display_license_agreement()
1098
{
1099
    echo '<div class="RequirementHeading"><h2>'.display_step_sequence().get_lang('Licence').'</h2>';
1100
    echo '<p>'.get_lang('Chamilo is free software distributed under the GNU General Public licence (GPL).').'</p>';
1101
    echo '<p><a href="../../documentation/license.html" target="_blank">'.get_lang('Printable version').'</a></p>';
1102
    echo '</div>'; ?>
1103
    <div class="form-group">
1104
        <pre style="overflow: auto; height: 200px; margin-top: 5px;">
1105
            <?php echo api_htmlentities(@file_get_contents(api_get_path(SYMFONY_SYS_PATH).'documentation/license.txt')); ?>
1106
        </pre>
1107
    </div>
1108
    <div class="form-group form-check">
1109
        <input type="checkbox" name="accept" id="accept_licence" value="1">
1110
        <label for="accept_licence"><?php echo get_lang('I Accept'); ?></label>
1111
    </div>
1112
    <div class="row">
1113
        <div class="col-md-12">
1114
            <p class="alert alert-info"><?php echo get_lang('The images and media galleries of Chamilo use images from Nuvola, Crystal Clear and Tango icon galleries. Other images and media like diagrams and Flash animations are borrowed from Wikimedia and Ali Pakdel\'s and Denis Hoa\'s courses with their agreement and released under BY-SA Creative Commons license. You may find the license details at <a href="http://creativecommons.org/licenses/by-sa/3.0/">the CC website</a>, where a link to the full text of the license is provided at the bottom of the page.'); ?></p>
1115
        </div>
1116
    </div>
1117
1118
    <!-- Contact information form -->
1119
    <div class="section-parameters">
1120
        <a href="javascript://" class = "advanced_parameters" >
1121
        <span id="img_plus_and_minus">&nbsp;<i class="fa fa-eye" aria-hidden="true"></i>&nbsp;<?php echo get_lang('Contact information'); ?></span>
1122
        </a>
1123
    </div>
1124
1125
    <div id="id_contact_form" style="display:block">
1126
        <div class="normal-message"><?php echo get_lang('Contact informationDescription'); ?></div>
1127
        <div id="contact_registration">
1128
            <p><?php echo get_contact_registration_form(); ?></p><br />
1129
        </div>
1130
    </div>
1131
    <div class="text-center">
1132
    <button type="submit" class="btn btn-default" name="step1" value="&lt; <?php echo get_lang('Previous'); ?>" >
1133
        <em class="fa fa-backward"> </em> <?php echo get_lang('Previous'); ?>
1134
    </button>
1135
    <input type="hidden" name="is_executable" id="is_executable" value="-" />
1136
    <button type="submit" id="license-next" class="btn btn-success" name="step3" onclick="javascript: if(!document.getElementById('accept_licence').checked) { alert('<?php echo get_lang('You must accept the licence'); ?>');return false;}" value="<?php echo get_lang('Next'); ?> &gt;" >
1137
        <em class="fa fa-forward"> </em> <?php echo get_lang('Next'); ?>
1138
    </button>
1139
    </div>
1140
    <?php
1141
}
1142
1143
/**
1144
 * Get contact registration form.
1145
 */
1146
function get_contact_registration_form()
1147
{
1148
    $html = '
1149
   <div class="form-horizontal">
1150
    <div class="panel panel-default">
1151
    <div class="panel-body">
1152
    <div id="div_sent_information"></div>
1153
    <div class="form-group row">
1154
            <label class="col-sm-3"><span class="form_required">*</span>'.get_lang('Name').'</label>
1155
            <div class="col-sm-9"><input id="person_name" class="form-control" type="text" name="person_name" size="30" /></div>
1156
    </div>
1157
    <div class="form-group row">
1158
            <label class="col-sm-3"><span class="form_required">*</span>'.get_lang('e-mail').'</label>
1159
            <div class="col-sm-9"><input id="person_email" class="form-control" type="text" name="person_email" size="30" /></div>
1160
    </div>
1161
    <div class="form-group row">
1162
            <label class="col-sm-3"><span class="form_required">*</span>'.get_lang('Your company\'s name').'</label>
1163
            <div class="col-sm-9"><input id="company_name" class="form-control" type="text" name="company_name" size="30" /></div>
1164
    </div>
1165
    <div class="form-group row">
1166
        <label class="col-sm-3"><span class="form_required">*</span>'.get_lang('Your company\'s activity').'</label>
1167
        <div class="col-sm-9">
1168
            <select class="selectpicker show-tick" name="company_activity" id="company_activity" >
1169
                <option value="">--- '.get_lang('Select one').' ---</option>
1170
                <Option value="Advertising/Marketing/PR">Advertising/Marketing/PR</Option><Option value="Agriculture/Forestry">Agriculture/Forestry</Option>
1171
                <Option value="Architecture">Architecture</Option><Option value="Banking/Finance">Banking/Finance</Option>
1172
                <Option value="Biotech/Pharmaceuticals">Biotech/Pharmaceuticals</Option><Option value="Business Equipment">Business Equipment</Option>
1173
                <Option value="Business Services">Business Services</Option><Option value="Construction">Construction</Option>
1174
                <Option value="Consulting/Research">Consulting/Research</Option><Option value="Education">Education</Option>
1175
                <Option value="Engineering">Engineering</Option><Option value="Environmental">Environmental</Option>
1176
                <Option value="Government">Government</Option><Option value="Healthcare">Health Care</Option>
1177
                <Option value="Hospitality/Lodging/Travel">Hospitality/Lodging/Travel</Option><Option value="Insurance">Insurance</Option>
1178
                <Option value="Legal">Legal</Option><Option value="Manufacturing">Manufacturing</Option>
1179
                <Option value="Media/Entertainment">Media/Entertainment</Option><Option value="Mortgage">Mortgage</Option>
1180
                <Option value="Non-Profit">Non-Profit</Option><Option value="Real Estate">Real Estate</Option>
1181
                <Option value="Restaurant">Restaurant</Option><Option value="Retail">Retail</Option>
1182
                <Option value="Shipping/Transportation">Shipping/Transportation</Option>
1183
                <Option value="Technology">Technology</Option><Option value="Telecommunications">Telecommunications</Option>
1184
                <Option value="Other">Other</Option>
1185
            </select>
1186
        </div>
1187
    </div>
1188
1189
    <div class="form-group row">
1190
        <label class="col-sm-3"><span class="form_required">*</span>'.get_lang('Your job\'s description').'</label>
1191
        <div class="col-sm-9">
1192
            <select class="selectpicker show-tick" name="person_role" id="person_role" >
1193
                <option value="">--- '.get_lang('Select one').' ---</option>
1194
                <Option value="Administration">Administration</Option><Option value="CEO/President/ Owner">CEO/President/ Owner</Option>
1195
                <Option value="CFO">CFO</Option><Option value="CIO/CTO">CIO/CTO</Option>
1196
                <Option value="Consultant">Consultant</Option><Option value="Customer Service">Customer Service</Option>
1197
                <Option value="Engineer/Programmer">Engineer/Programmer</Option><Option value="Facilities/Operations">Facilities/Operations</Option>
1198
                <Option value="Finance/ Accounting Manager">Finance/ Accounting Manager</Option><Option value="Finance/ Accounting Staff">Finance/ Accounting Staff</Option>
1199
                <Option value="General Manager">General Manager</Option><Option value="Human Resources">Human Resources</Option>
1200
                <Option value="IS/IT Management">IS/IT Management</Option><Option value="IS/ IT Staff">IS/ IT Staff</Option>
1201
                <Option value="Marketing Manager">Marketing Manager</Option><Option value="Marketing Staff">Marketing Staff</Option>
1202
                <Option value="Partner/Principal">Partner/Principal</Option><Option value="Purchasing Manager">Purchasing Manager</Option>
1203
                <Option value="Sales/ Business Dev. Manager">Sales/ Business Dev. Manager</Option><Option value="Sales/ Business Dev.">Sales/ Business Dev.</Option>
1204
                <Option value="Vice President/Senior Manager">Vice President/Senior Manager</Option><Option value="Other">Other</Option>
1205
            </select>
1206
        </div>
1207
    </div>
1208
1209
    <div class="form-group row">
1210
        <label class="col-sm-3"><span class="form_required">*</span>'.get_lang('Your company\'s home country').'</label>
1211
        <div class="col-sm-9">'.get_countries_list_from_array(true).'</div>
1212
    </div>
1213
    <div class="form-group row">
1214
        <label class="col-sm-3">'.get_lang('Company city').'</label>
1215
        <div class="col-sm-9">
1216
                <input type="text" class="form-control" id="company_city" name="company_city" size="30" />
1217
        </div>
1218
    </div>
1219
    <div class="form-group row">
1220
        <label class="col-sm-3">'.get_lang('Preferred contact language').'</label>
1221
        <div class="col-sm-9">
1222
            <select class="selectpicker show-tick" id="language" name="language">
1223
                <option value="bulgarian">Bulgarian</option>
1224
                <option value="indonesian">Bahasa Indonesia</option>
1225
                <option value="bosnian">Bosanski</option>
1226
                <option value="german">Deutsch</option>
1227
                <option selected="selected" value="english">English</option>
1228
                <option value="spanish">Spanish</option>
1229
                <option value="french">Français</option>
1230
                <option value="italian">Italian</option>
1231
                <option value="hungarian">Magyar</option>
1232
                <option value="dutch">Nederlands</option>
1233
                <option value="brazilian">Português do Brasil</option>
1234
                <option value="portuguese">Português europeu</option>
1235
                <option value="slovenian">Slovenčina</option>
1236
            </select>
1237
        </div>
1238
    </div>
1239
1240
    <div class="form-group row">
1241
        <label class="col-sm-3">'.get_lang('Do you have the power to take financial decisions on behalf of your company?').'</label>
1242
        <div class="col-sm-9">
1243
            <div class="radio">
1244
                <label>
1245
                    <input type="radio" name="financial_decision" id="financial_decision1" value="1" checked /> '.get_lang('Yes').'
1246
                </label>
1247
            </div>
1248
            <div class="radio">
1249
                <label>
1250
                    <input type="radio" name="financial_decision" id="financial_decision2" value="0" /> '.get_lang('No').'
1251
                </label>
1252
            </div>
1253
        </div>
1254
    </div>
1255
    <div class="clear"></div>
1256
    <div class="form-group row">
1257
            <div class="col-sm-3">&nbsp;</div>
1258
            <div class="col-sm-9"><button type="button" class="btn btn-default" onclick="javascript:send_contact_information();" value="'.get_lang('Send information').'" ><em class="fa fa-floppy-o"></em> '.get_lang('Send information').'</button> <span id="loader-button"></span></div>
1259
    </div>
1260
    <div class="form-group row">
1261
            <div class="col-sm-3">&nbsp;</div>
1262
            <div class="col-sm-9"><span class="form_required">*</span><small>'.get_lang('Mandatory field').'</small></div>
1263
    </div></div></div>
1264
    </div>';
1265
1266
    return $html;
1267
}
1268
1269
/**
1270
 * Displays a parameter in a table row.
1271
 * Used by the display_database_settings_form function.
1272
 *
1273
 * @param   string  Type of install
1274
 * @param   string  Name of parameter
1275
 * @param   string  Field name (in the HTML form)
1276
 * @param   string  Field value
1277
 * @param   string  Extra notice (to show on the right side)
1278
 * @param   bool Whether to display in update mode
1279
 * @param   string  Additional attribute for the <tr> element
1280
 */
1281
function displayDatabaseParameter(
1282
    $installType,
1283
    $parameterName,
1284
    $formFieldName,
1285
    $parameterValue,
1286
    $extra_notice,
1287
    $displayWhenUpdate = true,
1288
    $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

1288
    /** @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...
1289
) {
1290
    //echo "<tr ".$tr_attribute.">";
1291
    echo "<label class='col-sm-4'>$parameterName</label>";
1292
1293
    if ($installType == INSTALL_TYPE_UPDATE && $displayWhenUpdate) {
1294
        echo '<input type="hidden" name="'.$formFieldName.'" id="'.$formFieldName.'" value="'.api_htmlentities($parameterValue).'" />'.$parameterValue;
1295
    } else {
1296
        $inputType = $formFieldName == 'dbPassForm' ? 'password' : 'text';
1297
1298
        //Slightly limit the length of the database prefix to avoid having to cut down the databases names later on
1299
        $maxLength = $formFieldName == 'dbPrefixForm' ? '15' : MAX_FORM_FIELD_LENGTH;
1300
        if ($installType == INSTALL_TYPE_UPDATE) {
1301
            echo '<input type="hidden" name="'.$formFieldName.'" id="'.$formFieldName.'" value="'.api_htmlentities($parameterValue).'" />';
1302
            echo api_htmlentities($parameterValue);
1303
        } else {
1304
            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>";
1305
            echo '<div class="col-sm-3">'.$extra_notice.'</div>';
1306
        }
1307
    }
1308
}
1309
1310
/**
1311
 * Displays step 3 - a form where the user can enter the installation settings
1312
 * regarding the databases - login and password, names, prefixes, single
1313
 * or multiple databases, tracking or not...
1314
 *
1315
 * @param string $installType
1316
 * @param string $dbHostForm
1317
 * @param string $dbUsernameForm
1318
 * @param string $dbPassForm
1319
 * @param string $dbNameForm
1320
 * @param int    $dbPortForm
1321
 * @param string $installationProfile
1322
 */
1323
function display_database_settings_form(
1324
    $installType,
1325
    $dbHostForm,
1326
    $dbUsernameForm,
1327
    $dbPassForm,
1328
    $dbNameForm,
1329
    $dbPortForm = 3306,
1330
    $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

1330
    /** @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...
1331
) {
1332
    if ($installType == 'update') {
1333
        global $_configuration;
1334
        $dbHostForm = $_configuration['db_host'];
1335
        $dbUsernameForm = $_configuration['db_user'];
1336
        $dbPassForm = $_configuration['db_password'];
1337
        $dbNameForm = $_configuration['main_database'];
1338
        $dbPortForm = isset($_configuration['db_port']) ? $_configuration['db_port'] : '';
1339
1340
        echo '<div class="RequirementHeading"><h2>'.display_step_sequence().get_lang('Database settings').'</h2></div>';
1341
        echo '<div class="RequirementContent">';
1342
        echo get_lang('The upgrade script will recover and update the Chamilo database(s). In order to do this, this script will use the databases and settings defined below. Because our software runs on a wide range of systems and because all of them might not have been tested, we strongly recommend you do a full backup of your databases before you proceed with the upgrade!');
1343
        echo '</div>';
1344
    } else {
1345
        echo '<div class="RequirementHeading"><h2>'.display_step_sequence().get_lang('Database settings').'</h2></div>';
1346
        echo '<div class="RequirementContent">';
1347
        echo get_lang('The install script will create (or use) the Chamilo database using the database name given here. Please make sure the user you give has the right to create the database by the name given here. If a database with this name exists, it will be overwritten. Please do not use the root user as the Chamilo database user. This can lead to serious security issues.');
1348
        echo '</div>';
1349
    } ?>
1350
    <div class="panel panel-default">
1351
        <div class="panel-body">
1352
        <div class="form-group row">
1353
            <label class="col-sm-4"><?php echo get_lang('Database Host'); ?> </label>
1354
            <?php if ($installType == 'update') {
1355
        ?>
1356
            <div class="col-sm-5">
1357
                <input type="hidden" name="dbHostForm" value="<?php echo htmlentities($dbHostForm); ?>" /><?php echo $dbHostForm; ?>
1358
            </div>
1359
            <div class="col-sm-3"></div>
1360
            <?php
1361
    } else {
1362
        ?>
1363
            <div class="col-sm-5">
1364
                <input type="text" class="form-control" size="25" maxlength="50" name="dbHostForm" value="<?php echo htmlentities($dbHostForm); ?>" />
1365
            </div>
1366
            <div class="col-sm-3"><?php echo get_lang('ex.').' localhost'; ?></div>
1367
            <?php
1368
    } ?>
1369
        </div>
1370
        <div class="form-group row">
1371
            <label class="col-sm-4"><?php echo get_lang('Port'); ?> </label>
1372
            <?php if ($installType == 'update') {
1373
        ?>
1374
            <div class="col-sm-5">
1375
                <input type="hidden" name="dbPortForm" value="<?php echo htmlentities($dbPortForm); ?>" /><?php echo $dbPortForm; ?>
1376
            </div>
1377
            <div class="col-sm-3"></div>
1378
            <?php
1379
    } else {
1380
        ?>
1381
            <div class="col-sm-5">
1382
                <input type="text" class="form-control" size="25" maxlength="50" name="dbPortForm" value="<?php echo htmlentities($dbPortForm); ?>" />
1383
            </div>
1384
            <div class="col-sm-3"><?php echo get_lang('ex.').' 3306'; ?></div>
1385
            <?php
1386
    } ?>
1387
        </div>
1388
        <div class="form-group row">
1389
            <?php
1390
                //database user username
1391
                $example_login = get_lang('ex.').' root';
1392
    displayDatabaseParameter($installType, get_lang('Database Login'), 'dbUsernameForm', $dbUsernameForm, $example_login); ?>
1393
        </div>
1394
        <div class="form-group row">
1395
            <?php
1396
            //database user password
1397
            $example_password = get_lang('ex.').' '.api_generate_password();
1398
    displayDatabaseParameter($installType, get_lang('Database Password'), 'dbPassForm', $dbPassForm, $example_password); ?>
1399
        </div>
1400
        <div class="form-group row">
1401
            <?php
1402
            //Database Name fix replace weird chars
1403
            if ($installType != INSTALL_TYPE_UPDATE) {
1404
                $dbNameForm = str_replace(['-', '*', '$', ' ', '.'], '', $dbNameForm);
1405
            }
1406
1407
    displayDatabaseParameter(
1408
                $installType,
1409
                get_lang('Main Chamilo database (DB)'),
1410
                'dbNameForm',
1411
                $dbNameForm,
1412
                '&nbsp;',
1413
                null,
1414
                'id="optional_param1"'
1415
                ); ?>
1416
        </div>
1417
       <?php if ($installType != INSTALL_TYPE_UPDATE) {
1418
                    ?>
1419
        <div class="form-group row">
1420
            <div class="col-sm-4"></div>
1421
            <div class="col-sm-8">
1422
            <button type="submit" class="btn btn-primary" name="step3" value="step3">
1423
                <em class="fa fa-refresh"> </em>
1424
                <?php echo get_lang('Check database connection'); ?>
1425
            </button>
1426
            </div>
1427
        </div>
1428
        <?php
1429
                } ?>
1430
1431
        </div>
1432
    </div>
1433
    <?php
1434
        $database_exists_text = '';
1435
    $manager = null;
1436
    try {
1437
        if ($installType === 'update') {
1438
            /** @var \Database $manager */
1439
            $manager = connectToDatabase(
1440
                $dbHostForm,
1441
                $dbUsernameForm,
1442
                $dbPassForm,
1443
                $dbNameForm,
1444
                $dbPortForm
1445
            );
1446
1447
            $connection = $manager->getConnection();
1448
            $connection->connect();
1449
            $schemaManager = $connection->getSchemaManager();
1450
1451
            // Test create/alter/drop table
1452
            $table = 'zXxTESTxX_'.mt_rand(0, 1000);
1453
            $sql = "CREATE TABLE $table (id INT AUTO_INCREMENT NOT NULL, name varchar(255), PRIMARY KEY(id))";
1454
            $connection->query($sql);
1455
            $tableCreationWorks = false;
1456
            $tableDropWorks = false;
1457
            if ($schemaManager->tablesExist($table)) {
1458
                $tableCreationWorks = true;
1459
                $sql = "ALTER TABLE $table ADD COLUMN name2 varchar(140) ";
1460
                $connection->query($sql);
1461
                $schemaManager->dropTable($table);
1462
                $tableDropWorks = $schemaManager->tablesExist($table) === false;
1463
            }
1464
        } else {
1465
            $manager = connectToDatabase(
1466
                $dbHostForm,
1467
                $dbUsernameForm,
1468
                $dbPassForm,
1469
                null,
1470
                $dbPortForm
1471
            );
1472
1473
            $schemaManager = $manager->getConnection()->getSchemaManager();
1474
            $databases = $schemaManager->listDatabases();
1475
            if (in_array($dbNameForm, $databases)) {
1476
                $database_exists_text = '<div class="alert alert-warning">'.get_lang('A database with the same name <b>already exists</b>.').'</div>';
1477
            }
1478
        }
1479
    } catch (Exception $e) {
1480
        $database_exists_text = $e->getMessage();
1481
        $manager = false;
1482
    }
1483
1484
    if ($manager && $manager->getConnection()->isConnected()): ?>
1485
        <?php echo $database_exists_text; ?>
1486
        <div id="db_status" class="alert alert-success">
1487
            Database host: <strong><?php echo $manager->getConnection()->getHost(); ?></strong><br/>
1488
            Database port: <strong><?php echo $manager->getConnection()->getPort(); ?></strong><br/>
1489
            Database driver: <strong><?php echo $manager->getConnection()->getDriver()->getName(); ?></strong><br/>
1490
            <?php
1491
                if ($installType === 'update') {
1492
                    echo get_lang('CreateTableWorks').' <strong>Ok</strong>';
1493
                    echo '<br/ >';
1494
                    echo get_lang('AlterTableWorks').' <strong>Ok</strong>';
1495
                    echo '<br/ >';
1496
                    echo get_lang('DropColumnWorks').' <strong>Ok</strong>';
1497
                } ?>
1498
        </div>
1499
    <?php else: ?>
1500
        <div id="db_status" class="alert alert-danger">
1501
            <p><?php echo get_lang('The database connection has failed. This is generally due to the wrong user, the wrong password or the wrong database prefix being set above. Please review these settings and try again.'); ?></strong></p>
1502
            <code><?php echo $database_exists_text; ?></code>
1503
        </div>
1504
    <?php endif; ?>
1505
1506
   <div class="btn-group" role="group">
1507
       <button type="submit" name="step2"
1508
               class="btn btn-secondary float-right" value="&lt; <?php echo get_lang('Previous'); ?>" >
1509
           <em class="fa fa-backward"> </em> <?php echo get_lang('Previous'); ?>
1510
       </button>
1511
       <input type="hidden" name="is_executable" id="is_executable" value="-" />
1512
       <?php if ($manager) {
1513
                    ?>
1514
           <button type="submit" class="btn btn-success" name="step4" value="<?php echo get_lang('Next'); ?> &gt;" >
1515
               <em class="fa fa-forward"> </em> <?php echo get_lang('Next'); ?>
1516
           </button>
1517
       <?php
1518
                } else {
1519
                    ?>
1520
           <button
1521
                   disabled="disabled"
1522
                   type="submit" class="btn btn-success disabled" name="step4" value="<?php echo get_lang('Next'); ?> &gt;" >
1523
               <em class="fa fa-forward"> </em> <?php echo get_lang('Next'); ?>
1524
           </button>
1525
       <?php
1526
                } ?>
1527
   </div>
1528
    <?php
1529
}
1530
1531
function panel($content = null, $title = null, $id = null, $style = null)
1532
{
1533
    $html = '';
1534
    if (empty($style)) {
1535
        $style = 'default';
1536
    }
1537
    if (!empty($title)) {
1538
        $panelTitle = Display::div($title, ['class' => 'panel-heading']);
1539
        $panelBody = Display::div($content, ['class' => 'panel-body']);
1540
        $panelParent = Display::div($panelTitle.$panelBody, ['id' => $id, 'class' => 'panel panel-'.$style]);
1541
    } else {
1542
        $panelBody = Display::div($html, ['class' => 'panel-body']);
1543
        $panelParent = Display::div($panelBody, ['id' => $id, 'class' => 'panel panel-'.$style]);
1544
    }
1545
    $html .= $panelParent;
1546
1547
    return $html;
1548
}
1549
1550
/**
1551
 * Displays a parameter in a table row.
1552
 * Used by the display_configuration_settings_form function.
1553
 *
1554
 * @param string $installType
1555
 * @param string $parameterName
1556
 * @param string $formFieldName
1557
 * @param string $parameterValue
1558
 * @param string $displayWhenUpdate
1559
 *
1560
 * @return string
1561
 */
1562
function display_configuration_parameter(
1563
    $installType,
1564
    $parameterName,
1565
    $formFieldName,
1566
    $parameterValue,
1567
    $displayWhenUpdate = 'true'
1568
) {
1569
    $html = '<div class="form-group row">';
1570
    $html .= '<label class="col-sm-6 control-label">'.$parameterName.'</label>';
1571
    if ($installType == INSTALL_TYPE_UPDATE && $displayWhenUpdate) {
1572
        $html .= '<input type="hidden" name="'.$formFieldName.'" value="'.api_htmlentities($parameterValue, ENT_QUOTES).'" />'.$parameterValue;
1573
    } else {
1574
        $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>";
1575
    }
1576
    $html .= "</div>";
1577
1578
    return $html;
1579
}
1580
1581
/**
1582
 * Displays step 4 of the installation - configuration settings about Chamilo itself.
1583
 *
1584
 * @param string $installType
1585
 * @param string $urlForm
1586
 * @param string $languageForm
1587
 * @param string $emailForm
1588
 * @param string $adminFirstName
1589
 * @param string $adminLastName
1590
 * @param string $adminPhoneForm
1591
 * @param string $campusForm
1592
 * @param string $institutionForm
1593
 * @param string $institutionUrlForm
1594
 * @param string $encryptPassForm
1595
 * @param bool   $allowSelfReg
1596
 * @param bool   $allowSelfRegProf
1597
 * @param string $loginForm
1598
 * @param string $passForm
1599
 */
1600
function display_configuration_settings_form(
1601
    $installType,
1602
    $urlForm,
1603
    $languageForm,
1604
    $emailForm,
1605
    $adminFirstName,
1606
    $adminLastName,
1607
    $adminPhoneForm,
1608
    $campusForm,
1609
    $institutionForm,
1610
    $institutionUrlForm,
1611
    $encryptPassForm,
1612
    $allowSelfReg,
1613
    $allowSelfRegProf,
1614
    $loginForm,
1615
    $passForm
1616
) {
1617
    if ($installType != 'update' && empty($languageForm)) {
1618
        $languageForm = $_SESSION['install_language'];
1619
    }
1620
    echo '<div class="RequirementHeading">';
1621
    echo "<h2>".display_step_sequence().get_lang("ConfigurationSettings")."</h2>";
1622
    echo '</div>';
1623
1624
    // Parameter 1: administrator's login
1625
    $html = '';
1626
    $html .= display_configuration_parameter(
1627
        $installType,
1628
        get_lang('Administrator login'),
1629
        'loginForm',
1630
        $loginForm,
1631
        $installType == 'update'
1632
    );
1633
1634
    // Parameter 2: administrator's password
1635
    if ($installType != 'update') {
1636
        $html .= display_configuration_parameter($installType, get_lang('Administrator password (<font color="red">you may want to change this</font>)'), 'passForm', $passForm, false);
1637
    }
1638
1639
    // Parameters 3 and 4: administrator's names
1640
1641
    $html .= display_configuration_parameter(
1642
        $installType,
1643
        get_lang('Administrator first name'),
1644
        'adminFirstName',
1645
        $adminFirstName
1646
    );
1647
    $html .= display_configuration_parameter($installType, get_lang('Administrator last name'), 'adminLastName', $adminLastName);
1648
1649
    //Parameter 3: administrator's email
1650
    $html .= display_configuration_parameter($installType, get_lang('Admine-mail'), 'emailForm', $emailForm);
1651
1652
    //Parameter 6: administrator's telephone
1653
    $html .= display_configuration_parameter($installType, get_lang('Administrator telephone'), 'adminPhoneForm', $adminPhoneForm);
1654
    echo panel($html, get_lang('Administrator'), 'administrator');
1655
1656
    //First parameter: language
1657
    $html = '<div class="form-group row">';
1658
    $html .= '<label class="col-sm-6 control-label">'.get_lang('Main language')."</label>";
1659
    if ($installType == 'update') {
1660
        $html .= '<input type="hidden" name="languageForm" value="'.api_htmlentities($languageForm, ENT_QUOTES).'" />'.$languageForm;
1661
    } else { // new installation
1662
        $html .= '<div class="col-sm-6">';
1663
        $html .= display_language_selection_box('languageForm', $languageForm);
1664
        $html .= '</div>';
1665
    }
1666
    $html .= "</div>";
1667
1668
    //Second parameter: Chamilo URL
1669
    $html .= '<div class="form-group row">';
1670
    $html .= '<label class="col-sm-6 control-label">'.get_lang('Chamilo URL').get_lang('Required field').'</label>';
1671
1672
    if ($installType == 'update') {
1673
        $html .= api_htmlentities($urlForm, ENT_QUOTES)."\n";
1674
    } else {
1675
        $html .= '<div class="col-sm-6">';
1676
        $html .= '<input class="form-control" type="text" size="40" maxlength="100" name="urlForm" value="'.api_htmlentities($urlForm, ENT_QUOTES).'" />';
1677
        $html .= '</div>';
1678
    }
1679
    $html .= '</div>';
1680
1681
    //Parameter 9: campus name
1682
    $html .= display_configuration_parameter(
1683
        $installType,
1684
        get_lang('Your portal name'),
1685
        'campusForm',
1686
        $campusForm
1687
    );
1688
1689
    //Parameter 10: institute (short) name
1690
    $html .= display_configuration_parameter(
1691
        $installType,
1692
        get_lang('Your company short name'),
1693
        'institutionForm',
1694
        $institutionForm
1695
    );
1696
1697
    //Parameter 11: institute (short) name
1698
    $html .= display_configuration_parameter(
1699
        $installType,
1700
        get_lang('URL of this company'),
1701
        'institutionUrlForm',
1702
        $institutionUrlForm
1703
    );
1704
1705
    $html .= '<div class="form-group row">
1706
            <label class="col-sm-6 control-label">'.get_lang("Encryption method").'</label>
1707
        <div class="col-sm-6">';
1708
    if ($installType == 'update') {
1709
        $html .= '<input type="hidden" name="encryptPassForm" value="'.$encryptPassForm.'" />'.$encryptPassForm;
1710
    } else {
1711
        $html .= '<div class="checkbox">
1712
                    <label>
1713
                        <input  type="radio" name="encryptPassForm" value="bcrypt" id="encryptPass1" '.($encryptPassForm == 'bcrypt' ? 'checked="checked" ' : '').'/> bcrypt
1714
                    </label>';
1715
1716
        $html .= '<label>
1717
                        <input  type="radio" name="encryptPassForm" value="sha1" id="encryptPass1" '.($encryptPassForm == 'sha1' ? 'checked="checked" ' : '').'/> sha1
1718
                    </label>';
1719
1720
        $html .= '<label>
1721
                        <input type="radio" name="encryptPassForm" value="md5" id="encryptPass0" '.($encryptPassForm == 'md5' ? 'checked="checked" ' : '').'/> md5
1722
                    </label>';
1723
1724
        $html .= '<label>
1725
                        <input type="radio" name="encryptPassForm" value="none" id="encryptPass2" '.($encryptPassForm == 'none' ? 'checked="checked" ' : '').'/>'.get_lang('none').'
1726
                    </label>';
1727
        $html .= '</div>';
1728
    }
1729
    $html .= '</div></div>';
1730
1731
    $html .= '<div class="form-group row">
1732
            <label class="col-sm-6 control-label">'.get_lang('Allow self-registration').'</label>
1733
            <div class="col-sm-6">';
1734
    if ($installType == 'update') {
1735
        if ($allowSelfReg == 'true') {
1736
            $label = get_lang('Yes');
1737
        } elseif ($allowSelfReg == 'false') {
1738
            $label = get_lang('No');
1739
        } else {
1740
            $label = get_lang('After approval');
1741
        }
1742
        $html .= '<input type="hidden" name="allowSelfReg" value="'.$allowSelfReg.'" />'.$label;
1743
    } else {
1744
        $html .= '<div class="control-group">';
1745
        $html .= '<label class="checkbox-inline">
1746
                        <input type="radio" name="allowSelfReg" value="true" id="allowSelfReg1" '.($allowSelfReg == 'true' ? 'checked="checked" ' : '').' /> '.get_lang('Yes').'
1747
                    </label>';
1748
        $html .= '<label class="checkbox-inline">
1749
                        <input type="radio" name="allowSelfReg" value="false" id="allowSelfReg0" '.($allowSelfReg == 'false' ? '' : 'checked="checked" ').' /> '.get_lang('No').'
1750
                    </label>';
1751
        $html .= '<label class="checkbox-inline">
1752
                    <input type="radio" name="allowSelfReg" value="approval" id="allowSelfReg2" '.($allowSelfReg == 'approval' ? '' : 'checked="checked" ').' /> '.get_lang('After approval').'
1753
                </label>';
1754
        $html .= '</div>';
1755
    }
1756
    $html .= '</div>';
1757
    $html .= '</div>';
1758
1759
    $html .= '<div class="form-group row">';
1760
    $html .= '<label class="col-sm-6 control-label">'.get_lang('Allow self-registrationProf').'</label>
1761
        <div class="col-sm-6">';
1762
    if ($installType == 'update') {
1763
        if ($allowSelfRegProf == 'true') {
1764
            $label = get_lang('Yes');
1765
        } else {
1766
            $label = get_lang('No');
1767
        }
1768
        $html .= '<input type="hidden" name="allowSelfRegProf" value="'.$allowSelfRegProf.'" />'.$label;
1769
    } else {
1770
        $html .= '<div class="control-group">
1771
                <label class="checkbox-inline">
1772
                    <input type="radio" name="allowSelfRegProf" value="1" id="allowSelfRegProf1" '.($allowSelfRegProf ? 'checked="checked" ' : '').'/>
1773
                '.get_lang('Yes').'
1774
                </label>';
1775
        $html .= '<label class="checkbox-inline">
1776
                    <input type="radio" name="allowSelfRegProf" value="0" id="allowSelfRegProf0" '.($allowSelfRegProf ? '' : 'checked="checked" ').' />
1777
                   '.get_lang('No').'
1778
                </label>';
1779
        $html .= '</div>';
1780
    }
1781
    $html .= '</div>
1782
    </div>';
1783
1784
    echo panel($html, get_lang('Portal'), 'platform'); ?>
1785
    <div class='btn-group'>
1786
        <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>
1787
        <input type="hidden" name="is_executable" id="is_executable" value="-" />
1788
        <button class="btn btn-success" type="submit" name="step5">
1789
            <em class="fa fa-forward"> </em> <?php echo get_lang('Next'); ?>
1790
        </button>
1791
    </div>
1792
    <?php
1793
}
1794
1795
/**
1796
 * After installation is completed (step 6), this message is displayed.
1797
 */
1798
function display_after_install_message()
1799
{
1800
    $container = Container::$container;
1801
1802
    $trans = $container->get('translator');
1803
    $html = '<div class="RequirementContent">'.
1804
        $trans->trans(
1805
            'When you enter your portal for the first time, the best way to understand it is to create a course with the \'Create course\' link in the menu and play around a little.').'</div>';
1806
    $html .= '<div class="alert alert-warning">';
1807
    $html .= '<strong>'.$trans->trans('Security advice').'</strong>';
1808
    $html .= ': ';
1809
    $html .= sprintf($trans->trans(
1810
        'To protect your site, make the whole %s directory read-only (chmod -R 0555 on Linux) and delete the %s directory.'), 'var/config/', 'main/install/');
1811
    $html .= '</div></form>
1812
    <br />
1813
    <a class="btn btn-success btn-block" href="../../">
1814
        '.$trans->trans('Go to your newly created portal.').'
1815
    </a>';
1816
1817
    return $html;
1818
}
1819
1820
/**
1821
 * This function return countries list from array (hardcoded).
1822
 *
1823
 * @param bool $combo (Optional) True for returning countries list with select html
1824
 *
1825
 * @return array|string countries list
1826
 */
1827
function get_countries_list_from_array($combo = false)
1828
{
1829
    $a_countries = [
1830
        "Afghanistan", "Albania", "Algeria", "Andorra", "Angola", "Antigua and Barbuda", "Argentina", "Armenia", "Australia", "Austria", "Azerbaijan",
1831
        "Bahamas", "Bahrain", "Bangladesh", "Barbados", "Belarus", "Belgium", "Belize", "Benin", "Bhutan", "Bolivia", "Bosnia and Herzegovina", "Botswana", "Brazil", "Brunei", "Bulgaria", "Burkina Faso", "Burundi",
1832
        "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",
1833
        "Denmark", "Djibouti", "Dominica", "Dominican Republic",
1834
        "East Timor (Timor Timur)", "Ecuador", "Egypt", "El Salvador", "Equatorial Guinea", "Eritrea", "Estonia", "Ethiopia",
1835
        "Fiji", "Finland", "France",
1836
        "Gabon", "Gambia, The", "Georgia", "Germany", "Ghana", "Greece", "Grenada", "Guatemala", "Guinea", "Guinea-Bissau", "Guyana",
1837
        "Haiti", "Honduras", "Hungary",
1838
        "Iceland", "India", "Indonesia", "Iran", "Iraq", "Ireland", "Israel", "Italy",
1839
        "Jamaica", "Japan", "Jordan",
1840
        "Kazakhstan", "Kenya", "Kiribati", "Korea, North", "Korea, South", "Kuwait", "Kyrgyzstan",
1841
        "Laos", "Latvia", "Lebanon", "Lesotho", "Liberia", "Libya", "Liechtenstein", "Lithuania", "Luxembourg",
1842
        "Macedonia", "Madagascar", "Malawi", "Malaysia", "Maldives", "Mali", "Malta", "Marshall Islands", "Mauritania", "Mauritius", "Mexico", "Micronesia", "Moldova", "Monaco", "Mongolia", "Morocco", "Mozambique", "Myanmar",
1843
        "Namibia", "Nauru", "Nepa", "Netherlands", "New Zealand", "Nicaragua", "Niger", "Nigeria", "Norway",
1844
        "Oman",
1845
        "Pakistan", "Palau", "Panama", "Papua New Guinea", "Paraguay", "Peru", "Philippines", "Poland", "Portugal",
1846
        "Qatar",
1847
        "Romania", "Russia", "Rwanda",
1848
        "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",
1849
        "Taiwan", "Tajikistan", "Tanzania", "Thailand", "Togo", "Tonga", "Trinidad and Tobago", "Tunisia", "Turkey", "Turkmenistan", "Tuvalu",
1850
        "Uganda", "Ukraine", "United Arab Emirates", "United Kingdom", "United States", "Uruguay", "Uzbekistan",
1851
        "Vanuatu", "Vatican City", "Venezuela", "Vietnam",
1852
        "Yemen",
1853
        "Zambia", "Zimbabwe",
1854
    ];
1855
    if ($combo) {
1856
        $country_select = '<select class="selectpicker show-tick" id="country" name="country">';
1857
        $country_select .= '<option value="">--- '.get_lang('Select one').' ---</option>';
1858
        foreach ($a_countries as $country) {
1859
            $country_select .= '<option value="'.$country.'">'.$country.'</option>';
1860
        }
1861
        $country_select .= '</select>';
1862
1863
        return $country_select;
1864
    }
1865
1866
    return $a_countries;
1867
}
1868
1869
/**
1870
 * Lock settings that can't be changed in other portals.
1871
 */
1872
function lockSettings()
1873
{
1874
    $settings = api_get_locked_settings();
1875
    $table = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
1876
    foreach ($settings as $setting) {
1877
        $sql = "UPDATE $table SET access_url_locked = 1 WHERE variable  = '$setting'";
1878
        Database::query($sql);
1879
    }
1880
}
1881
1882
/**
1883
 * Update dir values.
1884
 */
1885
function updateDirAndFilesPermissions()
1886
{
1887
    $table = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
1888
    $permissions_for_new_directories = isset($_SESSION['permissions_for_new_directories']) ? $_SESSION['permissions_for_new_directories'] : 0770;
1889
    $permissions_for_new_files = isset($_SESSION['permissions_for_new_files']) ? $_SESSION['permissions_for_new_files'] : 0660;
1890
    // use decoct() to store as string
1891
    Database::update(
1892
        $table,
1893
        ['selected_value' => '0'.decoct($permissions_for_new_directories)],
1894
        ['variable = ?' => 'permissions_for_new_directories']
1895
    );
1896
1897
    Database::update(
1898
        $table,
1899
        ['selected_value' => '0'.decoct($permissions_for_new_files)],
1900
        ['variable = ?' => 'permissions_for_new_files']
1901
    );
1902
1903
    if (isset($_SESSION['permissions_for_new_directories'])) {
1904
        unset($_SESSION['permissions_for_new_directories']);
1905
    }
1906
1907
    if (isset($_SESSION['permissions_for_new_files'])) {
1908
        unset($_SESSION['permissions_for_new_files']);
1909
    }
1910
}
1911
1912
/**
1913
 * @param $current_value
1914
 * @param $wanted_value
1915
 *
1916
 * @return string
1917
 */
1918
function compare_setting_values($current_value, $wanted_value)
1919
{
1920
    $current_value_string = $current_value;
1921
    $current_value = (float) $current_value;
1922
    $wanted_value = (float) $wanted_value;
1923
1924
    if ($current_value >= $wanted_value) {
1925
        return Display::label($current_value_string, 'success');
1926
    } else {
1927
        return Display::label($current_value_string, 'important');
1928
    }
1929
}
1930
1931
/**
1932
 * Save settings values.
1933
 *
1934
 * @param string $organizationName
1935
 * @param string $organizationUrl
1936
 * @param string $siteName
1937
 * @param string $adminEmail
1938
 * @param string $adminLastName
1939
 * @param string $adminFirstName
1940
 * @param string $language
1941
 * @param string $allowRegistration
1942
 * @param string $allowTeacherSelfRegistration
1943
 * @param string $installationProfile          The name of an installation profile file in main/install/profiles/
1944
 */
1945
function installSettings(
1946
    $organizationName,
1947
    $organizationUrl,
1948
    $siteName,
1949
    $adminEmail,
1950
    $adminLastName,
1951
    $adminFirstName,
1952
    $language,
1953
    $allowRegistration,
1954
    $allowTeacherSelfRegistration,
1955
    $installationProfile = ''
1956
) {
1957
    error_log('installSettings');
1958
    $allowTeacherSelfRegistration = $allowTeacherSelfRegistration ? 'true' : 'false';
1959
1960
    $settings = [
1961
        'institution' => $organizationName,
1962
        'institution_url' => $organizationUrl,
1963
        'site_name' => $siteName,
1964
        'administrator_email' => $adminEmail,
1965
        'administrator_surname' => $adminLastName,
1966
        'administrator_name' => $adminFirstName,
1967
        'platform_language' => $language,
1968
        'allow_registration' => $allowRegistration,
1969
        'allow_registration_as_teacher' => $allowTeacherSelfRegistration,
1970
    ];
1971
1972
    foreach ($settings as $variable => $value) {
1973
        $sql = "UPDATE settings_current
1974
                SET selected_value = '$value'
1975
                WHERE variable = '$variable'";
1976
        Database::query($sql);
1977
    }
1978
    installProfileSettings($installationProfile);
1979
}
1980
1981
/**
1982
 * Executes DB changes based in the classes defined in
1983
 * src/CoreBundle/Migrations/Schema/*.
1984
 *
1985
 * @param string $chamiloVersion
1986
 *
1987
 * @throws \Doctrine\DBAL\DBALException
1988
 *
1989
 * @return bool
1990
 */
1991
function migrate($chamiloVersion, EntityManager $manager)
1992
{
1993
    $debug = true;
1994
    $connection = $manager->getConnection();
1995
1996
    $config = new \Doctrine\DBAL\Migrations\Configuration\Configuration($connection);
1997
1998
    // Table name that will store migrations log (will be created automatically,
1999
    // default name is: doctrine_migration_versions)
2000
    $config->setMigrationsTableName('version');
2001
    // Namespace of your migration classes, do not forget escape slashes, do not add last slash
2002
    $config->setMigrationsNamespace('Chamilo\CoreBundle\Migrations\Schema\V'.$chamiloVersion);
2003
    // Directory where your migrations are located
2004
    $versionPath = api_get_path(SYS_PATH).'src/CoreBundle/Migrations/Schema/V'.$chamiloVersion;
2005
    error_log("Reading files from dir: $versionPath");
2006
    $config->setMigrationsDirectory($versionPath);
2007
    // Load your migrations
2008
    $config->registerMigrationsFromDirectory($config->getMigrationsDirectory());
2009
2010
    $migration = new \Doctrine\DBAL\Migrations\Migration($config);
2011
    $versions = $config->getMigrations();
2012
2013
    /** @var Doctrine\DBAL\Migrations\Version $migrationItem */
2014
    foreach ($versions as $version) {
2015
        $version->getMigration()->setEntityManager($manager);
2016
    }
2017
2018
    $to = null; // if $to == null then schema will be migrated to latest version
2019
    echo '<pre>';
2020
    try {
2021
        // Execute migration!
2022
        $migratedSQL = $migration->migrate($to);
2023
2024
        if ($debug) {
2025
            foreach ($migratedSQL as $version => $sqlList) {
2026
                echo "VERSION: $version<br>";
2027
                echo '----------------------------------------------<br />';
2028
                $total = count($sqlList);
2029
                error_log("VERSION: $version");
2030
                error_log("# queries: $total");
2031
                $counter = 1;
2032
                foreach ($sqlList as $sql) {
2033
                    echo "<code>$sql</code><br>";
2034
                    error_log("$counter/$total : $sql");
2035
                    $counter++;
2036
                }
2037
            }
2038
2039
            echo "<br>DONE!<br>";
2040
        }
2041
2042
        return true;
2043
    } catch (Exception $ex) {
2044
        if ($debug) {
2045
            echo "ERROR: {$ex->getMessage()}<br>";
2046
2047
            return false;
2048
        }
2049
    }
2050
2051
    echo '</pre>';
2052
2053
    return false;
2054
}
2055
2056
/**
2057
 * @throws \Doctrine\DBAL\DBALException
2058
 */
2059
function fixIds(EntityManager $em)
2060
{
2061
    $connection = $em->getConnection();
2062
    $database = new Database();
2063
    $database->setManager($em);
2064
    $debug = true;
2065
    if ($debug) {
2066
        error_log('fixIds');
2067
    }
2068
2069
    // Create temporary indexes to increase speed of the following operations
2070
    // Adding and removing indexes will usually take much less time than
2071
    // the execution without indexes of the queries in this function, particularly
2072
    // for large tables
2073
    $sql = "ALTER TABLE c_document ADD INDEX tmpidx_doc(c_id, id)";
2074
    $connection->executeQuery($sql);
2075
    $sql = "ALTER TABLE c_student_publication ADD INDEX tmpidx_stud (c_id, id)";
2076
    $connection->executeQuery($sql);
2077
    $sql = "ALTER TABLE c_quiz ADD INDEX tmpidx_quiz (c_id, id)";
2078
    $connection->executeQuery($sql);
2079
    $sql = "ALTER TABLE c_item_property ADD INDEX tmpidx_ip (to_group_id)";
2080
    $connection->executeQuery($sql);
2081
2082
    $sql = "SELECT * FROM c_lp_item";
2083
    $result = $connection->fetchAll($sql);
2084
    foreach ($result as $item) {
2085
        $courseId = $item['c_id'];
2086
        $iid = isset($item['iid']) ? intval($item['iid']) : 0;
2087
        $ref = isset($item['ref']) ? intval($item['ref']) : 0;
2088
        $sql = null;
2089
2090
        $newId = '';
2091
2092
        switch ($item['item_type']) {
2093
            case TOOL_LINK:
2094
                $sql = "SELECT * FROM c_link WHERE c_id = $courseId AND id = $ref";
2095
                $data = $connection->fetchAssoc($sql);
2096
                if ($data) {
2097
                    $newId = $data['iid'];
2098
                }
2099
                break;
2100
            case TOOL_STUDENTPUBLICATION:
2101
                $sql = "SELECT * FROM c_student_publication WHERE c_id = $courseId AND id = $ref";
2102
                $data = $connection->fetchAssoc($sql);
2103
                if ($data) {
2104
                    $newId = $data['iid'];
2105
                }
2106
                break;
2107
            case TOOL_QUIZ:
2108
                $sql = "SELECT * FROM c_quiz WHERE c_id = $courseId AND id = $ref";
2109
                $data = $connection->fetchAssoc($sql);
2110
                if ($data) {
2111
                    $newId = $data['iid'];
2112
                }
2113
                break;
2114
            case TOOL_DOCUMENT:
2115
                $sql = "SELECT * FROM c_document WHERE c_id = $courseId AND id = $ref";
2116
                $data = $connection->fetchAssoc($sql);
2117
                if ($data) {
2118
                    $newId = $data['iid'];
2119
                }
2120
                break;
2121
            case TOOL_FORUM:
2122
                $sql = "SELECT * FROM c_forum_forum WHERE c_id = $courseId AND forum_id = $ref";
2123
                $data = $connection->fetchAssoc($sql);
2124
                if ($data) {
2125
                    $newId = $data['iid'];
2126
                }
2127
                break;
2128
            case 'thread':
2129
                $sql = "SELECT * FROM c_forum_thread WHERE c_id = $courseId AND thread_id = $ref";
2130
                $data = $connection->fetchAssoc($sql);
2131
                if ($data) {
2132
                    $newId = $data['iid'];
2133
                }
2134
                break;
2135
        }
2136
2137
        if (!empty($sql) && !empty($newId) && !empty($iid)) {
2138
            $sql = "UPDATE c_lp_item SET ref = $newId WHERE iid = $iid";
2139
            $connection->executeQuery($sql);
2140
        }
2141
    }
2142
2143
    // Set NULL if session = 0
2144
    $sql = "UPDATE c_item_property SET session_id = NULL WHERE session_id = 0";
2145
    $connection->executeQuery($sql);
2146
2147
    // Set NULL if group = 0
2148
    $sql = "UPDATE c_item_property SET to_group_id = NULL WHERE to_group_id = 0";
2149
    $connection->executeQuery($sql);
2150
2151
    // Set NULL if insert_user_id = 0
2152
    $sql = "UPDATE c_item_property SET insert_user_id = NULL WHERE insert_user_id = 0";
2153
    $connection->executeQuery($sql);
2154
2155
    // Delete session data of sessions that don't exist.
2156
    $sql = "DELETE FROM c_item_property
2157
            WHERE session_id IS NOT NULL AND session_id NOT IN (SELECT id FROM session)";
2158
    $connection->executeQuery($sql);
2159
2160
    // Delete group data of groups that don't exist.
2161
    $sql = "DELETE FROM c_item_property
2162
            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)";
2163
    $connection->executeQuery($sql);
2164
    // This updates the group_id with c_group_info.iid instead of c_group_info.id
2165
2166
    if ($debug) {
2167
        error_log('update iids');
2168
    }
2169
2170
    $groupTableToFix = [
2171
        'c_group_rel_user',
2172
        'c_group_rel_tutor',
2173
        'c_permission_group',
2174
        'c_role_group',
2175
        'c_survey_invitation',
2176
        'c_attendance_calendar_rel_group',
2177
    ];
2178
2179
    foreach ($groupTableToFix as $table) {
2180
        $sql = "SELECT * FROM $table";
2181
        $result = $connection->fetchAll($sql);
2182
        foreach ($result as $item) {
2183
            $iid = $item['iid'];
2184
            $courseId = $item['c_id'];
2185
            $groupId = intval($item['group_id']);
2186
2187
            // Fix group id
2188
            if (!empty($groupId)) {
2189
                $sql = "SELECT * FROM c_group_info
2190
                        WHERE c_id = $courseId AND id = $groupId
2191
                        LIMIT 1";
2192
                $data = $connection->fetchAssoc($sql);
2193
                if (!empty($data)) {
2194
                    $newGroupId = $data['iid'];
2195
                    $sql = "UPDATE $table SET group_id = $newGroupId
2196
                            WHERE iid = $iid";
2197
                    $connection->executeQuery($sql);
2198
                } else {
2199
                    // The group does not exists clean this record
2200
                    $sql = "DELETE FROM $table WHERE iid = $iid";
2201
                    $connection->executeQuery($sql);
2202
                }
2203
            }
2204
        }
2205
    }
2206
2207
    // Fix c_item_property
2208
    if ($debug) {
2209
        error_log('update c_item_property');
2210
    }
2211
2212
    $sql = "SELECT * FROM course";
2213
    $courseList = $connection->fetchAll($sql);
2214
    if ($debug) {
2215
        error_log('Getting course list');
2216
    }
2217
2218
    $totalCourse = count($courseList);
2219
    $counter = 0;
2220
2221
    foreach ($courseList as $courseData) {
2222
        $courseId = $courseData['id'];
2223
        if ($debug) {
2224
            error_log('Updating course: '.$courseData['code']);
2225
        }
2226
2227
        $sql = "SELECT * FROM c_item_property WHERE c_id = $courseId";
2228
        $result = $connection->fetchAll($sql);
2229
        foreach ($result as $item) {
2230
            $sessionId = intval($item['session_id']);
2231
            $groupId = intval($item['to_group_id']);
2232
            $iid = $item['iid'];
2233
            $ref = $item['ref'];
2234
2235
            // Fix group id
2236
            // Commented group id is already fixed in Version20150603181728.php
2237
            /*if (!empty($groupId)) {
2238
                $sql = "SELECT * FROM c_group_info
2239
                        WHERE c_id = $courseId AND id = $groupId";
2240
                $data = $connection->fetchAssoc($sql);
2241
                if (!empty($data)) {
2242
                    $newGroupId = $data['iid'];
2243
                    $sql = "UPDATE c_item_property SET to_group_id = $newGroupId
2244
                            WHERE iid = $iid";
2245
                    $connection->executeQuery($sql);
2246
                } else {
2247
                    // The group does not exists clean this record
2248
                    $sql = "DELETE FROM c_item_property WHERE iid = $iid";
2249
                    $connection->executeQuery($sql);
2250
                }
2251
            }*/
2252
2253
            $sql = '';
2254
            $newId = '';
2255
            switch ($item['tool']) {
2256
                case TOOL_LINK:
2257
                    $sql = "SELECT * FROM c_link WHERE c_id = $courseId AND id = $ref ";
2258
                    break;
2259
                case TOOL_STUDENTPUBLICATION:
2260
                    $sql = "SELECT * FROM c_student_publication WHERE c_id = $courseId AND id = $ref";
2261
                    break;
2262
                case TOOL_QUIZ:
2263
                    $sql = "SELECT * FROM c_quiz WHERE c_id = $courseId AND id = $ref";
2264
                    break;
2265
                case TOOL_DOCUMENT:
2266
                    $sql = "SELECT * FROM c_document WHERE c_id = $courseId AND id = $ref";
2267
                    break;
2268
                case TOOL_FORUM:
2269
                    $sql = "SELECT * FROM c_forum_forum WHERE c_id = $courseId AND id = $ref";
2270
                    break;
2271
                case 'thread':
2272
                    $sql = "SELECT * FROM c_forum_thread WHERE c_id = $courseId AND id = $ref";
2273
                    break;
2274
            }
2275
2276
            if (!empty($sql) && !empty($newId)) {
2277
                $data = $connection->fetchAssoc($sql);
2278
                if (isset($data['iid'])) {
2279
                    $newId = $data['iid'];
2280
                }
2281
                $sql = "UPDATE c_item_property SET ref = $newId WHERE iid = $iid";
2282
                error_log($sql);
2283
                $connection->executeQuery($sql);
2284
            }
2285
        }
2286
2287
        if ($debug) {
2288
            // Print a status in the log once in a while
2289
            error_log("Course process #$counter/$totalCourse");
2290
        }
2291
        $counter++;
2292
    }
2293
2294
    if ($debug) {
2295
        error_log('update gradebook_link');
2296
    }
2297
2298
    // Fix gradebook_link
2299
    $sql = "SELECT * FROM gradebook_link";
2300
    $result = $connection->fetchAll($sql);
2301
    foreach ($result as $item) {
2302
        $courseCode = $item['course_code'];
2303
        $categoryId = (int) $item['category_id'];
2304
2305
        $sql = "SELECT * FROM course WHERE code = '$courseCode'";
2306
        $courseInfo = $connection->fetchAssoc($sql);
2307
        if (empty($courseInfo)) {
2308
            continue;
2309
        }
2310
2311
        $courseId = $courseInfo['id'];
2312
2313
        $ref = $item['ref_id'];
2314
        $iid = $item['id'];
2315
2316
        $sql = '';
2317
        switch ($item['type']) {
2318
            case LINK_LEARNPATH:
2319
                $sql = "SELECT * FROM c_link WHERE c_id = $courseId AND id = $ref ";
2320
                break;
2321
            case LINK_STUDENTPUBLICATION:
2322
                $sql = "SELECT * FROM c_student_publication WHERE c_id = $courseId AND id = $ref";
2323
                break;
2324
            case LINK_EXERCISE:
2325
                $sql = "SELECT * FROM c_quiz WHERE c_id = $courseId AND id = $ref";
2326
                break;
2327
            case LINK_ATTENDANCE:
2328
                //$sql = "SELECT * FROM c_document WHERE c_id = $courseId AND id = $ref";
2329
                break;
2330
            case LINK_FORUM_THREAD:
2331
                $sql = "SELECT * FROM c_forum_thread WHERE c_id = $courseId AND thread_id = $ref";
2332
                break;
2333
        }
2334
2335
        if (!empty($sql)) {
2336
            $data = $connection->fetchAssoc($sql);
2337
            if (isset($data) && isset($data['iid'])) {
2338
                $newId = $data['iid'];
2339
                $sql = "UPDATE gradebook_link SET ref_id = $newId
2340
                        WHERE id = $iid AND course_code = '$courseCode' AND category_id = $categoryId ";
2341
                $connection->executeQuery($sql);
2342
            }
2343
        }
2344
    }
2345
2346
    if ($debug) {
2347
        error_log('update groups');
2348
    }
2349
2350
    $sql = 'SELECT * FROM groups';
2351
    $result = $connection->executeQuery($sql);
2352
    $groups = $result->fetchAll();
2353
    $oldGroups = [];
2354
    if (!empty($groups)) {
2355
        foreach ($groups as $group) {
2356
            if (empty($group['name'])) {
2357
                continue;
2358
            }
2359
2360
            $params = [
2361
                'name' => $group['name'],
2362
                'description' => $group['description'],
2363
                'group_type' => 1,
2364
                'picture' => $group['picture_uri'],
2365
                'url' => $group['url'],
2366
                'visibility' => $group['visibility'],
2367
                'updated_at' => $group['updated_on'],
2368
                'created_at' => $group['created_on'],
2369
            ];
2370
            $connection->insert('usergroup', $params);
2371
            $id = $connection->lastInsertId('id');
2372
            $oldGroups[$group['id']] = $id;
2373
        }
2374
    }
2375
2376
    if (!empty($oldGroups)) {
2377
        error_log('Moving group files');
2378
        foreach ($oldGroups as $oldId => $newId) {
2379
            $path = get_group_picture_path_by_id(
2380
                $oldId,
2381
                'system'
2382
            );
2383
2384
            if (!empty($path)) {
2385
                $newPath = str_replace(
2386
                    "groups/$oldId/",
2387
                    "groups/$newId/",
2388
                    $path['dir']
2389
                );
2390
                $command = "mv {$path['dir']} $newPath ";
2391
                error_log("Executing $command");
2392
                system($command);
2393
            }
2394
        }
2395
2396
        $sql = "SELECT * FROM group_rel_user";
2397
        $result = $connection->executeQuery($sql);
2398
        $dataList = $result->fetchAll();
2399
2400
        if (!empty($dataList)) {
2401
            foreach ($dataList as $data) {
2402
                if (isset($oldGroups[$data['group_id']])) {
2403
                    $data['group_id'] = $oldGroups[$data['group_id']];
2404
                    $userId = $data['user_id'];
2405
2406
                    $sql = "SELECT id FROM user WHERE user_id = $userId";
2407
                    $userResult = $connection->executeQuery($sql);
2408
                    $userInfo = $userResult->fetch();
2409
                    if (empty($userInfo)) {
2410
                        continue;
2411
                    }
2412
2413
                    $sql = "INSERT INTO usergroup_rel_user (usergroup_id, user_id, relation_type)
2414
                            VALUES ('{$data['group_id']}', '{$userId}', '{$data['relation_type']}')";
2415
                    $connection->executeQuery($sql);
2416
                }
2417
            }
2418
        }
2419
2420
        $sql = "SELECT * FROM group_rel_group";
2421
        $result = $connection->executeQuery($sql);
2422
        $dataList = $result->fetchAll();
2423
2424
        if (!empty($dataList)) {
2425
            foreach ($dataList as $data) {
2426
                if (isset($oldGroups[$data['group_id']]) && isset($oldGroups[$data['subgroup_id']])) {
2427
                    $data['group_id'] = $oldGroups[$data['group_id']];
2428
                    $data['subgroup_id'] = $oldGroups[$data['subgroup_id']];
2429
                    $sql = "INSERT INTO usergroup_rel_usergroup (group_id, subgroup_id, relation_type)
2430
                            VALUES ('{$data['group_id']}', '{$data['subgroup_id']}', '{$data['relation_type']}')";
2431
                    $connection->executeQuery($sql);
2432
                }
2433
            }
2434
        }
2435
2436
        $sql = "SELECT * FROM announcement_rel_group";
2437
        $result = $connection->executeQuery($sql);
2438
        $dataList = $result->fetchAll();
2439
2440
        if (!empty($dataList)) {
2441
            foreach ($dataList as $data) {
2442
                if (isset($oldGroups[$data['group_id']])) {
2443
                    // Deleting relation
2444
                    $sql = "DELETE FROM announcement_rel_group WHERE group_id = {$data['group_id']}";
2445
                    $connection->executeQuery($sql);
2446
2447
                    // Add new relation
2448
                    $data['group_id'] = $oldGroups[$data['group_id']];
2449
                    $sql = "INSERT INTO announcement_rel_group(group_id, announcement_id)
2450
                            VALUES ('{$data['group_id']}', '{$data['announcement_id']}')";
2451
                    $connection->executeQuery($sql);
2452
                }
2453
            }
2454
        }
2455
2456
        $sql = "SELECT * FROM group_rel_tag";
2457
        $result = $connection->executeQuery($sql);
2458
        $dataList = $result->fetchAll();
2459
        if (!empty($dataList)) {
2460
            foreach ($dataList as $data) {
2461
                if (isset($oldGroups[$data['group_id']])) {
2462
                    $data['group_id'] = $oldGroups[$data['group_id']];
2463
                    $sql = "INSERT INTO usergroup_rel_tag (tag_id, usergroup_id)
2464
                            VALUES ('{$data['tag_id']}', '{$data['group_id']}')";
2465
                    $connection->executeQuery($sql);
2466
                }
2467
            }
2468
        }
2469
    }
2470
2471
    if ($debug) {
2472
        error_log('update extra fields');
2473
    }
2474
2475
    // Extra fields
2476
    $extraFieldTables = [
2477
        ExtraField::USER_FIELD_TYPE => Database::get_main_table(TABLE_MAIN_USER_FIELD),
2478
        ExtraField::COURSE_FIELD_TYPE => Database::get_main_table(TABLE_MAIN_COURSE_FIELD),
2479
        //ExtraField::LP_FIELD_TYPE => Database::get_main_table(TABLE_MAIN_LP_FIELD),
2480
        ExtraField::SESSION_FIELD_TYPE => Database::get_main_table(TABLE_MAIN_SESSION_FIELD),
2481
        //ExtraField::CALENDAR_FIELD_TYPE => Database::get_main_table(TABLE_MAIN_CALENDAR_EVENT_FIELD),
2482
        //ExtraField::QUESTION_FIELD_TYPE => Database::get_main_table(TABLE_MAIN_CALENDAR_EVENT_FIELD),
2483
        //ExtraField::USER_FIELD_TYPE => //Database::get_main_table(TABLE_MAIN_SPECIFIC_FIELD),
2484
    ];
2485
2486
    foreach ($extraFieldTables as $type => $table) {
2487
        $sql = "SELECT * FROM $table ";
2488
        if ($debug) {
2489
            error_log($sql);
2490
        }
2491
        $result = $connection->query($sql);
2492
        $fields = $result->fetchAll();
2493
2494
        foreach ($fields as $field) {
2495
            if ($debug) {
2496
                error_log("Loading field: ".$field['field_variable']);
2497
            }
2498
            $originalId = $field['id'];
2499
2500
            $params = [
2501
                'extra_field_type' => $type,
2502
                'variable' => $field['field_variable'],
2503
                'field_type' => $field['field_type'],
2504
                'display_text' => $field['field_display_text'],
2505
                'default_value' => $field['field_default_value'],
2506
                'field_order' => $field['field_order'],
2507
                'visible' => $field['field_visible'],
2508
                'changeable' => $field['field_changeable'],
2509
                'filter' => $field['field_filter'],
2510
            ];
2511
2512
            $connection->insert('extra_field', $params);
2513
            $newExtraFieldId = $connection->lastInsertId();
2514
2515
            $values = [];
2516
            $handlerId = null;
2517
            switch ($type) {
2518
                case ExtraField::USER_FIELD_TYPE:
2519
                    $optionTable = Database::get_main_table(
2520
                        TABLE_MAIN_USER_FIELD_OPTIONS
2521
                    );
2522
                    $valueTable = Database::get_main_table(
2523
                        TABLE_MAIN_USER_FIELD_VALUES
2524
                    );
2525
                    $handlerId = 'user_id';
2526
                    break;
2527
                case ExtraField::COURSE_FIELD_TYPE:
2528
                    $optionTable = Database::get_main_table(
2529
                        TABLE_MAIN_COURSE_FIELD_OPTIONS
2530
                    );
2531
                    $valueTable = Database::get_main_table(
2532
                        TABLE_MAIN_COURSE_FIELD_VALUES
2533
                    );
2534
                    $handlerId = 'c_id';
2535
                    break;
2536
                case ExtraField::SESSION_FIELD_TYPE:
2537
                    $optionTable = Database::get_main_table(
2538
                        TABLE_MAIN_SESSION_FIELD_OPTIONS
2539
                    );
2540
                    $valueTable = Database::get_main_table(
2541
                        TABLE_MAIN_SESSION_FIELD_VALUES
2542
                    );
2543
                    $handlerId = 'session_id';
2544
                    break;
2545
            }
2546
2547
            if (!empty($optionTable)) {
2548
                $sql = "SELECT * FROM $optionTable WHERE field_id = $originalId ";
2549
                $result = $connection->query($sql);
2550
                $options = $result->fetchAll();
2551
2552
                foreach ($options as $option) {
2553
                    $params = [
2554
                        'display_text' => $option['option_display_text'],
2555
                        'field_id' => $newExtraFieldId,
2556
                        'option_order' => $option['option_order'],
2557
                        'option_value' => $option['option_value'],
2558
                    ];
2559
                    $connection->insert('extra_field_options', $params);
2560
                }
2561
2562
                $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...
2563
                $result = $connection->query($sql);
2564
                $values = $result->fetchAll();
2565
                if ($debug) {
2566
                    error_log("Fetch all values for field");
2567
                }
2568
            }
2569
2570
            if (!empty($values)) {
2571
                if ($debug) {
2572
                    error_log("Saving field value in new table");
2573
                }
2574
                $k = 0;
2575
                foreach ($values as $value) {
2576
                    if (isset($value[$handlerId])) {
2577
                        // Insert without the use of the entity as it reduces
2578
                        // speed to 2 records per second (much too slow)
2579
                        $params = [
2580
                            'field_id' => $newExtraFieldId,
2581
                            'value' => $value['field_value'],
2582
                            'item_id' => $value[$handlerId],
2583
                        ];
2584
                        $connection->insert('extra_field_values', $params);
2585
                        if ($debug && ($k % 10000 == 0)) {
2586
                            error_log("Saving field $k");
2587
                        }
2588
                        $k++;
2589
                    }
2590
                }
2591
            }
2592
        }
2593
    }
2594
2595
    if ($debug) {
0 ignored issues
show
introduced by
$debug is of type mixed, thus it always evaluated to true.
Loading history...
2596
        error_log('Remove index');
2597
    }
2598
2599
    // Drop temporary indexes added to increase speed of this function's queries
2600
    $sql = "ALTER TABLE c_document DROP INDEX tmpidx_doc";
2601
    $connection->executeQuery($sql);
2602
    $sql = "ALTER TABLE c_student_publication DROP INDEX tmpidx_stud";
2603
    $connection->executeQuery($sql);
2604
    $sql = "ALTER TABLE c_quiz DROP INDEX tmpidx_quiz";
2605
    $connection->executeQuery($sql);
2606
    $sql = "ALTER TABLE c_item_property DROP INDEX tmpidx_ip";
2607
    $connection->executeQuery($sql);
2608
2609
    if ($debug) {
2610
        error_log('Finish fixId function');
2611
    }
2612
2613
    fixLpId($connection, true);
2614
}
2615
2616
/**
2617
 * @param \Doctrine\DBAL\Connection $connection
2618
 * @param $debug
2619
 *
2620
 * @throws \Doctrine\DBAL\DBALException
2621
 */
2622
function fixLpId($connection, $debug)
2623
{
2624
    if ($debug) {
2625
        error_log('Fix lp.id lp.iids');
2626
    }
2627
2628
    $sql = 'SELECT id, title, code FROM course';
2629
    $result = $connection->query($sql);
2630
    $courses = $result->fetchAll();
2631
2632
    $sql = 'SELECT id FROM session';
2633
    $result = $connection->query($sql);
2634
    $sessions = $result->fetchAll();
2635
2636
    $tblCLp = Database::get_course_table(TABLE_LP_MAIN);
2637
    $tblCLpItem = Database::get_course_table(TABLE_LP_ITEM);
2638
    $toolTable = Database::get_course_table(TABLE_TOOL_LIST);
2639
2640
    if (!empty($sessions)) {
2641
        $sessions = array_column($sessions, 'id');
2642
        $sessions[] = 0;
2643
    } else {
2644
        $sessions = [0];
2645
    }
2646
2647
    foreach ($courses as $course) {
2648
        $courseId = $course['id'];
2649
        $sql = "SELECT * FROM $tblCLp WHERE c_id = $courseId AND iid <> id ORDER by iid";
2650
        $result = $connection->query($sql);
2651
        if ($debug) {
2652
            error_log('-------------');
2653
            error_log("Entering Lps in course #$courseId");
2654
            error_log($sql);
2655
        }
2656
        $lpList = $result->fetchAll();
2657
        $myOnlyLpList = [];
2658
        if (!empty($lpList)) {
2659
            foreach ($lpList as $lpInfo) {
2660
                $oldId = $lpInfo['id'];
2661
                $sql = "SELECT * FROM $tblCLpItem WHERE c_id = $courseId AND lp_id = $oldId ORDER by iid";
2662
                $result = $connection->query($sql);
2663
                $items = $result->fetchAll();
2664
                $lpInfo['lp_list'] = $items;
2665
                $myOnlyLpList[] = $lpInfo;
2666
            }
2667
        }
2668
2669
        if (!empty($myOnlyLpList)) {
2670
            foreach ($myOnlyLpList as $lpInfo) {
2671
                $lpIid = $lpInfo['iid'];
2672
                $oldId = $lpInfo['id'];
2673
                $items = $lpInfo['lp_list'];
2674
2675
                if (empty($items)) {
2676
                    continue;
2677
                }
2678
                $itemList = [];
2679
                foreach ($items as $subItem) {
2680
                    $itemList[$subItem['id']] = $subItem['iid'];
2681
                }
2682
                $variablesToFix = [
2683
                    'parent_item_id',
2684
                    'next_item_id',
2685
                    'prerequisite',
2686
                    'previous_item_id',
2687
                ];
2688
2689
                foreach ($sessions as $sessionId) {
2690
                    $correctLink = "lp/lp_controller.php?action=view&lp_id=$lpIid&id_session=$sessionId";
2691
                    $link = "newscorm/lp_controller.php?action=view&lp_id=$oldId&id_session=$sessionId";
2692
                    $secondLink = "lp/lp_controller.php?action=view&lp_id=$oldId&id_session=$sessionId";
2693
                    $sql = "UPDATE $toolTable
2694
                        SET link = '$correctLink'
2695
                        WHERE c_id = $courseId AND (link = '$link' OR link ='$secondLink')";
2696
                    $connection->query($sql);
2697
                }
2698
2699
                foreach ($items as $item) {
2700
                    $itemIid = $item['iid'];
2701
                    $itemId = $item['id'];
2702
                    foreach ($variablesToFix as $variable) {
2703
                        if (!empty($item[$variable]) && isset($itemList[$item[$variable]])) {
2704
                            $newId = $itemList[$item[$variable]];
2705
                            $sql = "UPDATE $tblCLpItem SET $variable = $newId
2706
                                    WHERE iid = $itemIid AND c_id = $courseId AND lp_id = $oldId";
2707
                            $connection->query($sql);
2708
                        }
2709
                    }
2710
2711
                    if ($item['item_type'] == 'document' && !empty($item['path'])) {
2712
                        $oldDocumentId = $item['path'];
2713
                        $sql = "SELECT * FROM c_document WHERE c_id = $courseId AND id = $oldDocumentId";
2714
                        $result = $connection->query($sql);
2715
                        $document = $result->fetch();
2716
                        if (!empty($document)) {
2717
                            $newDocumentId = $document['iid'];
2718
                            if (!empty($newDocumentId)) {
2719
                                $sql = "UPDATE $tblCLpItem SET path = $newDocumentId
2720
                                    WHERE iid = $itemIid AND c_id = $courseId";
2721
                                $connection->query($sql);
2722
                                if ($debug) {
2723
                                    //error_log("Fix document: ");
2724
                                    //error_log($sql);
2725
                                }
2726
                            }
2727
                        }
2728
                    }
2729
2730
                    // c_lp_view
2731
                    $sql = "UPDATE c_lp_view SET last_item = $itemIid
2732
                            WHERE c_id = $courseId AND last_item = $itemId AND lp_id = $oldId";
2733
                    $connection->query($sql);
2734
2735
                    // c_lp_item_view
2736
                    $sql = "UPDATE c_lp_item_view SET lp_item_id = $itemIid
2737
                            WHERE c_id = $courseId AND lp_item_id = $itemId";
2738
                    $connection->query($sql);
2739
2740
                    // Update track_exercises
2741
                    $sql = "UPDATE track_e_exercises SET orig_lp_item_id = $itemIid
2742
                            WHERE c_id = $courseId AND orig_lp_id = $oldId AND orig_lp_item_id = $itemId";
2743
                    $connection->query($sql);
2744
2745
                    // c_forum_thread
2746
                    $sql = "UPDATE c_forum_thread SET lp_item_id = $itemIid
2747
                            WHERE c_id = $courseId AND lp_item_id = $itemId";
2748
                    $connection->query($sql);
2749
2750
                    // orig_lp_item_view_id
2751
                    $sql = "SELECT * FROM c_lp_view
2752
                            WHERE c_id = $courseId AND lp_id = $oldId";
2753
                    $result = $connection->query($sql);
2754
                    $itemViewList = $result->fetchAll();
2755
                    if ($itemViewList) {
2756
                        foreach ($itemViewList as $itemView) {
2757
                            $userId = $itemView['user_id'];
2758
                            $oldItemViewId = $itemView['id'];
2759
                            $newItemView = $itemView['iid'];
2760
2761
                            if (empty($oldItemViewId)) {
2762
                                continue;
2763
                            }
2764
2765
                            $sql = "UPDATE track_e_exercises
2766
                                SET orig_lp_item_view_id = $newItemView
2767
                                WHERE
2768
                                  c_id = $courseId AND
2769
                                  orig_lp_id = $oldId AND
2770
                                  orig_lp_item_id = $itemIid AND
2771
                                  orig_lp_item_view_id = $oldItemViewId AND
2772
                                  exe_user_id = $userId
2773
                                  ";
2774
                            $connection->query($sql);
2775
2776
                            /*$sql = "UPDATE c_lp_item_view
2777
                                    SET lp_view_id = $newItemView
2778
                                    WHERE
2779
                                      lp_view_id = $oldItemViewId AND
2780
                                      c_id = $courseId
2781
                                  ";
2782
                            $connection->query($sql);*/
2783
                        }
2784
                    }
2785
2786
                    $sql = "UPDATE $tblCLpItem SET lp_id = $lpIid
2787
                            WHERE c_id = $courseId AND lp_id = $oldId AND id = $itemId";
2788
                    $connection->query($sql);
2789
2790
                    $sql = "UPDATE $tblCLpItem SET id = iid
2791
                            WHERE c_id = $courseId AND lp_id = $oldId AND id = $itemId";
2792
                    $connection->query($sql);
2793
                }
2794
2795
                $sql = "UPDATE c_lp_view SET lp_id = $lpIid WHERE c_id = $courseId AND lp_id = $oldId";
2796
                $connection->query($sql);
2797
2798
                $sql = "UPDATE c_forum_forum SET lp_id = $lpIid WHERE c_id = $courseId AND lp_id = $oldId";
2799
                $connection->query($sql);
2800
2801
                // Update track_exercises.
2802
                $sql = "UPDATE track_e_exercises SET orig_lp_id = $lpIid
2803
                        WHERE c_id = $courseId AND orig_lp_id = $oldId";
2804
                $connection->query($sql);
2805
2806
                $sql = "UPDATE $tblCLp SET id = iid WHERE c_id = $courseId AND id = $oldId ";
2807
                $connection->query($sql);
2808
            }
2809
        }
2810
    }
2811
2812
    if ($debug) {
2813
        error_log('END Fix lp.id lp.iids');
2814
    }
2815
}
2816
2817
/**
2818
 * @param string $distFile
2819
 * @param string $envFile
2820
 * @param array  $params
2821
 */
2822
function updateEnvFile($distFile, $envFile, $params)
2823
{
2824
    $requirements = [
2825
        'DATABASE_HOST',
2826
        'DATABASE_PORT',
2827
        'DATABASE_NAME',
2828
        'DATABASE_USER',
2829
        'DATABASE_PASSWORD',
2830
        'APP_INSTALLED',
2831
        'APP_ENCRYPT_METHOD',
2832
    ];
2833
2834
    foreach ($requirements as $requirement) {
2835
        if (!isset($params['{{'.$requirement.'}}'])) {
2836
            throw new \Exception("The parameter $requirement is needed in order to edit the .env.local file");
2837
        }
2838
    }
2839
2840
    $contents = file_get_contents($distFile);
2841
    $contents = str_replace(array_keys($params), array_values($params), $contents);
2842
    file_put_contents($envFile, $contents);
2843
}
2844
2845
/**
2846
 * @param SymfonyContainer $container
2847
 * @param EntityManager    $manager
2848
 */
2849
function installGroups($container, $manager)
0 ignored issues
show
Unused Code introduced by
The parameter $container is not used and could be removed. ( Ignorable by Annotation )

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

2849
function installGroups(/** @scrutinizer ignore-unused */ $container, $manager)

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...
2850
{
2851
    // Creating fos_group (groups and roles)
2852
    $groups = [
2853
        [
2854
            'code' => 'ADMIN',
2855
            'title' => 'Administrators',
2856
            'roles' => ['ROLE_ADMIN'],
2857
        ],
2858
        [
2859
            'code' => 'STUDENT',
2860
            'title' => 'Students',
2861
            'roles' => ['ROLE_STUDENT'],
2862
        ],
2863
        [
2864
            'code' => 'TEACHER',
2865
            'title' => 'Teachers',
2866
            'roles' => ['ROLE_TEACHER'],
2867
        ],
2868
        [
2869
            'code' => 'RRHH',
2870
            'title' => 'Human resources manager',
2871
            'roles' => ['ROLE_RRHH'],
2872
        ],
2873
        [
2874
            'code' => 'SESSION_MANAGER',
2875
            'title' => 'Session',
2876
            'roles' => ['ROLE_SESSION_MANAGER'],
2877
        ],
2878
        [
2879
            'code' => 'QUESTION_MANAGER',
2880
            'title' => 'Question manager',
2881
            'roles' => ['ROLE_QUESTION_MANAGER'],
2882
        ],
2883
        [
2884
            'code' => 'STUDENT_BOSS',
2885
            'title' => 'Student boss',
2886
            'roles' => ['ROLE_STUDENT_BOSS'],
2887
        ],
2888
        [
2889
            'code' => 'INVITEE',
2890
            'title' => 'Invitee',
2891
            'roles' => ['ROLE_INVITEE'],
2892
        ],
2893
    ];
2894
    $repo = $manager->getRepository('ChamiloUserBundle:Group');
2895
    foreach ($groups as $groupData) {
2896
        $criteria = ['code' => $groupData['code']];
2897
        $groupExists = $repo->findOneBy($criteria);
2898
        if (!$groupExists) {
2899
            $group = new Group($groupData['title']);
2900
            $group
2901
                ->setCode($groupData['code']);
2902
2903
            foreach ($groupData['roles'] as $role) {
2904
                $group->addRole($role);
2905
            }
2906
            $manager->persist($group);
2907
        }
2908
    }
2909
    $manager->flush();
2910
}
2911
2912
/**
2913
 * @param SymfonyContainer $container
2914
 */
2915
function installPages($container)
2916
{
2917
    error_log('installPages');
2918
2919
    $siteManager = Container::getSiteManager();
2920
2921
    // Create site
2922
    /** @var Chamilo\PageBundle\Entity\Site $site */
2923
    $site = $siteManager->create();
2924
    $site->setHost('localhost');
2925
    $site->setEnabled(true);
2926
    $site->setName('localhost');
2927
    $site->setEnabledFrom(new \DateTime('now'));
2928
    $site->setEnabledTo(new \DateTime('+20 years'));
2929
    $site->setRelativePath('');
2930
    $site->setIsDefault(true);
2931
    $site->setLocale('en');
2932
    $siteManager->save($site);
2933
2934
    // Create home page
2935
    /** @var PageManager $pageManager */
2936
    $pageManager = $container->get('sonata.page.manager.page');
2937
    /** @var \Sonata\PageBundle\Model\Page $page */
2938
    $page = $pageManager->create();
2939
    $page->setSlug('homepage');
2940
    $page->setUrl('/');
2941
    $page->setName('homepage');
2942
    $page->setTitle('home');
2943
    $page->setEnabled(true);
2944
    $page->setDecorate(1);
2945
    $page->setRequestMethod('GET|POST|HEAD|DELETE|PUT');
2946
    $page->setTemplateCode('default');
2947
    $page->setRouteName('homepage');
2948
    //$page->setParent($this->getReference('page-homepage'));
2949
    $page->setSite($site);
2950
    $pageManager->save($page);
2951
2952
    // Create welcome page
2953
    $pageWelcome = $pageManager->create();
2954
    $pageWelcome->setSlug('welcome');
2955
    $pageWelcome->setUrl('/welcome');
2956
    $pageWelcome->setName('welcome');
2957
    $pageWelcome->setTitle('welcome');
2958
    $pageWelcome->setEnabled(true);
2959
    $pageWelcome->setDecorate(1);
2960
    $pageWelcome->setRequestMethod('GET');
2961
    $pageWelcome->setTemplateCode('default');
2962
    $pageWelcome->setRouteName('welcome');
2963
    $pageWelcome->setParent($page);
2964
    $pageWelcome->setSite($site);
2965
    $pageManager->save($pageWelcome);
2966
2967
    // Creating page blocks
2968
    $templateManager = $container->get('sonata.page.template_manager');
2969
    $template = $templateManager->get('default');
2970
    $templateContainers = $template->getContainers();
2971
2972
    $containers = [];
2973
    foreach ($templateContainers as $id => $area) {
2974
        $containers[$id] = [
2975
            'area' => $area,
2976
            'block' => false,
2977
        ];
2978
    }
2979
2980
    // Create blocks for this page
2981
    $blockInteractor = $container->get('sonata.page.block_interactor');
2982
    $parentBlock = null;
2983
    foreach ($containers as $id => $area) {
2984
        if (false === $area['block'] && $templateContainers[$id]['shared'] === false) {
2985
            $block = $blockInteractor->createNewContainer(
2986
                [
2987
                    'page' => $pageWelcome,
2988
                    'name' => $templateContainers[$id]['name'],
2989
                    'code' => $id,
2990
                ]
2991
            );
2992
2993
            if ($id === 'content' && $templateContainers[$id]['name'] == 'Main content') {
2994
                $parentBlock = $block;
2995
            }
2996
        }
2997
    }
2998
2999
    // Create block in main content
3000
    $block = $container->get('sonata.page.manager.block');
3001
    /** @var \Sonata\BlockBundle\Model\Block $myBlock */
3002
    $myBlock = $block->create();
3003
    $myBlock->setType('sonata.formatter.block.formatter');
3004
    $myBlock->setSetting('format', 'richhtml');
3005
    $myBlock->setSetting('content', '');
3006
    $myBlock->setSetting('rawContent', '');
3007
    $myBlock->setSetting('template', '@SonataFormatter/Block/block_formatter.html.twig');
3008
    $myBlock->setParent($parentBlock);
3009
    $pageWelcome->addBlocks($myBlock);
3010
    $pageManager->save($pageWelcome);
3011
}
3012
3013
/**
3014
 * @param SymfonyContainer $container
3015
 * @param EntityManager    $manager
3016
 * @param bool             $upgrade
3017
 */
3018
function installSchemas($container, $manager, $upgrade = false)
3019
{
3020
    error_log('installSchemas');
3021
    $settingsManager = Container::getSettingsManager();
3022
3023
    // Install course tools (table "tool")
3024
    $toolChain = $container->get(ToolChain::class);
3025
    $toolChain->createTools($manager);
3026
3027
    $urlRepo = $container->get('Chamilo\CoreBundle\Repository\AccessUrlRepository');
3028
    $accessUrl = $urlRepo->find(1);
3029
    if (!$accessUrl) {
3030
        $em = $urlRepo->getEntityManager();
3031
3032
        // Creating AccessUrl
3033
        $accessUrl = new AccessUrl();
3034
        $accessUrl
3035
            ->setUrl('http://localhost/')
3036
            ->setDescription('')
3037
            ->setActive(1)
3038
        ;
3039
        $em->persist($accessUrl);
3040
        $em->flush();
3041
    }
3042
3043
    if ($upgrade) {
3044
        $settingsManager->updateSchemas($accessUrl);
3045
    } else {
3046
        // Installing schemas (filling settings_current table)
3047
        $settingsManager->installSchemas($accessUrl);
3048
    }
3049
}
3050
3051
/**
3052
 * @param SymfonyContainer $container
3053
 */
3054
function upgradeWithContainer($container)
3055
{
3056
    Container::setContainer($container);
3057
    Container::setLegacyServices($container, false);
3058
    error_log('setLegacyServices');
3059
    $manager = Database::getManager();
3060
    installGroups($container, $manager);
3061
    error_log('installGroups');
3062
    // @todo check if adminId = 1
3063
    installSchemas($container, $manager, 1, true);
3064
    installPages($container);
3065
    fixMedia($container);
3066
}
3067
3068
function fixMedia($container)
3069
{
3070
    error_log('fix medias');
3071
    $pool = $container->get('sonata.media.pool');
3072
    $contextManager = $container->get('sonata.classification.manager.context');
3073
    $categoryManager = $container->get('sonata.media.manager.category');
3074
3075
    foreach ($pool->getContexts() as $context => $contextAttrs) {
3076
        /** @var ContextInterface $defaultContext */
3077
        $defaultContext = $contextManager->findOneBy([
3078
            'id' => $context,
3079
        ]);
3080
3081
        if (!$defaultContext) {
3082
            $defaultContext = $contextManager->create();
3083
            $defaultContext->setId($context);
3084
            $defaultContext->setName(ucfirst($context));
3085
            $defaultContext->setEnabled(true);
3086
3087
            $contextManager->save($defaultContext);
3088
        }
3089
3090
        $defaultCategory = $categoryManager->getRootCategory($defaultContext);
3091
3092
        if (!$defaultCategory) {
3093
            $defaultCategory = $categoryManager->create();
3094
            $defaultCategory->setContext($defaultContext);
3095
            $defaultCategory->setName(ucfirst($context));
3096
            $defaultCategory->setEnabled(true);
3097
            $defaultCategory->setPosition(0);
3098
3099
            $categoryManager->save($defaultCategory);
3100
        }
3101
    }
3102
}
3103
3104
/**
3105
 * After the schema was created (table creation), the function adds
3106
 * admin/platform information.
3107
 *
3108
 * @param \Psr\Container\ContainerInterface $container
3109
 * @param string                            $sysPath
3110
 * @param string                            $encryptPassForm
3111
 * @param string                            $passForm
3112
 * @param string                            $adminLastName
3113
 * @param string                            $adminFirstName
3114
 * @param string                            $loginForm
3115
 * @param string                            $emailForm
3116
 * @param string                            $adminPhoneForm
3117
 * @param string                            $languageForm
3118
 * @param string                            $institutionForm
3119
 * @param string                            $institutionUrlForm
3120
 * @param string                            $siteName
3121
 * @param string                            $allowSelfReg
3122
 * @param string                            $allowSelfRegProf
3123
 * @param string                            $installationProfile Installation profile, if any was provided
3124
 */
3125
function finishInstallationWithContainer(
3126
    $container,
3127
    $sysPath,
3128
    $encryptPassForm,
3129
    $passForm,
3130
    $adminLastName,
3131
    $adminFirstName,
3132
    $loginForm,
3133
    $emailForm,
3134
    $adminPhoneForm,
3135
    $languageForm,
3136
    $institutionForm,
3137
    $institutionUrlForm,
3138
    $siteName,
3139
    $allowSelfReg,
3140
    $allowSelfRegProf,
3141
    $installationProfile = ''
3142
) {
3143
    error_log('finishInstallationWithContainer');
3144
    $sysPath = !empty($sysPath) ? $sysPath : api_get_path(SYS_PATH);
3145
    Container::setContainer($container);
3146
    Container::setLegacyServices($container, false);
3147
3148
    $manager = Database::getManager();
3149
    $connection = $manager->getConnection();
3150
    $trans = $container->get('translator');
3151
    $sql = getVersionTable();
3152
3153
    // Add version table
3154
    $connection->executeQuery($sql);
3155
3156
    // Add tickets defaults
3157
    $ticketProject = new TicketProject();
3158
    $ticketProject
3159
        ->setId(1)
3160
        ->setName('Ticket System')
3161
        ->setInsertUserId(1);
3162
3163
    $manager->persist($ticketProject);
3164
3165
    $categories = [
3166
        $trans->trans('Enrollment') => $trans->trans('Tickets about enrollment'),
3167
        $trans->trans('General information') => $trans->trans('Tickets about general information'),
3168
        $trans->trans('Requests and paperwork') => $trans->trans('Tickets about requests and paperwork'),
3169
        $trans->trans('Academic Incidents') => $trans->trans('Tickets about academic incidents, like exams, practices, tasks, etc.'),
3170
        $trans->trans('Virtual campus') => $trans->trans('Tickets about virtual campus'),
3171
        $trans->trans('Online evaluation') => $trans->trans('Tickets about online evaluation'),
3172
    ];
3173
3174
    $i = 1;
3175
    foreach ($categories as $category => $description) {
3176
        // Online evaluation requires a course
3177
        $ticketCategory = new TicketCategory();
3178
        $ticketCategory
3179
            ->setId($i)
3180
            ->setName($category)
3181
            ->setDescription($description)
3182
            ->setProject($ticketProject)
3183
            ->setInsertUserId(1);
3184
3185
        $isRequired = $i == 6;
3186
        $ticketCategory->setCourseRequired($isRequired);
3187
3188
        $manager->persist($ticketCategory);
3189
        $i++;
3190
    }
3191
3192
    // Default Priorities
3193
    $defaultPriorities = [
3194
        TicketManager::PRIORITY_NORMAL => $trans->trans('Normal'),
3195
        TicketManager::PRIORITY_HIGH => $trans->trans('High'),
3196
        TicketManager::PRIORITY_LOW => $trans->trans('Low'),
3197
    ];
3198
3199
    $i = 1;
3200
    foreach ($defaultPriorities as $code => $priority) {
3201
        $ticketPriority = new TicketPriority();
3202
        $ticketPriority
3203
            ->setId($i)
3204
            ->setName($priority)
3205
            ->setCode($code)
3206
            ->setInsertUserId(1);
3207
3208
        $manager->persist($ticketPriority);
3209
        $i++;
3210
    }
3211
    $manager->flush();
3212
3213
    $table = Database::get_main_table(TABLE_TICKET_STATUS);
3214
3215
    // Default status
3216
    $defaultStatus = [
3217
        TicketManager::STATUS_NEW => $trans->trans('New'),
3218
        TicketManager::STATUS_PENDING => $trans->trans('Pending'),
3219
        TicketManager::STATUS_UNCONFIRMED => $trans->trans('Unconfirmed'),
3220
        TicketManager::STATUS_CLOSE => $trans->trans('Close'),
3221
        TicketManager::STATUS_FORWARDED => $trans->trans('Forwarded'),
3222
    ];
3223
3224
    $i = 1;
3225
    foreach ($defaultStatus as $code => $status) {
3226
        $attributes = [
3227
            'id' => $i,
3228
            'code' => $code,
3229
            'name' => $status,
3230
        ];
3231
        Database::insert($table, $attributes);
3232
        $i++;
3233
    }
3234
3235
    installGroups($container, $manager);
3236
    installSchemas($container, $manager, false);
3237
    installPages($container);
3238
3239
    error_log('Inserting data.sql');
3240
    // Inserting default data
3241
    $data = file_get_contents($sysPath.'main/install/data.sql');
3242
    $result = $manager->getConnection()->prepare($data);
3243
    $result->execute();
3244
    $result->closeCursor();
3245
3246
    UserManager::setPasswordEncryption($encryptPassForm);
3247
3248
    error_log('user creation - admin');
3249
3250
    // Create admin user.
3251
    $adminId = UserManager::create_user(
3252
        $adminFirstName,
3253
        $adminLastName,
3254
        1,
3255
        $emailForm,
3256
        $loginForm,
3257
        $passForm,
3258
        'ADMIN',
3259
        $languageForm,
3260
        $adminPhoneForm,
3261
        '',
3262
        PLATFORM_AUTH_SOURCE,
3263
        '',
3264
        1,
3265
        0,
3266
        null,
3267
        '',
3268
        false,
3269
        true,
3270
        '',
3271
        false,
3272
        '',
3273
        0,
3274
        [],
3275
        '',
3276
        false
3277
    );
3278
3279
    error_log('user creation - anon');
3280
    // Create anonymous user.
3281
    $anonId = UserManager::create_user(
3282
        'Joe',
3283
        'Anonymous',
3284
        6,
3285
        'anonymous@localhost',
3286
        'anon',
3287
        'anon',
3288
        'anonymous',
3289
        $languageForm,
3290
        '',
3291
        '',
3292
        PLATFORM_AUTH_SOURCE,
3293
        '',
3294
        1,
3295
        0,
3296
        null,
3297
        '',
3298
        false,
3299
        false,
3300
        '',
3301
        false,
3302
        '',
3303
        $adminId,
3304
        [],
3305
        '',
3306
        false
3307
    );
3308
3309
    error_log('Adding access url as a node');
3310
    $userManager = $container->get('Chamilo\UserBundle\Repository\UserRepository');
3311
    $urlRepo = $container->get('Chamilo\CoreBundle\Repository\AccessUrlRepository');
3312
3313
    $accessUrl = $urlRepo->find(1);
3314
3315
    $branch = new BranchSync();
3316
    $branch->setBranchName('localhost');
3317
    $branch->setUrl($accessUrl);
3318
3319
    $manager->persist($branch);
3320
3321
    $admin = $userManager->find($adminId);
3322
3323
    $userManager->addUserToResourceNode($adminId, $adminId);
3324
    $userManager->addUserToResourceNode($anonId, $adminId);
3325
3326
    $urlRepo->addResourceNode($accessUrl, $admin);
3327
3328
    $manager->flush();
3329
3330
    // Set default language
3331
    Database::update(
3332
        Database::get_main_table(TABLE_MAIN_LANGUAGE),
3333
        ['available' => 1],
3334
        ['dokeos_folder = ?' => $languageForm]
3335
    );
3336
3337
    // Install settings
3338
    installSettings(
3339
        $institutionForm,
3340
        $institutionUrlForm,
3341
        $siteName,
3342
        $emailForm,
3343
        $adminLastName,
3344
        $adminFirstName,
3345
        $languageForm,
3346
        $allowSelfReg,
3347
        $allowSelfRegProf,
3348
        $installationProfile
3349
    );
3350
3351
    lockSettings();
3352
    updateDirAndFilesPermissions();
3353
    fixMedia($container);
3354
3355
    // Set the latest version
3356
    /*$path = $sysPath.'app/Migrations/Schema/V111/';
3357
    $finder = new \Symfony\Component\Finder\Finder();
3358
    $files = $finder->files()->in($path);
3359
3360
    // Needed for chash
3361
    createVersionTable();
3362
3363
    foreach ($files as $version) {
3364
        $version = str_replace(['Version', '.php'], '', $version->getFilename());
3365
        $sql = "INSERT INTO version (version) VALUES ('$version')";
3366
        Database::query($sql);
3367
    }*/
3368
}
3369
3370
/**
3371
 * Creates 'version' table.
3372
 */
3373
function createVersionTable()
3374
{
3375
    $sql = getVersionTable();
3376
    Database::query($sql);
3377
}
3378
3379
/**
3380
 * Get version creation table query.
3381
 *
3382
 * @return string
3383
 */
3384
function getVersionTable()
3385
{
3386
    return 'CREATE TABLE IF NOT EXISTS version (id int unsigned NOT NULL AUTO_INCREMENT, version varchar(20), PRIMARY KEY(id), UNIQUE(version));';
3387
}
3388
3389
/**
3390
 * Update settings based on installation profile defined in a JSON file.
3391
 *
3392
 * @param string $installationProfile The name of the JSON file in main/install/profiles/ folder
3393
 *
3394
 * @return bool false on failure (no bad consequences anyway, just ignoring profile)
3395
 */
3396
function installProfileSettings($installationProfile = '')
3397
{
3398
    if (empty($installationProfile)) {
3399
        return false;
3400
    }
3401
    $jsonPath = api_get_path(SYS_PATH).'main/install/profiles/'.$installationProfile.'.json';
3402
    // Make sure the path to the profile is not hacked
3403
    if (!Security::check_abs_path($jsonPath, api_get_path(SYS_PATH).'main/install/profiles/')) {
3404
        return false;
3405
    }
3406
    if (!is_file($jsonPath)) {
3407
        return false;
3408
    }
3409
    if (!is_readable($jsonPath)) {
3410
        return false;
3411
    }
3412
    if (!function_exists('json_decode')) {
3413
        // The php-json extension is not available. Ignore profile.
3414
        return false;
3415
    }
3416
    $json = file_get_contents($jsonPath);
3417
    $params = json_decode($json);
3418
    if ($params === false or $params === null) {
3419
        return false;
3420
    }
3421
    $settings = $params->params;
3422
    if (!empty($params->parent)) {
3423
        installProfileSettings($params->parent);
3424
    }
3425
3426
    $tblSettings = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
3427
3428
    foreach ($settings as $id => $param) {
3429
        $conditions = ['variable = ? ' => $param->variable];
3430
3431
        if (!empty($param->subkey)) {
3432
            $conditions['AND subkey = ? '] = $param->subkey;
3433
        }
3434
3435
        Database::update(
3436
            $tblSettings,
3437
            ['selected_value' => $param->selected_value],
3438
            $conditions
3439
        );
3440
    }
3441
3442
    return true;
3443
}
3444
3445
/**
3446
 * Quick function to remove a directory with its subdirectories.
3447
 *
3448
 * @param $dir
3449
 */
3450
function rrmdir($dir)
3451
{
3452
    if (is_dir($dir)) {
3453
        $objects = scandir($dir);
3454
        foreach ($objects as $object) {
3455
            if ($object != "." && $object != "..") {
3456
                if (filetype($dir."/".$object) == "dir") {
3457
                    @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

3457
                    /** @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...
3458
                } else {
3459
                    @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

3459
                    /** @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...
3460
                }
3461
            }
3462
        }
3463
        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

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