GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Pull Request — integration (#2604)
by Brendan
04:17
created

Installer::__checkConfiguration()   F

Complexity

Conditions 17
Paths 3456

Size

Total Lines 126
Code Lines 72

Duplication

Lines 0
Ratio 0 %

Importance

Changes 6
Bugs 1 Features 1
Metric Value
cc 17
eloc 72
c 6
b 1
f 1
nc 3456
nop 0
dl 0
loc 126
rs 2

How to fix   Long Method    Complexity   

Long Method

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

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

Commonly applied refactorings include:

1
<?php
2
3
    class Installer extends Administration
4
    {
5
        /**
6
         * Override the default Symphony constructor to initialise the Log, Config
7
         * and Database objects for installation/update. This allows us to use the
8
         * normal accessors.
9
         */
10
        protected function __construct()
0 ignored issues
show
Coding Style introduced by
__construct uses the super-global variable $_SERVER which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
Coding Style introduced by
__construct uses the super-global variable $_COOKIE which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
Coding Style introduced by
__construct uses the super-global variable $_POST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
11
        {
12
            self::$Profiler = Profiler::instance();
13
            self::$Profiler->sample('Engine Initialisation');
14
15
            if (get_magic_quotes_gpc()) {
16
                General::cleanArray($_SERVER);
17
                General::cleanArray($_COOKIE);
18
                General::cleanArray($_GET);
19
                General::cleanArray($_POST);
20
            }
21
22
            // Include the default Config for installation.
23
            include(INSTALL . '/includes/config_default.php');
24
            static::initialiseConfiguration($settings);
0 ignored issues
show
Bug introduced by
The variable $settings does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
25
26
            // Initialize date/time
27
            define_safe('__SYM_DATE_FORMAT__', self::Configuration()->get('date_format', 'region'));
28
            define_safe('__SYM_TIME_FORMAT__', self::Configuration()->get('time_format', 'region'));
29
            define_safe('__SYM_DATETIME_FORMAT__',
30
                __SYM_DATE_FORMAT__ . self::Configuration()->get('datetime_separator', 'region') . __SYM_TIME_FORMAT__);
31
            DateTimeObj::setSettings(self::Configuration()->get('region'));
32
33
            // Initialize Language, Logs and Database
34
            static::initialiseLang();
35
            static::initialiseLog(INSTALL_LOGS . '/install');
36
            static::initialiseDatabase();
37
38
            // Initialize error handlers
39
            GenericExceptionHandler::initialise(Symphony::Log());
40
            GenericErrorHandler::initialise(Symphony::Log());
41
        }
42
43
        /**
44
         * Initialises the language by looking at the `lang` key,
45
         * passed via GET or POST
46
         */
47
        public static function initialiseLang()
48
        {
49
            $lang = !empty($_REQUEST['lang']) ? preg_replace('/[^a-zA-Z\-]/', null, $_REQUEST['lang']) : 'en';
50
            Lang::initialize();
51
            Lang::set($lang, false);
52
        }
53
54
        /**
55
         * Overrides the default `initialiseLog()` method and writes
56
         * logs to manifest/logs/install
57
         *
58
         * @param null $filename
59
         * @return boolean|void
60
         * @throws Exception
61
         */
62 View Code Duplication
        public static function initialiseLog($filename = null)
63
        {
64
            if (is_dir(INSTALL_LOGS) || General::realiseDirectory(INSTALL_LOGS,
65
                self::Configuration()->get('write_mode', 'directory'))
66
            ) {
67
                return parent::initialiseLog($filename);
68
            }
69
70
            return;
71
        }
72
73
        /**
74
         * Overrides the default `initialiseDatabase()` method
75
         * This allows us to still use the normal accessor
76
         */
77
        public static function initialiseDatabase()
78
        {
79
            self::setDatabase();
80
        }
81
82
        /**
83
         * This function returns an instance of the Installer
84
         * class. It is the only way to create a new Installer, as
85
         * it implements the Singleton interface
86
         *
87
         * @return Installer
88
         */
89
        public static function instance()
90
        {
91
            if (!(self::$_instance instanceof Installer)) {
92
                self::$_instance = new Installer;
93
            }
94
95
            return self::$_instance;
96
        }
97
98
        public function run()
99
        {
100
            // Make sure a log file is available
101
            if (is_null(Symphony::Log())) {
102
                self::__render(new InstallerPage('missing-log'));
103
            }
104
105
            // Check essential server requirements
106
            $errors = self::__checkRequirements();
107 View Code Duplication
            if (!empty($errors)) {
108
                Symphony::Log()->error('Installer - Missing requirements.');
109
110
                foreach ($errors as $err) {
111
                    Symphony::Log()->error(
112
                        sprintf('Requirement - %s', $err['msg'])
113
                    );
114
                }
115
116
                self::__render(new InstallerPage('requirements', array(
117
                    'errors' => $errors
118
                )));
119
            }
120
121
            // If language is not set and there is language packs available, show language selection pages
122
            if (!isset($_POST['lang']) && count(Lang::getAvailableLanguages(false)) > 1) {
123
                self::__render(new InstallerPage('languages'));
124
            }
125
126
            // Check for configuration errors and, if there are no errors, install Symphony!
127
            if (isset($_POST['fields'])) {
128
                $errors = self::__checkConfiguration();
129 View Code Duplication
                if (!empty($errors)) {
130
                    Symphony::Log()->error('Installer - Wrong configuration.');
131
132
                    foreach ($errors as $err) {
133
                        Symphony::Log()->error(
134
                            sprintf('Configuration - %s', $err['msg'])
135
                        );
136
                    }
137
                } else {
138
                    $disabled_extensions = self::__install();
139
140
                    self::__render(new InstallerPage('success', array(
141
                        'disabled-extensions' => $disabled_extensions
142
                    )));
143
                }
144
            }
145
146
            // Display the Installation page
147
            self::__render(new InstallerPage('configuration', array(
148
                'errors' => $errors,
149
                'default-config' => Symphony::Configuration()->get()
150
            )));
151
        }
152
153
        protected static function __render(InstallerPage $page)
154
        {
155
            $output = $page->generate();
156
157
            header('Content-Type: text/html; charset=utf-8');
158
            echo $output;
159
            exit;
0 ignored issues
show
Coding Style Compatibility introduced by
The method __render() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
160
        }
161
162
        /**
163
         * This function checks the server can support a Symphony installation.
164
         * It checks that PHP is 5.2+, MySQL, Zlib, LibXML, XSLT modules are enabled
165
         * and a `install.sql` file exists.
166
         * If any of these requirements fail the installation will not proceed.
167
         *
168
         * @return array
169
         *  An associative array of errors, with `msg` and `details` keys
170
         */
171
        private static function __checkRequirements()
172
        {
173
            $errors = array();
174
175
            // Check for PHP 5.2+
176
            if (version_compare(phpversion(), '5.3', '<=')) {
177
                $errors[] = array(
178
                    'msg' => __('PHP Version is not correct'),
179
                    'details' => __('Symphony requires %1$s or greater to work, however version %2$s was detected.',
180
                        array(
181
                            '<code><abbr title="PHP: Hypertext Pre-processor">PHP</abbr> 5.3</code>',
182
                            '<code>' . phpversion() . '</code>'
183
                        ))
184
                );
185
            }
186
187
            // Make sure the install.sql file exists
188
            if (!file_exists(INSTALL . '/includes/install.sql') || !is_readable(INSTALL . '/includes/install.sql')) {
189
                $errors[] = array(
190
                    'msg' => __('Missing install.sql file'),
191
                    'details' => __('It appears that %s is either missing or not readable. This is required to populate the database and must be uploaded before installation can commence. Ensure that PHP has read permissions.',
192
                        array('<code>install.sql</code>'))
193
                );
194
            }
195
196
            // Is MySQL available?
197 View Code Duplication
            if (!function_exists('mysqli_connect')) {
198
                $errors[] = array(
199
                    'msg' => __('MySQLi extension not present'),
200
                    'details' => __('Symphony requires PHP to be configured with MySQLi to work.')
201
                );
202
            }
203
204
            // Is ZLib available?
205 View Code Duplication
            if (!extension_loaded('zlib')) {
206
                $errors[] = array(
207
                    'msg' => __('ZLib extension not present'),
208
                    'details' => __('Symphony uses the ZLib compression library for log rotation.')
209
                );
210
            }
211
212
            // Is libxml available?
213 View Code Duplication
            if (!extension_loaded('xml') && !extension_loaded('libxml')) {
214
                $errors[] = array(
215
                    'msg' => __('XML extension not present'),
216
                    'details' => __('Symphony needs the XML extension to pass data to the site frontend.')
217
                );
218
            }
219
220
            // Is libxslt available?
221
            if (!extension_loaded('xsl') && !extension_loaded('xslt') && !function_exists('domxml_xslt_stylesheet')) {
222
                $errors[] = array(
223
                    'msg' => __('XSLT extension not present'),
224
                    'details' => __('Symphony needs an XSLT processor such as %s or Sablotron to build pages.',
225
                        array('Lib<abbr title="eXtensible Stylesheet Language Transformation">XSLT</abbr>'))
226
                );
227
            }
228
229
            // Is json_encode available?
230 View Code Duplication
            if (!function_exists('json_decode')) {
231
                $errors[] = array(
232
                    'msg' => __('JSON functionality is not present'),
233
                    'details' => __('Symphony uses JSON functionality throughout the backend for translations and the interface.')
234
                );
235
            }
236
237
            // Cannot write to root folder.
238
            if (!is_writable(DOCROOT)) {
239
                $errors['no-write-permission-root'] = array(
240
                    'msg' => 'Root folder not writable: ' . DOCROOT,
241
                    'details' => __('Symphony does not have write permission to the root directory. Please modify permission settings on %s. This can be reverted once installation is complete.',
242
                        array('<code>' . DOCROOT . '</code>'))
243
                );
244
            }
245
246
            // Cannot write to workspace
247
            if (is_dir(DOCROOT . '/workspace') && !is_writable(DOCROOT . '/workspace')) {
248
                $errors['no-write-permission-workspace'] = array(
249
                    'msg' => 'Workspace folder not writable: ' . DOCROOT . '/workspace',
250
                    'details' => __('Symphony does not have write permission to the existing %1$s directory. Please modify permission settings on this directory and its contents to allow this, such as with a recursive %2$s command.',
251
                        array('<code>/workspace</code>', '<code>chmod -R</code>'))
252
                );
253
            }
254
255
            return $errors;
256
        }
257
258
        /**
259
         * This function checks the current Configuration (which is the values entered
260
         * by the user on the installation form) to ensure that `/symphony` and `/workspace`
261
         * folders exist and are writable and that the Database credentials are correct.
262
         * Once those initial checks pass, the rest of the form values are validated.
263
         *
264
         * @return array An associative array of errors if something went wrong, otherwise an empty array.
265
         */
266
        private static function __checkConfiguration()
0 ignored issues
show
Coding Style introduced by
__checkConfiguration uses the super-global variable $_POST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
267
        {
268
            $errors = array();
269
            $fields = $_POST['fields'];
270
271
            // Testing the database connection
272
            try {
273
                Symphony::Database()->connect(
274
                    $fields['database']['host'],
275
                    $fields['database']['user'],
276
                    $fields['database']['password'],
277
                    $fields['database']['port'],
278
                    $fields['database']['db']
279
                );
280
            } catch (DatabaseException $e) {
281
                // Invalid credentials
282
                // @link http://dev.mysql.com/doc/refman/5.5/en/error-messages-server.html
283
                if ($e->getDatabaseErrorCode() === 1044 || $e->getDatabaseErrorCode() === 1045) {
284
                    $errors['database-invalid-credentials'] = array(
285
                        'msg' => 'Database credentials were denied',
286
                        'details' => __('Symphony was unable to access the database with these credentials.')
287
                    );
288
                } // Connection related
289
                else {
290
                    $errors['no-database-connection'] = array(
291
                        'msg' => 'Could not establish database connection.',
292
                        'details' => __('Symphony was unable to establish a valid database connection. You may need to modify host or port settings.')
293
                    );
294
                }
295
            }
296
297
            try {
298
                // Check the database table prefix is legal. #1815
299
                if (!preg_match('/^[0-9a-zA-Z\$_]*$/', $fields['database']['tbl_prefix'])) {
300
                    $errors['database-table-prefix'] = array(
301
                        'msg' => 'Invalid database table prefix: ‘' . $fields['database']['tbl_prefix'] . '’',
302
                        'details' => __('The table prefix %s is invalid. The table prefix must only contain numbers, letters or underscore characters.',
303
                            array('<code>' . $fields['database']['tbl_prefix'] . '</code>'))
304
                    );
305
                } // Check the database credentials
306
                elseif (Symphony::Database()->isConnected()) {
307
                    // Incorrect MySQL version
308
                    $version = Symphony::Database()->fetchVar('version', 0, "SELECT VERSION() AS `version`;");
309
                    if (version_compare($version, '5.5', '<')) {
310
                        $errors['database-incorrect-version'] = array(
311
                            'msg' => 'MySQL Version is not correct. ' . $version . ' detected.',
312
                            'details' => __('Symphony requires %1$s or greater to work, however version %2$s was detected. This requirement must be met before installation can proceed.',
313
                                array('<code>MySQL 5.5</code>', '<code>' . $version . '</code>'))
314
                        );
315
                    } else {
316
                        // Existing table prefix
317
                        if (Symphony::Database()->tableExists($fields['database']['tbl_prefix'] . '%')) {
318
                            $errors['database-table-prefix'] = array(
319
                                'msg' => 'Database table prefix clash with ‘' . $fields['database']['db'] . '’',
320
                                'details' => __('The table prefix %s is already in use. Please choose a different prefix to use with Symphony.',
321
                                    array(
322
323
                                        '<code>' . $fields['database']['tbl_prefix'] . '</code>'
324
                                    ))
325
                            );
326
                        }
327
                    }
328
                }
329
            } catch (DatabaseException $e) {
330
                $errors['unknown-database'] = array(
331
                    'msg' => 'Database ‘' . $fields['database']['db'] . '’ not found.',
332
                    'details' => __('Symphony was unable to connect to the specified database.')
333
                );
334
            }
335
336
            // Website name not entered
337
            if (trim($fields['general']['sitename']) === '') {
338
                $errors['general-no-sitename'] = array(
339
                    'msg' => 'No sitename entered.',
340
                    'details' => __('You must enter a Site name. This will be shown at the top of your backend.')
341
                );
342
            }
343
344
            // Username Not Entered
345
            if (trim($fields['user']['username']) === '') {
346
                $errors['user-no-username'] = array(
347
                    'msg' => 'No username entered.',
348
                    'details' => __('You must enter a Username. This will be your Symphony login information.')
349
                );
350
            }
351
352
            // Password Not Entered
353
            if (trim($fields['user']['password']) === '') {
354
                $errors['user-no-password'] = array(
355
                    'msg' => 'No password entered.',
356
                    'details' => __('You must enter a Password. This will be your Symphony login information.')
357
                );
358
            } // Password mismatch
359
            elseif ($fields['user']['password'] !== $fields['user']['confirm-password']) {
360
                $errors['user-password-mismatch'] = array(
361
                    'msg' => 'Passwords did not match.',
362
                    'details' => __('The password and confirmation did not match. Please retype your password.')
363
                );
364
            }
365
366
            // No Name entered
367
            if (trim($fields['user']['firstname']) === '' || trim($fields['user']['lastname']) === '') {
368
                $errors['user-no-name'] = array(
369
                    'msg' => 'Did not enter First and Last names.',
370
                    'details' => __('You must enter your name.')
371
                );
372
            }
373
374
            // Invalid Email
375
            if (!preg_match('/^\w(?:\.?[\w%+-]+)*@\w(?:[\w-]*\.)+?[a-z]{2,}$/i', $fields['user']['email'])) {
376
                $errors['user-invalid-email'] = array(
377
                    'msg' => 'Invalid email address supplied.',
378
                    'details' => __('This is not a valid email address. You must provide an email address since you will need it if you forget your password.')
379
                );
380
            }
381
382
            // Admin path not entered
383
            if (trim($fields['symphony']['admin-path']) === '') {
384
                $errors['no-symphony-path'] = array(
385
                    'msg' => 'No Symphony path entered.',
386
                    'details' => __('You must enter a path for accessing Symphony, or leave the default. This will be used to access Symphony\'s backend.')
387
                );
388
            }
389
390
            return $errors;
391
        }
392
393
        private static function __install()
0 ignored issues
show
Coding Style introduced by
__install uses the super-global variable $_POST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
394
        {
395
            $start = microtime(true);
396
            $fields = $_POST['fields'];
397
            Symphony::Log()->info('INSTALLATION PROCESS STARTED (' . DateTimeObj::get('c') . ')');
398
399
            // Configuration: Populating array
400
            $conf = Symphony::Configuration()->get();
401
402
            foreach ($conf as $group => $settings) {
403
                foreach ($settings as $key => $value) {
404
                    if (isset($fields[$group]) && isset($fields[$group][$key])) {
405
                        $conf[$group][$key] = $fields[$group][$key];
406
                    }
407
                }
408
            }
409
410
            // Don't like this. Find another way.
411
            $conf['directory']['write_mode'] = octdec($conf['directory']['write_mode']);
412
            $conf['file']['write_mode'] = octdec($conf['file']['write_mode']);
413
414
            Symphony::Configuration()->setArray($conf);
415
416
            $steps = [
417
                // Create database
418
                CreateDatabase::class,
419
                // Create manifest folder structure
420
                CreateManifest::class,
421
                // Write .htaccess
422
                CreateHtaccess::class,
423
                // Create or import the workspace
424
                Workspace::class,
425
                // Enable extensions
426
                EnableExtensions::class,
427
                // Enable language
428
                EnableLanguage::class
429
            ];
430
431
            try {
432
                foreach ($steps as $step) {
433
                    (new $step(Symphony::Log()->getLog()))->handle(Symphony::Configuration());
434
                }
435
            } catch (Exception $ex) {
436
                self::__abort($ex->getMessage(), $start);
437
            }
438
439
            // Writing configuration file
440
            Symphony::Log()->info('WRITING: Configuration File');
441
            if (!Symphony::Configuration()->write(CONFIG, Symphony::Configuration()->get('write_mode', 'file'))) {
442
                self::__abort(
443
                    'Could not create config file ‘' . CONFIG . '’. Check permission on /manifest.',
444
                    $start
445
                );
446
            }
447
448
            // Installation completed. Woo-hoo!
449
            Symphony::Log()->info(sprintf('INSTALLATION COMPLETED: Execution Time - %d sec (%s)',
450
                max(1, time() - $start),
451
                date('d.m.y H:i:s')
452
            ));
453
454
            return [];
455
        }
456
457
        /**
458
         * If something went wrong, the `__abort` function will write an entry to the Log
459
         * file and display the failure page to the user.
460
         *
461
         * @todo: Resume installation after an error has been fixed.
462
         * @param string $message
463
         * @param integer $start
464
         */
465
        protected static function __abort($message, $start)
466
        {
467
            Symphony::Log()->error($message);
468
            Symphony::Log()->error(sprintf('INSTALLATION ABORTED: Execution Time - %f sec (%s)',
469
                microtime(true) - $start,
470
                date('d.m.y H:i:s')
471
            ));
472
473
            self::__render(new InstallerPage('failure'));
474
        }
475
    }
476