Admin   B
last analyzed

Complexity

Total Complexity 41

Size/Duplication

Total Lines 171
Duplicated Lines 9.36 %

Coupling/Cohesion

Components 1
Dependencies 14

Importance

Changes 0
Metric Value
dl 16
loc 171
rs 8.2769
c 0
b 0
f 0
wmc 41
lcom 1
cbo 14

3 Methods

Rating   Name   Duplication   Size   Complexity  
F init() 0 118 29
C setPage() 16 44 11
A resolveRoute() 0 4 1

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like Admin often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Admin, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
  * osCommerce Online Merchant
4
  *
5
  * @copyright (c) 2016 osCommerce; https://www.oscommerce.com
6
  * @license MIT; https://www.oscommerce.com/license/mit.txt
7
  */
8
9
namespace OSC\Sites\Admin;
10
11
use OSC\OM\Apps;
12
use OSC\OM\Cookies;
13
use OSC\OM\Db;
14
use OSC\OM\ErrorHandler;
15
use OSC\OM\FileSystem;
16
use OSC\OM\Hooks;
17
use OSC\OM\Language;
18
use OSC\OM\MessageStack;
19
use OSC\OM\OSCOM;
20
use OSC\OM\Registry;
21
use OSC\OM\Session;
22
23
class Admin extends \OSC\OM\SitesAbstract
24
{
25
    protected function init()
26
    {
27
        global $PHP_SELF, $login_request, $cfgModules, $oscTemplate;
28
29
        $OSCOM_Cookies = new Cookies();
30
        Registry::set('Cookies', $OSCOM_Cookies);
31
32
        try {
33
            $OSCOM_Db = Db::initialize();
34
            Registry::set('Db', $OSCOM_Db);
35
        } catch (\Exception $e) {
36
            include(OSCOM::getConfig('dir_root', 'Shop') . 'includes/error_documents/maintenance.php');
37
            exit;
38
        }
39
40
        Registry::set('Hooks', new Hooks());
41
42
        Registry::set('MessageStack', new MessageStack());
43
44
// set the application parameters
45
        $Qcfg = $OSCOM_Db->get('configuration', [
46
            'configuration_key as k',
47
            'configuration_value as v'
48
        ]);//, null, null, null, 'configuration'); // TODO add cache when supported by admin
49
50
        while ($Qcfg->fetch()) {
51
            define($Qcfg->value('k'), $Qcfg->value('v'));
52
        }
53
54
// Used in the "Backup Manager" to compress backups
55
        define('LOCAL_EXE_GZIP', 'gzip');
56
        define('LOCAL_EXE_GUNZIP', 'gunzip');
57
        define('LOCAL_EXE_ZIP', 'zip');
58
        define('LOCAL_EXE_UNZIP', 'unzip');
59
60
// set php_self in the global scope
61
        $req = parse_url($_SERVER['SCRIPT_NAME']);
62
        $PHP_SELF = substr($req['path'], strlen(OSCOM::getConfig('http_path')));
63
64
        $OSCOM_Session = Session::load();
65
        Registry::set('Session', $OSCOM_Session);
66
67
        $OSCOM_Session->start();
68
69
        $OSCOM_Language = new Language();
70
        Registry::set('Language', $OSCOM_Language);
71
72
// set the language
73
        if (!isset($_SESSION['language']) || isset($_GET['language'])) {
74
            if (isset($_GET['language']) && !empty($_GET['language']) && $OSCOM_Language->exists($_GET['language'])) {
75
                $OSCOM_Language->set($_GET['language']);
76
            }
77
78
            $_SESSION['language'] = $OSCOM_Language->get('code');
79
        }
80
81
// redirect to login page if administrator is not yet logged in
82
        if (!isset($_SESSION['admin'])) {
83
            $redirect = false;
84
85
            $current_page = $PHP_SELF;
86
87
// if the first page request is to the login page, set the current page to the index page
88
// so the redirection on a successful login is not made to the login page again
89
            if (($current_page == FILENAME_LOGIN) && !isset($_SESSION['redirect_origin'])) {
90
                $current_page = FILENAME_DEFAULT;
91
            }
92
93
            if ($current_page != FILENAME_LOGIN) {
94
                if (!isset($_SESSION['redirect_origin'])) {
95
                    $_SESSION['redirect_origin'] = [
96
                        'page' => $current_page,
97
                        'get' => []
98
                    ];
99
                }
100
101
// try to automatically login with the HTTP Authentication values if it exists
102
                if (!isset($_SESSION['auth_ignore'])) {
103
                    if (isset($_SERVER['PHP_AUTH_USER']) && !empty($_SERVER['PHP_AUTH_USER']) && isset($_SERVER['PHP_AUTH_PW']) && !empty($_SERVER['PHP_AUTH_PW'])) {
104
                        $_SESSION['redirect_origin']['auth_user'] = $_SERVER['PHP_AUTH_USER'];
105
                        $_SESSION['redirect_origin']['auth_pw'] = $_SERVER['PHP_AUTH_PW'];
106
                    }
107
                }
108
109
                $redirect = true;
110
            }
111
112
            if (!isset($login_request) || isset($_GET['login_request']) || isset($_POST['login_request']) || isset($_COOKIE['login_request']) || isset($_SESSION['login_request']) || isset($_FILES['login_request']) || isset($_SERVER['login_request'])) {
113
                $redirect = true;
114
            }
115
116
            if ($redirect == 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...
117
                OSCOM::redirect(FILENAME_LOGIN, (isset($_SESSION['redirect_origin']['auth_user']) ? 'action=process' : ''));
118
            }
119
        }
120
121
// include the language translations
122
        $OSCOM_Language->loadDefinitions('main');
123
124
// Prevent LC_ALL from setting LC_NUMERIC to a locale with 1,0 float/decimal values instead of 1.0 (see bug #634)
125
        $system_locale_numeric = setlocale(LC_NUMERIC, 0);
126
        setlocale(LC_ALL, explode(';', OSCOM::getDef('system_locale')));
127
        setlocale(LC_NUMERIC, $system_locale_numeric);
128
129
        $current_page = basename($PHP_SELF);
130
131
        if ($OSCOM_Language->definitionsExist(pathinfo($current_page, PATHINFO_FILENAME))) {
132
            $OSCOM_Language->loadDefinitions(pathinfo($current_page, PATHINFO_FILENAME));
133
        }
134
135
        $oscTemplate = new \oscTemplate();
136
137
        $cfgModules = new \cfg_modules();
138
139
        if (!FileSystem::isWritable(ErrorHandler::getDirectory())) {
140
            Registry::get('MessageStack')->add('The log directory is not writable. Please allow the web server to write to: ' . FileSystem::displayPath(ErrorHandler::getDirectory()));
141
        }
142
    }
143
144
    public function setPage()
145
    {
146
        if (!empty($_GET)) {
147
            $req = basename(array_keys($_GET)[0]);
148
149
            if (($req == 'A') && (count($_GET) > 1)) {
150
                $app = array_keys($_GET)[1];
151
152
                if (strpos($app, '\\') !== false) {
153
                    list($vendor, $app) = explode('\\', $app);
154
155
                    if (Apps::exists($vendor . '\\' . $app) && ($page = Apps::getRouteDestination(null, $vendor . '\\' . $app)) !== null) {
156
// get controller class name from namespace
157
                        $page_namespace = explode('\\', $page);
158
                        $page_code = $page_namespace[count($page_namespace)-1];
159
160
                        if (class_exists('OSC\Apps\\' . $vendor . '\\' . $app . '\\' . $page . '\\' . $page_code)) {
161
                            $this->app = $vendor . '\\' . $app;
162
                            $this->route = $this->app . '\\' . $page;
163
                            $this->actions_index = 2;
164
165
                            $class = 'OSC\Apps\\' . $this->app . '\\' . $page . '\\' . $page_code;
166
                        }
167
                    }
168
                }
169 View Code Duplication
            } else {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
170
                if (class_exists('OSC\Sites\\' . $this->code . '\Pages\\' . $req . '\\' . $req)) {
171
                    $page_code = $req;
172
173
                    $class = 'OSC\Sites\\' . $this->code . '\Pages\\' . $page_code . '\\' . $page_code;
174
                }
175
            }
176
        }
177
178 View Code Duplication
        if (isset($class)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
179
            if (is_subclass_of($class, 'OSC\OM\PagesInterface')) {
0 ignored issues
show
Bug introduced by
Due to PHP Bug #53727, is_subclass_of returns inconsistent results on some PHP versions for interfaces; you could instead use ReflectionClass::implementsInterface.
Loading history...
180
                $this->page = new $class($this);
181
182
                $this->page->runActions();
183
            } else {
184
                trigger_error('OSC\Sites\Admin\Admin::setPage() - ' . $page_code . ': Page does not implement OSC\OM\PagesInterface and cannot be loaded.');
0 ignored issues
show
Bug introduced by
The variable $page_code does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
185
            }
186
        }
187
    }
188
189
    public static function resolveRoute(array $route, array $routes)
190
    {
191
        return array_values($routes)[0];
192
    }
193
}
194