Completed
Push — master ( bdff43...b35e01 )
by Julito
08:47
created

fixMedia()   A

Complexity

Conditions 4
Paths 5

Size

Total Lines 32
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

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

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

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

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

// Bar.php
namespace OtherDir;

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

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

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

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

// Bar.php
namespace OtherDir;

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

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

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

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

Loading history...
122
) {
123
    $currentPhpValue = getPhpSetting($phpSetting);
124
    if ($currentPhpValue == $recommendedValue) {
125
        return Display::label($currentPhpValue.' '.$returnSuccess, 'success');
0 ignored issues
show
Bug introduced by
Are you sure $returnSuccess of type false|mixed can be used in concatenation? ( Ignorable by Annotation )

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

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

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

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

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

363
    fclose(/** @scrutinizer ignore-type */ $fp);
Loading history...
364
365
    return explode('<br />', nl2br($buffer));
366
}
367
368
/**
369
 * We assume this function is called from install scripts that reside inside the install folder.
370
 */
371
function set_file_folder_permissions()
372
{
373
    @chmod('.', 0755); //set permissions on install dir
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for chmod(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

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

373
    /** @scrutinizer ignore-unhandled */ @chmod('.', 0755); //set permissions on install dir

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

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

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
374
    @chmod('..', 0755); //set permissions on parent dir of install dir
375
}
376
377
/**
378
 * Write the main system config file.
379
 *
380
 * @param string $path Path to the config file
381
 */
382
function write_system_config_file($path)
383
{
384
    global $dbHostForm;
385
    global $dbPortForm;
386
    global $dbUsernameForm;
387
    global $dbPassForm;
388
    global $dbNameForm;
389
    global $urlForm;
390
    global $pathForm;
391
    global $urlAppendPath;
392
    global $languageForm;
393
    global $encryptPassForm;
394
    global $session_lifetime;
395
    global $new_version;
396
    global $new_version_stable;
397
398
    $root_sys = api_add_trailing_slash(str_replace('\\', '/', realpath($pathForm)));
399
    $content = file_get_contents(__DIR__.'/'.SYSTEM_CONFIG_FILENAME);
400
401
    $config['{DATE_GENERATED}'] = date('r');
0 ignored issues
show
Comprehensibility Best Practice introduced by
$config was never initialized. Although not strictly required by PHP, it is generally a good practice to add $config = array(); before regardless.
Loading history...
402
    $config['{DATABASE_HOST}'] = $dbHostForm;
403
    $config['{DATABASE_PORT}'] = $dbPortForm;
404
    $config['{DATABASE_USER}'] = $dbUsernameForm;
405
    $config['{DATABASE_PASSWORD}'] = $dbPassForm;
406
    $config['{DATABASE_MAIN}'] = $dbNameForm;
407
    $config['{ROOT_WEB}'] = $urlForm;
408
    $config['{ROOT_SYS}'] = $root_sys;
409
    $config['{URL_APPEND_PATH}'] = $urlAppendPath;
410
    $config['{PLATFORM_LANGUAGE}'] = $languageForm;
411
    $config['{SECURITY_KEY}'] = md5(uniqid(rand().time()));
412
    $config['{ENCRYPT_PASSWORD}'] = $encryptPassForm;
413
414
    $config['SESSION_LIFETIME'] = $session_lifetime;
415
    $config['{NEW_VERSION}'] = $new_version;
416
    $config['NEW_VERSION_STABLE'] = trueFalse($new_version_stable);
417
418
    foreach ($config as $key => $value) {
419
        $content = str_replace($key, $value, $content);
420
    }
421
    $fp = @fopen($path, 'w');
422
423
    if (!$fp) {
0 ignored issues
show
introduced by
$fp is of type false|resource, thus it always evaluated to false.
Loading history...
424
        echo '<strong>
425
                <font color="red">Your script doesn\'t have write access to the config directory</font></strong><br />
426
                <em>('.str_replace('\\', '/', realpath($path)).')</em><br /><br />
427
                You probably do not have write access on Chamilo root directory,
428
                i.e. you should <em>CHMOD 777</em> or <em>755</em> or <em>775</em>.<br /><br />
429
                Your problems can be related on two possible causes:<br />
430
                <ul>
431
                  <li>Permission problems.<br />Try initially with <em>chmod -R 777</em> and increase restrictions gradually.</li>
432
                  <li>PHP is running in <a href="http://www.php.net/manual/en/features.safe-mode.php" target="_blank">Safe-Mode</a>. 
433
                  If possible, try to switch it off.</li>
434
                </ul>
435
                <a href="http://forum.chamilo.org/" target="_blank">Read about this problem in Support Forum</a><br /><br />
436
                Please go back to step 5.
437
                <p><input type="submit" name="step5" value="&lt; Back" /></p>
438
                </td></tr></table></form></body></html>';
439
        exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
440
    }
441
442
    fwrite($fp, $content);
443
    fclose($fp);
444
}
445
446
/**
447
 * Returns a list of language directories.
448
 */
449
function get_language_folder_list()
450
{
451
    return [
452
        'ar' => 'arabic',
453
        'ast' => 'asturian',
454
        'bg' => 'bulgarian',
455
        'bs' => 'bosnian',
456
        'ca' => 'catalan',
457
        'zh' => 'simpl_chinese',
458
        'zh-tw' => 'trad_chinese',
459
        'cs' => 'czech',
460
        'da' => 'danish',
461
        'prs' => 'dari',
462
        'de' => 'german',
463
        'el' => 'greek',
464
        'en' => 'english',
465
        'es' => 'spanish',
466
        'eo' => 'esperanto',
467
        'eu' => 'basque',
468
        'fa' => 'persian',
469
        'fr' => 'french',
470
        'fur' => 'friulian',
471
        'gl' => 'galician',
472
        'ka' => 'georgian',
473
        'hr' => 'croatian',
474
        'he' => 'hebrew',
475
        'hi' => 'hindi',
476
        'id' => 'indonesian',
477
        'it' => 'italian',
478
        'ko' => 'korean',
479
        'lv' => 'latvian',
480
        'lt' => 'lithuanian',
481
        'mk' => 'macedonian',
482
        'hu' => 'hungarian',
483
        'ms' => 'malay',
484
        'nl' => 'dutch',
485
        'ja' => 'japanese',
486
        'no' => 'norwegian',
487
        'oc' => 'occitan',
488
        'ps' => 'pashto',
489
        'pl' => 'polish',
490
        'pt' => 'portuguese',
491
        'pt-br' => 'brazilian',
492
        'ro' => 'romanian',
493
        'qu' => 'quechua_cusco',
494
        'ru' => 'russian',
495
        'sk' => 'slovak',
496
        'sl' => 'slovenian',
497
        'sr' => 'serbian',
498
        'fi' => 'finnish',
499
        'sv' => 'swedish',
500
        'th' => 'thai',
501
        'tr' => 'turkish',
502
        'uk' => 'ukrainian',
503
        'vi' => 'vietnamese',
504
        'sw' => 'swahili',
505
        'yo' => 'yoruba',
506
    ];
507
}
508
509
/**
510
 * This function returns the value of a parameter from the configuration file.
511
 *
512
 * WARNING - this function relies heavily on global variables $updateFromConfigFile
513
 * and $configFile, and also changes these globals. This can be rewritten.
514
 *
515
 * @param string $param      the parameter of which the value is returned
516
 * @param string $updatePath If we want to give the path rather than take it from POST
517
 *
518
 * @return string the value of the parameter
519
 *
520
 * @author Olivier Brouckaert
521
 * @author Reworked by Ivan Tcholakov, 2010
522
 */
523
function get_config_param($param, $updatePath = '')
524
{
525
    global $configFile, $updateFromConfigFile;
526
527
    // Look if we already have the queried parameter.
528
    if (is_array($configFile) && isset($configFile[$param])) {
529
        return $configFile[$param];
530
    }
531
    if (empty($updatePath) && !empty($_POST['updatePath'])) {
532
        $updatePath = $_POST['updatePath'];
533
    }
534
535
    if (empty($updatePath)) {
536
        $updatePath = api_get_path(SYS_PATH);
537
    }
538
    $updatePath = api_add_trailing_slash(str_replace('\\', '/', realpath($updatePath)));
539
    $updateFromInstalledVersionFile = '';
540
541
    if (empty($updateFromConfigFile)) {
542
        // If update from previous install was requested,
543
        // try to recover config file from Chamilo 1.9.x
544
        if (file_exists($updatePath.'main/inc/conf/configuration.php')) {
545
            $updateFromConfigFile = 'main/inc/conf/configuration.php';
546
        } elseif (file_exists($updatePath.'app/config/configuration.php')) {
547
            $updateFromConfigFile = 'app/config/configuration.php';
548
        } elseif (file_exists($updatePath.'config/configuration.php')) {
549
            $updateFromConfigFile = 'config/configuration.php';
550
        } else {
551
            // Give up recovering.
552
            //error_log('Chamilo Notice: Could not find previous config file at '.$updatePath.'main/inc/conf/configuration.php nor at '.$updatePath.'claroline/inc/conf/claro_main.conf.php in get_config_param(). Will start new config (in '.__FILE__.', line '.__LINE__.')', 0);
553
            return null;
554
        }
555
    }
556
557
    if (file_exists($updatePath.$updateFromConfigFile) &&
558
        !is_dir($updatePath.$updateFromConfigFile)
559
    ) {
560
        require $updatePath.$updateFromConfigFile;
561
        $config = new Zend\Config\Config($_configuration);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $_configuration does not exist. Did you maybe mean $config?
Loading history...
562
563
        return $config->get($param);
564
    }
565
566
    error_log('Config array could not be found in get_config_param()', 0);
567
568
    return null;
569
}
570
571
/*      DATABASE RELATED FUNCTIONS */
572
573
/**
574
 * Gets a configuration parameter from the database. Returns returns null on failure.
575
 *
576
 * @param string $param Name of param we want
577
 *
578
 * @return mixed The parameter value or null if not found
579
 */
580
function get_config_param_from_db($param = '')
581
{
582
    $param = Database::escape_string($param);
583
584
    if (($res = Database::query("SELECT * FROM settings_current WHERE variable = '$param'")) !== false) {
585
        if (Database::num_rows($res) > 0) {
586
            $row = Database::fetch_array($res);
587
588
            return $row['selected_value'];
589
        }
590
    }
591
592
    return null;
593
}
594
595
/**
596
 * Connect to the database and returns the entity manager.
597
 *
598
 * @param string $dbHostForm     DB host
599
 * @param string $dbUsernameForm DB username
600
 * @param string $dbPassForm     DB password
601
 * @param string $dbNameForm     DB name
602
 * @param int    $dbPortForm     DB port
603
 *
604
 * @return \Database
605
 */
606
function connectToDatabase(
607
    $dbHostForm,
608
    $dbUsernameForm,
609
    $dbPassForm,
610
    $dbNameForm,
611
    $dbPortForm = 3306
612
) {
613
    $dbParams = [
614
        'driver' => 'pdo_mysql',
615
        'host' => $dbHostForm,
616
        'port' => $dbPortForm,
617
        'user' => $dbUsernameForm,
618
        'password' => $dbPassForm,
619
        'dbname' => $dbNameForm,
620
    ];
621
622
    $database = new \Database();
623
    $database->connect($dbParams);
624
625
    return $database;
626
}
627
628
/*      DISPLAY FUNCTIONS */
629
630
/**
631
 * This function prints class=active_step $current_step=$param.
632
 *
633
 * @param int $param A step in the installer process
634
 *
635
 * @author Patrick Cool <[email protected]>, Ghent University
636
 */
637
function step_active($param)
638
{
639
    global $current_step;
640
    if ($param == $current_step) {
641
        echo 'active';
642
    }
643
}
644
645
/**
646
 * This function displays the Step X of Y -.
647
 *
648
 * @return string String that says 'Step X of Y' with the right values
649
 */
650
function display_step_sequence()
651
{
652
    global $current_step;
653
654
    return get_lang('Step'.$current_step).' &ndash; ';
655
}
656
657
/**
658
 * Displays a drop down box for selection the preferred language.
659
 */
660
function display_language_selection_box(
661
    $name = 'language_list',
0 ignored issues
show
Unused Code introduced by
The parameter $name is not used and could be removed. ( Ignorable by Annotation )

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

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

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

Loading history...
662
    $default_language = 'english'
663
) {
664
    // Reading language list.
665
    $language_list = get_language_folder_list();
666
667
    // Sanity checks due to the possibility for customizations.
668
    if (!is_array($language_list) || empty($language_list)) {
669
        $language_list = ['en' => 'English'];
670
    }
671
672
    // Sorting again, if it is necessary.
673
    //asort($language_list);
674
675
    // More sanity checks.
676
    if (!array_key_exists($default_language, $language_list)) {
677
        if (array_key_exists('en', $language_list)) {
678
            $default_language = 'en';
679
        } else {
680
            $language_keys = array_keys($language_list);
681
            $default_language = $language_keys[0];
682
        }
683
    }
684
685
    // Displaying the box.
686
687
    $html = Display::select(
688
        'language_list',
689
        $language_list,
690
        $default_language,
691
        ['class' => 'form-control selectpicker show-tick form-control'],
692
        false
693
    );
694
695
    return $html;
696
}
697
698
/**
699
 * This function displays a language dropdown box so that the installatioin
700
 * can be done in the language of the user.
701
 */
702
function display_language_selection()
703
{
704
    ?>
705
        <div class="install-icon">
706
            <img width="150px;" src="chamilo-install.svg"/>
707
        </div>
708
        <h2 class="install-title">
709
            <?php echo display_step_sequence(); ?>
710
            <?php echo get_lang('InstallationLanguage'); ?>
711
        </h2>
712
        <label for="language_list"><?php echo get_lang('Please select installation language'); ?></label>
713
        <div class="form-group">
714
            <?php echo display_language_selection_box('language_list', api_get_interface_language()); ?>
715
        </div>
716
        <button type="submit" name="step1" class="btn btn-success" value="<?php echo get_lang('Next'); ?>">
717
            <em class="fa fa-forward"> </em>
718
            <?php echo get_lang('Next'); ?>
719
        </button>
720
        <input type="hidden" name="is_executable" id="is_executable" value="-" />
721
        <div class="RequirementHeading">
722
            <?php echo get_lang('YourLanguageNotThereContactUs'); ?>
723
        </div>
724
<?php
725
}
726
727
/**
728
 * This function displays the requirements for installing Chamilo.
729
 *
730
 * @param string $installType
731
 * @param bool   $badUpdatePath
732
 * @param bool   $badUpdatePath
733
 * @param string $updatePath            The updatePath given (if given)
734
 * @param array  $update_from_version_8 The different subversions from version 1.9
735
 *
736
 * @author unknow
737
 * @author Patrick Cool <[email protected]>, Ghent University
738
 */
739
function display_requirements(
740
    $installType,
741
    $badUpdatePath,
742
    $updatePath = '',
743
    $update_from_version_8 = []
744
) {
745
    global $_setting, $originalMemoryLimit;
746
    echo '<h2 class="install-title">'.display_step_sequence().get_lang('Requirements')."</h2>";
747
    echo '<div class="RequirementText">';
748
    echo '<strong>'.get_lang('ReadThoroughly').'</strong><br />';
749
    echo get_lang('MoreDetails').' <a href="../../documentation/installation_guide.html" target="_blank">'.get_lang('ReadTheInstallationGuide').'</a>.<br />'."\n";
750
751
    if ($installType == 'update') {
752
        echo get_lang('IfYouPlanToUpgradeFromOlderVersionYouMightWantToHaveAlookAtTheChangelog').'<br />';
753
    }
754
    echo '</div>';
755
756
    $properlyAccessUrl = checkAccessUrl();
757
    if (!$properlyAccessUrl) {
758
        echo '
759
            <div class="alert alert-danger">
760
            <i class="fa fa-exclamation-triangle" aria-hidden="true"></i>&nbsp;'.
761
            sprintf(get_lang('InstallMultiURLDetectedNotMainURL'), api_get_configuration_value('root_web')).'
762
            </div>
763
        ';
764
    }
765
766
    //  SERVER REQUIREMENTS
767
    echo '<h4 class="install-subtitle">'.get_lang('ServerRequirements').'</h4>';
768
    $timezone = checkPhpSettingExists('date.timezone');
769
    if (!$timezone) {
770
        echo "<div class='alert alert-warning'>
771
            <i class=\"fa fa-exclamation-triangle\" aria-hidden=\"true\"></i>&nbsp;".
772
            get_lang('DateTimezoneSettingNotSet')."</div>";
773
    }
774
775
    echo '<div class="install-requirement">'.get_lang('ServerRequirementsInfo').'</div>';
776
    echo '<div class="table-responsive">';
777
    echo '<table class="table table-bordered">
778
            <tr>
779
                <td class="requirements-item">'.get_lang('PHPVersion').' >= '.REQUIRED_PHP_VERSION.'</td>
780
                <td class="requirements-value">';
781
    if (version_compare(phpversion(), REQUIRED_PHP_VERSION, '>=') > 1) {
782
        echo '<strong class="text-danger">'.get_lang('PHPVersionError').'</strong>';
783
    } else {
784
        echo '<strong class="text-success">'.get_lang('PHPVersionOK').' '.phpversion().'</strong>';
785
    }
786
    echo '</td>
787
            </tr>
788
            <tr>
789
                <td class="requirements-item"><a href="http://php.net/manual/en/book.session.php" target="_blank">Session</a> '.get_lang('Support').'</td>
790
                <td class="requirements-value">'.checkExtension('session', get_lang('Yes'), get_lang('ExtensionSessionsNotAvailable')).'</td>
791
            </tr>
792
            <tr>
793
                <td class="requirements-item"><a href="http://php.net/manual/en/book.mysql.php" target="_blank">pdo_mysql</a> '.get_lang('Support').'</td>
794
                <td class="requirements-value">'.checkExtension('pdo_mysql', get_lang('Yes'), get_lang('ExtensionMySQLNotAvailable')).'</td>
795
            </tr>
796
            <tr>
797
                <td class="requirements-item"><a href="http://php.net/manual/en/book.zip.php" target="_blank">Zip</a> '.get_lang('Support').'</td>
798
                <td class="requirements-value">'.checkExtension('zip', get_lang('Yes'), get_lang('ExtensionNotAvailable')).'</td>
799
            </tr>
800
            <tr>
801
                <td class="requirements-item"><a href="http://php.net/manual/en/book.zlib.php" target="_blank">Zlib</a> '.get_lang('Support').'</td>
802
                <td class="requirements-value">'.checkExtension('zlib', get_lang('Yes'), get_lang('ExtensionZlibNotAvailable')).'</td>
803
            </tr>
804
            <tr>
805
                <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>
806
                <td class="requirements-value">'.checkExtension('pcre', get_lang('Yes'), get_lang('ExtensionPCRENotAvailable')).'</td>
807
            </tr>
808
            <tr>
809
                <td class="requirements-item"><a href="http://php.net/manual/en/book.xml.php" target="_blank">XML</a> '.get_lang('Support').'</td>
810
                <td class="requirements-value">'.checkExtension('xml', get_lang('Yes'), get_lang('No')).'</td>
811
            </tr>
812
            <tr>
813
                <td class="requirements-item"><a href="http://php.net/manual/en/book.intl.php" target="_blank">Internationalization</a> '.get_lang('Support').'</td>
814
                <td class="requirements-value">'.checkExtension('intl', get_lang('Yes'), get_lang('No')).'</td>
815
            </tr>
816
               <tr>
817
                <td class="requirements-item"><a href="http://php.net/manual/en/book.json.php" target="_blank">JSON</a> '.get_lang('Support').'</td>
818
                <td class="requirements-value">'.checkExtension('json', get_lang('Yes'), get_lang('No')).'</td>
819
            </tr>
820
             <tr>
821
                <td class="requirements-item"><a href="http://php.net/manual/en/book.image.php" target="_blank">GD</a> '.get_lang('Support').'</td>
822
                <td class="requirements-value">'.checkExtension('gd', get_lang('Yes'), get_lang('ExtensionGDNotAvailable')).'</td>
823
            </tr>
824
            <tr>
825
                <td class="requirements-item"><a href="http://php.net/manual/en/book.curl.php" target="_blank">cURL</a>'.get_lang('Support').'</td>
826
                <td class="requirements-value">'.checkExtension('curl', get_lang('Yes'), get_lang('No')).'</td>
827
            </tr>
828
829
            <tr>
830
                <td class="requirements-item"><a href="http://php.net/manual/en/book.mbstring.php" target="_blank">Multibyte string</a> '.get_lang('Support').' ('.get_lang('Optional').')</td>
831
                <td class="requirements-value">'.checkExtension('mbstring', get_lang('Yes'), get_lang('ExtensionMBStringNotAvailable'), true).'</td>
832
            </tr>
833
            <tr>
834
                <td class="requirements-item"><a href="http://php.net/opcache" target="_blank">Zend OpCache</a> '.get_lang('Support').' ('.get_lang('Optional').')</td>
835
                <td class="requirements-value">'.checkExtension('Zend OPcache', get_lang('Yes'), get_lang('No'), true, 'opcache.enable').'</td>
836
            </tr>
837
            <tr>
838
                <td class="requirements-item"><a href="http://php.net/apcu" target="_blank">APCu</a> '.get_lang('Support').' ('.get_lang('Optional').')</td>
839
                <td class="requirements-value">'.checkExtension('apcu', get_lang('Yes'), get_lang('No'), true, 'apc.enabled').'</td>
840
            </tr>
841
            <tr>
842
                <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>
843
                <td class="requirements-value">'.checkExtension('iconv', get_lang('Yes'), get_lang('No'), true).'</td>
844
            </tr>
845
            <tr>
846
                <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>
847
                <td class="requirements-value">'.checkExtension('ldap', get_lang('Yes'), get_lang('ExtensionLDAPNotAvailable'), true).'</td>
848
            </tr>
849
            <tr>
850
                <td class="requirements-item"><a href="http://xapian.org/" target="_blank">Xapian</a> '.get_lang('Support').' ('.get_lang('Optional').')</td>
851
                <td class="requirements-value">'.checkExtension('xapian', get_lang('Yes'), get_lang('No'), true).'</td>
852
            </tr>
853
        </table>';
854
    echo '</div>';
855
856
    // RECOMMENDED SETTINGS
857
    // Note: these are the settings for Joomla, does this also apply for Chamilo?
858
    // Note: also add upload_max_filesize here so that large uploads are possible
859
    echo '<h4 class="install-subtitle">'.get_lang('RecommendedSettings').'</h4>';
860
    echo '<div class="install-requirement">'.get_lang('RecommendedSettingsInfo').'</div>';
861
    echo '<div class="table-responsive">';
862
    echo '<table class="table table-bordered">
863
            <tr>
864
                <th>'.get_lang('Setting').'</th>
865
                <th>'.get_lang('Recommended').'</th>
866
                <th>'.get_lang('Actual').'</th>
867
            </tr>
868
            
869
            <tr>
870
                <td class="requirements-item"><a href="http://php.net/manual/ref.errorfunc.php#ini.display-errors">Display Errors</a></td>
871
                <td class="requirements-recommended">'.Display::label('OFF', 'success').'</td>
872
                <td class="requirements-value">'.checkPhpSetting('display_errors', 'OFF').'</td>
873
            </tr>
874
            <tr>
875
                <td class="requirements-item"><a href="http://php.net/manual/ini.core.php#ini.file-uploads">File Uploads</a></td>
876
                <td class="requirements-recommended">'.Display::label('ON', 'success').'</td>
877
                <td class="requirements-value">'.checkPhpSetting('file_uploads', 'ON').'</td>
878
            </tr>
879
            <tr>
880
                <td class="requirements-item"><a href="http://php.net/manual/ref.session.php#ini.session.auto-start">Session auto start</a></td>
881
                <td class="requirements-recommended">'.Display::label('OFF', 'success').'</td>
882
                <td class="requirements-value">'.checkPhpSetting('session.auto_start', 'OFF').'</td>
883
            </tr>
884
            <tr>
885
                <td class="requirements-item"><a href="http://php.net/manual/ini.core.php#ini.short-open-tag">Short Open Tag</a></td>
886
                <td class="requirements-recommended">'.Display::label('OFF', 'success').'</td>
887
                <td class="requirements-value">'.checkPhpSetting('short_open_tag', 'OFF').'</td>
888
            </tr>
889
            <tr>
890
                <td class="requirements-item"><a href="http://www.php.net/manual/en/session.configuration.php#ini.session.cookie-httponly">Cookie HTTP Only</a></td>
891
                <td class="requirements-recommended">'.Display::label('ON', 'success').'</td>
892
                <td class="requirements-value">'.checkPhpSetting('session.cookie_httponly', 'ON').'</td>
893
            </tr>
894
            <tr>
895
                <td class="requirements-item"><a href="http://php.net/manual/ini.core.php#ini.upload-max-filesize">Maximum upload file size</a></td>
896
                <td class="requirements-recommended">'.Display::label('>= '.REQUIRED_MIN_UPLOAD_MAX_FILESIZE.'M', 'success').'</td>
897
                <td class="requirements-value">'.compare_setting_values(ini_get('upload_max_filesize'), REQUIRED_MIN_UPLOAD_MAX_FILESIZE).'</td>
898
            </tr>
899
            <tr>
900
                <td class="requirements-item"><a href="http://php.net/manual/ini.core.php#ini.post-max-size">Maximum post size</a></td>
901
                <td class="requirements-recommended">'.Display::label('>= '.REQUIRED_MIN_POST_MAX_SIZE.'M', 'success').'</td>
902
                <td class="requirements-value">'.compare_setting_values(ini_get('post_max_size'), REQUIRED_MIN_POST_MAX_SIZE).'</td>
903
            </tr>
904
            <tr>
905
                <td class="requirements-item"><a href="http://www.php.net/manual/en/ini.core.php#ini.memory-limit">Memory Limit</a></td>
906
                <td class="requirements-recommended">'.Display::label('>= '.REQUIRED_MIN_MEMORY_LIMIT.'M', 'success').'</td>
907
                <td class="requirements-value">'.compare_setting_values($originalMemoryLimit, REQUIRED_MIN_MEMORY_LIMIT).'</td>
908
            </tr>
909
          </table>';
910
    echo '</div>';
911
912
    // DIRECTORY AND FILE PERMISSIONS
913
    echo '<h4 class="install-subtitle">'.get_lang('DirectoryAndFilePermissions').'</h4>';
914
    echo '<div class="install-requirement">'.get_lang('DirectoryAndFilePermissionsInfo').'</div>';
915
    echo '<div class="table-responsive">';
916
917
    $course_attempt_name = '__XxTestxX__';
918
    $course_dir = api_get_path(SYS_COURSE_PATH).$course_attempt_name;
919
    $fileToCreate = 'test.html';
920
    //Just in case
921
    @unlink($course_dir.'/'.$fileToCreate);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for unlink(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

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

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

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

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

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

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

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

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

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

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
923
924
    $perms_dir = [0777, 0755, 0775, 0770, 0750, 0700];
925
    $perms_fil = [0666, 0644, 0664, 0660, 0640, 0600];
926
    $course_test_was_created = false;
927
    $dir_perm_verified = 0777;
928
    foreach ($perms_dir as $perm) {
929
        $r = @mkdir($course_dir, $perm);
930
        if ($r === true) {
931
            $dir_perm_verified = $perm;
932
            $course_test_was_created = true;
933
            break;
934
        }
935
    }
936
937
    $fil_perm_verified = 0666;
938
    $file_course_test_was_created = false;
939
    if (is_dir($course_dir)) {
940
        foreach ($perms_fil as $perm) {
941
            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...
942
                break;
943
            }
944
            $r = @touch($course_dir.'/'.$fileToCreate, $perm);
945
            if ($r === true) {
946
                $fil_perm_verified = $perm;
947
                if (checkCourseScriptCreation($course_dir, $course_attempt_name, $fileToCreate)) {
948
                    $file_course_test_was_created = true;
949
                }
950
            }
951
        }
952
    }
953
954
    @unlink($course_dir.'/'.$fileToCreate);
955
    @rmdir($course_dir);
956
957
    $_SESSION['permissions_for_new_directories'] = $_setting['permissions_for_new_directories'] = $dir_perm_verified;
958
    $_SESSION['permissions_for_new_files'] = $_setting['permissions_for_new_files'] = $fil_perm_verified;
959
960
    $dir_perm = Display::label('0'.decoct($dir_perm_verified), 'info');
961
    $file_perm = Display::label('0'.decoct($fil_perm_verified), 'info');
962
963
    $courseTestLabel = Display::label(get_lang('No'), 'important');
964
    if ($course_test_was_created && $file_course_test_was_created) {
965
        $courseTestLabel = Display::label(get_lang('Yes'), 'success');
966
    }
967
968
    if ($course_test_was_created && !$file_course_test_was_created) {
969
        $courseTestLabel = Display::label(get_lang('Warning'), 'warning');
970
        $courseTestLabel .= '<br />'.sprintf(
971
            get_lang('InstallWarningCouldNotInterpretPHP'),
972
            api_get_path(WEB_COURSE_PATH).$course_attempt_name.'/'.$fileToCreate
973
        );
974
    }
975
976
    if (!$course_test_was_created && !$file_course_test_was_created) {
977
        $courseTestLabel = Display::label(get_lang('No'), 'important');
978
    }
979
980
    $oldConf = '';
981
    if (file_exists(api_get_path(SYS_CODE_PATH).'inc/conf/configuration.php')) {
982
        $oldConf = '<tr>
983
            <td class="requirements-item">'.api_get_path(SYS_CODE_PATH).'inc/conf</td>
984
            <td class="requirements-value">'.check_writable(api_get_path(SYS_CODE_PATH).'inc/conf').'</td>
985
        </tr>';
986
    }
987
988
    echo '<table class="table table-bordered">
989
            '.$oldConf.'
990
            <tr>
991
                <td class="requirements-item">'.api_get_path(SYS_APP_PATH).'</td>
992
                <td class="requirements-value">'.check_writable(api_get_path(SYS_APP_PATH)).'</td>
993
            </tr>
994
            <tr>
995
                <td class="requirements-item">'.api_get_path(SYS_PATH).'config</td>
996
                <td class="requirements-value">'.check_writable(api_get_path(SYS_PATH).'config').'</td>
997
            </tr>
998
            <tr>
999
                <td class="requirements-item">'.api_get_path(SYS_PATH).'vendor/</td>
1000
                <td class="requirements-value">'.checkReadable(api_get_path(SYS_PATH).'vendor').'</td>
1001
            </tr>
1002
            <tr>
1003
                <td class="requirements-item">'.api_get_path(SYS_PUBLIC_PATH).'</td>
1004
                <td class="requirements-value">'.check_writable(api_get_path(SYS_PUBLIC_PATH)).'</td>
1005
            </tr>
1006
            <tr>
1007
                <td class="requirements-item">'.get_lang('CourseTestWasCreated').'</td>
1008
                <td class="requirements-value">'.$courseTestLabel.' </td>
1009
            </tr>
1010
            <tr>
1011
                <td class="requirements-item">'.get_lang('PermissionsForNewDirs').'</td>
1012
                <td class="requirements-value">'.$dir_perm.' </td>
1013
            </tr>
1014
            <tr>
1015
                <td class="requirements-item">'.get_lang('PermissionsForNewFiles').'</td>
1016
                <td class="requirements-value">'.$file_perm.' </td>
1017
            </tr>
1018
        </table>';
1019
1020
    echo '</div>';
1021
1022
    if ($installType == 'update' && (empty($updatePath) || $badUpdatePath)) {
1023
        if ($badUpdatePath) {
1024
            ?>
1025
            <div class="alert alert-warning">
1026
                <?php echo get_lang('Error'); ?>!<br />
1027
                Chamilo <?php echo implode('|', $update_from_version_8).' '.get_lang('HasNotBeenFoundInThatDir'); ?>.
1028
            </div>
1029
        <?php
1030
        } else {
1031
            echo '<br />';
1032
        } ?>
1033
            <div class="row">
1034
                <div class="col-md-12">
1035
                    <p><?php echo get_lang('OldVersionRootPath'); ?>:
1036
                        <input type="text" name="updatePath" size="50" value="<?php echo ($badUpdatePath && !empty($updatePath)) ? htmlentities($updatePath) : ''; ?>" />
1037
                    </p>
1038
                    <p>
1039
                        <div class="btn-group">
1040
                            <button type="submit" class="btn btn-secondary" name="step1" value="<?php echo get_lang('Back'); ?>" >
1041
                                <em class="fa fa-backward"> <?php echo get_lang('Back'); ?></em>
1042
                            </button>
1043
                            <input type="hidden" name="is_executable" id="is_executable" value="-" />
1044
                            <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;" >
1045
                                <em class="fa fa-forward"> </em> <?php echo get_lang('Next'); ?>
1046
                            </button>
1047
                        </div>
1048
                    </p>
1049
                </div>
1050
            </div>
1051
1052
        <?php
1053
    } else {
1054
        $error = false;
1055
        // First, attempt to set writing permissions if we don't have them yet
1056
        $perm = api_get_permissions_for_new_directories();
1057
        $perm_file = api_get_permissions_for_new_files();
1058
        $notWritable = [];
1059
1060
        $checked_writable = api_get_path(SYS_APP_PATH);
1061
        if (!is_writable($checked_writable)) {
1062
            $notWritable[] = $checked_writable;
1063
            @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

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

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

1394
    /** @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...
1395
) {
1396
    if ($installType == 'update') {
1397
        global $_configuration;
1398
        $dbHostForm = $_configuration['db_host'];
1399
        $dbUsernameForm = $_configuration['db_user'];
1400
        $dbPassForm = $_configuration['db_password'];
1401
        $dbNameForm = $_configuration['main_database'];
1402
        $dbPortForm = isset($_configuration['db_port']) ? $_configuration['db_port'] : '';
1403
1404
        echo '<div class="RequirementHeading"><h2>'.display_step_sequence().get_lang('Database settings').'</h2></div>';
1405
        echo '<div class="RequirementContent">';
1406
        echo get_lang('DBSettingUpgradeIntro');
1407
        echo '</div>';
1408
    } else {
1409
        echo '<div class="RequirementHeading"><h2>'.display_step_sequence().get_lang('Database settings').'</h2></div>';
1410
        echo '<div class="RequirementContent">';
1411
        echo get_lang('DBSettingIntro');
1412
        echo '</div>';
1413
    } ?>
1414
    <div class="panel panel-default">
1415
        <div class="panel-body">
1416
        <div class="form-group row">
1417
            <label class="col-sm-4"><?php echo get_lang('DBHost'); ?> </label>
1418
            <?php if ($installType == 'update') {
1419
        ?>
1420
            <div class="col-sm-5">
1421
                <input type="hidden" name="dbHostForm" value="<?php echo htmlentities($dbHostForm); ?>" /><?php echo $dbHostForm; ?>
1422
            </div>
1423
            <div class="col-sm-3"></div>
1424
            <?php
1425
    } else {
1426
        ?>
1427
            <div class="col-sm-5">
1428
                <input type="text" class="form-control" size="25" maxlength="50" name="dbHostForm" value="<?php echo htmlentities($dbHostForm); ?>" />
1429
            </div>
1430
            <div class="col-sm-3"><?php echo get_lang('EG').' localhost'; ?></div>
1431
            <?php
1432
    } ?>
1433
        </div>
1434
        <div class="form-group row">
1435
            <label class="col-sm-4"><?php echo get_lang('DBPort'); ?> </label>
1436
            <?php if ($installType == 'update') {
1437
        ?>
1438
            <div class="col-sm-5">
1439
                <input type="hidden" name="dbPortForm" value="<?php echo htmlentities($dbPortForm); ?>" /><?php echo $dbPortForm; ?>
1440
            </div>
1441
            <div class="col-sm-3"></div>
1442
            <?php
1443
    } else {
1444
        ?>
1445
            <div class="col-sm-5">
1446
                <input type="text" class="form-control" size="25" maxlength="50" name="dbPortForm" value="<?php echo htmlentities($dbPortForm); ?>" />
1447
            </div>
1448
            <div class="col-sm-3"><?php echo get_lang('EG').' 3306'; ?></div>
1449
            <?php
1450
    } ?>
1451
        </div>
1452
        <div class="form-group row">
1453
            <?php
1454
                //database user username
1455
                $example_login = get_lang('EG').' root';
1456
    displayDatabaseParameter($installType, get_lang('DBLogin'), 'dbUsernameForm', $dbUsernameForm, $example_login); ?>
1457
        </div>
1458
        <div class="form-group row">
1459
            <?php
1460
            //database user password
1461
            $example_password = get_lang('EG').' '.api_generate_password();
1462
    displayDatabaseParameter($installType, get_lang('DBPassword'), 'dbPassForm', $dbPassForm, $example_password); ?>
1463
        </div>
1464
        <div class="form-group row">
1465
            <?php
1466
            //Database Name fix replace weird chars
1467
            if ($installType != INSTALL_TYPE_UPDATE) {
1468
                $dbNameForm = str_replace(['-', '*', '$', ' ', '.'], '', $dbNameForm);
1469
            }
1470
1471
    displayDatabaseParameter(
1472
                $installType,
1473
                get_lang('MainDB'),
1474
                'dbNameForm',
1475
                $dbNameForm,
1476
                '&nbsp;',
1477
                null,
1478
                'id="optional_param1"'
1479
                ); ?>
1480
        </div>
1481
       <?php if ($installType != INSTALL_TYPE_UPDATE) {
1482
                    ?>
1483
        <div class="form-group row">
1484
            <div class="col-sm-4"></div>
1485
            <div class="col-sm-8">
1486
            <button type="submit" class="btn btn-primary" name="step3" value="step3">
1487
                <em class="fa fa-refresh"> </em>
1488
                <?php echo get_lang('CheckDatabaseConnection'); ?>
1489
            </button>
1490
            </div>
1491
        </div>
1492
        <?php
1493
                } ?>
1494
1495
        </div>
1496
    </div>
1497
    <?php
1498
        $database_exists_text = '';
1499
    $manager = null;
1500
    try {
1501
        if ($installType === 'update') {
1502
            /** @var \Database $manager */
1503
            $manager = connectToDatabase(
1504
                $dbHostForm,
1505
                $dbUsernameForm,
1506
                $dbPassForm,
1507
                $dbNameForm,
1508
                $dbPortForm
1509
            );
1510
1511
            $connection = $manager->getConnection();
1512
            $connection->connect();
1513
            $schemaManager = $connection->getSchemaManager();
1514
1515
            // Test create/alter/drop table
1516
            $table = 'zXxTESTxX_'.mt_rand(0, 1000);
1517
            $sql = "CREATE TABLE $table (id INT AUTO_INCREMENT NOT NULL, name varchar(255), PRIMARY KEY(id))";
1518
            $connection->query($sql);
1519
            $tableCreationWorks = false;
1520
            $tableDropWorks = false;
1521
            if ($schemaManager->tablesExist($table)) {
1522
                $tableCreationWorks = true;
1523
                $sql = "ALTER TABLE $table ADD COLUMN name2 varchar(140) ";
1524
                $connection->query($sql);
1525
                $schemaManager->dropTable($table);
1526
                $tableDropWorks = $schemaManager->tablesExist($table) === false;
1527
            }
1528
        } else {
1529
            $manager = connectToDatabase(
1530
                $dbHostForm,
1531
                $dbUsernameForm,
1532
                $dbPassForm,
1533
                null,
1534
                $dbPortForm
1535
            );
1536
1537
            $schemaManager = $manager->getConnection()->getSchemaManager();
1538
            $databases = $schemaManager->listDatabases();
1539
            if (in_array($dbNameForm, $databases)) {
1540
                $database_exists_text = '<div class="alert alert-warning">'.get_lang('ADatabaseWithTheSameNameAlreadyExists').'</div>';
1541
            }
1542
        }
1543
    } catch (Exception $e) {
1544
        $database_exists_text = $e->getMessage();
1545
        $manager = false;
1546
    }
1547
1548
    if ($manager && $manager->getConnection()->isConnected()): ?>
1549
        <?php echo $database_exists_text; ?>
1550
        <div id="db_status" class="alert alert-success">
1551
            Database host: <strong><?php echo $manager->getConnection()->getHost(); ?></strong><br/>
1552
            Database port: <strong><?php echo $manager->getConnection()->getPort(); ?></strong><br/>
1553
            Database driver: <strong><?php echo $manager->getConnection()->getDriver()->getName(); ?></strong><br/>
1554
            <?php
1555
                if ($installType === 'update') {
1556
                    echo get_lang('CreateTableWorks').' <strong>Ok</strong>';
1557
                    echo '<br/ >';
1558
                    echo get_lang('AlterTableWorks').' <strong>Ok</strong>';
1559
                    echo '<br/ >';
1560
                    echo get_lang('DropColumnWorks').' <strong>Ok</strong>';
1561
                } ?>
1562
        </div>
1563
    <?php else: ?>
1564
        <div id="db_status" class="alert alert-danger">
1565
            <p><?php echo get_lang('FailedConectionDatabase'); ?></strong></p>
1566
            <code><?php echo $database_exists_text; ?></code>
1567
        </div>
1568
    <?php endif; ?>
1569
1570
   <div class="btn-group" role="group">
1571
       <button type="submit" name="step2"
1572
               class="btn btn-secondary float-right" value="&lt; <?php echo get_lang('Previous'); ?>" >
1573
           <em class="fa fa-backward"> </em> <?php echo get_lang('Previous'); ?>
1574
       </button>
1575
       <input type="hidden" name="is_executable" id="is_executable" value="-" />
1576
       <?php if ($manager) {
1577
                    ?>
1578
           <button type="submit" class="btn btn-success" name="step4" value="<?php echo get_lang('Next'); ?> &gt;" >
1579
               <em class="fa fa-forward"> </em> <?php echo get_lang('Next'); ?>
1580
           </button>
1581
       <?php
1582
                } else {
1583
                    ?>
1584
           <button
1585
                   disabled="disabled"
1586
                   type="submit" class="btn btn-success disabled" name="step4" value="<?php echo get_lang('Next'); ?> &gt;" >
1587
               <em class="fa fa-forward"> </em> <?php echo get_lang('Next'); ?>
1588
           </button>
1589
       <?php
1590
                } ?>
1591
   </div>
1592
    <?php
1593
}
1594
1595
function panel($content = null, $title = null, $id = null, $style = null)
1596
{
1597
    $html = '';
1598
    if (empty($style)) {
1599
        $style = 'default';
1600
    }
1601
    if (!empty($title)) {
1602
        $panelTitle = Display::div($title, ['class' => 'panel-heading']);
1603
        $panelBody = Display::div($content, ['class' => 'panel-body']);
1604
        $panelParent = Display::div($panelTitle.$panelBody, ['id' => $id, 'class' => 'panel panel-'.$style]);
1605
    } else {
1606
        $panelBody = Display::div($html, ['class' => 'panel-body']);
1607
        $panelParent = Display::div($panelBody, ['id' => $id, 'class' => 'panel panel-'.$style]);
1608
    }
1609
    $html .= $panelParent;
1610
1611
    return $html;
1612
}
1613
1614
/**
1615
 * Displays a parameter in a table row.
1616
 * Used by the display_configuration_settings_form function.
1617
 *
1618
 * @param string $installType
1619
 * @param string $parameterName
1620
 * @param string $formFieldName
1621
 * @param string $parameterValue
1622
 * @param string $displayWhenUpdate
1623
 *
1624
 * @return string
1625
 */
1626
function display_configuration_parameter(
1627
    $installType,
1628
    $parameterName,
1629
    $formFieldName,
1630
    $parameterValue,
1631
    $displayWhenUpdate = 'true'
1632
) {
1633
    $html = '<div class="form-group row">';
1634
    $html .= '<label class="col-sm-6 control-label">'.$parameterName.'</label>';
1635
    if ($installType == INSTALL_TYPE_UPDATE && $displayWhenUpdate) {
1636
        $html .= '<input type="hidden" name="'.$formFieldName.'" value="'.api_htmlentities($parameterValue, ENT_QUOTES).'" />'.$parameterValue;
1637
    } else {
1638
        $html .= '<div class="col-sm-6"><input class="form-control" type="text" size="'.FORM_FIELD_DISPLAY_LENGTH.'" maxlength="'.MAX_FORM_FIELD_LENGTH.'" name="'.$formFieldName.'" value="'.api_htmlentities($parameterValue, ENT_QUOTES).'" />'."</div>";
1639
    }
1640
    $html .= "</div>";
1641
1642
    return $html;
1643
}
1644
1645
/**
1646
 * Displays step 4 of the installation - configuration settings about Chamilo itself.
1647
 *
1648
 * @param string $installType
1649
 * @param string $urlForm
1650
 * @param string $languageForm
1651
 * @param string $emailForm
1652
 * @param string $adminFirstName
1653
 * @param string $adminLastName
1654
 * @param string $adminPhoneForm
1655
 * @param string $campusForm
1656
 * @param string $institutionForm
1657
 * @param string $institutionUrlForm
1658
 * @param string $encryptPassForm
1659
 * @param bool   $allowSelfReg
1660
 * @param bool   $allowSelfRegProf
1661
 * @param string $loginForm
1662
 * @param string $passForm
1663
 */
1664
function display_configuration_settings_form(
1665
    $installType,
1666
    $urlForm,
1667
    $languageForm,
1668
    $emailForm,
1669
    $adminFirstName,
1670
    $adminLastName,
1671
    $adminPhoneForm,
1672
    $campusForm,
1673
    $institutionForm,
1674
    $institutionUrlForm,
1675
    $encryptPassForm,
1676
    $allowSelfReg,
1677
    $allowSelfRegProf,
1678
    $loginForm,
1679
    $passForm
1680
) {
1681
    if ($installType != 'update' && empty($languageForm)) {
1682
        $languageForm = $_SESSION['install_language'];
1683
    }
1684
    echo '<div class="RequirementHeading">';
1685
    echo "<h2>".display_step_sequence().get_lang("ConfigurationSettings")."</h2>";
1686
    echo '</div>';
1687
1688
    // Parameter 1: administrator's login
1689
    $html = '';
1690
    $html .= display_configuration_parameter(
1691
        $installType,
1692
        get_lang('AdminLogin'),
1693
        'loginForm',
1694
        $loginForm,
1695
        $installType == 'update'
1696
    );
1697
1698
    // Parameter 2: administrator's password
1699
    if ($installType != 'update') {
1700
        $html .= display_configuration_parameter($installType, get_lang('AdminPass'), 'passForm', $passForm, false);
1701
    }
1702
1703
    // Parameters 3 and 4: administrator's names
1704
1705
    $html .= display_configuration_parameter(
1706
        $installType,
1707
        get_lang('AdminFirstName'),
1708
        'adminFirstName',
1709
        $adminFirstName
1710
    );
1711
    $html .= display_configuration_parameter($installType, get_lang('AdminLastName'), 'adminLastName', $adminLastName);
1712
1713
    //Parameter 3: administrator's email
1714
    $html .= display_configuration_parameter($installType, get_lang('AdminEmail'), 'emailForm', $emailForm);
1715
1716
    //Parameter 6: administrator's telephone
1717
    $html .= display_configuration_parameter($installType, get_lang('AdminPhone'), 'adminPhoneForm', $adminPhoneForm);
1718
    echo panel($html, get_lang('Administrator'), 'administrator');
1719
1720
    //First parameter: language
1721
    $html = '<div class="form-group row">';
1722
    $html .= '<label class="col-sm-6 control-label">'.get_lang('MainLang')."</label>";
1723
    if ($installType == 'update') {
1724
        $html .= '<input type="hidden" name="languageForm" value="'.api_htmlentities($languageForm, ENT_QUOTES).'" />'.$languageForm;
1725
    } else { // new installation
1726
        $html .= '<div class="col-sm-6">';
1727
        $html .= display_language_selection_box('languageForm', $languageForm);
1728
        $html .= '</div>';
1729
    }
1730
    $html .= "</div>";
1731
1732
    //Second parameter: Chamilo URL
1733
    $html .= '<div class="form-group row">';
1734
    $html .= '<label class="col-sm-6 control-label">'.get_lang('ChamiloURL').get_lang('ThisFieldIsRequired').'</label>';
1735
1736
    if ($installType == 'update') {
1737
        $html .= api_htmlentities($urlForm, ENT_QUOTES)."\n";
1738
    } else {
1739
        $html .= '<div class="col-sm-6">';
1740
        $html .= '<input class="form-control" type="text" size="40" maxlength="100" name="urlForm" value="'.api_htmlentities($urlForm, ENT_QUOTES).'" />';
1741
        $html .= '</div>';
1742
    }
1743
    $html .= '</div>';
1744
1745
    //Parameter 9: campus name
1746
    $html .= display_configuration_parameter(
1747
        $installType,
1748
        get_lang('CampusName'),
1749
        'campusForm',
1750
        $campusForm
1751
    );
1752
1753
    //Parameter 10: institute (short) name
1754
    $html .= display_configuration_parameter(
1755
        $installType,
1756
        get_lang('InstituteShortName'),
1757
        'institutionForm',
1758
        $institutionForm
1759
    );
1760
1761
    //Parameter 11: institute (short) name
1762
    $html .= display_configuration_parameter(
1763
        $installType,
1764
        get_lang('InstituteURL'),
1765
        'institutionUrlForm',
1766
        $institutionUrlForm
1767
    );
1768
1769
    $html .= '<div class="form-group row">
1770
            <label class="col-sm-6 control-label">'.get_lang("EncryptMethodUserPass").'</label>
1771
        <div class="col-sm-6">';
1772
    if ($installType == 'update') {
1773
        $html .= '<input type="hidden" name="encryptPassForm" value="'.$encryptPassForm.'" />'.$encryptPassForm;
1774
    } else {
1775
        $html .= '<div class="checkbox">
1776
                    <label>
1777
                        <input  type="radio" name="encryptPassForm" value="bcrypt" id="encryptPass1" '.($encryptPassForm == 'bcrypt' ? 'checked="checked" ' : '').'/> bcrypt
1778
                    </label>';
1779
1780
        $html .= '<label>
1781
                        <input  type="radio" name="encryptPassForm" value="sha1" id="encryptPass1" '.($encryptPassForm == 'sha1' ? 'checked="checked" ' : '').'/> sha1
1782
                    </label>';
1783
1784
        $html .= '<label>
1785
                        <input type="radio" name="encryptPassForm" value="md5" id="encryptPass0" '.($encryptPassForm == 'md5' ? 'checked="checked" ' : '').'/> md5
1786
                    </label>';
1787
1788
        $html .= '<label>
1789
                        <input type="radio" name="encryptPassForm" value="none" id="encryptPass2" '.($encryptPassForm == 'none' ? 'checked="checked" ' : '').'/>'.get_lang('None').'
1790
                    </label>';
1791
        $html .= '</div>';
1792
    }
1793
    $html .= '</div></div>';
1794
1795
    $html .= '<div class="form-group row">
1796
            <label class="col-sm-6 control-label">'.get_lang('AllowSelfReg').'</label>
1797
            <div class="col-sm-6">';
1798
    if ($installType == 'update') {
1799
        if ($allowSelfReg == 'true') {
1800
            $label = get_lang('Yes');
1801
        } elseif ($allowSelfReg == 'false') {
1802
            $label = get_lang('No');
1803
        } else {
1804
            $label = get_lang('AfterApproval');
1805
        }
1806
        $html .= '<input type="hidden" name="allowSelfReg" value="'.$allowSelfReg.'" />'.$label;
1807
    } else {
1808
        $html .= '<div class="control-group">';
1809
        $html .= '<label class="checkbox-inline">
1810
                        <input type="radio" name="allowSelfReg" value="true" id="allowSelfReg1" '.($allowSelfReg == 'true' ? 'checked="checked" ' : '').' /> '.get_lang('Yes').'
1811
                    </label>';
1812
        $html .= '<label class="checkbox-inline">
1813
                        <input type="radio" name="allowSelfReg" value="false" id="allowSelfReg0" '.($allowSelfReg == 'false' ? '' : 'checked="checked" ').' /> '.get_lang('No').'
1814
                    </label>';
1815
        $html .= '<label class="checkbox-inline">
1816
                    <input type="radio" name="allowSelfReg" value="approval" id="allowSelfReg2" '.($allowSelfReg == 'approval' ? '' : 'checked="checked" ').' /> '.get_lang('AfterApproval').'
1817
                </label>';
1818
        $html .= '</div>';
1819
    }
1820
    $html .= '</div>';
1821
    $html .= '</div>';
1822
1823
    $html .= '<div class="form-group row">';
1824
    $html .= '<label class="col-sm-6 control-label">'.get_lang('AllowSelfRegProf').'</label>
1825
        <div class="col-sm-6">';
1826
    if ($installType == 'update') {
1827
        if ($allowSelfRegProf == 'true') {
1828
            $label = get_lang('Yes');
1829
        } else {
1830
            $label = get_lang('No');
1831
        }
1832
        $html .= '<input type="hidden" name="allowSelfRegProf" value="'.$allowSelfRegProf.'" />'.$label;
1833
    } else {
1834
        $html .= '<div class="control-group">
1835
                <label class="checkbox-inline">
1836
                    <input type="radio" name="allowSelfRegProf" value="1" id="allowSelfRegProf1" '.($allowSelfRegProf ? 'checked="checked" ' : '').'/>
1837
                '.get_lang('Yes').'
1838
                </label>';
1839
        $html .= '<label class="checkbox-inline">
1840
                    <input type="radio" name="allowSelfRegProf" value="0" id="allowSelfRegProf0" '.($allowSelfRegProf ? '' : 'checked="checked" ').' />
1841
                   '.get_lang('No').'
1842
                </label>';
1843
        $html .= '</div>';
1844
    }
1845
    $html .= '</div>
1846
    </div>';
1847
1848
    echo panel($html, get_lang('Platform'), 'platform'); ?>
1849
    <div class='btn-group'>
1850
        <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>
1851
        <input type="hidden" name="is_executable" id="is_executable" value="-" />
1852
        <button class="btn btn-success" type="submit" name="step5" value="<?php echo get_lang('Next'); ?> &gt;" ><em class="fa fa-forward"> </em> <?php echo get_lang('Next'); ?></button>
1853
    </div>
1854
1855
    <?php
1856
}
1857
1858
/**
1859
 * After installation is completed (step 6), this message is displayed.
1860
 */
1861
function display_after_install_message()
1862
{
1863
    $html = '<div class="RequirementContent">'.get_lang('FirstUseTip').'</div>';
1864
    $html .= '<div class="alert alert-warning">';
1865
    $html .= '<strong>'.get_lang('SecurityAdvice').'</strong>';
1866
    $html .= ': ';
1867
    $html .= sprintf(get_lang('ToProtectYourSiteMakeXReadOnlyAndDeleteY'), 'app/config/', 'main/install/');
1868
    $html .= '</div></form>
1869
    <br />
1870
    <a class="btn btn-success btn-block" href="../../index.php">
1871
        '.get_lang('GoToYourNewlyCreatedPortal').'
1872
    </a>';
1873
1874
    return $html;
1875
}
1876
1877
/**
1878
 * This function return countries list from array (hardcoded).
1879
 *
1880
 * @param bool $combo (Optional) True for returning countries list with select html
1881
 *
1882
 * @return array|string countries list
1883
 */
1884
function get_countries_list_from_array($combo = false)
1885
{
1886
    $a_countries = [
1887
        "Afghanistan", "Albania", "Algeria", "Andorra", "Angola", "Antigua and Barbuda", "Argentina", "Armenia", "Australia", "Austria", "Azerbaijan",
1888
        "Bahamas", "Bahrain", "Bangladesh", "Barbados", "Belarus", "Belgium", "Belize", "Benin", "Bhutan", "Bolivia", "Bosnia and Herzegovina", "Botswana", "Brazil", "Brunei", "Bulgaria", "Burkina Faso", "Burundi",
1889
        "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",
1890
        "Denmark", "Djibouti", "Dominica", "Dominican Republic",
1891
        "East Timor (Timor Timur)", "Ecuador", "Egypt", "El Salvador", "Equatorial Guinea", "Eritrea", "Estonia", "Ethiopia",
1892
        "Fiji", "Finland", "France",
1893
        "Gabon", "Gambia, The", "Georgia", "Germany", "Ghana", "Greece", "Grenada", "Guatemala", "Guinea", "Guinea-Bissau", "Guyana",
1894
        "Haiti", "Honduras", "Hungary",
1895
        "Iceland", "India", "Indonesia", "Iran", "Iraq", "Ireland", "Israel", "Italy",
1896
        "Jamaica", "Japan", "Jordan",
1897
        "Kazakhstan", "Kenya", "Kiribati", "Korea, North", "Korea, South", "Kuwait", "Kyrgyzstan",
1898
        "Laos", "Latvia", "Lebanon", "Lesotho", "Liberia", "Libya", "Liechtenstein", "Lithuania", "Luxembourg",
1899
        "Macedonia", "Madagascar", "Malawi", "Malaysia", "Maldives", "Mali", "Malta", "Marshall Islands", "Mauritania", "Mauritius", "Mexico", "Micronesia", "Moldova", "Monaco", "Mongolia", "Morocco", "Mozambique", "Myanmar",
1900
        "Namibia", "Nauru", "Nepa", "Netherlands", "New Zealand", "Nicaragua", "Niger", "Nigeria", "Norway",
1901
        "Oman",
1902
        "Pakistan", "Palau", "Panama", "Papua New Guinea", "Paraguay", "Peru", "Philippines", "Poland", "Portugal",
1903
        "Qatar",
1904
        "Romania", "Russia", "Rwanda",
1905
        "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",
1906
        "Taiwan", "Tajikistan", "Tanzania", "Thailand", "Togo", "Tonga", "Trinidad and Tobago", "Tunisia", "Turkey", "Turkmenistan", "Tuvalu",
1907
        "Uganda", "Ukraine", "United Arab Emirates", "United Kingdom", "United States", "Uruguay", "Uzbekistan",
1908
        "Vanuatu", "Vatican City", "Venezuela", "Vietnam",
1909
        "Yemen",
1910
        "Zambia", "Zimbabwe",
1911
    ];
1912
    if ($combo) {
1913
        $country_select = '<select class="selectpicker show-tick" id="country" name="country">';
1914
        $country_select .= '<option value="">--- '.get_lang('SelectOne').' ---</option>';
1915
        foreach ($a_countries as $country) {
1916
            $country_select .= '<option value="'.$country.'">'.$country.'</option>';
1917
        }
1918
        $country_select .= '</select>';
1919
1920
        return $country_select;
1921
    }
1922
1923
    return $a_countries;
1924
}
1925
1926
/**
1927
 * Lock settings that can't be changed in other portals.
1928
 */
1929
function lockSettings()
1930
{
1931
    $settings = api_get_locked_settings();
1932
    $table = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
1933
    foreach ($settings as $setting) {
1934
        $sql = "UPDATE $table SET access_url_locked = 1 WHERE variable  = '$setting'";
1935
        Database::query($sql);
1936
    }
1937
}
1938
1939
/**
1940
 * Update dir values.
1941
 */
1942
function updateDirAndFilesPermissions()
1943
{
1944
    $table = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
1945
    $permissions_for_new_directories = isset($_SESSION['permissions_for_new_directories']) ? $_SESSION['permissions_for_new_directories'] : 0770;
1946
    $permissions_for_new_files = isset($_SESSION['permissions_for_new_files']) ? $_SESSION['permissions_for_new_files'] : 0660;
1947
    // use decoct() to store as string
1948
    Database::update(
1949
        $table,
1950
        ['selected_value' => '0'.decoct($permissions_for_new_directories)],
1951
        ['variable = ?' => 'permissions_for_new_directories']
1952
    );
1953
1954
    Database::update(
1955
        $table,
1956
        ['selected_value' => '0'.decoct($permissions_for_new_files)],
1957
        ['variable = ?' => 'permissions_for_new_files']
1958
    );
1959
1960
    if (isset($_SESSION['permissions_for_new_directories'])) {
1961
        unset($_SESSION['permissions_for_new_directories']);
1962
    }
1963
1964
    if (isset($_SESSION['permissions_for_new_files'])) {
1965
        unset($_SESSION['permissions_for_new_files']);
1966
    }
1967
}
1968
1969
/**
1970
 * @param $current_value
1971
 * @param $wanted_value
1972
 *
1973
 * @return string
1974
 */
1975
function compare_setting_values($current_value, $wanted_value)
1976
{
1977
    $current_value_string = $current_value;
1978
    $current_value = (float) $current_value;
1979
    $wanted_value = (float) $wanted_value;
1980
1981
    if ($current_value >= $wanted_value) {
1982
        return Display::label($current_value_string, 'success');
1983
    } else {
1984
        return Display::label($current_value_string, 'important');
1985
    }
1986
}
1987
1988
/**
1989
 * @param string $course_dir
1990
 * @param string $course_attempt_name
1991
 * @param string $file
1992
 *
1993
 * @return bool
1994
 */
1995
function checkCourseScriptCreation(
1996
    $course_dir,
1997
    $course_attempt_name,
1998
    $file
1999
) {
2000
    $output = false;
2001
    //Write in file
2002
    $file_name = $course_dir.'/'.$file;
2003
    $content = '123';
2004
2005
    if (is_writable($file_name)) {
2006
        if ($handler = @fopen($file_name, 'w')) {
2007
            //write content
2008
            if (fwrite($handler, $content)) {
2009
                $sock_errno = '';
2010
                $sock_errmsg = '';
2011
                $url = api_get_path(WEB_PATH).'app/courses/'.$course_attempt_name.'/'.$file;
2012
2013
                $parsed_url = parse_url($url);
2014
                //$scheme = isset($parsedUrl['scheme']) ? $parsedUrl['scheme'] : ''; //http
2015
                $host = isset($parsed_url['host']) ? $parsed_url['host'] : '';
2016
                // Patch if the host is the default host and is used through
2017
                // the IP address (sometimes the host is not taken correctly
2018
                // in this case)
2019
                if (empty($host) && !empty($_SERVER['HTTP_HOST'])) {
2020
                    $host = $_SERVER['HTTP_HOST'];
2021
                    $url = preg_replace('#:///#', '://'.$host.'/', $url);
2022
                }
2023
                $path = isset($parsed_url['path']) ? $parsed_url['path'] : '/';
2024
                $port = '';
2025
                $scheme = '';
2026
                switch ($parsed_url['scheme']) {
2027
                    case 'https':
2028
                        $scheme = 'ssl://';
2029
                        $port = 443;
2030
                        break;
2031
                    case 'http':
2032
                    default:
2033
                        $scheme = '';
2034
                        $port = 80;
2035
                }
2036
2037
                //Check fsockopen (not sure it works with https). If that is your case, you might want to try the
2038
                // suggestion at https://support.chamilo.org/issues/8260#note-3 (although it ignores SSL peer checks)
2039
                if ($fp = @fsockopen(str_replace('http://', $scheme, $url), $port, $sock_errno, $sock_errmsg, 60)) {
2040
                    $out = "GET $path HTTP/1.1\r\n";
2041
                    $out .= "Host: $host\r\n";
2042
                    $out .= "Connection: Close\r\n\r\n";
2043
2044
                    fwrite($fp, $out);
2045
                    while (!feof($fp)) {
2046
                        $result = str_replace("\r\n", '', fgets($fp, 128));
2047
                        if (!empty($result) && $result == '123') {
2048
                            $output = true;
2049
                        }
2050
                    }
2051
                    fclose($fp);
2052
                } elseif (ini_get('allow_url_fopen')) {
2053
                    // Check allow_url_fopen
2054
                    if ($fp = @fopen($url, 'r')) {
2055
                        while ($result = fgets($fp, 1024)) {
2056
                            if (!empty($result) && $result == '123') {
2057
                                $output = true;
2058
                            }
2059
                        }
2060
                        fclose($fp);
2061
                    }
2062
                } elseif (function_exists('curl_init')) {
2063
                    // Check if has support for cURL
2064
                    $ch = curl_init();
2065
                    curl_setopt($ch, CURLOPT_HEADER, 0);
2066
                    curl_setopt($ch, CURLOPT_URL, $url);
2067
                    //curl_setopt($ch, CURLOPT_TIMEOUT, 30);
2068
                    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
2069
                    $result = curl_exec($ch);
2070
                    if (!empty($result) && $result == '123') {
2071
                        $output = true;
2072
                    }
2073
                    curl_close($ch);
2074
                }
2075
            }
2076
            @fclose($handler);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for fclose(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

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

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

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

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

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
2077
        }
2078
    }
2079
2080
    return $output;
2081
}
2082
2083
/**
2084
 * Save settings values.
2085
 *
2086
 * @param string $organizationName
2087
 * @param string $organizationUrl
2088
 * @param string $siteName
2089
 * @param string $adminEmail
2090
 * @param string $adminLastName
2091
 * @param string $adminFirstName
2092
 * @param string $language
2093
 * @param string $allowRegistration
2094
 * @param string $allowTeacherSelfRegistration
2095
 * @param string $installationProfile          The name of an installation profile file in main/install/profiles/
2096
 */
2097
function installSettings(
2098
    $organizationName,
2099
    $organizationUrl,
2100
    $siteName,
2101
    $adminEmail,
2102
    $adminLastName,
2103
    $adminFirstName,
2104
    $language,
2105
    $allowRegistration,
2106
    $allowTeacherSelfRegistration,
2107
    $installationProfile = ''
2108
) {
2109
    $allowTeacherSelfRegistration = $allowTeacherSelfRegistration ? 'true' : 'false';
2110
2111
    $settings = [
2112
        'institution' => $organizationName,
2113
        'institution_url' => $organizationUrl,
2114
        'site_name' => $siteName,
2115
        'administrator_email' => $adminEmail,
2116
        'administrator_surname' => $adminLastName,
2117
        'administrator_name' => $adminFirstName,
2118
        'platform_language' => $language,
2119
        'allow_registration' => $allowRegistration,
2120
        'allow_registration_as_teacher' => $allowTeacherSelfRegistration,
2121
    ];
2122
2123
    foreach ($settings as $variable => $value) {
2124
        $sql = "UPDATE settings_current
2125
                SET selected_value = '$value'
2126
                WHERE variable = '$variable'";
2127
        Database::query($sql);
2128
    }
2129
    installProfileSettings($installationProfile);
2130
}
2131
2132
/**
2133
 * Executes DB changes based in the classes defined in
2134
 * src/CoreBundle/Migrations/Schema/*.
2135
 *
2136
 * @param string        $chamiloVersion
2137
 * @param EntityManager $manager
2138
 *
2139
 * @throws \Doctrine\DBAL\DBALException
2140
 *
2141
 * @return bool
2142
 */
2143
function migrate($chamiloVersion, EntityManager $manager)
2144
{
2145
    $debug = true;
2146
    $connection = $manager->getConnection();
2147
2148
    $config = new \Doctrine\DBAL\Migrations\Configuration\Configuration($connection);
2149
2150
    // Table name that will store migrations log (will be created automatically,
2151
    // default name is: doctrine_migration_versions)
2152
    $config->setMigrationsTableName('version');
2153
    // Namespace of your migration classes, do not forget escape slashes, do not add last slash
2154
    $config->setMigrationsNamespace('Chamilo\CoreBundle\Migrations\Schema\V'.$chamiloVersion);
2155
    // Directory where your migrations are located
2156
    $versionPath = api_get_path(SYS_PATH).'src/CoreBundle/Migrations/Schema/V'.$chamiloVersion;
2157
    error_log("Reading files from dir: $versionPath");
2158
    $config->setMigrationsDirectory($versionPath);
2159
    // Load your migrations
2160
    $config->registerMigrationsFromDirectory($config->getMigrationsDirectory());
2161
2162
    $migration = new \Doctrine\DBAL\Migrations\Migration($config);
2163
    $versions = $config->getMigrations();
2164
2165
    /** @var Doctrine\DBAL\Migrations\Version $migrationItem */
2166
    foreach ($versions as $version) {
2167
        $version->getMigration()->setEntityManager($manager);
2168
    }
2169
2170
    $to = null; // if $to == null then schema will be migrated to latest version
2171
    echo '<pre>';
2172
    try {
2173
        // Execute migration!
2174
        $migratedSQL = $migration->migrate($to);
2175
2176
        if ($debug) {
2177
            foreach ($migratedSQL as $version => $sqlList) {
2178
                echo "VERSION: $version<br>";
2179
                echo '----------------------------------------------<br />';
2180
                $total = count($sqlList);
2181
                error_log("VERSION: $version");
2182
                error_log("# queries: $total");
2183
                $counter = 1;
2184
                foreach ($sqlList as $sql) {
2185
                    echo "<code>$sql</code><br>";
2186
                    error_log("$counter/$total : $sql");
2187
                    $counter++;
2188
                }
2189
            }
2190
2191
            echo "<br>DONE!<br>";
2192
        }
2193
2194
        return true;
2195
    } catch (Exception $ex) {
2196
        if ($debug) {
2197
            echo "ERROR: {$ex->getMessage()}<br>";
2198
2199
            return false;
2200
        }
2201
    }
2202
2203
    echo '</pre>';
2204
2205
    return false;
2206
}
2207
2208
/**
2209
 * @param EntityManager $em
2210
 *
2211
 * @throws \Doctrine\DBAL\DBALException
2212
 */
2213
function fixIds(EntityManager $em)
2214
{
2215
    $connection = $em->getConnection();
2216
    $database = new Database();
2217
    $database->setManager($em);
2218
    $debug = true;
2219
    if ($debug) {
2220
        error_log('fixIds');
2221
    }
2222
2223
    // Create temporary indexes to increase speed of the following operations
2224
    // Adding and removing indexes will usually take much less time than
2225
    // the execution without indexes of the queries in this function, particularly
2226
    // for large tables
2227
    $sql = "ALTER TABLE c_document ADD INDEX tmpidx_doc(c_id, id)";
2228
    $connection->executeQuery($sql);
2229
    $sql = "ALTER TABLE c_student_publication ADD INDEX tmpidx_stud (c_id, id)";
2230
    $connection->executeQuery($sql);
2231
    $sql = "ALTER TABLE c_quiz ADD INDEX tmpidx_quiz (c_id, id)";
2232
    $connection->executeQuery($sql);
2233
    $sql = "ALTER TABLE c_item_property ADD INDEX tmpidx_ip (to_group_id)";
2234
    $connection->executeQuery($sql);
2235
2236
    $sql = "SELECT * FROM c_lp_item";
2237
    $result = $connection->fetchAll($sql);
2238
    foreach ($result as $item) {
2239
        $courseId = $item['c_id'];
2240
        $iid = isset($item['iid']) ? intval($item['iid']) : 0;
2241
        $ref = isset($item['ref']) ? intval($item['ref']) : 0;
2242
        $sql = null;
2243
2244
        $newId = '';
2245
2246
        switch ($item['item_type']) {
2247
            case TOOL_LINK:
2248
                $sql = "SELECT * FROM c_link WHERE c_id = $courseId AND id = $ref";
2249
                $data = $connection->fetchAssoc($sql);
2250
                if ($data) {
2251
                    $newId = $data['iid'];
2252
                }
2253
                break;
2254
            case TOOL_STUDENTPUBLICATION:
2255
                $sql = "SELECT * FROM c_student_publication WHERE c_id = $courseId AND id = $ref";
2256
                $data = $connection->fetchAssoc($sql);
2257
                if ($data) {
2258
                    $newId = $data['iid'];
2259
                }
2260
                break;
2261
            case TOOL_QUIZ:
2262
                $sql = "SELECT * FROM c_quiz WHERE c_id = $courseId AND id = $ref";
2263
                $data = $connection->fetchAssoc($sql);
2264
                if ($data) {
2265
                    $newId = $data['iid'];
2266
                }
2267
                break;
2268
            case TOOL_DOCUMENT:
2269
                $sql = "SELECT * FROM c_document WHERE c_id = $courseId AND id = $ref";
2270
                $data = $connection->fetchAssoc($sql);
2271
                if ($data) {
2272
                    $newId = $data['iid'];
2273
                }
2274
                break;
2275
            case TOOL_FORUM:
2276
                $sql = "SELECT * FROM c_forum_forum WHERE c_id = $courseId AND forum_id = $ref";
2277
                $data = $connection->fetchAssoc($sql);
2278
                if ($data) {
2279
                    $newId = $data['iid'];
2280
                }
2281
                break;
2282
            case 'thread':
2283
                $sql = "SELECT * FROM c_forum_thread WHERE c_id = $courseId AND thread_id = $ref";
2284
                $data = $connection->fetchAssoc($sql);
2285
                if ($data) {
2286
                    $newId = $data['iid'];
2287
                }
2288
                break;
2289
        }
2290
2291
        if (!empty($sql) && !empty($newId) && !empty($iid)) {
2292
            $sql = "UPDATE c_lp_item SET ref = $newId WHERE iid = $iid";
2293
            $connection->executeQuery($sql);
2294
        }
2295
    }
2296
2297
    // Set NULL if session = 0
2298
    $sql = "UPDATE c_item_property SET session_id = NULL WHERE session_id = 0";
2299
    $connection->executeQuery($sql);
2300
2301
    // Set NULL if group = 0
2302
    $sql = "UPDATE c_item_property SET to_group_id = NULL WHERE to_group_id = 0";
2303
    $connection->executeQuery($sql);
2304
2305
    // Set NULL if insert_user_id = 0
2306
    $sql = "UPDATE c_item_property SET insert_user_id = NULL WHERE insert_user_id = 0";
2307
    $connection->executeQuery($sql);
2308
2309
    // Delete session data of sessions that don't exist.
2310
    $sql = "DELETE FROM c_item_property
2311
            WHERE session_id IS NOT NULL AND session_id NOT IN (SELECT id FROM session)";
2312
    $connection->executeQuery($sql);
2313
2314
    // Delete group data of groups that don't exist.
2315
    $sql = "DELETE FROM c_item_property
2316
            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)";
2317
    $connection->executeQuery($sql);
2318
    // This updates the group_id with c_group_info.iid instead of c_group_info.id
2319
2320
    if ($debug) {
2321
        error_log('update iids');
2322
    }
2323
2324
    $groupTableToFix = [
2325
        'c_group_rel_user',
2326
        'c_group_rel_tutor',
2327
        'c_permission_group',
2328
        'c_role_group',
2329
        'c_survey_invitation',
2330
        'c_attendance_calendar_rel_group',
2331
    ];
2332
2333
    foreach ($groupTableToFix as $table) {
2334
        $sql = "SELECT * FROM $table";
2335
        $result = $connection->fetchAll($sql);
2336
        foreach ($result as $item) {
2337
            $iid = $item['iid'];
2338
            $courseId = $item['c_id'];
2339
            $groupId = intval($item['group_id']);
2340
2341
            // Fix group id
2342
            if (!empty($groupId)) {
2343
                $sql = "SELECT * FROM c_group_info
2344
                        WHERE c_id = $courseId AND id = $groupId
2345
                        LIMIT 1";
2346
                $data = $connection->fetchAssoc($sql);
2347
                if (!empty($data)) {
2348
                    $newGroupId = $data['iid'];
2349
                    $sql = "UPDATE $table SET group_id = $newGroupId
2350
                            WHERE iid = $iid";
2351
                    $connection->executeQuery($sql);
2352
                } else {
2353
                    // The group does not exists clean this record
2354
                    $sql = "DELETE FROM $table WHERE iid = $iid";
2355
                    $connection->executeQuery($sql);
2356
                }
2357
            }
2358
        }
2359
    }
2360
2361
    // Fix c_item_property
2362
    if ($debug) {
2363
        error_log('update c_item_property');
2364
    }
2365
2366
    $sql = "SELECT * FROM course";
2367
    $courseList = $connection->fetchAll($sql);
2368
    if ($debug) {
2369
        error_log('Getting course list');
2370
    }
2371
2372
    $totalCourse = count($courseList);
2373
    $counter = 0;
2374
2375
    foreach ($courseList as $courseData) {
2376
        $courseId = $courseData['id'];
2377
        if ($debug) {
2378
            error_log('Updating course: '.$courseData['code']);
2379
        }
2380
2381
        $sql = "SELECT * FROM c_item_property WHERE c_id = $courseId";
2382
        $result = $connection->fetchAll($sql);
2383
        foreach ($result as $item) {
2384
            $sessionId = intval($item['session_id']);
2385
            $groupId = intval($item['to_group_id']);
2386
            $iid = $item['iid'];
2387
            $ref = $item['ref'];
2388
2389
            // Fix group id
2390
            // Commented group id is already fixed in Version20150603181728.php
2391
            /*if (!empty($groupId)) {
2392
                $sql = "SELECT * FROM c_group_info
2393
                        WHERE c_id = $courseId AND id = $groupId";
2394
                $data = $connection->fetchAssoc($sql);
2395
                if (!empty($data)) {
2396
                    $newGroupId = $data['iid'];
2397
                    $sql = "UPDATE c_item_property SET to_group_id = $newGroupId
2398
                            WHERE iid = $iid";
2399
                    $connection->executeQuery($sql);
2400
                } else {
2401
                    // The group does not exists clean this record
2402
                    $sql = "DELETE FROM c_item_property WHERE iid = $iid";
2403
                    $connection->executeQuery($sql);
2404
                }
2405
            }*/
2406
2407
            $sql = '';
2408
            $newId = '';
2409
            switch ($item['tool']) {
2410
                case TOOL_LINK:
2411
                    $sql = "SELECT * FROM c_link WHERE c_id = $courseId AND id = $ref ";
2412
                    break;
2413
                case TOOL_STUDENTPUBLICATION:
2414
                    $sql = "SELECT * FROM c_student_publication WHERE c_id = $courseId AND id = $ref";
2415
                    break;
2416
                case TOOL_QUIZ:
2417
                    $sql = "SELECT * FROM c_quiz WHERE c_id = $courseId AND id = $ref";
2418
                    break;
2419
                case TOOL_DOCUMENT:
2420
                    $sql = "SELECT * FROM c_document WHERE c_id = $courseId AND id = $ref";
2421
                    break;
2422
                case TOOL_FORUM:
2423
                    $sql = "SELECT * FROM c_forum_forum WHERE c_id = $courseId AND id = $ref";
2424
                    break;
2425
                case 'thread':
2426
                    $sql = "SELECT * FROM c_forum_thread WHERE c_id = $courseId AND id = $ref";
2427
                    break;
2428
            }
2429
2430
            if (!empty($sql) && !empty($newId)) {
2431
                $data = $connection->fetchAssoc($sql);
2432
                if (isset($data['iid'])) {
2433
                    $newId = $data['iid'];
2434
                }
2435
                $sql = "UPDATE c_item_property SET ref = $newId WHERE iid = $iid";
2436
                error_log($sql);
2437
                $connection->executeQuery($sql);
2438
            }
2439
        }
2440
2441
        if ($debug) {
2442
            // Print a status in the log once in a while
2443
            error_log("Course process #$counter/$totalCourse");
2444
        }
2445
        $counter++;
2446
    }
2447
2448
    if ($debug) {
2449
        error_log('update gradebook_link');
2450
    }
2451
2452
    // Fix gradebook_link
2453
    $sql = "SELECT * FROM gradebook_link";
2454
    $result = $connection->fetchAll($sql);
2455
    foreach ($result as $item) {
2456
        $courseCode = $item['course_code'];
2457
        $categoryId = (int) $item['category_id'];
2458
2459
        $sql = "SELECT * FROM course WHERE code = '$courseCode'";
2460
        $courseInfo = $connection->fetchAssoc($sql);
2461
        if (empty($courseInfo)) {
2462
            continue;
2463
        }
2464
2465
        $courseId = $courseInfo['id'];
2466
2467
        $ref = $item['ref_id'];
2468
        $iid = $item['id'];
2469
2470
        $sql = '';
2471
        switch ($item['type']) {
2472
            case LINK_LEARNPATH:
2473
                $sql = "SELECT * FROM c_link WHERE c_id = $courseId AND id = $ref ";
2474
                break;
2475
            case LINK_STUDENTPUBLICATION:
2476
                $sql = "SELECT * FROM c_student_publication WHERE c_id = $courseId AND id = $ref";
2477
                break;
2478
            case LINK_EXERCISE:
2479
                $sql = "SELECT * FROM c_quiz WHERE c_id = $courseId AND id = $ref";
2480
                break;
2481
            case LINK_ATTENDANCE:
2482
                //$sql = "SELECT * FROM c_document WHERE c_id = $courseId AND id = $ref";
2483
                break;
2484
            case LINK_FORUM_THREAD:
2485
                $sql = "SELECT * FROM c_forum_thread WHERE c_id = $courseId AND thread_id = $ref";
2486
                break;
2487
        }
2488
2489
        if (!empty($sql)) {
2490
            $data = $connection->fetchAssoc($sql);
2491
            if (isset($data) && isset($data['iid'])) {
2492
                $newId = $data['iid'];
2493
                $sql = "UPDATE gradebook_link SET ref_id = $newId
2494
                        WHERE id = $iid AND course_code = '$courseCode' AND category_id = $categoryId ";
2495
                $connection->executeQuery($sql);
2496
            }
2497
        }
2498
    }
2499
2500
    if ($debug) {
2501
        error_log('update groups');
2502
    }
2503
2504
    $sql = 'SELECT * FROM groups';
2505
    $result = $connection->executeQuery($sql);
2506
    $groups = $result->fetchAll();
2507
    $oldGroups = [];
2508
    if (!empty($groups)) {
2509
        foreach ($groups as $group) {
2510
            if (empty($group['name'])) {
2511
                continue;
2512
            }
2513
2514
            $params = [
2515
                'name' => $group['name'],
2516
                'description' => $group['description'],
2517
                'group_type' => 1,
2518
                'picture' => $group['picture_uri'],
2519
                'url' => $group['url'],
2520
                'visibility' => $group['visibility'],
2521
                'updated_at' => $group['updated_on'],
2522
                'created_at' => $group['created_on'],
2523
            ];
2524
            $connection->insert('usergroup', $params);
2525
            $id = $connection->lastInsertId('id');
2526
            $oldGroups[$group['id']] = $id;
2527
        }
2528
    }
2529
2530
    if (!empty($oldGroups)) {
2531
        error_log('Moving group files');
2532
        foreach ($oldGroups as $oldId => $newId) {
2533
            $path = get_group_picture_path_by_id(
2534
                $oldId,
2535
                'system'
2536
            );
2537
2538
            if (!empty($path)) {
2539
                $newPath = str_replace(
2540
                    "groups/$oldId/",
2541
                    "groups/$newId/",
2542
                    $path['dir']
2543
                );
2544
                $command = "mv {$path['dir']} $newPath ";
2545
                error_log("Executing $command");
2546
                system($command);
2547
            }
2548
        }
2549
2550
        $sql = "SELECT * FROM group_rel_user";
2551
        $result = $connection->executeQuery($sql);
2552
        $dataList = $result->fetchAll();
2553
2554
        if (!empty($dataList)) {
2555
            foreach ($dataList as $data) {
2556
                if (isset($oldGroups[$data['group_id']])) {
2557
                    $data['group_id'] = $oldGroups[$data['group_id']];
2558
                    $userId = $data['user_id'];
2559
2560
                    $sql = "SELECT id FROM user WHERE user_id = $userId";
2561
                    $userResult = $connection->executeQuery($sql);
2562
                    $userInfo = $userResult->fetch();
2563
                    if (empty($userInfo)) {
2564
                        continue;
2565
                    }
2566
2567
                    $sql = "INSERT INTO usergroup_rel_user (usergroup_id, user_id, relation_type)
2568
                            VALUES ('{$data['group_id']}', '{$userId}', '{$data['relation_type']}')";
2569
                    $connection->executeQuery($sql);
2570
                }
2571
            }
2572
        }
2573
2574
        $sql = "SELECT * FROM group_rel_group";
2575
        $result = $connection->executeQuery($sql);
2576
        $dataList = $result->fetchAll();
2577
2578
        if (!empty($dataList)) {
2579
            foreach ($dataList as $data) {
2580
                if (isset($oldGroups[$data['group_id']]) && isset($oldGroups[$data['subgroup_id']])) {
2581
                    $data['group_id'] = $oldGroups[$data['group_id']];
2582
                    $data['subgroup_id'] = $oldGroups[$data['subgroup_id']];
2583
                    $sql = "INSERT INTO usergroup_rel_usergroup (group_id, subgroup_id, relation_type)
2584
                            VALUES ('{$data['group_id']}', '{$data['subgroup_id']}', '{$data['relation_type']}')";
2585
                    $connection->executeQuery($sql);
2586
                }
2587
            }
2588
        }
2589
2590
        $sql = "SELECT * FROM announcement_rel_group";
2591
        $result = $connection->executeQuery($sql);
2592
        $dataList = $result->fetchAll();
2593
2594
        if (!empty($dataList)) {
2595
            foreach ($dataList as $data) {
2596
                if (isset($oldGroups[$data['group_id']])) {
2597
                    // Deleting relation
2598
                    $sql = "DELETE FROM announcement_rel_group WHERE group_id = {$data['group_id']}";
2599
                    $connection->executeQuery($sql);
2600
2601
                    // Add new relation
2602
                    $data['group_id'] = $oldGroups[$data['group_id']];
2603
                    $sql = "INSERT INTO announcement_rel_group(group_id, announcement_id)
2604
                            VALUES ('{$data['group_id']}', '{$data['announcement_id']}')";
2605
                    $connection->executeQuery($sql);
2606
                }
2607
            }
2608
        }
2609
2610
        $sql = "SELECT * FROM group_rel_tag";
2611
        $result = $connection->executeQuery($sql);
2612
        $dataList = $result->fetchAll();
2613
        if (!empty($dataList)) {
2614
            foreach ($dataList as $data) {
2615
                if (isset($oldGroups[$data['group_id']])) {
2616
                    $data['group_id'] = $oldGroups[$data['group_id']];
2617
                    $sql = "INSERT INTO usergroup_rel_tag (tag_id, usergroup_id)
2618
                            VALUES ('{$data['tag_id']}', '{$data['group_id']}')";
2619
                    $connection->executeQuery($sql);
2620
                }
2621
            }
2622
        }
2623
    }
2624
2625
    if ($debug) {
2626
        error_log('update extra fields');
2627
    }
2628
2629
    // Extra fields
2630
    $extraFieldTables = [
2631
        ExtraField::USER_FIELD_TYPE => Database::get_main_table(TABLE_MAIN_USER_FIELD),
2632
        ExtraField::COURSE_FIELD_TYPE => Database::get_main_table(TABLE_MAIN_COURSE_FIELD),
2633
        //ExtraField::LP_FIELD_TYPE => Database::get_main_table(TABLE_MAIN_LP_FIELD),
2634
        ExtraField::SESSION_FIELD_TYPE => Database::get_main_table(TABLE_MAIN_SESSION_FIELD),
2635
        //ExtraField::CALENDAR_FIELD_TYPE => Database::get_main_table(TABLE_MAIN_CALENDAR_EVENT_FIELD),
2636
        //ExtraField::QUESTION_FIELD_TYPE => Database::get_main_table(TABLE_MAIN_CALENDAR_EVENT_FIELD),
2637
        //ExtraField::USER_FIELD_TYPE => //Database::get_main_table(TABLE_MAIN_SPECIFIC_FIELD),
2638
    ];
2639
2640
    foreach ($extraFieldTables as $type => $table) {
2641
        $sql = "SELECT * FROM $table ";
2642
        if ($debug) {
2643
            error_log($sql);
2644
        }
2645
        $result = $connection->query($sql);
2646
        $fields = $result->fetchAll();
2647
2648
        foreach ($fields as $field) {
2649
            if ($debug) {
2650
                error_log("Loading field: ".$field['field_variable']);
2651
            }
2652
            $originalId = $field['id'];
2653
2654
            $params = [
2655
                'extra_field_type' => $type,
2656
                'variable' => $field['field_variable'],
2657
                'field_type' => $field['field_type'],
2658
                'display_text' => $field['field_display_text'],
2659
                'default_value' => $field['field_default_value'],
2660
                'field_order' => $field['field_order'],
2661
                'visible' => $field['field_visible'],
2662
                'changeable' => $field['field_changeable'],
2663
                'filter' => $field['field_filter'],
2664
            ];
2665
2666
            $connection->insert('extra_field', $params);
2667
            $newExtraFieldId = $connection->lastInsertId();
2668
2669
            $values = [];
2670
            $handlerId = null;
2671
            switch ($type) {
2672
                case ExtraField::USER_FIELD_TYPE:
2673
                    $optionTable = Database::get_main_table(
2674
                        TABLE_MAIN_USER_FIELD_OPTIONS
2675
                    );
2676
                    $valueTable = Database::get_main_table(
2677
                        TABLE_MAIN_USER_FIELD_VALUES
2678
                    );
2679
                    $handlerId = 'user_id';
2680
                    break;
2681
                case ExtraField::COURSE_FIELD_TYPE:
2682
                    $optionTable = Database::get_main_table(
2683
                        TABLE_MAIN_COURSE_FIELD_OPTIONS
2684
                    );
2685
                    $valueTable = Database::get_main_table(
2686
                        TABLE_MAIN_COURSE_FIELD_VALUES
2687
                    );
2688
                    $handlerId = 'c_id';
2689
                    break;
2690
                case ExtraField::SESSION_FIELD_TYPE:
2691
                    $optionTable = Database::get_main_table(
2692
                        TABLE_MAIN_SESSION_FIELD_OPTIONS
2693
                    );
2694
                    $valueTable = Database::get_main_table(
2695
                        TABLE_MAIN_SESSION_FIELD_VALUES
2696
                    );
2697
                    $handlerId = 'session_id';
2698
                    break;
2699
            }
2700
2701
            if (!empty($optionTable)) {
2702
                $sql = "SELECT * FROM $optionTable WHERE field_id = $originalId ";
2703
                $result = $connection->query($sql);
2704
                $options = $result->fetchAll();
2705
2706
                foreach ($options as $option) {
2707
                    $params = [
2708
                        'display_text' => $option['option_display_text'],
2709
                        'field_id' => $newExtraFieldId,
2710
                        'option_order' => $option['option_order'],
2711
                        'option_value' => $option['option_value'],
2712
                    ];
2713
                    $connection->insert('extra_field_options', $params);
2714
                }
2715
2716
                $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...
2717
                $result = $connection->query($sql);
2718
                $values = $result->fetchAll();
2719
                if ($debug) {
2720
                    error_log("Fetch all values for field");
2721
                }
2722
            }
2723
2724
            if (!empty($values)) {
2725
                if ($debug) {
2726
                    error_log("Saving field value in new table");
2727
                }
2728
                $k = 0;
2729
                foreach ($values as $value) {
2730
                    if (isset($value[$handlerId])) {
2731
                        // Insert without the use of the entity as it reduces
2732
                        // speed to 2 records per second (much too slow)
2733
                        $params = [
2734
                            'field_id' => $newExtraFieldId,
2735
                            'value' => $value['field_value'],
2736
                            'item_id' => $value[$handlerId],
2737
                        ];
2738
                        $connection->insert('extra_field_values', $params);
2739
                        if ($debug && ($k % 10000 == 0)) {
2740
                            error_log("Saving field $k");
2741
                        }
2742
                        $k++;
2743
                    }
2744
                }
2745
            }
2746
        }
2747
    }
2748
2749
    if ($debug) {
0 ignored issues
show
introduced by
$debug is of type mixed, thus it always evaluated to true.
Loading history...
2750
        error_log('Remove index');
2751
    }
2752
2753
    // Drop temporary indexes added to increase speed of this function's queries
2754
    $sql = "ALTER TABLE c_document DROP INDEX tmpidx_doc";
2755
    $connection->executeQuery($sql);
2756
    $sql = "ALTER TABLE c_student_publication DROP INDEX tmpidx_stud";
2757
    $connection->executeQuery($sql);
2758
    $sql = "ALTER TABLE c_quiz DROP INDEX tmpidx_quiz";
2759
    $connection->executeQuery($sql);
2760
    $sql = "ALTER TABLE c_item_property DROP INDEX tmpidx_ip";
2761
    $connection->executeQuery($sql);
2762
2763
    if ($debug) {
2764
        error_log('Finish fixId function');
2765
    }
2766
2767
    fixLpId($connection, true);
2768
}
2769
2770
/**
2771
 * @param \Doctrine\DBAL\Connection $connection
2772
 * @param $debug
2773
 *
2774
 * @throws \Doctrine\DBAL\DBALException
2775
 */
2776
function fixLpId($connection, $debug)
2777
{
2778
    if ($debug) {
2779
        error_log('Fix lp.id lp.iids');
2780
    }
2781
2782
    $sql = 'SELECT id, title, code FROM course';
2783
    $result = $connection->query($sql);
2784
    $courses = $result->fetchAll();
2785
2786
    $sql = 'SELECT id FROM session';
2787
    $result = $connection->query($sql);
2788
    $sessions = $result->fetchAll();
2789
2790
    $tblCLp = Database::get_course_table(TABLE_LP_MAIN);
2791
    $tblCLpItem = Database::get_course_table(TABLE_LP_ITEM);
2792
    $toolTable = Database::get_course_table(TABLE_TOOL_LIST);
2793
2794
    if (!empty($sessions)) {
2795
        $sessions = array_column($sessions, 'id');
2796
        $sessions[] = 0;
2797
    } else {
2798
        $sessions = [0];
2799
    }
2800
2801
    foreach ($courses as $course) {
2802
        $courseId = $course['id'];
2803
        $sql = "SELECT * FROM $tblCLp WHERE c_id = $courseId AND iid <> id ORDER by iid";
2804
        $result = $connection->query($sql);
2805
        if ($debug) {
2806
            error_log('-------------');
2807
            error_log("Entering Lps in course #$courseId");
2808
            error_log($sql);
2809
        }
2810
        $lpList = $result->fetchAll();
2811
        $myOnlyLpList = [];
2812
        if (!empty($lpList)) {
2813
            foreach ($lpList as $lpInfo) {
2814
                $oldId = $lpInfo['id'];
2815
                $sql = "SELECT * FROM $tblCLpItem WHERE c_id = $courseId AND lp_id = $oldId ORDER by iid";
2816
                $result = $connection->query($sql);
2817
                $items = $result->fetchAll();
2818
                $lpInfo['lp_list'] = $items;
2819
                $myOnlyLpList[] = $lpInfo;
2820
            }
2821
        }
2822
2823
        if (!empty($myOnlyLpList)) {
2824
            foreach ($myOnlyLpList as $lpInfo) {
2825
                $lpIid = $lpInfo['iid'];
2826
                $oldId = $lpInfo['id'];
2827
                $items = $lpInfo['lp_list'];
2828
2829
                if (empty($items)) {
2830
                    continue;
2831
                }
2832
                $itemList = [];
2833
                foreach ($items as $subItem) {
2834
                    $itemList[$subItem['id']] = $subItem['iid'];
2835
                }
2836
                $variablesToFix = [
2837
                    'parent_item_id',
2838
                    'next_item_id',
2839
                    'prerequisite',
2840
                    'previous_item_id',
2841
                ];
2842
2843
                foreach ($sessions as $sessionId) {
2844
                    $correctLink = "lp/lp_controller.php?action=view&lp_id=$lpIid&id_session=$sessionId";
2845
                    $link = "newscorm/lp_controller.php?action=view&lp_id=$oldId&id_session=$sessionId";
2846
                    $secondLink = "lp/lp_controller.php?action=view&lp_id=$oldId&id_session=$sessionId";
2847
                    $sql = "UPDATE $toolTable 
2848
                        SET link = '$correctLink'
2849
                        WHERE c_id = $courseId AND (link = '$link' OR link ='$secondLink')";
2850
                    $connection->query($sql);
2851
                }
2852
2853
                foreach ($items as $item) {
2854
                    $itemIid = $item['iid'];
2855
                    $itemId = $item['id'];
2856
                    foreach ($variablesToFix as $variable) {
2857
                        if (!empty($item[$variable]) && isset($itemList[$item[$variable]])) {
2858
                            $newId = $itemList[$item[$variable]];
2859
                            $sql = "UPDATE $tblCLpItem SET $variable = $newId 
2860
                                    WHERE iid = $itemIid AND c_id = $courseId AND lp_id = $oldId";
2861
                            $connection->query($sql);
2862
                        }
2863
                    }
2864
2865
                    if ($item['item_type'] == 'document' && !empty($item['path'])) {
2866
                        $oldDocumentId = $item['path'];
2867
                        $sql = "SELECT * FROM c_document WHERE c_id = $courseId AND id = $oldDocumentId";
2868
                        $result = $connection->query($sql);
2869
                        $document = $result->fetch();
2870
                        if (!empty($document)) {
2871
                            $newDocumentId = $document['iid'];
2872
                            if (!empty($newDocumentId)) {
2873
                                $sql = "UPDATE $tblCLpItem SET path = $newDocumentId 
2874
                                    WHERE iid = $itemIid AND c_id = $courseId";
2875
                                $connection->query($sql);
2876
                                if ($debug) {
2877
                                    //error_log("Fix document: ");
2878
                                    //error_log($sql);
2879
                                }
2880
                            }
2881
                        }
2882
                    }
2883
2884
                    // c_lp_view
2885
                    $sql = "UPDATE c_lp_view SET last_item = $itemIid 
2886
                            WHERE c_id = $courseId AND last_item = $itemId AND lp_id = $oldId";
2887
                    $connection->query($sql);
2888
2889
                    // c_lp_item_view
2890
                    $sql = "UPDATE c_lp_item_view SET lp_item_id = $itemIid 
2891
                            WHERE c_id = $courseId AND lp_item_id = $itemId";
2892
                    $connection->query($sql);
2893
2894
                    // Update track_exercises
2895
                    $sql = "UPDATE track_e_exercises SET orig_lp_item_id = $itemIid 
2896
                            WHERE c_id = $courseId AND orig_lp_id = $oldId AND orig_lp_item_id = $itemId";
2897
                    $connection->query($sql);
2898
2899
                    // c_forum_thread
2900
                    $sql = "UPDATE c_forum_thread SET lp_item_id = $itemIid 
2901
                            WHERE c_id = $courseId AND lp_item_id = $itemId";
2902
                    $connection->query($sql);
2903
2904
                    // orig_lp_item_view_id
2905
                    $sql = "SELECT * FROM c_lp_view
2906
                            WHERE c_id = $courseId AND lp_id = $oldId";
2907
                    $result = $connection->query($sql);
2908
                    $itemViewList = $result->fetchAll();
2909
                    if ($itemViewList) {
2910
                        foreach ($itemViewList as $itemView) {
2911
                            $userId = $itemView['user_id'];
2912
                            $oldItemViewId = $itemView['id'];
2913
                            $newItemView = $itemView['iid'];
2914
2915
                            if (empty($oldItemViewId)) {
2916
                                continue;
2917
                            }
2918
2919
                            $sql = "UPDATE track_e_exercises 
2920
                                SET orig_lp_item_view_id = $newItemView 
2921
                                WHERE 
2922
                                  c_id = $courseId AND 
2923
                                  orig_lp_id = $oldId AND 
2924
                                  orig_lp_item_id = $itemIid AND 
2925
                                  orig_lp_item_view_id = $oldItemViewId AND 
2926
                                  exe_user_id = $userId                                       
2927
                                  ";
2928
                            $connection->query($sql);
2929
2930
                            /*$sql = "UPDATE c_lp_item_view
2931
                                    SET lp_view_id = $newItemView
2932
                                    WHERE
2933
                                      lp_view_id = $oldItemViewId AND
2934
                                      c_id = $courseId
2935
                                  ";
2936
                            $connection->query($sql);*/
2937
                        }
2938
                    }
2939
2940
                    $sql = "UPDATE $tblCLpItem SET lp_id = $lpIid 
2941
                            WHERE c_id = $courseId AND lp_id = $oldId AND id = $itemId";
2942
                    $connection->query($sql);
2943
2944
                    $sql = "UPDATE $tblCLpItem SET id = iid 
2945
                            WHERE c_id = $courseId AND lp_id = $oldId AND id = $itemId";
2946
                    $connection->query($sql);
2947
                }
2948
2949
                $sql = "UPDATE c_lp_view SET lp_id = $lpIid WHERE c_id = $courseId AND lp_id = $oldId";
2950
                $connection->query($sql);
2951
2952
                $sql = "UPDATE c_forum_forum SET lp_id = $lpIid WHERE c_id = $courseId AND lp_id = $oldId";
2953
                $connection->query($sql);
2954
2955
                // Update track_exercises.
2956
                $sql = "UPDATE track_e_exercises SET orig_lp_id = $lpIid 
2957
                        WHERE c_id = $courseId AND orig_lp_id = $oldId";
2958
                $connection->query($sql);
2959
2960
                $sql = "UPDATE $tblCLp SET id = iid WHERE c_id = $courseId AND id = $oldId ";
2961
                $connection->query($sql);
2962
            }
2963
        }
2964
    }
2965
2966
    if ($debug) {
2967
        error_log('END Fix lp.id lp.iids');
2968
    }
2969
}
2970
2971
/**
2972
 * @param string $distFile
2973
 * @param string $envFile
2974
 * @param array  $params
2975
 */
2976
function updateEnvFile($distFile, $envFile, $params)
2977
{
2978
    $contents = file_get_contents($distFile);
2979
    $contents = str_replace(array_keys($params), array_values($params), $contents);
2980
    file_put_contents($envFile, $contents);
2981
}
2982
2983
/**
2984
 * @param SymfonyContainer $container
2985
 * @param EntityManager    $manager
2986
 */
2987
function installGroups($container, $manager)
2988
{
2989
    // Creating fos_group (groups and roles)
2990
    $groupManager = $container->get('fos_user.group_manager');
2991
    $groups = [
2992
        [
2993
            'code' => 'ADMIN',
2994
            'title' => 'Administrators',
2995
            'roles' => ['ROLE_ADMIN'],
2996
        ],
2997
        [
2998
            'code' => 'STUDENT',
2999
            'title' => 'Students',
3000
            'roles' => ['ROLE_STUDENT'],
3001
        ],
3002
        [
3003
            'code' => 'TEACHER',
3004
            'title' => 'Teachers',
3005
            'roles' => ['ROLE_TEACHER'],
3006
        ],
3007
        [
3008
            'code' => 'RRHH',
3009
            'title' => 'Human resources manager',
3010
            'roles' => ['ROLE_RRHH'],
3011
        ],
3012
        [
3013
            'code' => 'SESSION_MANAGER',
3014
            'title' => 'Session',
3015
            'roles' => ['ROLE_SESSION_MANAGER'],
3016
        ],
3017
        [
3018
            'code' => 'QUESTION_MANAGER',
3019
            'title' => 'Question manager',
3020
            'roles' => ['ROLE_QUESTION_MANAGER'],
3021
        ],
3022
        [
3023
            'code' => 'STUDENT_BOSS',
3024
            'title' => 'Student boss',
3025
            'roles' => ['ROLE_STUDENT_BOSS'],
3026
        ],
3027
        [
3028
            'code' => 'INVITEE',
3029
            'title' => 'Invitee',
3030
            'roles' => ['ROLE_INVITEE'],
3031
        ],
3032
    ];
3033
3034
    foreach ($groups as $groupData) {
3035
        $criteria = ['code' => $groupData['code']];
3036
        $groupExists = $groupManager->findGroupBy($criteria);
3037
        if (!$groupExists) {
3038
            $group = $groupManager->createGroup($groupData['title']);
3039
            $group->setCode($groupData['code']);
3040
            foreach ($groupData['roles'] as $role) {
3041
                $group->addRole($role);
3042
            }
3043
            $manager->persist($group);
3044
            $groupManager->updateGroup($group, true);
3045
        }
3046
    }
3047
}
3048
3049
/**
3050
 * @param SymfonyContainer $container
3051
 */
3052
function installPages($container)
3053
{
3054
    error_log('installPages');
3055
3056
    $siteManager = Container::getSiteManager();
3057
3058
    // Create site
3059
    /** @var Chamilo\PageBundle\Entity\Site $site */
3060
    $site = $siteManager->create();
3061
    $site->setHost('localhost');
3062
    $site->setEnabled(true);
3063
    $site->setName('localhost');
3064
    $site->setEnabledFrom(new \DateTime('now'));
3065
    $site->setEnabledTo(new \DateTime('+20 years'));
3066
    $site->setRelativePath('');
3067
    $site->setIsDefault(true);
3068
    $site->setLocale('en');
3069
    $siteManager->save($site);
3070
3071
    // Create home page
3072
    /** @var PageManager $pageManager */
3073
    $pageManager = $container->get('sonata.page.manager.page');
3074
    /** @var \Sonata\PageBundle\Model\Page $page */
3075
    $page = $pageManager->create();
3076
    $page->setSlug('homepage');
3077
    $page->setUrl('/');
3078
    $page->setName('homepage');
3079
    $page->setTitle('home');
3080
    $page->setEnabled(true);
3081
    $page->setDecorate(1);
3082
    $page->setRequestMethod('GET|POST|HEAD|DELETE|PUT');
3083
    $page->setTemplateCode('default');
3084
    $page->setRouteName('homepage');
3085
    //$page->setParent($this->getReference('page-homepage'));
3086
    $page->setSite($site);
3087
    $pageManager->save($page);
3088
3089
    // Create welcome page
3090
    $pageWelcome = $pageManager->create();
3091
    $pageWelcome->setSlug('welcome');
3092
    $pageWelcome->setUrl('/welcome');
3093
    $pageWelcome->setName('welcome');
3094
    $pageWelcome->setTitle('welcome');
3095
    $pageWelcome->setEnabled(true);
3096
    $pageWelcome->setDecorate(1);
3097
    $pageWelcome->setRequestMethod('GET');
3098
    $pageWelcome->setTemplateCode('default');
3099
    $pageWelcome->setRouteName('welcome');
3100
    $pageWelcome->setParent($page);
3101
    $pageWelcome->setSite($site);
3102
    $pageManager->save($pageWelcome);
3103
3104
    // Creating page blocks
3105
    $templateManager = $container->get('sonata.page.template_manager');
3106
    $template = $templateManager->get('default');
3107
    $templateContainers = $template->getContainers();
3108
3109
    $containers = [];
3110
    foreach ($templateContainers as $id => $area) {
3111
        $containers[$id] = [
3112
            'area' => $area,
3113
            'block' => false,
3114
        ];
3115
    }
3116
3117
    // Create blocks for this page
3118
    $blockInteractor = $container->get('sonata.page.block_interactor');
3119
    $parentBlock = null;
3120
    foreach ($containers as $id => $area) {
3121
        if (false === $area['block'] && $templateContainers[$id]['shared'] === false) {
3122
            $block = $blockInteractor->createNewContainer(
3123
                [
3124
                    'page' => $pageWelcome,
3125
                    'name' => $templateContainers[$id]['name'],
3126
                    'code' => $id,
3127
                ]
3128
            );
3129
3130
            if ($id === 'content' && $templateContainers[$id]['name'] == 'Main content') {
3131
                $parentBlock = $block;
3132
            }
3133
        }
3134
    }
3135
3136
    // Create block in main content
3137
    $block = $container->get('sonata.page.manager.block');
3138
    /** @var \Sonata\BlockBundle\Model\Block $myBlock */
3139
    $myBlock = $block->create();
3140
    $myBlock->setType('sonata.formatter.block.formatter');
3141
    $myBlock->setSetting('format', 'richhtml');
3142
    $myBlock->setSetting('content', '');
3143
    $myBlock->setSetting('rawContent', '');
3144
    $myBlock->setSetting('template', '@SonataFormatter/Block/block_formatter.html.twig');
3145
    $myBlock->setParent($parentBlock);
3146
    $pageWelcome->addBlocks($myBlock);
3147
    $pageManager->save($pageWelcome);
3148
}
3149
3150
/**
3151
 * @param SymfonyContainer $container
3152
 * @param EntityManager    $manager
3153
 * @param bool             $upgrade
3154
 */
3155
function installSchemas($container, $manager, $upgrade = false)
3156
{
3157
    error_log('installSchemas');
3158
    $settingsManager = Container::getSettingsManager();
3159
3160
    $accessUrl = $manager->getRepository('ChamiloCoreBundle:AccessUrl')->find(1);
3161
    if (!$accessUrl) {
3162
        // Creating AccessUrl
3163
        $accessUrl = new AccessUrl();
3164
        $accessUrl
3165
            ->setUrl('http://localhost/')
3166
            ->setDescription('')
3167
            ->setActive(1)
3168
        ;
3169
        $manager->persist($accessUrl);
3170
        $manager->flush();
3171
    }
3172
3173
    // Install course tools (table "tool")
3174
    $toolChain = $container->get('chamilo_course.tool_chain');
3175
    $toolChain->createTools($manager);
3176
3177
    if ($upgrade) {
3178
        $settingsManager->updateSchemas($accessUrl);
3179
    } else {
3180
        // Installing schemas (filling settings_current table)
3181
        $settingsManager->installSchemas($accessUrl);
3182
    }
3183
}
3184
3185
/**
3186
 * @param SymfonyContainer $container
3187
 */
3188
function upgradeWithContainer($container)
3189
{
3190
    Container::setContainer($container);
3191
    Container::setLegacyServices($container, false);
3192
    error_log('setLegacyServices');
3193
    $manager = Database::getManager();
3194
    installGroups($container, $manager);
3195
    error_log('installGroups');
3196
    installSchemas($container, $manager, true);
3197
    installPages($container);
3198
    fixMedia($container);
3199
}
3200
3201
function fixMedia($container)
3202
{
3203
    error_log('fix medias');
3204
    $pool = $container->get('sonata.media.pool');
3205
    $contextManager = $container->get('sonata.classification.manager.context');
3206
    $categoryManager = $container->get('sonata.media.manager.category');
3207
3208
    foreach ($pool->getContexts() as $context => $contextAttrs) {
3209
        /** @var ContextInterface $defaultContext */
3210
        $defaultContext = $contextManager->findOneBy([
3211
            'id' => $context,
3212
        ]);
3213
3214
        if (!$defaultContext) {
3215
            $defaultContext = $contextManager->create();
3216
            $defaultContext->setId($context);
3217
            $defaultContext->setName(ucfirst($context));
3218
            $defaultContext->setEnabled(true);
3219
3220
            $contextManager->save($defaultContext);
3221
        }
3222
3223
        $defaultCategory = $categoryManager->getRootCategory($defaultContext);
3224
3225
        if (!$defaultCategory) {
3226
            $defaultCategory = $categoryManager->create();
3227
            $defaultCategory->setContext($defaultContext);
3228
            $defaultCategory->setName(ucfirst($context));
3229
            $defaultCategory->setEnabled(true);
3230
            $defaultCategory->setPosition(0);
3231
3232
            $categoryManager->save($defaultCategory);
3233
        }
3234
    }
3235
}
3236
3237
/**
3238
 * After the schema was created (table creation), the function adds
3239
 * admin/platform information.
3240
 *
3241
 * @param \Psr\Container\ContainerInterface $container
3242
 * @param string                            $sysPath
3243
 * @param string                            $encryptPassForm
3244
 * @param string                            $passForm
3245
 * @param string                            $adminLastName
3246
 * @param string                            $adminFirstName
3247
 * @param string                            $loginForm
3248
 * @param string                            $emailForm
3249
 * @param string                            $adminPhoneForm
3250
 * @param string                            $languageForm
3251
 * @param string                            $institutionForm
3252
 * @param string                            $institutionUrlForm
3253
 * @param string                            $siteName
3254
 * @param string                            $allowSelfReg
3255
 * @param string                            $allowSelfRegProf
3256
 * @param string                            $installationProfile Installation profile, if any was provided
3257
 */
3258
function finishInstallationWithContainer(
3259
    $container,
3260
    $sysPath,
3261
    $encryptPassForm,
3262
    $passForm,
3263
    $adminLastName,
3264
    $adminFirstName,
3265
    $loginForm,
3266
    $emailForm,
3267
    $adminPhoneForm,
3268
    $languageForm,
3269
    $institutionForm,
3270
    $institutionUrlForm,
3271
    $siteName,
3272
    $allowSelfReg,
3273
    $allowSelfRegProf,
3274
    $installationProfile = ''
3275
) {
3276
    $sysPath = !empty($sysPath) ? $sysPath : api_get_path(SYS_PATH);
3277
    Container::setContainer($container);
3278
    Container::setLegacyServices($container, false);
3279
3280
    $manager = Database::getManager();
3281
    $connection = $manager->getConnection();
3282
    $sql = getVersionTable();
3283
    // Add version table
3284
    $connection->executeQuery($sql);
3285
3286
    // Add tickets defaults
3287
    $ticketProject = new TicketProject();
3288
    $ticketProject
3289
        ->setId(1)
3290
        ->setName('Ticket System')
3291
        ->setInsertUserId(1);
3292
3293
    $manager->persist($ticketProject);
3294
    $manager->flush();
3295
3296
    $categories = [
3297
        get_lang('TicketEnrollment') => get_lang('TicketsAboutEnrollment'),
3298
        get_lang('TicketGeneralInformation') => get_lang('TicketsAboutGeneralInformation'),
3299
        get_lang('TicketRequestAndPapework') => get_lang('TicketsAboutRequestAndPapework'),
3300
        get_lang('TicketAcademicIncidence') => get_lang('TicketsAboutAcademicIncidence'),
3301
        get_lang('TicketVirtualCampus') => get_lang('TicketsAboutVirtualCampus'),
3302
        get_lang('TicketOnlineEvaluation') => get_lang('TicketsAboutOnlineEvaluation'),
3303
    ];
3304
3305
    $i = 1;
3306
    foreach ($categories as $category => $description) {
3307
        // Online evaluation requires a course
3308
        $ticketCategory = new TicketCategory();
3309
        $ticketCategory
3310
            ->setId($i)
3311
            ->setName($category)
3312
            ->setDescription($description)
3313
            ->setProject($ticketProject)
3314
            ->setInsertUserId(1);
3315
3316
        $isRequired = $i == 6;
3317
        $ticketCategory->setCourseRequired($isRequired);
3318
3319
        $manager->persist($ticketCategory);
3320
        $manager->flush();
3321
3322
        $i++;
3323
    }
3324
3325
    // Default Priorities
3326
    $defaultPriorities = [
3327
        TicketManager::PRIORITY_NORMAL => get_lang('PriorityNormal'),
3328
        TicketManager::PRIORITY_HIGH => get_lang('PriorityHigh'),
3329
        TicketManager::PRIORITY_LOW => get_lang('PriorityLow'),
3330
    ];
3331
3332
    $i = 1;
3333
    foreach ($defaultPriorities as $code => $priority) {
3334
        $ticketPriority = new TicketPriority();
3335
        $ticketPriority
3336
            ->setId($i)
3337
            ->setName($priority)
3338
            ->setCode($code)
3339
            ->setInsertUserId(1);
3340
3341
        $manager->persist($ticketPriority);
3342
        $manager->flush();
3343
        $i++;
3344
    }
3345
3346
    $table = Database::get_main_table(TABLE_TICKET_STATUS);
3347
3348
    // Default status
3349
    $defaultStatus = [
3350
        TicketManager::STATUS_NEW => get_lang('StatusNew'),
3351
        TicketManager::STATUS_PENDING => get_lang('StatusPending'),
3352
        TicketManager::STATUS_UNCONFIRMED => get_lang('StatusUnconfirmed'),
3353
        TicketManager::STATUS_CLOSE => get_lang('StatusClose'),
3354
        TicketManager::STATUS_FORWARDED => get_lang('StatusForwarded'),
3355
    ];
3356
3357
    $i = 1;
3358
    foreach ($defaultStatus as $code => $status) {
3359
        $attributes = [
3360
            'id' => $i,
3361
            'code' => $code,
3362
            'name' => $status,
3363
        ];
3364
        Database::insert($table, $attributes);
3365
        $i++;
3366
    }
3367
3368
    installGroups($container, $manager);
3369
    installSchemas($container, $manager);
3370
    installPages($container);
3371
3372
    // Inserting default data
3373
    $data = file_get_contents($sysPath.'main/install/data.sql');
3374
    $result = $manager->getConnection()->prepare($data);
3375
    $result->execute();
3376
    $result->closeCursor();
3377
3378
    UserManager::setPasswordEncryption($encryptPassForm);
3379
3380
    // Create admin user.
3381
    @UserManager::create_user(
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for create_user(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

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

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

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

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

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
3382
        $adminFirstName,
3383
        $adminLastName,
3384
        1,
3385
        $emailForm,
3386
        $loginForm,
3387
        $passForm,
3388
        'ADMIN', //$official_code = '',
3389
        $languageForm,
3390
        $adminPhoneForm,
3391
        '', //$picture_uri = '',
3392
        PLATFORM_AUTH_SOURCE,
3393
        '', //$expirationDate,
3394
        1,
3395
        0,
3396
        null,
3397
        '',
3398
        false, //$send_mail = false,
3399
        true, //$isAdmin = false
3400
        '',
3401
        false,
3402
        '',
3403
        1
3404
    );
3405
3406
    // Create anonymous user.
3407
    @UserManager::create_user(
3408
        'Joe',
3409
        'Anonymous',
3410
        6,
3411
        'anonymous@localhost',
3412
        'anon',
3413
        'anon',
3414
        'anonymous', //$official_code = '',
3415
        $languageForm,
3416
        '',
3417
        '', //$picture_uri = '',
3418
        PLATFORM_AUTH_SOURCE,
3419
        '',
3420
        1,
3421
        0,
3422
        null,
3423
        '',
3424
        false, //$send_mail = false,
3425
        false, //$isAdmin = false
3426
        '',
3427
        false,
3428
        '',
3429
        1
3430
    );
3431
3432
    // Set default language
3433
    Database::update(
3434
        Database::get_main_table(TABLE_MAIN_LANGUAGE),
3435
        ['available' => 1],
3436
        ['dokeos_folder = ?' => $languageForm]
3437
    );
3438
3439
    // Install settings
3440
    installSettings(
3441
        $institutionForm,
3442
        $institutionUrlForm,
3443
        $siteName,
3444
        $emailForm,
3445
        $adminLastName,
3446
        $adminFirstName,
3447
        $languageForm,
3448
        $allowSelfReg,
3449
        $allowSelfRegProf,
3450
        $installationProfile
3451
    );
3452
3453
    lockSettings();
3454
    updateDirAndFilesPermissions();
3455
    fixMedia($container);
3456
3457
    // Set the latest version
3458
    /*$path = $sysPath.'app/Migrations/Schema/V111/';
3459
    $finder = new \Symfony\Component\Finder\Finder();
3460
    $files = $finder->files()->in($path);
3461
3462
    // Needed for chash
3463
    createVersionTable();
3464
3465
    foreach ($files as $version) {
3466
        $version = str_replace(['Version', '.php'], '', $version->getFilename());
3467
        $sql = "INSERT INTO version (version) VALUES ('$version')";
3468
        Database::query($sql);
3469
    }*/
3470
}
3471
3472
/**
3473
 * Creates 'version' table.
3474
 */
3475
function createVersionTable()
3476
{
3477
    $sql = getVersionTable();
3478
    Database::query($sql);
3479
}
3480
3481
/**
3482
 * Get version creation table query.
3483
 *
3484
 * @return string
3485
 */
3486
function getVersionTable()
3487
{
3488
    return 'CREATE TABLE IF NOT EXISTS version (id int unsigned NOT NULL AUTO_INCREMENT, version varchar(20), PRIMARY KEY(id), UNIQUE(version));';
3489
}
3490
3491
/**
3492
 * Update settings based on installation profile defined in a JSON file.
3493
 *
3494
 * @param string $installationProfile The name of the JSON file in main/install/profiles/ folder
3495
 *
3496
 * @return bool false on failure (no bad consequences anyway, just ignoring profile)
3497
 */
3498
function installProfileSettings($installationProfile = '')
3499
{
3500
    if (empty($installationProfile)) {
3501
        return false;
3502
    }
3503
    $jsonPath = api_get_path(SYS_PATH).'main/install/profiles/'.$installationProfile.'.json';
3504
    // Make sure the path to the profile is not hacked
3505
    if (!Security::check_abs_path($jsonPath, api_get_path(SYS_PATH).'main/install/profiles/')) {
3506
        return false;
3507
    }
3508
    if (!is_file($jsonPath)) {
3509
        return false;
3510
    }
3511
    if (!is_readable($jsonPath)) {
3512
        return false;
3513
    }
3514
    if (!function_exists('json_decode')) {
3515
        // The php-json extension is not available. Ignore profile.
3516
        return false;
3517
    }
3518
    $json = file_get_contents($jsonPath);
3519
    $params = json_decode($json);
3520
    if ($params === false or $params === null) {
3521
        return false;
3522
    }
3523
    $settings = $params->params;
3524
    if (!empty($params->parent)) {
3525
        installProfileSettings($params->parent);
3526
    }
3527
3528
    $tblSettings = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
3529
3530
    foreach ($settings as $id => $param) {
3531
        $conditions = ['variable = ? ' => $param->variable];
3532
3533
        if (!empty($param->subkey)) {
3534
            $conditions['AND subkey = ? '] = $param->subkey;
3535
        }
3536
3537
        Database::update(
3538
            $tblSettings,
3539
            ['selected_value' => $param->selected_value],
3540
            $conditions
3541
        );
3542
    }
3543
3544
    return true;
3545
}
3546
3547
/**
3548
 * Quick function to remove a directory with its subdirectories.
3549
 *
3550
 * @param $dir
3551
 */
3552
function rrmdir($dir)
3553
{
3554
    if (is_dir($dir)) {
3555
        $objects = scandir($dir);
3556
        foreach ($objects as $object) {
3557
            if ($object != "." && $object != "..") {
3558
                if (filetype($dir."/".$object) == "dir") {
3559
                    @rrmdir($dir."/".$object);
0 ignored issues
show
Bug introduced by
Are you sure the usage of rrmdir($dir . '/' . $object) is correct as it seems to always return null.

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

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

}

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

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

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

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

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

3559
                    /** @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...
3560
                } else {
3561
                    @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

3561
                    /** @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...
3562
                }
3563
            }
3564
        }
3565
        reset($objects);
3566
        rmdir($dir);
3567
    }
3568
}
3569
3570
/**
3571
 * @param        $id
3572
 * @param string $type
3573
 * @param bool   $preview
3574
 * @param bool   $anonymous
3575
 *
3576
 * @throws \Doctrine\DBAL\DBALException
3577
 *
3578
 * @return array
3579
 */
3580
function get_group_picture_path_by_id($id, $type = 'web', $preview = false, $anonymous = false)
3581
{
3582
    switch ($type) {
3583
        case 'system': // Base: absolute system path.
3584
            $base = api_get_path(SYS_UPLOAD_PATH);
3585
            break;
3586
        case 'web': // Base: absolute web path.
3587
        default:
3588
            $base = api_get_path(WEB_UPLOAD_PATH);
3589
            break;
3590
    }
3591
3592
    $noPicturePath = ['dir' => $base.'img/', 'file' => 'unknown.jpg'];
3593
3594
    if (empty($id) || empty($type)) {
3595
        return $anonymous ? $noPicturePath : ['dir' => '', 'file' => ''];
3596
    }
3597
3598
    $id = intval($id);
3599
3600
    //$group_table = Database::get_main_table(TABLE_MAIN_GROUP);
3601
    $group_table = 'groups';
3602
    $sql = "SELECT picture_uri FROM $group_table WHERE id=".$id;
3603
    $res = Database::query($sql);
3604
3605
    if (!Database::num_rows($res)) {
3606
        return $anonymous ? $noPicturePath : ['dir' => '', 'file' => ''];
3607
    }
3608
3609
    $user = Database::fetch_array($res);
3610
    $picture_filename = trim($user['picture_uri']);
3611
3612
    if (api_get_setting('split_users_upload_directory') === 'true') {
3613
        if (!empty($picture_filename)) {
3614
            $dir = $base.'groups/'.substr($picture_filename, 0, 1).'/'.$id.'/';
3615
        } elseif ($preview) {
3616
            $dir = $base.'groups/'.substr((string) $id, 0, 1).'/'.$id.'/';
3617
        } else {
3618
            $dir = $base.'groups/'.$id.'/';
3619
        }
3620
    } else {
3621
        $dir = $base.'groups/'.$id.'/';
3622
    }
3623
3624
    if (empty($picture_filename) && $anonymous) {
3625
        return $noPicturePath;
3626
    }
3627
3628
    return ['dir' => $dir, 'file' => $picture_filename];
3629
}
3630
3631
/**
3632
 * Control the different steps of the migration through a big switch.
3633
 *
3634
 * @param string        $fromVersion
3635
 * @param EntityManager $manager
3636
 * @param bool          $processFiles
3637
 *
3638
 * @throws \Doctrine\DBAL\DBALException
3639
 *
3640
 * @return bool Always returns true except if the process is broken
3641
 */
3642
function migrateSwitch($fromVersion, $manager, $processFiles = true)
3643
{
3644
    error_log('Starting migration process from '.$fromVersion.' ('.date('Y-m-d H:i:s').')');
3645
3646
    echo '<a class="btn btn-secondary" href="javascript:void(0)" id="details_button">'.get_lang('Details').'</a><br />';
3647
    echo '<div id="details" style="display:none">';
3648
3649
    $connection = $manager->getConnection();
3650
3651
    $database = new Database();
3652
    $database->setManager($manager);
3653
3654
    switch ($fromVersion) {
3655
        case '1.9.0':
3656
        case '1.9.2':
3657
        case '1.9.4':
3658
        case '1.9.6':
3659
        case '1.9.6.1':
3660
        case '1.9.8':
3661
        case '1.9.8.1':
3662
        case '1.9.8.2':
3663
        case '1.9.10':
3664
        case '1.9.10.2':
3665
        case '1.9.10.4':
3666
        case '1.9.10.6':
3667
            $database = new Database();
3668
            $database->setManager($manager);
3669
3670
            // Fix type "enum" before running the migration with Doctrine
3671
            $connection->executeQuery("ALTER TABLE course_category MODIFY COLUMN auth_course_child VARCHAR(40) DEFAULT 'TRUE'");
3672
            $connection->executeQuery("ALTER TABLE course_category MODIFY COLUMN auth_cat_child VARCHAR(40) DEFAULT 'TRUE'");
3673
            $connection->executeQuery('ALTER TABLE c_quiz_answer MODIFY COLUMN hotspot_type varchar(40) default NULL');
3674
            $connection->executeQuery("ALTER TABLE c_tool MODIFY COLUMN target varchar(20) NOT NULL default '_self'");
3675
            $connection->executeQuery("ALTER TABLE c_link MODIFY COLUMN on_homepage char(10) NOT NULL default '0'");
3676
            $connection->executeQuery("ALTER TABLE c_blog_rating MODIFY COLUMN rating_type char(40) NOT NULL default 'post'");
3677
            $connection->executeQuery("ALTER TABLE c_survey MODIFY COLUMN anonymous char(10) NOT NULL default '0'");
3678
            $connection->executeQuery("ALTER TABLE c_document MODIFY COLUMN filetype char(10) NOT NULL default 'file'");
3679
            $connection->executeQuery("ALTER TABLE c_student_publication MODIFY COLUMN filetype char(10) NOT NULL default 'file'");
3680
3681
            // Migrate using the migration files located in:
3682
            // src/Chamilo/CoreBundle/Migrations/Schema/V110
3683
            $result = migrate(
3684
                110,
3685
                $manager
3686
            );
3687
3688
            if ($result) {
3689
                error_log('Migrations files were executed ('.date('Y-m-d H:i:s').')');
3690
                fixIds($manager);
3691
                error_log('fixIds finished ('.date('Y-m-d H:i:s').')');
3692
3693
                $connection->executeQuery("UPDATE settings_current SET selected_value = '1.10.0' WHERE variable = 'chamilo_database_version'");
3694
3695
                if ($processFiles) {
3696
                    $fromVersionShort = '1.9';
3697
                    include __DIR__.'/update-files-1.9.0-1.10.0.inc.php';
3698
                    // Only updates the configuration.inc.php with the new version
3699
                    include __DIR__.'/update-configuration.inc.php';
3700
                }
3701
3702
                error_log('Upgrade 1.10.x process concluded! ('.date('Y-m-d H:i:s').')');
3703
            } else {
3704
                error_log('There was an error during running migrations. Check error.log');
3705
                break;
3706
            }
3707
            // no break
3708
        case '1.10.0':
3709
        case '1.10.2':
3710
        case '1.10.4':
3711
        case '1.10.6':
3712
        case '1.10.8':
3713
            $database = new Database();
3714
            $database->setManager($manager);
3715
            // Migrate using the migration files located in:
3716
            // src/Chamilo/CoreBundle/Migrations/Schema/V111
3717
            $result = migrate(111, $manager);
3718
3719
            if ($result) {
3720
                error_log('Migrations files were executed ('.date('Y-m-d H:i:s').')');
3721
3722
                fixPostGroupIds($connection);
3723
3724
                $sql = "UPDATE settings_current SET selected_value = '1.11.0' WHERE variable = 'chamilo_database_version'";
3725
                $connection->executeQuery($sql);
3726
                if ($processFiles) {
3727
                    error_log('Update config files');
3728
                    $fromVersionShort = '1.10';
3729
                    include __DIR__.'/update-files-1.10.0-1.11.0.inc.php';
3730
                    // Only updates the configuration.inc.php with the new version
3731
                    include __DIR__.'/update-configuration.inc.php';
3732
                }
3733
                error_log('Upgrade 1.11.x process concluded!  ('.date('Y-m-d H:i:s').')');
3734
            } else {
3735
                error_log('There was an error during running migrations. Check error.log');
3736
            }
3737
            // no break
3738
        case '1.11.0':
3739
        case '1.11.1':
3740
        case '1.11.2':
3741
        case '1.11.4':
3742
        case '1.11.6':
3743
        case '1.11.8':
3744
        case '1.11.10':
3745
            $database = new Database();
3746
            $database->setManager($manager);
3747
            // Migrate using the migration files located in:
3748
            // src/Chamilo/CoreBundle/Migrations/Schema/V111
3749
            $result = migrate(200, $manager);
3750
3751
            if ($result) {
3752
                error_log('Migrations files were executed ('.date('Y-m-d H:i:s').')');
3753
                $sql = "UPDATE settings_current SET selected_value = '2.0.0' WHERE variable = 'chamilo_database_version'";
3754
                $connection->executeQuery($sql);
3755
                if ($processFiles) {
3756
                    error_log('Update config files');
3757
                    $fromVersionShort = '1.11';
3758
                    include __DIR__.'/update-files-1.11.0-2.0.0.inc.php';
3759
                    // Only updates the configuration.inc.php with the new version
3760
                    include __DIR__.'/update-configuration.inc.php';
3761
                }
3762
                error_log('Upgrade 2.0.0 process concluded!  ('.date('Y-m-d H:i:s').')');
3763
            } else {
3764
                error_log('There was an error during running migrations. Check error.log');
3765
            }
3766
            break;
3767
        default:
3768
            break;
3769
    }
3770
3771
    echo '</div>';
3772
3773
    return true;
3774
}
3775
3776
/**
3777
 * @param \Doctrine\DBAL\Connection $connection
3778
 *
3779
 * @throws \Doctrine\DBAL\DBALException
3780
 */
3781
function fixPostGroupIds($connection)
3782
{
3783
    $connection->executeQuery("ALTER TABLE course_category MODIFY COLUMN auth_course_child VARCHAR(40) DEFAULT 'TRUE'");
3784
    error_log('Fix c_student_publication.post_group_id');
3785
3786
    // Fix post_group_id
3787
    $sql = "SELECT * FROM c_student_publication 
3788
            WHERE (post_group_id <> 0 AND post_group_id is not null)";
3789
    $statement = $connection->executeQuery($sql);
3790
    $result = $statement->fetchAll();
3791
3792
    foreach ($result as $row) {
3793
        $groupId = $row['post_group_id'];
3794
        $courseId = $row['c_id'];
3795
        $workIid = $row['iid'];
3796
        $sql = "SELECT iid from c_group_info 
3797
                WHERE c_id = $courseId AND id = $groupId";
3798
        $statement = $connection->executeQuery($sql);
3799
        $count = $statement->rowCount();
3800
        if ($count > 0) {
3801
            $rowGroup = $statement->fetch();
3802
            $newGroupId = $rowGroup['iid'];
3803
            if ($newGroupId == $groupId) {
3804
                continue;
3805
            }
3806
            if ($newGroupId) {
3807
                $sql = "UPDATE c_student_publication 
3808
                        SET post_group_id = $newGroupId 
3809
                        WHERE 
3810
                            c_id = $courseId AND
3811
                            iid = $workIid
3812
                        ";
3813
                $connection->executeQuery($sql);
3814
            }
3815
        }
3816
    }
3817
3818
    error_log('End - Fix c_student_publication.post_group_id');
3819
3820
    // Delete c_student_publication from any session that doesn't exist anymore
3821
    $sql = "DELETE FROM c_student_publication 
3822
            WHERE session_id NOT IN (SELECT id FROM session) AND (session_id <> 0 AND session_id is not null)";
3823
    $connection->executeQuery($sql);
3824
3825
    error_log('Fix work documents');
3826
    // Fix work documents that don't have c_item_property value
3827
    $sql = "SELECT * FROM c_student_publication WHERE parent_id IS NOT NULL";
3828
    $statement = $connection->executeQuery($sql);
3829
    $result = $statement->fetchAll();
3830
    foreach ($result as $row) {
3831
        $groupId = $row['post_group_id'];
3832
        $courseId = $row['c_id'];
3833
        $sessionId = $row['session_id'];
3834
        $workId = $row['id'];
3835
        $sessionCondition = " session_id = $sessionId";
3836
        if (empty($sessionId)) {
3837
            $sessionCondition = ' (session_id = 0 OR session_id IS NULL) ';
3838
        }
3839
        $sql = "SELECT * FROM c_item_property
3840
                WHERE
3841
                    c_id = $courseId AND
3842
                    tool = 'work' AND
3843
                    ref = $workId AND
3844
                    $sessionCondition ";
3845
        $itemInfo = $connection->fetchAssoc($sql);
3846
        if (empty($itemInfo)) {
3847
            $params = [
3848
                'c_id' => $courseId,
3849
                'to_group_id' => $groupId,
3850
                //'to_user_id' => null,
3851
                'insert_user_id' => 1,
3852
                'session_id' => $sessionId,
3853
                'tool' => 'work',
3854
                'insert_date' => api_get_utc_datetime(),
3855
                'lastedit_date' => api_get_utc_datetime(),
3856
                'ref' => $workId,
3857
                'lastedit_type' => 'visible',
3858
                'lastedit_user_id' => 1,
3859
                'visibility' => 1,
3860
            ];
3861
            $connection->insert('c_item_property', $params);
3862
            $id = $connection->lastInsertId();
3863
            $sql = "UPDATE c_item_property SET id = iid WHERE iid = $id";
3864
            $connection->executeQuery($sql);
3865
        }
3866
    }
3867
    error_log('End - Fix work documents');
3868
}
3869