OSCOM   D
last analyzed

Complexity

Total Complexity 83

Size/Duplication

Total Lines 353
Duplicated Lines 17.28 %

Coupling/Cohesion

Components 2
Dependencies 5

Importance

Changes 0
Metric Value
dl 61
loc 353
rs 4.8717
c 0
b 0
f 0
wmc 83
lcom 2
cbo 5

22 Methods

Rating   Name   Duplication   Size   Complexity  
A initialize() 0 10 1
A getVersion() 0 16 3
A siteExists() 5 15 4
A loadSite() 0 8 2
A setSite() 0 15 2
A getSite() 0 4 1
A hasSitePage() 0 4 1
A getSitePageFile() 0 4 1
A useSiteTemplateWithPageFile() 0 4 1
A isRPC() 0 6 2
F link() 0 69 24
B linkImage() 28 28 6
B linkPublic() 28 28 6
A redirect() 0 12 3
A getDef() 0 6 1
A hasRoute() 0 4 1
B loadConfig() 0 20 6
B loadConfigFile() 0 16 5
A getConfig() 0 12 3
A configExists() 0 12 3
A setConfig() 0 8 2
B autoload() 0 22 5

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 OSCOM 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 OSCOM, 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\OM;
10
11
use OSC\OM\DateTime;
12
use OSC\OM\ErrorHandler;
13
use OSC\OM\FileSystem;
14
use OSC\OM\HTML;
15
use OSC\OM\HTTP;
16
use OSC\OM\Registry;
17
18
class OSCOM
19
{
20
    const BASE_DIR = OSCOM_BASE_DIR;
21
22
    protected static $version;
23
    protected static $site = 'Shop';
24
    protected static $cfg = [];
25
26
    public static function initialize()
27
    {
28
        static::loadConfig();
29
30
        DateTime::setTimeZone();
31
32
        ErrorHandler::initialize();
33
34
        HTTP::setRequestType();
35
    }
36
37
    public static function getVersion()
38
    {
39
        if (!isset(static::$version)) {
40
            $file = static::BASE_DIR . 'version.txt';
41
42
            $v = trim(file_get_contents($file));
43
44
            if (preg_match('/^(\d+\.)?(\d+\.)?(\d+)$/', $v)) {
45
                static::$version = $v;
46
            } else {
47
                trigger_error('Version number is not numeric. Please verify: ' . $file);
48
            }
49
        }
50
51
        return static::$version;
52
    }
53
54
    public static function siteExists($site, $strict = true) {
55
        $class = 'OSC\Sites\\' . $site . '\\' . $site;
56
57
        if (class_exists($class)) {
58 View Code Duplication
            if (is_subclass_of($class, 'OSC\OM\SitesInterface')) {
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...
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...
59
                return true;
60
            } else {
61
                trigger_error('OSC\OM\OSCOM::siteExists() - ' . $site . ': Site does not implement OSC\OM\SitesInterface and cannot be loaded.');
62
            }
63
        } elseif ($strict === true) {
64
            trigger_error('OSC\OM\OSCOM::siteExists() - ' . $site . ': Site does not exist.');
65
        }
66
67
        return false;
68
    }
69
70
    public static function loadSite($site = null)
71
    {
72
        if (!isset($site)) {
73
            $site = static::$site;
74
        }
75
76
        static::setSite($site);
77
    }
78
79
    public static function setSite($site)
80
    {
81
        if (!static::siteExists($site)) {
82
            $site = static::$site;
83
        }
84
85
        static::$site = $site;
86
87
        $class = 'OSC\Sites\\' . $site . '\\' . $site;
88
89
        $OSCOM_Site = new $class();
90
        Registry::set('Site', $OSCOM_Site);
91
92
        $OSCOM_Site->setPage();
93
    }
94
95
    public static function getSite()
96
    {
97
        return static::$site;
98
    }
99
100
    public static function hasSitePage()
101
    {
102
        return Registry::get('Site')->hasPage();
103
    }
104
105
    public static function getSitePageFile()
106
    {
107
        return Registry::get('Site')->getPage()->getFile();
108
    }
109
110
    public static function useSiteTemplateWithPageFile()
111
    {
112
        return Registry::get('Site')->getPage()->useSiteTemplate();
113
    }
114
115
    public static function isRPC()
116
    {
117
        $OSCOM_Site = Registry::get('Site');
118
119
        return $OSCOM_Site->hasPage() && $OSCOM_Site->getPage()->isRPC();
120
    }
121
122
    public static function link($page, $parameters = null, $add_session_id = true, $search_engine_safe = true)
123
    {
124
        $page = HTML::sanitize($page);
125
126
        $site = $req_site = static::$site;
127
128
        if ((strpos($page, '/') !== false) && (preg_match('/^([A-Z][A-Za-z0-9-_]*)\/(.*)$/', $page, $matches) === 1) && OSCOM::siteExists($matches[1], false)) {
129
            $req_site = $matches[1];
130
            $page = $matches[2];
131
        }
132
133
        if (!is_bool($add_session_id)) {
134
            $add_session_id = true;
135
        }
136
137
        if (!is_bool($search_engine_safe)) {
138
            $search_engine_safe = true;
139
        }
140
141
        if (($add_session_id === true) && ($site !== $req_site)) {
142
            $add_session_id = false;
143
        }
144
145
        $link = static::getConfig('http_server', $req_site) . static::getConfig('http_path', $req_site) . $page;
146
147
        if (!empty($parameters)) {
148
            $p = HTML::sanitize($parameters);
149
150
            $p = str_replace([
151
                "\\", // apps
152
                '{', // product attributes
153
                '}' // product attributes
154
            ], [
155
                '%5C',
156
                '%7B',
157
                '%7D'
158
            ], $p);
159
160
            $link .= '?' . $p;
161
            $separator = '&';
162
        } else {
163
            $separator = '?';
164
        }
165
166
        while ((substr($link, -1) == '&') || (substr($link, -1) == '?')) {
167
            $link = substr($link, 0, -1);
168
        }
169
170
// Add the session ID when moving from different HTTP and HTTPS servers, or when SID is defined
171
        if (($add_session_id == true) && Registry::exists('Session')) {
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...
172
            $OSCOM_Session = Registry::get('Session');
173
174
            if ($OSCOM_Session->hasStarted() && ($OSCOM_Session->isForceCookies() === false)) {
175
                if ((strlen(SID) > 0) || (((HTTP::getRequestType() == 'NONSSL') && (parse_url(static::getConfig('http_server', $req_site), PHP_URL_SCHEME) == 'https')) || ((HTTP::getRequestType() == 'SSL') && (parse_url(static::getConfig('http_server', $req_site), PHP_URL_SCHEME) == 'http')))) {
176
                    $link .= $separator . HTML::sanitize(session_name() . '=' . session_id());
177
                }
178
            }
179
        }
180
181
        while (strpos($link, '&&') !== false) {
182
            $link = str_replace('&&', '&', $link);
183
        }
184
185
        if (($search_engine_safe == true) && defined('SEARCH_ENGINE_FRIENDLY_URLS') && (SEARCH_ENGINE_FRIENDLY_URLS == '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...
186
            $link = str_replace(['?', '&', '='], '/', $link);
187
        }
188
189
        return $link;
190
    }
191
192 View Code Duplication
    public static function linkImage()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
193
    {
194
        $args = func_get_args();
195
196
        if (!isset($args[0])) {
197
            $args[0] = null;
198
        }
199
200
        if (!isset($args[1])) {
201
            $args[1] = null;
202
        }
203
204
        $args[2] = false;
205
206
        $page = $args[0];
207
        $req_site = static::$site;
208
209
        if ((strpos($page, '/') !== false) && (preg_match('/^([A-Z][A-Za-z0-9-_]*)\/(.*)$/', $page, $matches) === 1) && OSCOM::siteExists($matches[1], false)) {
210
            $req_site = $matches[1];
211
            $page = $matches[2];
212
        }
213
214
        $args[0] = $req_site . '/' . static::getConfig('http_images_path', $req_site) . $page;
215
216
        $url = forward_static_call_array('static::link', $args);
217
218
        return $url;
219
    }
220
221 View Code Duplication
    public static function linkPublic()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
222
    {
223
        $args = func_get_args();
224
225
        if (!isset($args[0])) {
226
            $args[0] = null;
227
        }
228
229
        if (!isset($args[1])) {
230
            $args[1] = null;
231
        }
232
233
        $args[2] = false;
234
235
        $page = $args[0];
236
        $req_site = static::$site;
237
238
        if ((strpos($page, '/') !== false) && (preg_match('/^([A-Z][A-Za-z0-9-_]*)\/(.*)$/', $page, $matches) === 1) && OSCOM::siteExists($matches[1], false)) {
239
            $req_site = $matches[1];
240
            $page = $matches[2];
241
        }
242
243
        $args[0] = 'Shop/public/Sites/' . $req_site . '/' . $page;
244
245
        $url = forward_static_call_array('static::link', $args);
246
247
        return $url;
248
    }
249
250
    public static function redirect()
251
    {
252
        $args = func_get_args();
253
254
        $url = forward_static_call_array('static::link', $args);
255
256
        if ((strstr($url, "\n") !== false) || (strstr($url, "\r") !== false)) {
257
            $url = static::link('index.php', '', false);
258
        }
259
260
        HTTP::redirect($url);
261
    }
262
263
    public static function getDef()
264
    {
265
        $OSCOM_Language = Registry::get('Language');
266
267
        return call_user_func_array([$OSCOM_Language, 'getDef'], func_get_args());
268
    }
269
270
    public static function hasRoute(array $path)
271
    {
272
        return array_slice(array_keys($_GET), 0, count($path)) == $path;
273
    }
274
275
    public static function loadConfig()
276
    {
277
        static::loadConfigFile(static::BASE_DIR . 'Conf/global.php', 'global');
278
279
        if (is_file(static::BASE_DIR . 'Custom/Conf/global.php')) {
280
            static::loadConfigFile(static::BASE_DIR . 'Custom/Conf/global.php', 'global');
281
        }
282
283
        foreach (glob(static::BASE_DIR . 'Sites/*', GLOB_ONLYDIR) as $s) {
284
            $s = basename($s);
285
286
            if (static::siteExists($s, false) && is_file(static::BASE_DIR . 'Sites/' . $s . '/site_conf.php')) {
287
                static::loadConfigFile(static::BASE_DIR . 'Sites/' . $s . '/site_conf.php', $s);
288
289
                if (is_file(static::BASE_DIR . 'Custom/Sites/' . $s . '/site_conf.php')) {
290
                    static::loadConfigFile(static::BASE_DIR . 'Custom/Sites/' . $s . '/site_conf.php', $s);
291
                }
292
            }
293
        }
294
    }
295
296
    public static function loadConfigFile($file, $group)
297
    {
298
        $cfg = [];
299
300
        if (is_file($file)) {
301
            include($file);
302
303
            if (isset($ini)) {
0 ignored issues
show
Bug introduced by
The variable $ini seems to never exist, and therefore isset should always return false. Did you maybe rename this variable?

This check looks for calls to isset(...) or empty() on variables that are yet undefined. These calls will always produce the same result and can be removed.

This is most likely caused by the renaming of a variable or the removal of a function/method parameter.

Loading history...
304
                $cfg = parse_ini_string($ini);
305
            }
306
        }
307
308
        if (!empty($cfg)) {
309
            static::$cfg[$group] = (isset(static::$cfg[$group])) ? array_merge(static::$cfg[$group], $cfg) : $cfg;
310
        }
311
    }
312
313
    public static function getConfig($key, $group = null)
314
    {
315
        if (!isset($group)) {
316
            $group = static::getSite();
317
        }
318
319
        if (isset(static::$cfg[$group][$key])) {
320
            return static::$cfg[$group][$key];
321
        }
322
323
        return static::$cfg['global'][$key];
324
    }
325
326
    public static function configExists($key, $group = null)
327
    {
328
        if (!isset($group)) {
329
            $group = static::getSite();
330
        }
331
332
        if (isset(static::$cfg[$group][$key])) {
333
            return true;
334
        }
335
336
        return isset(static::$cfg['global'][$key]);
337
    }
338
339
    public static function setConfig($key, $value, $group = null)
340
    {
341
        if (!isset($group)) {
342
            $group = 'global';
343
        }
344
345
        static::$cfg[$group][$key] = $value;
346
    }
347
348
    public static function autoload($class)
349
    {
350
        $prefix = 'OSC\\';
351
352
        if (strncmp($prefix, $class, strlen($prefix)) !== 0) {
353
            return false;
354
        }
355
356
        if (strncmp($prefix . 'OM\Module\\', $class, strlen($prefix . 'OM\Module\\')) === 0) { // TODO remove and fix namespace
357
          $file = dirname(OSCOM_BASE_DIR) . '/' . str_replace(['OSC\OM\\', '\\'], ['', '/'], $class) . '.php';
358
          $custom = dirname(OSCOM_BASE_DIR) . '/' . str_replace(['OSC\OM\\', '\\'], ['OSC\Custom\OM\\', '/'], $class) . '.php';
359
        } else {
360
          $file = dirname(OSCOM_BASE_DIR) . '/' . str_replace('\\', '/', $class) . '.php';
361
          $custom = str_replace('OSC/OM/', 'OSC/Custom/OM/', $file);
362
        }
363
364
        if (is_file($custom)) {
365
            require($custom);
366
        } elseif (is_file($file)) {
367
            require($file);
368
        }
369
    }
370
}
371