Completed
Push — master ( d0941c...c232a4 )
by Richard
14s
created

Xoops::getBaseDomain()   D

Complexity

Conditions 9
Paths 19

Size

Total Lines 32
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 17
CRAP Score 9.0139

Importance

Changes 0
Metric Value
cc 9
eloc 18
nc 19
nop 2
dl 0
loc 32
ccs 17
cts 18
cp 0.9444
crap 9.0139
rs 4.909
c 0
b 0
f 0
1
<?php
2
/*
3
 You may not change or alter any portion of this comment or credits
4
 of supporting developers from this source code or any supporting source code
5
 which is considered copyrighted (c) material of the original comment or credit authors.
6
7
 This program is distributed in the hope that it will be useful,
8
 but WITHOUT ANY WARRANTY; without even the implied warranty of
9
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
10
*/
11
12
use Xoops\Core\HttpRequest;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, HttpRequest.

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...
13
use Xmf\Request;
14
use Xoops\Core\FixedGroups;
15
use Xoops\Core\Handler\Factory as HandlerFactory;
16
use Xoops\Core\Kernel\Handlers\XoopsModule;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, XoopsModule.

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...
17
use Xoops\Core\Kernel\Handlers\XoopsUser;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, XoopsUser.

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...
18
use Xoops\Core\Theme\XoopsTheme;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, XoopsTheme.

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...
19
use Xoops\Core\XoopsTpl;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, XoopsTpl.

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...
20
use Psr\Log\LogLevel;
21
22
/**
23
 * XOOPS
24
 *
25
 * @category  Xoops
26
 * @package   Xoops
27
 * @author    trabis <[email protected]>
28
 * @author    formuss
29
 * @author    Richard Griffith <[email protected]>
30
 * @copyright 2011-2015 XOOPS Project (http://xoops.org)
31
 * @license   GNU GPL 2 or later (http://www.gnu.org/licenses/gpl-2.0.html)
32
 * @link      http://xoops.org
33
 */
34
class Xoops
0 ignored issues
show
Coding Style introduced by
Since you have declared the constructor as private, maybe you should also declare the class as final.
Loading history...
35
{
36
    const VERSION = 'XOOPS 2.6.0-Alpha 3';
37
38
    /**
39
     * @var null|Xoops\Core\Session\Manager
40
     */
41
    public $sessionManager = null;
42
43
    /**
44
     * @var null|XoopsModule
45
     */
46
    public $module = null;
47
48
    /**
49
     * @var array
50
     */
51
    public $config = array();
52
53
    /**
54
     * @var array
55
     */
56
    public $moduleConfig = array();
57
58
    /**
59
     * @var array
60
     */
61
    public $moduleDirname = '';
62
63
    /**
64
     * @var XoopsUser|string
65
     */
66
    public $user = '';
67
68
    /**
69
     * @var bool
70
     */
71
    public $userIsAdmin = false;
72
73
    /**
74
     * @var array
75
     */
76
    public $option = array();
77
78
    /**
79
     * @var XoopsTpl|null
80
     */
81
    private $tpl = null;
82
83
    /**
84
     * @var XoopsTheme|null
85
     */
86
    private $theme = null;
87
88
    /**
89
     * @var array
90
     */
91
    public $paths = array(
92
        'XOOPS'  => array(), 'www' => array(), 'var' => array(), 'lib' => array(), 'modules' => array(),
93
        'themes' => array(), 'media' => array()
94
    );
95
96
    /**
97
     * @var string
98
     */
99
    public $tpl_name = '';
100
101
    /**
102
     * @var HandlerFactory
103
     */
104
    private $handlerFactory;
105
106
    /**
107
     * @var array
108
     */
109
    private $kernelHandlers = array();
110
111
    /**
112
     * @var array
113
     */
114
    private $moduleHandlers = array();
115
116
    /**
117
     * @var null|array
118
     */
119
    private $activeModules = null;
120
121
    /**
122
     * @var array
123
     */
124
    private $moduleConfigs = array();
125
126
    /**
127
     * @var bool
128
     */
129
    public $isAdminSide = false;
130
131
    /**
132
     * Actual Xoops OS
133
     */
134
    private function __construct()
135
    {
136
        $root = \XoopsBaseConfig::get('root-path');
137
        $lib = \XoopsBaseConfig::get('lib-path');
138
        $var = \XoopsBaseConfig::get('var-path');
139
140
        $url = \XoopsBaseConfig::get('url');
141
142
        $this->paths['www'] = array($root, $url);
143
        $this->paths['var'] = array($var, null);
144
        $this->paths['lib'] = array($lib, $url . '/browse.php');
145
        $this->paths['XOOPS'] = array($lib, $url . '/browse.php');
146
        $this->paths['assets'] = array(\XoopsBaseConfig::get('asset-path'), \XoopsBaseConfig::get('asset-url'));
147
        $this->paths['images'] = array($root . '/images', $url . '/images');
148
        $this->paths['language'] = array($root . '/language', $url . '/language');
149
        $this->paths['locale'] = array($root . '/locale', $url . '/locale');
150
        $this->paths['media'] = array(\XoopsBaseConfig::get('media-path'), \XoopsBaseConfig::get('media-url'));
151
        $this->paths['modules'] = array($root . '/modules', $url . '/modules');
152
        $this->paths['themes'] = array(\XoopsBaseConfig::get('themes-path'), \XoopsBaseConfig::get('themes-url'));
153
        $this->paths['uploads'] = array(\XoopsBaseConfig::get('uploads-path'), \XoopsBaseConfig::get('uploads-url'));
154
155
        $this->pathTranslation();
156
    }
157
158
    /**
159
     * Access the only instance of this class
160
     *
161
     * @return Xoops
162
     */
163 412
    public static function getInstance()
164
    {
165 412
        static $instance;
166 412
        if (!isset($instance)) {
167
            $class = __CLASS__;
168
            $instance = new $class();
169
        }
170 412
        return $instance;
171
    }
172
173
    /**
174
     * get database connection instance
175
     *
176
     * @return Xoops\Core\Database\Connection
177
     */
178 145
    public function db()
179
    {
180 145
        return \Xoops\Core\Database\Factory::getConnection();
181
    }
182
183
    /**
184
     * get a \Xoops\Core\Cache\Access object for a named cache
185
     *
186
     * @param string $cacheName a named cached pool
187
     *
188
     * @return \Xoops\Core\Cache\Access
189
     */
190 28
    public function cache($cacheName = 'default')
191
    {
192 28
        static $cacheManager;
193
194 28
        if (!isset($cacheManager)) {
195
            $cacheManager = new \Xoops\Core\Cache\CacheManager();
196
        }
197
198 28
        return $cacheManager->getCache($cacheName);
199
    }
200
201
    /**
202
     * get the system logger instance
203
     *
204
     * @return \Xoops\Core\Logger
205
     */
206 17
    public function logger()
207
    {
208 17
        return \Xoops\Core\Logger::getInstance();
209
    }
210
211
212
    /**
213
     * get the event processor
214
     *
215
     * @return \Xoops\Core\Events instance
216
     */
217 140
    public function events()
218
    {
219 140
        return \Xoops\Core\Events::getInstance();
220
    }
221
222
    /**
223
     * get the asset utility
224
     *
225
     * @return Xoops\Core\Assets instance
226
     */
227 4
    public function assets()
228
    {
229 4
        static $instance;
230 4
        if (!isset($instance)) {
231 1
            $instance = new \Xoops\Core\Assets;
232
        }
233 4
        return $instance;
234
    }
235
236
    /**
237
     * get the service manager
238
     *
239
     * @param string $service - service name
240
     *
241
     * @return Xoops\Core\Service\Provider instance
242
     */
243 4
    public function service($service)
244
    {
245 4
        static $instance;
246 4
        if (!isset($instance)) {
247 1
            $instance = \Xoops\Core\Service\Manager::getInstance();
248
        }
249 4
        return $instance->locate($service);
250
    }
251
252
    /**
253
     * provide a common registry instance
254
     *
255
     * @return Xoops\Core\Registry
256
     */
257 2
    public function registry()
258
    {
259 2
        static $instance;
260 2
        if (!isset($instance)) {
261
            $instance = new \Xoops\Core\Registry();
262
        }
263 2
        return $instance;
264
    }
265
266
    /**
267
     * get security instance
268
     *
269
     * @return XoopsSecurity
270
     */
271 6
    public function security()
272
    {
273 6
        static $instance;
274 6
        if (!isset($instance)) {
275
            $instance = new \Xoops\Core\Security();
276
        }
277 6
        return $instance;
278
    }
279
280
    /**
281
     * get current template engine
282
     *
283
     * @return null|XoopsTpl
284
     */
285 9
    public function tpl()
286
    {
287 9
        return $this->tpl;
288
    }
289
290
    /**
291
     * set current template engine
292
     *
293
     * @param XoopsTpl $tpl template engine
294
     *
295
     * @return XoopsTpl
296
     */
297 6
    public function setTpl(XoopsTpl $tpl)
298
    {
299 6
        return $this->tpl = $tpl;
300
    }
301
302
    /**
303
     * establish the theme
304
     *
305
     * @param null|string $tpl_name base template
306
     *
307
     * @return null|XoopsTheme
308
     */
309 6
    public function theme($tpl_name = null)
0 ignored issues
show
Coding Style introduced by
theme uses the super-global variable $GLOBALS 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...
310
    {
311 6
        if (!isset($this->theme)) {
312
            if ($tpl_name) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $tpl_name of type null|string is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
313
                $tpl_info = $this->getTplInfo($tpl_name);
314
                $this->tpl_name = $tpl_info['tpl_name'];
315
            } else {
316
                $tpl_name = 'module:system/system_dummy.tpl';
317
                $tpl_info = $this->getTplInfo($tpl_name);
318
                $this->tpl_name = $tpl_info['tpl_name'];
319
            }
320
            if (!$this->isAdminSide) {
321
                $xoopsThemeFactory = new \Xoops\Core\Theme\Factory();
322
                $xoopsThemeFactory->allowedThemes = $this->getConfig('theme_set_allowed');
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->getConfig('theme_set_allowed') of type * is incompatible with the declared type array of property $allowedThemes.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
323
                $xoopsThemeFactory->defaultTheme = $this->getConfig('theme_set');
324
                $this->setTheme($xoopsThemeFactory->createInstance(array('contentTemplate' => $this->tpl_name)));
325
            } else {
326
                $adminThemeFactory = new \Xoops\Core\Theme\AdminFactory();
327
                $this->setTheme($adminThemeFactory->createInstance(array(
328
                    'folderName'      => 'default', 'themesPath' => 'modules/system/themes',
329
                    'contentTemplate' => $this->tpl_name
330
                )));
331
                //$this->theme()->loadLocalization('admin');
332
                list($cssAssets, $jsAssets) = $this->theme()->getLocalizationAssets('admin');
333
                if (!empty($cssAssets)) {
334
                    $this->theme()->addBaseStylesheetAssets($cssAssets);
335
                }
336
                if (!empty($jsAssets)) {
337
                    $this->theme()->addBaseScriptAssets($jsAssets);
338
                }
339
            }
340
        } else {
341 6
            if ($tpl_name) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $tpl_name of type null|string is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
342
                $tpl_info = $this->getTplInfo($tpl_name);
343
                $this->tpl_name = $tpl_info['tpl_name'];
344
                $this->theme->contentTemplate = $this->tpl_name;
345
            }
346
        }
347 6
        $GLOBALS['xoTheme'] = $this->theme;
348 6
        return $this->theme;
349
    }
350
351
    /**
352
     * set theme
353
     *
354
     * @param XoopsTheme $theme theme
355
     *
356
     * @return XoopsTheme
357
     */
358 5
    public function setTheme(XoopsTheme $theme)
359
    {
360 5
        return $this->theme = $theme;
361
    }
362
363
    /**
364
     * Convert a XOOPS path to a physical one
365
     *
366
     * @param string $url     url to derive path from
367
     * @param bool   $virtual virtual
368
     *
369
     * @return string
370
     */
371 31
    public function path($url, $virtual = false)
372
    {
373 31
        $url = $this->normalizePath($url);
374 31
        $rootPath = $this->normalizePath(\XoopsBaseConfig::get('root-path') . '/');
375 31
        if (0 === strpos($url, $rootPath)) {
376 1
            $url = substr($url, strlen($rootPath));
377
        }
378
        //$url = ltrim($url, '/');
379 31
        $parts = explode('/', $url, 2);
380 31
        $root = isset($parts[0]) ? $parts[0] : '';
381 31
        $path = isset($parts[1]) ? $parts[1] : '';
382 31
        if (!isset($this->paths[$root])) {
383 7
            list($root, $path) = array('www', $url);
384
        }
385 31
        if (!$virtual) { // Returns a physical path
386 29
            $path = $this->paths[$root][0] . '/' . $path;
387
            //$path = str_replace('/', DIRECTORY_SEPARATOR, $path);
388 29
            return $path;
389
        }
390 5
        return !isset($this->paths[$root][1]) ? '' : ($this->paths[$root][1] . '/' . $path);
391
    }
392
393
    /**
394
     * Convert path separators to unix style
395
     *
396
     * @param string $path path to normalize
397
     *
398
     * @return string normalized path
399
     */
400 31
    public function normalizePath($path)
401
    {
402 31
        return str_replace('\\', '/', $path);
403
    }
404
405
    /**
406
     * Convert a XOOPS path to an URL
407
     *
408
     * @param string $url path (or url)
409
     *
410
     * @return string
411
     */
412 5
    public function url($url)
413
    {
414 5
        return (false !== strpos($url, '://') ? $url : $this->path($url, true));
415
    }
416
417
    /**
418
     * Build an URL with the specified request params
419
     *
420
     * @param string $url    base url
421
     * @param array  $params parameters to add to the url
422
     *
423
     * @return string
424
     */
425 1
    public function buildUrl($url, $params = array())
0 ignored issues
show
Coding Style introduced by
buildUrl 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...
426
    {
427 1
        if ($url === '.') {
428 1
            $url = $_SERVER['REQUEST_URI'];
429
        }
430 1
        $split = explode('?', $url);
431 1
        if (count($split) > 1) {
432 1
            list($url, $query) = $split;
433 1
            parse_str($query, $query);
434 1
            $params = array_merge($query, $params);
435
        }
436 1
        if (!empty($params)) {
437 1
            foreach ($params as $k => $v) {
438 1
                $params[$k] = $k . '=' . rawurlencode($v);
439
            }
440 1
            $url .= '?' . implode('&', $params);
441
        }
442 1
        return $url;
443
    }
444
445
    /**
446
     * Check if a path exists
447
     *
448
     * @param string $path       filesystem path
449
     * @param string $error_type error level i.e. Psr\Log\LogLevel
450
     *
451
     * @return string|false
452
     */
453 2
    public function pathExists($path, $error_type)
454
    {
455 2
        if (XoopsLoad::fileExists($path)) {
456 1
            return $path;
457
        } else {
458 1
            $this->logger()->log(
459 1
                LogLevel::WARNING,
460 1
                \XoopsLocale::E_FILE_NOT_FOUND,
461 1
                array($path, $error_type)
462
            );
463
464
            //trigger_error(XoopsLocale::E_FILE_NOT_FOUND, $error_type);
465 1
            return false;
466
        }
467
    }
468
469
    /**
470
     * Start gzipCompression output buffer
471
     *
472
     * @return void
473
     */
474 1
    public function gzipCompression()
0 ignored issues
show
Coding Style introduced by
gzipCompression 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...
475
    {
476
        /**
477
         * Disable gzip compression if PHP is run under CLI mode and needs refactored to work correctly
478
         */
479 1
        if (empty($_SERVER['SERVER_NAME']) || substr(PHP_SAPI, 0, 3) === 'cli') {
480 1
            $this->setConfig('gzip_compression', 0);
481
        }
482
483 1
        if ($this->getConfig('gzip_compression') == 1
484 1
            && extension_loaded('zlib')
485 1
            && !ini_get('zlib.output_compression')
486
        ) {
487
            if (@ini_get('zlib.output_compression_level') < 0) {
488
                ini_set('zlib.output_compression_level', 6);
489
            }
490
            ob_start('ob_gzhandler');
491
        }
492 1
    }
493
494
    /**
495
     * Translate a path
496
     *
497
     * @return void
498
     */
499 1
    public function pathTranslation()
0 ignored issues
show
Coding Style introduced by
pathTranslation 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...
500
    {
501
        /**
502
         * *#@+
503
         * Host abstraction layer
504
         */
505 1
        if (!isset($_SERVER['PATH_TRANSLATED']) && isset($_SERVER['SCRIPT_FILENAME'])) {
506 1
            $_SERVER['PATH_TRANSLATED'] = $_SERVER['SCRIPT_FILENAME']; // For Apache CGI
507
        } else {
508 1
            if (isset($_SERVER['PATH_TRANSLATED']) && !isset($_SERVER['SCRIPT_FILENAME'])) {
509 1
                $_SERVER['SCRIPT_FILENAME'] = $_SERVER['PATH_TRANSLATED']; // For IIS/2K now I think :-(
510
            }
511
        }
512
        /**
513
         * User Mulitbytes
514
         */
515 1 View Code Duplication
        if (empty($_SERVER['REQUEST_URI'])) { // Not defined by IIS
516
            // Under some configs, IIS makes SCRIPT_NAME point to php.exe :-(
517 1
            if (!($_SERVER['REQUEST_URI'] = @$_SERVER['PHP_SELF'])) {
518 1
                $_SERVER['REQUEST_URI'] = $_SERVER['SCRIPT_NAME'];
519
            }
520 1
            if (isset($_SERVER['QUERY_STRING'])) {
521 1
                $_SERVER['REQUEST_URI'] .= '?' . $_SERVER['QUERY_STRING'];
522
            }
523
        }
524 1
    }
525
526
    /**
527
     * Select Theme
528
     *
529
     * @return void
530
     */
531 1
    public function themeSelect()
0 ignored issues
show
Coding Style introduced by
themeSelect uses the super-global variable $_SESSION 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...
532
    {
533 1
        $xoopsThemeSelect = Request::getString('xoops_theme_select', '', 'POST');
534 1
        if (!empty($xoopsThemeSelect) && in_array($xoopsThemeSelect, $this->getConfig('theme_set_allowed'))) {
535 1
            $this->setConfig('theme_set', $xoopsThemeSelect);
536 1
            $_SESSION['xoopsUserTheme'] = $xoopsThemeSelect;
537
        } else {
538 1
            if (!empty($_SESSION['xoopsUserTheme'])
539 1
                && in_array($_SESSION['xoopsUserTheme'], $this->getConfig('theme_set_allowed'))
540
            ) {
541 1
                $this->setConfig('theme_set', $_SESSION['xoopsUserTheme']);
542
            }
543
        }
544 1
    }
545
546
    /**
547
     * Gets module, type and file from a tpl name
548
     *
549
     * @param string $tpl_name in form type:module/filename.tpl
550
     *
551
     * @return array|false associative array of 'tpl_name', 'type', 'module', 'file'
552
     *                     or false on error
553
     */
554 8
    public function getTplInfo($tpl_name)
555
    {
556 8
        $parts = array();
557 8
        $matched = preg_match('#(\w+):(\w+)/(.*)$#', $tpl_name, $parts);
558 8
        if ($matched) {
559 7
            $names = array('tpl_name', 'type', 'module', 'file');
560 7
            $ret = array();
561 7
            for ($i=0; $i<4; ++$i) {
562 7
                $ret[$names[$i]] = $parts[$i];
563
            }
564
        } else {
565
            // this should be eliminated
566 1
            $this->events()->triggerEvent('debug.log', "Sloppy template: " . $tpl_name);
567 1
            $ret = array();
568 1
            $ret['type'] = $this->isAdminSide ? 'admin' : 'module';
569 1
            $info = explode(':', $tpl_name);
570 1
            if (count($info) == 2) {
571 1
                $ret['type'] = $info[0];
572 1
                $tpl_name = str_replace($ret['type'] . ':', '', $tpl_name);
573
            }
574
575 1
            if ($ret['type'] === 'db') {
576
                //For legacy compatibility
577 1
                $ret['type'] = $this->isAdminSide ? 'admin' : 'module';
578
            }
579
580 1
            $info = explode('|', $tpl_name);
581 1
            if (count($info) == 2) {
582
                $ret['module'] = $info[0];
583
                $ret['file'] = $info[1];
584
            } else {
585 1
                $ret['module'] = 'system';
586 1
                $ret['file'] = $tpl_name;
587 1
                if ($this->isModule()) {
588
                    $ret['module'] = $this->module->getVar('dirname', 'n');
589
                }
590
            }
591 1
            $ret['tpl_name'] = $ret['type'] . ':' . $ret['module'] . '/' . $ret['file'];
592
        }
593
594 8
        return $ret;
595
    }
596
597
    /**
598
     * Render Header
599
     *
600
     * @param string|null $tpl_name template name
601
     *
602
     * @return null|boolean
603
     */
604
    public function header($tpl_name = null)
605
    {
606
        static $included = false;
607
        if ($included) {
608
            return false;
609
        }
610
        $included = true;
611
612
        $this->events()->triggerEvent('core.header.start');
613
614
        //For legacy
615
        if (!$tpl_name && isset($this->option['template_main'])) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $tpl_name of type string|null is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
616
            $tpl_name = $this->option['template_main'];
617
            $this->deprecated(
618
                'XoopsOption \'template_main\' is deprecated, please use $xoops->header(\'templatename.tpl\') instead'
619
            );
620
        }
621
        $this->theme($tpl_name);
622
        $this->tpl()->assign('xoops', $this);
623
624
        if ($this->isAdminSide) {
625
            $this->events()->triggerEvent('system.class.gui.header');
626
            include_once $this->path('modules/system/themes/default/default.php');
627
            $gui = new XoopsGuiDefault();
628
            $gui->header();
629
        } else {
630
            $this->events()->triggerEvent('core.header.addmeta');
631
            // Temporary solution for start page redirection
632
            if (defined("XOOPS_STARTPAGE_REDIRECTED")) {
633
                $smarty = $repeat = null;
634
                $this->theme()->headContent(
635
                    null,
636
                    "<base href='" . \XoopsBaseConfig::get('url') . '/modules/'
637
                    . $this->getConfig('startpage') . "/' />",
638
                    $smarty,
639
                    $repeat
640
                );
641
            }
642
643
            // Sets cache time
644
            if ($this->isModule()) {
645
                $cache_times = $this->getConfig('module_cache');
646
                $this->theme()->contentCacheLifetime =
647
                    isset($cache_times[$this->module->getVar('mid')]) ? $cache_times[$this->module->getVar('mid')] : 0;
648
                // Tricky solution for setting cache time for homepage
649
            } else {
650
                if ($this->tpl_name === 'module:system/system_homepage.tpl') {
0 ignored issues
show
Unused Code introduced by
This if statement is empty and can be removed.

This check looks for the bodies of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These if bodies can be removed. If you have an empty if but statements in the else branch, consider inverting the condition.

if (rand(1, 6) > 3) {
//print "Check failed";
} else {
    print "Check succeeded";
}

could be turned into

if (rand(1, 6) <= 3) {
    print "Check succeeded";
}

This is much more concise to read.

Loading history...
651
                    // $this->theme->contentCacheLifetime = 604800;
652
                }
653
            }
654
            $this->events()->triggerEvent('core.header.checkcache');
655
            if ($this->theme()->checkCache()) {
656
                exit();
0 ignored issues
show
Coding Style Compatibility introduced by
The method header() 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...
657
            }
658
        }
659
660
        if (!isset($this->tpl_name) && $this->isModule()) {
661
            ob_start();
662
        }
663
664
        $this->events()->triggerEvent('core.header.end');
665
        return true;
666
    }
667
668
    /**
669
     * Render Footer
670
     *
671
     * @return false|null
672
     */
673
    public function footer()
674
    {
675
        static $included = false;
676
        if ($included) {
677
            return false;
678
        }
679
        $included = true;
680
681
        $this->events()->triggerEvent('core.footer.start');
682
683
        if (!headers_sent()) {
684
            header('Content-Type:text/html; charset=' . XoopsLocale::getCharset());
685
            header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
686
            header('Cache-Control: private, no-cache');
687
            header('Pragma: no-cache');
688
        }
689
690
        if (isset($this->option['template_main'])
691
            && $this->option['template_main'] != $this->theme()->contentTemplate
692
        ) {
693
            trigger_error("xoopsOption[template_main] should be defined before including header.php", E_USER_WARNING);
694
            $this->theme()->contentTemplate = $this->tpl_name;
695
        }
696
        $this->theme()->render();
697
        $this->events()->triggerEvent('core.footer.end');
698
        exit();
0 ignored issues
show
Coding Style Compatibility introduced by
The method footer() 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...
699
    }
700
701
    /**
702
     * Check if a module is set
703
     *
704
     * @return bool
705
     */
706 12
    public function isModule()
707
    {
708 12
        return $this->module instanceof XoopsModule ? true : false;
709
    }
710
711
    /**
712
     * Check if a user is set
713
     *
714
     * @return bool
715
     */
716 8
    public function isUser()
717
    {
718 8
        return $this->user instanceof XoopsUser ? true : false;
719
    }
720
721
    /**
722
     * Check if user is admin
723
     *
724
     * @return bool
725
     */
726 1
    public function isAdmin()
727
    {
728 1
        return $this->userIsAdmin;
729
    }
730
731
    /**
732
     * Get handler of Block
733
     *
734
     * @param boolean $optional true if failure to load handler should be considered a warning, not an error
735
     *
736
     * @return \Xoops\Core\Kernel\Handlers\XoopsBlockHandler
737
     */
738 4
    public function getHandlerBlock($optional = false)
739
    {
740 4
        return $this->getHandler('Block', $optional);
741
    }
742
743
    /**
744
     * Get handler of Block Module Link
745
     *
746
     * @param boolean $optional true if failure to load handler should be considered a warning, not an error
747
     *
748
     * @return \Xoops\Core\Kernel\Handlers\XoopsBlockModuleLinkHandler
749
     */
750 1
    public function getHandlerBlockModuleLink($optional = false)
751
    {
752 1
        return $this->getHandler('BlockModuleLink', $optional);
753
    }
754
755
    /**
756
     * Get handler of Config
757
     *
758
     * @param boolean $optional true if failure to load handler should be considered a warning, not an error
759
     *
760
     * @return \Xoops\Core\Kernel\Handlers\XoopsConfigHandler
761
     */
762 1
    public function getHandlerConfig($optional = false)
763
    {
764 1
        return $this->getHandler('Config', $optional);
765
    }
766
767
    /**
768
     * Get handler of Config  Item
769
     *
770
     * @param boolean $optional true if failure to load handler should be considered a warning, not an error
771
     *
772
     * @return \Xoops\Core\Kernel\Handlers\XoopsConfigItemHandler
773
     */
774 18
    public function getHandlerConfigItem($optional = false)
775
    {
776 18
        return $this->getHandler('ConfigItem', $optional);
777
    }
778
779
    /**
780
     * Get handler of Config Option
781
     *
782
     * @param boolean $optional true if failure to load handler should be considered a warning, not an error
783
     *
784
     * @return \Xoops\Core\Kernel\Handlers\XoopsConfigOptionHandler
785
     */
786 18
    public function getHandlerConfigOption($optional = false)
787
    {
788 18
        return $this->getHandler('ConfigOption', $optional);
789
    }
790
791
    /**
792
     * Get handler of Group
793
     *
794
     * @param boolean $optional true if failure to load handler should be considered a warning, not an error
795
     *
796
     * @return \Xoops\Core\Kernel\Handlers\XoopsGroupHandler
797
     */
798 8
    public function getHandlerGroup($optional = false)
799
    {
800 8
        return $this->getHandler('Group', $optional);
801
    }
802
803
    /**
804
     * Get handler of Group Permission
805
     *
806
     * @param boolean $optional true if failure to load handler should be considered a warning, not an error
807
     *
808
     * @return \Xoops\Core\Kernel\Handlers\XoopsGroupPermHandler
809
     */
810 4
    public function getHandlerGroupPermission($optional = false)
811
    {
812 4
        return $this->getHandler('GroupPerm', $optional);
813
    }
814
815
    /**
816
     * Get handler of Member
817
     *
818
     * @param boolean $optional true if failure to load handler should be considered a warning, not an error
819
     *
820
     * @return \Xoops\Core\Kernel\Handlers\XoopsMemberHandler
821
     */
822 18
    public function getHandlerMember($optional = false)
823
    {
824 18
        return $this->getHandler('Member', $optional);
825
    }
826
827
    /**
828
     * Get handler of Membership
829
     *
830
     * @param boolean $optional true if failure to load handler should be considered a warning, not an error
831
     *
832
     * @return \Xoops\Core\Kernel\Handlers\XoopsMembershipHandler
833
     */
834 8
    public function getHandlerMembership($optional = false)
835
    {
836 8
        return $this->getHandler('Membership', $optional);
837
    }
838
839
    /**
840
     * Get handler of Module
841
     *
842
     * @param boolean $optional true if failure to load handler should be considered a warning, not an error
843
     *
844
     * @return \Xoops\Core\Kernel\Handlers\XoopsModuleHandler
845
     */
846 11
    public function getHandlerModule($optional = false)
847
    {
848 11
        return $this->getHandler('Module', $optional);
849
    }
850
851
    /**
852
     * Get handler of Online
853
     *
854
     * @param boolean $optional true if failure to load handler should be considered a warning, not an error
855
     *
856
     * @return \Xoops\Core\Kernel\Handlers\XoopsOnlineHandler
857
     */
858 2
    public function getHandlerOnline($optional = false)
859
    {
860 2
        return $this->getHandler('Online', $optional);
861
    }
862
863
    /**
864
     * Get handler of Private Message
865
     *
866
     * @param boolean $optional true if failure to load handler should be considered a warning, not an error
867
     *
868
     * @return \Xoops\Core\Kernel\Handlers\XoopsPrivateMessageHandler
869
     */
870 1
    public function getHandlerPrivateMessage($optional = false)
871
    {
872 1
        return $this->getHandler('Privmessage', $optional);
873
    }
874
875
    /**
876
     * Get the session manager
877
     *
878
     * @return Xoops\Core\Session\Manager
879
     */
880 1
    public function session()
881
    {
882 1
        if ($this->sessionManager === null) {
883 1
            $this->sessionManager = new \Xoops\Core\Session\Manager();
884
        }
885 1
        return $this->sessionManager;
886
    }
887
888
    /**
889
     * Get handler of Template File
890
     *
891
     * @param boolean $optional true if failure to load handler should be considered a warning, not an error
892
     *
893
     * @return \Xoops\Core\Kernel\Handlers\XoopsTplFileHandler
894
     */
895 2
    public function getHandlerTplFile($optional = false)
896
    {
897 2
        return $this->getHandler('tplfile', $optional);
898
    }
899
900
    /**
901
     * Get handler of Template Set
902
     *
903
     * @param boolean $optional true if failure to load handler should be considered a warning, not an error
904
     *
905
     * @return \Xoops\Core\Kernel\Handlers\XoopsTplSetHandler
906
     */
907 1
    public function getHandlerTplSet($optional = false)
908
    {
909 1
        return $this->getHandler('Tplset', $optional);
910
    }
911
912
    /**
913
     * Get handler of User
914
     *
915
     * @param boolean $optional true if failure to load handler should be considered a warning, not an error
916
     *
917
     * @return \Xoops\Core\Kernel\Handlers\XoopsUserHandler
918
     */
919 8
    public function getHandlerUser($optional = false)
920
    {
921 8
        return $this->getHandler('user', $optional);
922
    }
923
924
    /**
925
     * Get handler
926
     *
927
     * @param string  $name     name of handler
928
     * @param boolean $optional true if failure to load handler should be considered a warning, not an error
929
     *
930
     * @return XoopsObjectHandler|XoopsPersistableObjectHandler|null
931
     */
932 69
    protected function getHandler($name, $optional = false)
933
    {
934 69
        if (!isset($this->kernelHandlers[$name])) {
935 6
            if (!isset($this->handlerFactory)) {
936
                $this->handlerFactory = HandlerFactory::getInstance();
937
            }
938 6
            $handler = $this->handlerFactory->newSpec()->scheme('kernel')->name($name)->optional($optional)->build();
939 6
            if ($handler === null) {
940
                $this->logger()->log(
941
                    \Psr\Log\LogLevel::WARNING,
942
                    sprintf('A handler for %s is not available', $name)
943
                );
944
            }
945 6
            $this->kernelHandlers[$name] = $handler;
946
        }
947
948 69
        return $this->kernelHandlers[$name];
949
    }
950
951
    /**
952
     * Get Module Handler
953
     *
954
     * @param string|null $name       name of handler
955
     * @param string|null $module_dir dirname of module
956
     * @param boolean     $optional   true if failure to load handler should be considered a warning, not an error
957
     *
958
     * @return XoopsObjectHandler|XoopsPersistableObjectHandler|bool
959
     */
960 2
    public function getModuleHandler($name = null, $module_dir = null, $optional = false)
961
    {
962
        // if $module_dir is not specified
963 2
        if (!isset($module_dir)) {
964
            // if a module is loaded
965
            if ($this->module instanceof XoopsModule) {
966
                $module_dir = $this->module->getVar('dirname', 'n');
967
            } else {
968
                trigger_error('No Module is loaded', E_USER_ERROR);
969
            }
970
        } else {
971 2
            $module_dir = trim($module_dir);
972
        }
973 2
        $name = (!isset($name)) ? $module_dir : trim($name);
974 2
        if (!isset($this->moduleHandlers[$module_dir][$name])) {
975 2
            if (!isset($this->handlerFactory)) {
976
                $this->handlerFactory = HandlerFactory::getInstance();
977
            }
978 2
            $handler = $this->handlerFactory->create($name, $module_dir, $optional);
979 2
            if ($handler === null) {
980
                $this->logger()->log(
981
                    LogLevel::WARNING,
982
                    sprintf('No handler for %s exists in module %s', $name, $module_dir)
983
                );
984
            }
985 2
            $this->moduleHandlers[$module_dir][$name] = $handler;
986
        }
987 2
        return $this->moduleHandlers[$module_dir][$name];
988
    }
989
990
    /**
991
     * Get Module Form
992
     *
993
     * @param XoopsObject $obj        object to populate form
994
     * @param string      $name       name of form
995
     * @param string      $module_dir dirname of associated module
996
     *
997
     * @return Xoops\Form\Form|bool
998
     */
999 1
    public function getModuleForm($obj, $name, $module_dir = null)
1000
    {
1001 1
        if (empty($name)) {
1002 1
            return false;
1003
        }
1004
        if (empty($module_dir)) {
1005
            if ($this->isModule()) {
1006
                $module_dir = $this->module->getVar('dirname', 'n');
1007
            } else {
1008
                return false;
1009
            }
1010
        }
1011
        if (XoopsLoad::fileExists(
1012
            $hnd_file = \XoopsBaseConfig::get('root-path') . "/modules/{$module_dir}/class/form/{$name}.php"
1013
        )) {
1014
            include_once $hnd_file;
1015
            $class = ucfirst(strtolower($module_dir)) . ucfirst($name) . 'Form';
1016
            if (class_exists($class)) {
1017
                $instance = new $class($obj);
1018
                if ($instance instanceof \Xoops\Form\Form) {
1019
                    return $instance;
1020
                }
1021
            }
1022
        }
1023
        return false;
1024
    }
1025
1026
    /**
1027
     * Get Module Helper
1028
     *
1029
     * @param string $dirname dirname of module
1030
     *
1031
     * @return bool|Xoops\Module\Helper\HelperAbstract
1032
     */
1033 1
    public static function getModuleHelper($dirname)
1034
    {
1035 1
        return \Xoops\Module\Helper::getHelper($dirname);
1036
    }
1037
1038
    /**
1039
     * XOOPS language loader wrapper
1040
     * Temporary solution, not encouraged to use
1041
     *
1042
     * @param string $name     Name of language file to be loaded, without extension
1043
     * @param mixed  $domain   string: Module dirname; global language file will be loaded if
1044
     *                           $domain is set to 'global' or not specified
1045
     *                          array:  example; array('Frameworks/moduleclasses/moduleadmin')
1046
     * @param string $language Language to be loaded, current language content will be loaded if not specified
1047
     *
1048
     * @return  boolean
1049
     */
1050 8
    public function loadLanguage($name, $domain = '', $language = null)
1051
    {
1052 8
        if (empty($name)) {
1053 1
            return false;
1054
        }
1055
1056 8
        $language = empty($language) ? XoopsLocale::getLegacyLanguage() : $language;
1057
        // expanded domain to multiple categories, e.g. module:Fsystem, framework:filter, etc.
1058 8 View Code Duplication
        if ((empty($domain) || 'global' === $domain)) {
1059 1
            $path = '';
1060
        } else {
1061 7
            $path = (is_array($domain)) ? array_shift($domain) . '/' : "modules/{$domain}/";
1062
        }
1063 8
        $path .= 'language';
1064
1065 8
        if (!XoopsLoad::fileExists($file = $this->path("{$path}/{$language}/{$name}.php"))) {
1066 7
            if (!XoopsLoad::fileExists($file = $this->path("{$path}/english/{$name}.php"))) {
1067 7
                return false;
1068
            }
1069
        }
1070 1
        $ret = include_once $file;
1071 1
        return $ret;
1072
    }
1073
1074
    /**
1075
     * loadLocale
1076
     *
1077
     * @param string $domain Module dirname; global language file will be loaded if set to 'global' or not specified
1078
     * @param string $locale Locale to be loaded, current language content will be loaded if not specified
1079
     *
1080
     * @return  boolean
1081
     */
1082 5
    public static function loadLocale($domain = null, $locale = null)
1083
    {
1084 5
        return \Xoops\Locale::loadLocale($domain, $locale);
1085
    }
1086
1087
    /**
1088
     * Translate a key value
1089
     *
1090
     * @param string $key     constant name
1091
     * @param string $dirname dirname of module (domain)
1092
     *
1093
     * @return string
1094
     */
1095 1
    public function translate($key, $dirname = 'xoops')
1096
    {
1097 1
        return \Xoops\Locale::translate($key, $dirname);
1098
    }
1099
1100
    /**
1101
     * Get active modules from cache file
1102
     *
1103
     * @return array
1104
     */
1105 9
    public function getActiveModules()
1106
    {
1107 9
        if (is_array($this->activeModules)) {
1108 9
            return $this->activeModules;
1109
        }
1110
1111
        try {
1112
            if (!$this->activeModules = $this->cache()->read('system/modules/active')) {
1113
                $this->setActiveModules();
1114
            }
1115
        } catch (\Exception $e) {
1116
            $this->activeModules = array();
1117
        }
1118
        return $this->activeModules;
1119
    }
1120
1121
    /**
1122
     * Write active modules to cache file
1123
     *
1124
     * @return array
1125
     */
1126 1
    public function setActiveModules()
1127
    {
1128 1
        $module_handler = $this->getHandlerModule();
1129 1
        $modules_array = $module_handler->getAll(new Criteria('isactive', 1), array('dirname'), false, false);
0 ignored issues
show
Bug introduced by
The method getAll does only exist in XoopsPersistableObjectHandler, but not in XoopsObjectHandler.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
1130 1
        $modules_active = array();
1131 1
        foreach ($modules_array as $module) {
1132 1
            $modules_active[$module['mid']] = $module['dirname'];
1133
        }
1134 1
        $this->cache()->write('system/modules/active', $modules_active);
1135 1
        $this->activeModules = $modules_active;
1136 1
        return $modules_active;
1137
    }
1138
1139
    /**
1140
     * Checks is module is installed and active
1141
     *
1142
     * @param string $dirname module directory
1143
     *
1144
     * @return bool
1145
     */
1146 7
    public function isActiveModule($dirname)
1147
    {
1148 7
        if (isset($dirname) && in_array($dirname, $this->getActiveModules())) {
1149 2
            return true;
1150
        }
1151 6
        return false;
1152
    }
1153
1154
    /**
1155
     * get module object from module name (dirname)
1156
     *
1157
     * @param string $dirname dirname of the module
1158
     *
1159
     * @return bool|XoopsModule
1160
     */
1161 5 View Code Duplication
    public function getModuleByDirname($dirname)
1162
    {
1163 5
        $key = "system/module/dirname/{$dirname}";
1164 5
        if (!$module = $this->cache()->read($key)) {
1165 5
            $module = $this->getHandlerModule()->getByDirname($dirname);
1166 5
            $this->cache()->write($key, $module);
1167
        }
1168 5
        return $module;
1169
    }
1170
1171
    /**
1172
     * Get Module By Id
1173
     *
1174
     * @param int $id Id of the module
1175
     *
1176
     * @return bool|XoopsModule
1177
     */
1178 1 View Code Duplication
    public function getModuleById($id)
1179
    {
1180 1
        $key = "system/module/id/{$id}";
1181 1
        if (!$module = $this->cache()->read($key)) {
1182 1
            $module = $this->getHandlerModule()->getById($id);
1183 1
            $this->cache()->write($key, $module);
1184
        }
1185 1
        return $module;
1186
    }
1187
1188
    /**
1189
     * Render Simple Header
1190
     *
1191
     * @param bool $closehead true to close the HTML head element
1192
     *
1193
     * @return void
1194
     */
1195 1
    public function simpleHeader($closehead = true)
1196
    {
1197 1
        $this->events()->triggerEvent('core.header.start');
1198 1
        $this->theme();
1199 1
        $xoopsConfigMetaFooter = $this->getConfigs();
1200
1201 1
        if (!headers_sent()) {
1202
            header('Content-Type:text/html; charset=' . XoopsLocale::getCharset());
1203
            header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
1204
            header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
1205
            header(
1206
                'Cache-Control: no-store, no-cache, max-age=1, s-maxage=1, must-revalidate, post-check=0, pre-check=0'
1207
            );
1208
            header("Pragma: no-cache");
1209
        }
1210
1211 1
        echo "<!DOCTYPE html>\n";
1212 1
        $xoops_url = \XoopsBaseConfig::get('url');
1213 1
        echo '<html lang="' . XoopsLocale::getLangCode() . '">
1214
              <head>
1215
              <meta charset="utf-8">
1216
              <meta http-equiv="X-UA-Compatible" content="IE=edge">
1217
              <meta name="viewport" content="width=device-width, initial-scale=1">
1218 1
              <meta name="robots" content="' . htmlspecialchars($xoopsConfigMetaFooter['meta_robots']) . '" />
1219 1
              <meta name="keywords" content="' . htmlspecialchars($xoopsConfigMetaFooter['meta_keywords']) . '" />
1220 1
              <meta name="description" content="' . htmlspecialchars($xoopsConfigMetaFooter['meta_description']) . '" />
1221 1
              <meta name="rating" content="' . htmlspecialchars($xoopsConfigMetaFooter['meta_rating']) . '" />
1222 1
              <meta name="author" content="' . htmlspecialchars($xoopsConfigMetaFooter['meta_author']) . '" />
1223
              <meta name="generator" content="XOOPS" />
1224 1
              <title>' . htmlspecialchars($this->getConfig('sitename')) . '</title>'
1225 1
            . $this->theme->renderBaseAssets();
1226
1227 1
        $locale = $this->getConfig('locale');
1228 1
        if (XoopsLoad::fileExists($this->path('locale/' . $locale . '/style.css'))) {
1229
            echo '<link rel="stylesheet" type="text/css" media="all" href="' . $xoops_url
1230
                . '/locale/' . $locale . '/style.css" />';
1231
        }
1232 1
        $themecss = $this->getCss($this->getConfig('theme_set'));
1233 1
        if ($themecss) {
1234 1
            echo '<link rel="stylesheet" type="text/css" media="all" href="' . $themecss . '" />';
1235
        }
1236 1
        if ($closehead) {
1237 1
            echo '</head><body>';
1238
        }
1239 1
    }
1240
1241
    /**
1242
     * Render simpleFooter
1243
     *
1244
     * @return void
1245
     */
1246 2
    public function simpleFooter()
1247
    {
1248 2
        $this->events()->triggerEvent('core.header.footer');
1249 2
        echo '</body></html>';
1250 2
        ob_end_flush();
1251 2
    }
1252
    /**
1253
     * render an alert message to a string
1254
     *
1255
     * @param string $type  alert type, one of 'info', 'error', 'success' or 'warning'
1256
     * @param mixed  $msg   string or array of strings
1257
     * @param string $title title for alert
1258
     *
1259
     * @return string
1260
     */
1261 1
    public function alert($type, $msg, $title = '/')
1262
    {
1263 1
        $tpl = new XoopsTpl();
1264
        switch ($type) {
1265 1
            case 'info':
1266
            default:
1267 1
                $tpl->assign('alert_type', 'alert-info');
1268 1
                if ($title === '/') {
1269 1
                    $title = XoopsLocale::INFORMATION;
1270
                }
1271 1
                break;
1272
1273 1
            case 'error':
0 ignored issues
show
Unused Code introduced by
case 'error': $tpl->...ERROR; } break; does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
1274 1
                $tpl->assign('alert_type', 'alert-danger');
1275 1
                if ($title === '/') {
1276 1
                    $title = XoopsLocale::ERROR;
1277
                }
1278 1
                break;
1279
1280 1
            case 'success':
1281 1
                $tpl->assign('alert_type', 'alert-success');
1282 1
                if ($title === '/') {
1283 1
                    $title = XoopsLocale::SUCCESS;
1284
                }
1285 1
                break;
1286
1287 1
            case 'warning':
1288 1
                $tpl->assign('alert_type', 'alert-warning');
1289 1
                if ($title === '/') {
1290 1
                    $title = XoopsLocale::WARNING;
1291
                }
1292 1
                break;
1293
        }
1294
1295 1
        if ($title != '') {
1296 1
            $tpl->assign('alert_title', $title);
1297
        }
1298 1
        if (!is_scalar($msg) && !is_array($msg)) {
1299 1
            $msg = ''; // don't know what to do with this, so make it blank
1300
        }
1301 1
        $alert_msg = (is_array($msg)) ? @implode("<br />", $msg) : $msg;
1302
1303 1
        if (empty($alert_msg)) {
1304 1
            return '';
1305
        }
1306 1
        $tpl->assign('alert_msg', $alert_msg);
1307 1
        $ret = $tpl->fetch('module:system/system_alert.tpl');
1308 1
        return $ret;
1309
1310
    }
1311
1312
    /**
1313
     * Render a confirmation form to a string
1314
     *
1315
     * @param array   $hiddens  associative array of values used to complete confirmed action
1316
     * @param string  $action   form action (URL)
1317
     * @param string  $msg      message to display
1318
     * @param string  $submit   submit button message
1319
     * @param boolean $addtoken true to add CSRF token
1320
     *
1321
     * @return string rendered confirm message
1322
     */
1323 1
    public function confirm($hiddens, $action, $msg, $submit = '', $addtoken = true)
1324
    {
1325 1
        $tpl = new XoopsTpl();
1326 1
        $submit = ($submit != '') ? trim($submit) : XoopsLocale::A_SUBMIT;
1327 1
        $tpl->assign('msg', $msg);
1328 1
        $tpl->assign('action', $action);
1329 1
        $tpl->assign('submit', $submit);
1330 1
        $str_hiddens = '';
1331 1
        foreach ($hiddens as $name => $value) {
1332 1
            if (is_array($value)) {
1333 1
                foreach ($value as $caption => $newvalue) {
1334 1
                    $str_hiddens .= '<input type="radio" name="' . $name . '" value="'
1335 1
                        . htmlspecialchars($newvalue) . '" > ' . $caption . NWLINE;
1336
                }
1337 1
                $str_hiddens .= '<br />' . NWLINE;
1338
            } else {
1339 1
                $str_hiddens .= '<input type="hidden" name="' . $name . '" value="'
1340 1
                    . htmlspecialchars($value) . '" />' . NWLINE;
1341
            }
1342
        }
1343 1
        if ($addtoken != 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...
1344 1
            $tpl->assign('token', $this->security()->getTokenHTML());
1345
        }
1346 1
        $tpl->assign('hiddens', $str_hiddens);
1347 1
        return $tpl->fetch('module:system/system_confirm.tpl');
1348
    }
1349
1350
    /**
1351
     * Get User Timestamp (kind of pointless, since timestamps are UTC?)
1352
     *
1353
     * @param \DateTime|int $time DateTime object or unix timestamp
1354
     *
1355
     * @return int unix timestamp
1356
     */
1357 1
    public function getUserTimestamp($time)
1358
    {
1359 1
        $dt = \Xoops\Core\Locale\Time::cleanTime($time);
1360 1
        return $dt->getTimestamp();
1361
    }
1362
1363
    /**
1364
     * Function to calculate server timestamp from user entered time (timestamp)
1365
     *
1366
     * @param int  $timestamp time stamp
1367
     * @param null $userTZ    timezone
1368
     *
1369
     * @return int
1370
     */
1371 1
    public function userTimeToServerTime($timestamp, $userTZ = null)
1372
    {
1373 1
        if (!isset($userTZ)) {
1374 1
            $userTZ = $this->getConfig('default_TZ');
1375
        }
1376 1
        $timestamp = $timestamp - (($userTZ - $this->getConfig('server_TZ')) * 3600);
1377 1
        return (int)$timestamp;
1378
    }
1379
1380
    /**
1381
     * get the groups associated with the current user
1382
     *
1383
     * @return int[]
1384
     */
1385 3
    public function getUserGroups()
1386
    {
1387 3
        $groups = $this->isUser() ? $this->user->getGroups() : array(FixedGroups::ANONYMOUS);
1388
1389 3
        return $groups;
1390
    }
1391
1392
    /**
1393
     * generate a temporary password
1394
     *
1395
     * @return string
1396
     *
1397
     * @todo make better passwords
1398
     */
1399 1
    public function makePass()
1400
    {
1401 1
        $makepass = '';
1402
        $syllables = array(
1403 1
            'er', 'in', 'tia', 'wol', 'fe', 'pre', 'vet', 'jo', 'nes', 'al', 'len', 'son', 'cha', 'ir', 'ler', 'bo',
1404
            'ok', 'tio', 'nar', 'sim', 'ple', 'bla', 'ten', 'toe', 'cho', 'co', 'lat', 'spe', 'ak', 'er', 'po', 'co',
1405
            'lor', 'pen', 'cil', 'li', 'ght', 'wh', 'at', 'the', 'he', 'ck', 'is', 'mam', 'bo', 'no', 'fi', 've', 'any',
1406
            'way', 'pol', 'iti', 'cs', 'ra', 'dio', 'sou', 'rce', 'sea', 'rch', 'pa', 'per', 'com', 'bo', 'sp', 'eak',
1407
            'st', 'fi', 'rst', 'gr', 'oup', 'boy', 'ea', 'gle', 'tr', 'ail', 'bi', 'ble', 'brb', 'pri', 'dee', 'kay',
1408
            'en', 'be', 'se'
1409
        );
1410 1
        for ($count = 1; $count <= 4; ++$count) {
1411 1
            if (1 == mt_rand() % 10) {
1412 1
                $makepass .= sprintf('%0.0f', (rand() % 50) + 1);
1413
            } else {
1414 1
                $makepass .= sprintf('%s', $syllables[rand() % 62]);
1415
            }
1416
        }
1417 1
        return $makepass;
1418
    }
1419
1420
    /**
1421
     * Check Email
1422
     *
1423
     * @param string $email    check email
1424
     * @param bool   $antispam true if returned email should be have anti-SPAM measures applied
1425
     *
1426
     * @return false|string email address if valid, otherwise false
1427
     */
1428 2
    public function checkEmail($email, $antispam = false)
1429
    {
1430 2
        if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
1431 1
            return false;
1432
        }
1433 2
        if ($antispam) {
1434 1
            $email = str_replace("@", " at ", $email);
1435 1
            $email = str_replace(".", " dot ", $email);
1436
        }
1437 2
        return $email;
1438
    }
1439
1440
    /**
1441
     * formatURL - add default http:// if no valid protocol specified
1442
     *
1443
     * @param string $url full or partial url
1444
     *
1445
     * @return string
1446
     */
1447 1
    public function formatURL($url)
1448
    {
1449 1
        $url = trim($url);
1450 1
        if ($url != '') {
1451 1
            if (!preg_match('/^(https?|ftps?|ed2k)\:\/\//i', $url)) {
1452 1
                $url = 'http://' . $url;
1453
            }
1454
        }
1455 1
        return $url;
1456
    }
1457
1458
    /**
1459
     * Function to get banner html tags for use in templates
1460
     *
1461
     * @return string
1462
     */
1463 3
    public function getBanner()
1464
    {
1465 3
        $options = '';
1466 3
        $this->events()->triggerEvent('core.banner.display', array(&$options));
1467 3
        return $options;
1468
    }
1469
1470
    /**
1471
     * Function to redirect a user to certain pages
1472
     *
1473
     * @param string $url               URL to redirect to
1474
     * @param int    $time              time to wait (to allow reading message display)
1475
     * @param string $message           message to display
1476
     * @param bool   $addredirect       add xoops_redirect parameter with current URL to the redirect
1477
     *                                   URL -  used for return from login redirect
1478
     * @param bool   $allowExternalLink allow redirect to external URL
1479
     *
1480
     * @return void
1481
     */
1482
    public function redirect($url, $time = 3, $message = '', $addredirect = true, $allowExternalLink = false)
0 ignored issues
show
Coding Style introduced by
redirect 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...
1483
    {
1484
        $this->events()->triggerEvent('core.redirect.start', array(
1485
            $url, $time, $message, $addredirect, $allowExternalLink
1486
        ));
1487
        // if conditions are right, system preloads will exit on this call
1488
        // so don't use it if you want to be called, use start version above.
1489
        $this->events()->triggerEvent('core.include.functions.redirectheader', array(
1490
            $url, $time, $message, $addredirect, $allowExternalLink
1491
        ));
1492
1493
        $xoops_url = \XoopsBaseConfig::get('url');
1494
1495
        if (preg_match("/[\\0-\\31]|about:|script:/i", $url)) {
1496
            if (!preg_match('/^\b(java)?script:([\s]*)history\.go\(-[0-9]*\)([\s]*[;]*[\s]*)$/si', $url)) {
1497
                $url = $xoops_url;
1498
            }
1499
        }
1500 View Code Duplication
        if (!$allowExternalLink && $pos = strpos($url, '://')) {
1501
            $xoopsLocation = substr($xoops_url, strpos($xoops_url, '://') + 3);
1502
            if (strcasecmp(substr($url, $pos + 3, strlen($xoopsLocation)), $xoopsLocation)) {
1503
                $url = $xoops_url;
1504
            }
1505
        }
1506
        if (!defined('XOOPS_CPFUNC_LOADED')) {
1507
            $theme = 'default';
1508
        } else {
1509
            $theme = $this->getConfig('theme_set');
1510
        }
1511
1512
        $xoopsThemeFactory = null;
0 ignored issues
show
Unused Code introduced by
$xoopsThemeFactory is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
1513
        $xoopsThemeFactory = new \Xoops\Core\Theme\Factory();
1514
        $xoopsThemeFactory->allowedThemes = $this->getConfig('theme_set_allowed');
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->getConfig('theme_set_allowed') of type * is incompatible with the declared type array of property $allowedThemes.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
1515
        $xoopsThemeFactory->defaultTheme = $theme;
1516
        $this->setTheme($xoopsThemeFactory->createInstance(array(
1517
            "plugins" => array(), "renderBanner" => false
1518
        )));
1519
        $this->setTpl($this->theme()->template);
1520
        $this->tpl()->assign(array(
1521
            'xoops_theme'      => $theme, 'xoops_imageurl' => \XoopsBaseConfig::get('themes-url') . '/' . $theme . '/',
1522
            'xoops_themecss'   => $this->getCss($theme),
1523
            'xoops_requesturi' => htmlspecialchars($_SERVER['REQUEST_URI'], ENT_QUOTES),
1524
            'xoops_sitename'   => htmlspecialchars($this->getConfig('sitename'), ENT_QUOTES),
1525
            'xoops_slogan'     => htmlspecialchars($this->getConfig('slogan'), ENT_QUOTES),
1526
            'xoops_dirname'    => $this->isModule() ? $this->module->getVar('dirname') : 'system',
1527
            'xoops_pagetitle'  => $this->isModule() ? $this->module->getVar('name')
1528
                : htmlspecialchars($this->getConfig('slogan'), ENT_QUOTES)
1529
        ));
1530
1531
        $this->tpl()->assign('time', (int)($time));
1532
        if (!empty($_SERVER['REQUEST_URI']) && $addredirect && strstr($url, 'user.php')) {
1533
            $joiner = (false===strpos($url, '?')) ? '?' : '&amp;';
1534
            $url .= $joiner . 'xoops_redirect=' . urlencode($_SERVER['REQUEST_URI']);
1535
        }
1536
        $url = preg_replace("/&amp;/i", '&', htmlspecialchars($url, ENT_QUOTES));
1537
        $this->tpl()->assign('url', $url);
1538
        $message = trim($message) != '' ? $message : XoopsLocale::E_TAKING_YOU_BACK;
1539
        $this->tpl()->assign('message', $message);
1540
        $this->tpl()->assign('lang_ifnotreload', sprintf(XoopsLocale::F_IF_PAGE_NOT_RELOAD_CLICK_HERE, $url));
1541
1542
        $this->events()->triggerEvent('core.include.functions.redirectheader.end');
1543
        $this->tpl()->display('module:system/system_redirect.tpl');
1544
        exit();
0 ignored issues
show
Coding Style Compatibility introduced by
The method redirect() 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...
1545
    }
1546
1547
    /**
1548
     * Do an immediate redirect to the specified url. Use this instead of using PHP's header()
1549
     * directly so that a core.redirect.start event is triggered. An example is debugbar, that
1550
     * stacks data so the details for both original and redirected scripts data are available.
1551
     *
1552
     * @param string $url URL to redirect to
1553
     *
1554
     * @return void
1555
     */
1556
    public static function simpleRedirect($url)
1557
    {
1558
        header("location: {$url}");
1559
        $xoops = \Xoops::getInstance();
1560
        $xoops->events()->triggerEvent('core.redirect.start', array($url));
1561
        exit;
0 ignored issues
show
Coding Style Compatibility introduced by
The method simpleRedirect() 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...
1562
    }
1563
1564
    /**
1565
     * Get Environment Value
1566
     *
1567
     * @param string $key key (name) in the environment
1568
     *
1569
     * @return string
1570
     */
1571 7
    public function getEnv($key)
1572
    {
1573 7
        return HttpRequest::getInstance()->getEnv($key, '');
1574
    }
1575
1576
    /**
1577
     * Function to get css file for a certain themeset
1578
     *
1579
     * @param string $theme theme name
1580
     *
1581
     * @return string
1582
     */
1583 5
    public function getCss($theme = '')
1584
    {
1585 5
        if ($theme == '') {
1586
            $theme = $this->getConfig('theme_set');
1587
        }
1588 5
        $userAgent = $this->getEnv('HTTP_USER_AGENT');
1589 5
        if (stristr($userAgent, 'mac')) {
1590
            $str_css = 'styleMAC.css';
1591 5
        } elseif (preg_match("/MSIE ([0-9]\.[0-9]{1,2})/i", $userAgent)) {
1592
            $str_css = 'style.css';
1593
        } else {
1594 5
            $str_css = 'styleNN.css';
1595
        }
1596 5
        $xoops_theme_path = \XoopsBaseConfig::get('themes-path');
1597 5
        $xoops_theme_url = \XoopsBaseConfig::get('themes-url');
1598 5 View Code Duplication
        if (is_dir($xoops_theme_path . '/' . $theme)) {
1599 5
            if (XoopsLoad::fileExists($xoops_theme_path . '/' . $theme . '/' . $str_css)) {
1600
                return $xoops_theme_url . '/' . $theme . '/' . $str_css;
1601 5
            } elseif (XoopsLoad::fileExists($xoops_theme_path . '/' . $theme . '/style.css')) {
1602
                return $xoops_theme_url . '/' . $theme . '/style.css';
1603
            }
1604
        }
1605 5 View Code Duplication
        if (is_dir($xoops_theme_path . '/' . $theme . '/css')) {
1606
            if (XoopsLoad::fileExists($xoops_theme_path . '/' . $theme . '/css/' . $str_css)) {
1607
                return $xoops_theme_url . '/' . $theme . '/css/' . $str_css;
1608
            } elseif (XoopsLoad::fileExists($xoops_theme_path . '/' . $theme . '/css/style.css')) {
1609
                return $xoops_theme_url . '/' . $theme . '/css/style.css';
1610
            }
1611
        }
1612 5 View Code Duplication
        if (is_dir($xoops_theme_path . '/' . $theme . '/assets/css')) {
1613 5
            if (XoopsLoad::fileExists($xoops_theme_path . '/' . $theme . '/assets/css/' . $str_css)) {
1614
                return $xoops_theme_url . '/' . $theme . '/assets/css/' . $str_css;
1615 5
            } elseif (XoopsLoad::fileExists($xoops_theme_path . '/' . $theme . '/assets/css/style.css')) {
1616 5
                return $xoops_theme_url . '/' . $theme . '/assets/css/style.css';
1617
            }
1618
        }
1619
        return '';
1620
    }
1621
1622
    /**
1623
     * Get Mailer
1624
     *
1625
     * @return XoopsMailer|XoopsMailerLocale
1626
     */
1627 1
    public function getMailer()
1628
    {
1629 1
        static $mailer;
1630 1
        if (is_object($mailer)) {
1631
            return $mailer;
1632
        }
1633 1
        \Xoops\Locale::loadMailerLocale();
1634 1
        if (class_exists('XoopsMailerLocale')) {
1635 1
            $mailer = new XoopsMailerLocale();
1636
        } else {
1637
            $mailer = new XoopsMailer();
1638
        }
1639 1
        return $mailer;
1640
    }
1641
1642
    /**
1643
     * Get Option
1644
     *
1645
     * @param string $key key (name) of option
1646
     *
1647
     * @return string
1648
     */
1649 4
    public function getOption($key)
1650
    {
1651 4
        $ret = '';
1652 4
        if (isset($this->option[$key])) {
1653 1
            $ret = $this->option[$key];
1654
        }
1655 4
        return $ret;
1656
    }
1657
1658
    /**
1659
     * Set Option
1660
     *
1661
     * @param string $key   key (name) of option
1662
     * @param null   $value value for option
1663
     *
1664
     * @return void
1665
     */
1666 1
    public function setOption($key, $value = null)
1667
    {
1668 1
        if (!is_null($value)) {
1669 1
            $this->option[$key] = $value;
1670
        }
1671 1
    }
1672
1673
    /**
1674
     * Get Config value
1675
     *
1676
     * @param string $key key (name) of configuration
1677
     *
1678
     * @return mixed
1679
     */
1680 62
    public function getConfig($key)
1681
    {
1682 62
        return $this->getModuleConfig($key, 'system');
1683
    }
1684
1685
    /**
1686
     * Get all Config Values
1687
     *
1688
     * @return array
1689
     */
1690 19
    public function getConfigs()
1691
    {
1692 19
        return $this->getModuleConfigs('system');
1693
    }
1694
1695
    /**
1696
     * Add Config Values
1697
     *
1698
     * @param array  $configs array of configs
1699
     * @param string $dirname module name
1700
     *
1701
     * @return void
1702
     */
1703 1 View Code Duplication
    public function addConfigs($configs, $dirname = 'system')
1704
    {
1705 1
        $dirname = trim(strtolower($dirname));
1706 1
        if (empty($dirname)) {
1707 1
            $dirname = $this->isModule() ? $this->module->getVar('dirname') : 'system';
1708
        }
1709 1
        if (!empty($dirname)) {
1710 1
            $this->moduleConfigs[$dirname] = array_merge($this->moduleConfigs[$dirname], (array)$configs);
1711
        }
1712 1
    }
1713
1714
    /**
1715
     * Set Config Value
1716
     *
1717
     * @param string $key     key (name) of the configuration item
1718
     * @param mixed  $value   configuration value
1719
     * @param string $dirname dirname of module
1720
     *
1721
     * @return void
1722
     */
1723 13 View Code Duplication
    public function setConfig($key, $value = null, $dirname = 'system')
1724
    {
1725 13
        if (!is_null($value)) {
1726 13
            $dirname = trim(strtolower($dirname));
1727 13
            if (empty($dirname)) {
1728
                $dirname = $this->isModule() ? $this->module->getVar('dirname') : 'system';
1729
            }
1730 13
            $this->moduleConfigs[$dirname][$key] =& $value;
1731
        }
1732 13
    }
1733
1734
    /**
1735
     * Unset Config Value
1736
     *
1737
     * @param string $key     key (name) of the configuration item
1738
     * @param string $dirname dirname of module
1739
     *
1740
     * @return void
1741
     */
1742 3
    public function unsetConfig($key, $dirname = 'system')
1743
    {
1744 3
        $dirname = trim(strtolower($dirname));
1745 3
        if (empty($dirname)) {
1746
            $dirname = $this->isModule() ? $this->module->getVar('dirname') : 'system';
1747
        }
1748 3
        unset($this->moduleConfigs[$dirname][$key]);
1749 3
        if (empty($this->moduleConfigs[$dirname])) {
1750 1
            unset($this->moduleConfigs[$dirname]);
1751
        }
1752 3
    }
1753
1754
    /**
1755
     * Unset all module configs
1756
     *
1757
     * @return void
1758
     */
1759
    public function clearModuleConfigsCache()
1760
    {
1761
        $this->moduleConfigs = array();
1762
    }
1763
1764
    /**
1765
     * getModuleConfig
1766
     *
1767
     * @param string $key     config name
1768
     * @param string $dirname module directory
1769
     *
1770
     * @return mixed the value for the named config
1771
     */
1772 64
    public function getModuleConfig($key, $dirname = '')
1773
    {
1774 64
        $dirname = trim(strtolower($dirname));
1775 64
        if (empty($dirname)) {
1776 1
            $dirname = $this->isModule() ? $this->module->getVar('dirname') : 'system';
1777
        }
1778
1779 64
        if (isset($this->moduleConfigs[$dirname][$key])) {
1780 61
            return $this->moduleConfigs[$dirname][$key];
1781
        }
1782
1783 5
        $this->getModuleConfigs($dirname);
1784
1785 5
        if (!isset($this->moduleConfigs[$dirname][$key])) {
1786 5
            $this->moduleConfigs[$dirname][$key] = '';
1787
        }
1788 5
        return $this->moduleConfigs[$dirname][$key];
1789
    }
1790
1791
    /**
1792
     * Get Module Configs
1793
     *
1794
     * @param string $dirname dirname of module
1795
     *
1796
     * @return array
1797
     */
1798 27
    public function getModuleConfigs($dirname = '')
1799
    {
1800 27
        $dirname = trim($dirname);
1801 27
        if (empty($dirname)) {
1802 2
            $dirname = $this->isModule() ? $this->module->getVar('dirname') : 'system';
1803
        }
1804 27
        if (isset($this->moduleConfigs[$dirname])) {
1805 26
            return $this->moduleConfigs[$dirname];
1806
        }
1807 1
        $this->moduleConfigs[$dirname] = array();
1808 1
        $key = "system/module/configs/{$dirname}";
1809 1
        if (!$configs = $this->cache()->read($key)) {
1810 1
            $module = $this->getModuleByDirname($dirname);
1811 1
            if (is_object($module)) {
1812
                $configs = $this->getHandlerConfig()->getConfigsByModule($module->getVar('mid'));
1813
                $this->cache()->write($key, $configs);
1814 1
                $this->moduleConfigs[$dirname] =& $configs;
1815
            }
1816
        } else {
1817
            $this->moduleConfigs[$dirname] =& $configs;
1818
        }
1819
1820 1
        if ($this->isModule()) {
1821
            //for legacy
1822 1
            $this->moduleConfig =& $this->moduleConfigs[$this->module->getVar('dirname')];
1823
        }
1824 1
        if ($dirname === 'system') {
1825
            $this->config =& $this->moduleConfigs['system'];
1826
        }
1827 1
        return $this->moduleConfigs[$dirname];
1828
    }
1829
1830
    /**
1831
     * Append Config Value
1832
     *
1833
     * @param string $key           key (name) of the configuration item
1834
     * @param array  $values        array of configuration value
1835
     * @param bool   $appendWithKey true to add each $value element with associative value
1836
     *                               false to add $values as a single index element
1837
     * @param string $dirname       dirname of module
1838
     *
1839
     * @return void
1840
     */
1841 3
    public function appendConfig($key, array $values, $appendWithKey = false, $dirname = 'system')
1842
    {
1843 3
        $dirname = trim(strtolower($dirname));
1844 3
        if (empty($dirname)) {
1845
            $dirname = $this->isModule() ? $this->module->getVar('dirname') : 'system';
1846
        }
1847 3
        if (!isset($this->moduleConfigs[$dirname][$key]) || !is_array($this->moduleConfigs[$dirname][$key])) {
1848 2
            $this->moduleConfigs[$dirname][$key] = array();
1849
        }
1850 3
        if ($appendWithKey) {
1851 3
            foreach ($values as $key2 => $value) {
1852 3
                $this->moduleConfigs[$dirname][$key][$key2] =& $value;
1853
            }
1854
        } else {
1855 1
            $this->moduleConfigs[$dirname][$key][] =& $values;
1856
        }
1857 3
    }
1858
1859
    /**
1860
     * Disables page cache by overriding module cache settings
1861
     *
1862
     * @return void
1863
     */
1864 1
    public function disableModuleCache()
1865
    {
1866 1
        if ($this->isModule()) {
1867 1
            $this->appendConfig('module_cache', array($this->module->getVar('mid') => 0), true);
1868
        }
1869 1
    }
1870
1871
    /**
1872
     * getBaseDomain
1873
     *
1874
     * Get domain name from a URL. This will check that the domain is valid for registering,
1875
     * preventing return of constructs like 'co.uk' as the domain. See https://publicsuffix.org/
1876
     *
1877
     * @param string  $url              URL
1878
     * @param boolean $includeSubdomain true to include include subdomains,
1879
     *                                  default is false registerable domain only
1880
     *
1881
     * @return string|null domain, or null if domain is invalid
1882
     */
1883 1
    public function getBaseDomain($url, $includeSubdomain = false)
1884
    {
1885 1
        $url=mb_strtolower($url, 'UTF-8');
1886
1887 1
        $host = parse_url($url, PHP_URL_HOST);
1888 1
        if (empty($host)) {
1889 1
            $host = parse_url($url, PHP_URL_PATH); // bare host name
1890 1
            if (empty($host)) {
1891
                return null;
1892
            }
1893
        }
1894
1895
        // check for exceptions, localhost and ip address (v4 & v6)
1896 1
        if ($host==='localhost') {
1897 1
            return $host;
1898
        }
1899
        // Check for IPV6 URL (see http://www.ietf.org/rfc/rfc2732.txt)
1900
        // strip brackets before validating
1901 1
        if (substr($host, 0, 1)==='[' && substr($host, -1)===']') {
1902 1
            $host = substr($host, 1, (strlen($host)-2));
1903
        }
1904 1
        if (filter_var($host, FILTER_VALIDATE_IP)) {
1905 1
            return $host;
1906
        }
1907
1908 1
        $regdom = new \Geekwright\RegDom\RegisteredDomain();
1909 1
        $regHost = $regdom->getRegisteredDomain($host);
1910 1
        if (null === $regHost) {
1911 1
            return null;
1912
        }
1913 1
        return $includeSubdomain ? $host : $regHost;
1914
    }
1915
1916
    /**
1917
     * function to update compiled template file in cache folder
1918
     *
1919
     * @param string $tpl_id template id
1920
     *
1921
     * @return boolean
1922
     */
1923 1
    public function templateTouch($tpl_id)
1924
    {
1925 1
        $tplfile = $this->getHandlerTplFile()->get($tpl_id);
1926
1927 1
        if (is_object($tplfile)) {
1928 1
            $file = $tplfile->getVar('tpl_file', 'n');
1929 1
            $module = $tplfile->getVar('tpl_module', 'n');
1930 1
            $type = $tplfile->getVar('tpl_type', 'n');
1931 1
            $tpl = new XoopsTpl();
1932 1
            return $tpl->touch($type . ':' . $module . '/' . $file);
1933
        }
1934
        return false;
1935
    }
1936
1937
    /**
1938
     * Clear the module cache
1939
     *
1940
     * @param int $mid Module ID
1941
     *
1942
     * @return void
1943
     */
1944
    public function templateClearModuleCache($mid)
1945
    {
1946
        $module = $this->getModuleById($mid);
1947
        $xoopsTpl = new XoopsTpl();
1948
        $xoopsTpl->clearModuleCompileCache($module->getVar('dirname'));
1949
    }
1950
1951
    /**
1952
     * Support for deprecated messages events
1953
     *
1954
     * @param string $message message
1955
     *
1956
     * @return void
1957
     */
1958 15
    public function deprecated($message)
1959
    {
1960 15
        $message = $this->logger()->sanitizePath($message);
1961 15
        $this->events()->triggerEvent('core.deprecated', array($message));
1962 15
    }
1963
1964
    /**
1965
     * Support for disabling error reporting
1966
     *
1967
     * @return void
1968
     */
1969 3
    public function disableErrorReporting()
1970
    {
1971
        //error_reporting(0);
1972 3
        $this->events()->triggerEvent('core.disableerrorreporting');
1973 3
    }
1974
}
1975