Completed
Push — master ( 29f185...9200bf )
by Michael
18s
created

Xoops::getModuleHelper()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1
Metric Value
dl 0
loc 4
rs 10
ccs 2
cts 2
cp 1
cc 1
eloc 2
nc 1
nop 1
crap 1
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 384
    public static function getInstance()
164
    {
165 384
        static $instance;
166 384
        if (!isset($instance)) {
167
            $class = __CLASS__;
168
            $instance = new $class();
169
        }
170 384
        return $instance;
171
    }
172
173
    /**
174
     * get database connection instance
175
     *
176
     * @return Xoops\Core\Database\Connection
177
     */
178 138
    public function db()
179
    {
180 138
        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 25
    public function cache($cacheName = 'default')
191
    {
192 25
        static $cacheManager;
193
194 25
        if (!isset($cacheManager)) {
195
            $cacheManager = new \Xoops\Core\Cache\CacheManager();
196
        }
197
198 25
        return $cacheManager->getCache($cacheName);
199
    }
200
201
    /**
202
     * get the system logger instance
203
     *
204
     * @return \Xoops\Core\Logger
205
     */
206 18
    public function logger()
207
    {
208 18
        return \Xoops\Core\Logger::getInstance();
209
    }
210
211
212
    /**
213
     * get the event processor
214
     *
215
     * @return \Xoops\Core\Events instance
216
     */
217 130
    public function events()
218
    {
219 130
        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 4
    public function security()
272
    {
273 4
        static $instance;
274 4
        if (!isset($instance)) {
275
            $instance = new \Xoops\Core\Security();
276
        }
277 4
        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 = 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...
322
                $xoopsThemeFactory = new \Xoops\Core\Theme\Factory();
323
                $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...
324
                $xoopsThemeFactory->defaultTheme = $this->getConfig('theme_set');
325
                $this->setTheme($xoopsThemeFactory->createInstance(array('contentTemplate' => $this->tpl_name)));
326
            } else {
327
                $adminThemeFactory = new \Xoops\Core\Theme\AdminFactory();
328
                $this->setTheme($adminThemeFactory->createInstance(array(
329
                    'folderName'      => 'default', 'themesPath' => 'modules/system/themes',
330
                    'contentTemplate' => $this->tpl_name
331
                )));
332
                //$this->theme()->loadLocalization('admin');
333
                list($cssAssets, $jsAssets) = $this->theme()->getLocalizationAssets('admin');
334
                if (!empty($cssAssets)) {
335
                    $this->theme()->addBaseStylesheetAssets($cssAssets);
336
                }
337
                if (!empty($jsAssets)) {
338
                    $this->theme()->addBaseScriptAssets($jsAssets);
339
                }
340
            }
341
        } else {
342 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...
343
                $tpl_info = $this->getTplInfo($tpl_name);
344
                $this->tpl_name = $tpl_info['tpl_name'];
345
                $this->theme->contentTemplate = $this->tpl_name;
346
            }
347
        }
348 6
        $GLOBALS['xoTheme'] = $this->theme;
349 6
        return $this->theme;
350
    }
351
352
    /**
353
     * set theme
354
     *
355
     * @param XoopsTheme $theme theme
356
     *
357
     * @return XoopsTheme
358
     */
359 4
    public function setTheme(XoopsTheme $theme)
360
    {
361 4
        return $this->theme = $theme;
362
    }
363
364
    /**
365
     * Convert a XOOPS path to a physical one
366
     *
367
     * @param string $url     url to derive path from
368
     * @param bool   $virtual virtual
369
     *
370
     * @return string
371
     */
372 31
    public function path($url, $virtual = false)
373
    {
374 31
        $url = $this->normalizePath($url);
375 31
        $rootPath = $this->normalizePath(\XoopsBaseConfig::get('root-path') . '/');
376 31
        if (0 === strpos($url, $rootPath)) {
377
            $url = substr($url, strlen($rootPath));
378
        }
379
        //$url = ltrim($url, '/');
380 31
        $parts = explode('/', $url, 2);
381 31
        $root = isset($parts[0]) ? $parts[0] : '';
382 31
        $path = isset($parts[1]) ? $parts[1] : '';
383 31
        if (!isset($this->paths[$root])) {
384 7
            list($root, $path) = array('www', $url);
385
        }
386 31
        if (!$virtual) { // Returns a physical path
387 29
            $path = $this->paths[$root][0] . '/' . $path;
388
            //$path = str_replace('/', DIRECTORY_SEPARATOR, $path);
389 29
            return $path;
390
        }
391 5
        return !isset($this->paths[$root][1]) ? '' : ($this->paths[$root][1] . '/' . $path);
392
    }
393
394
    /**
395
     * Convert path separators to unix style
396
     *
397
     * @param string $path path to normalize
398
     *
399
     * @return string normalized path
400
     */
401 31
    public function normalizePath($path)
402
    {
403 31
        return str_replace('\\', '/', $path);
404
    }
405
406
    /**
407
     * Convert a XOOPS path to an URL
408
     *
409
     * @param string $url path (or url)
410
     *
411
     * @return string
412
     */
413 5
    public function url($url)
414
    {
415 5
        return (false !== strpos($url, '://') ? $url : $this->path($url, true));
416
    }
417
418
    /**
419
     * Build an URL with the specified request params
420
     *
421
     * @param string $url    base url
422
     * @param array  $params parameters to add to the url
423
     *
424
     * @return string
425
     */
426 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...
427
    {
428 1
        if ($url === '.') {
429 1
            $url = $_SERVER['REQUEST_URI'];
430
        }
431 1
        $split = explode('?', $url);
432 1
        if (count($split) > 1) {
433 1
            list($url, $query) = $split;
434 1
            parse_str($query, $query);
435 1
            $params = array_merge($query, $params);
436
        }
437 1
        if (!empty($params)) {
438 1
            foreach ($params as $k => $v) {
439 1
                $params[$k] = $k . '=' . rawurlencode($v);
440
            }
441 1
            $url .= '?' . implode('&', $params);
442
        }
443 1
        return $url;
444
    }
445
446
    /**
447
     * Check if a path exists
448
     *
449
     * @param string $path       filesystem path
450
     * @param string $error_type error level i.e. Psr\Log\LogLevel
451
     *
452
     * @return string|false
453
     */
454 2
    public function pathExists($path, $error_type)
455
    {
456 2
        if (XoopsLoad::fileExists($path)) {
457 1
            return $path;
458
        } else {
459 1
            $this->logger()->log(
460 1
                LogLevel::WARNING,
461 1
                \XoopsLocale::E_FILE_NOT_FOUND,
462 1
                array($path, $error_type)
463
            );
464
465
            //trigger_error(XoopsLocale::E_FILE_NOT_FOUND, $error_type);
466 1
            return false;
467
        }
468
    }
469
470
    /**
471
     * Start gzipCompression output buffer
472
     *
473
     * @return void
474
     */
475 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...
476
    {
477
        /**
478
         * Disable gzip compression if PHP is run under CLI mode and needs refactored to work correctly
479
         */
480 1
        if (empty($_SERVER['SERVER_NAME']) || substr(PHP_SAPI, 0, 3) === 'cli') {
481 1
            $this->setConfig('gzip_compression', 0);
482
        }
483
484 1
        if ($this->getConfig('gzip_compression') == 1
485 1
            && extension_loaded('zlib')
486 1
            && !ini_get('zlib.output_compression')
487
        ) {
488
            if (@ini_get('zlib.output_compression_level') < 0) {
489
                ini_set('zlib.output_compression_level', 6);
490
            }
491
            ob_start('ob_gzhandler');
492
        }
493 1
    }
494
495
    /**
496
     * Translate a path
497
     *
498
     * @return void
499
     */
500 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...
501
    {
502
        /**
503
         * *#@+
504
         * Host abstraction layer
505
         */
506 1
        if (!isset($_SERVER['PATH_TRANSLATED']) && isset($_SERVER['SCRIPT_FILENAME'])) {
507 1
            $_SERVER['PATH_TRANSLATED'] = $_SERVER['SCRIPT_FILENAME']; // For Apache CGI
508
        } else {
509 1
            if (isset($_SERVER['PATH_TRANSLATED']) && !isset($_SERVER['SCRIPT_FILENAME'])) {
510 1
                $_SERVER['SCRIPT_FILENAME'] = $_SERVER['PATH_TRANSLATED']; // For IIS/2K now I think :-(
511
            }
512
        }
513
        /**
514
         * User Mulitbytes
515
         */
516 1 View Code Duplication
        if (empty($_SERVER['REQUEST_URI'])) { // Not defined by IIS
517
            // Under some configs, IIS makes SCRIPT_NAME point to php.exe :-(
518 1
            if (!($_SERVER['REQUEST_URI'] = @$_SERVER['PHP_SELF'])) {
519 1
                $_SERVER['REQUEST_URI'] = $_SERVER['SCRIPT_NAME'];
520
            }
521 1
            if (isset($_SERVER['QUERY_STRING'])) {
522 1
                $_SERVER['REQUEST_URI'] .= '?' . $_SERVER['QUERY_STRING'];
523
            }
524
        }
525 1
    }
526
527
    /**
528
     * Select Theme
529
     *
530
     * @return void
531
     */
532 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...
533
    {
534 1
        $xoopsThemeSelect = Request::getString('xoops_theme_select', '', 'POST');
535 1
        if (!empty($xoopsThemeSelect) && in_array($xoopsThemeSelect, $this->getConfig('theme_set_allowed'))) {
536 1
            $this->setConfig('theme_set', $xoopsThemeSelect);
537 1
            $_SESSION['xoopsUserTheme'] = $xoopsThemeSelect;
538
        } else {
539 1
            if (!empty($_SESSION['xoopsUserTheme'])
540 1
                && in_array($_SESSION['xoopsUserTheme'], $this->getConfig('theme_set_allowed'))
541
            ) {
542 1
                $this->setConfig('theme_set', $_SESSION['xoopsUserTheme']);
543
            }
544
        }
545 1
    }
546
547
    /**
548
     * Gets module, type and file from a tpl name
549
     *
550
     * @param string $tpl_name in form type:module/filename.tpl
551
     *
552
     * @return array|false associative array of 'tpl_name', 'type', 'module', 'file'
553
     *                     or false on error
554
     */
555 9
    public function getTplInfo($tpl_name)
556
    {
557 9
        $parts = array();
558 9
        $matched = preg_match('#(\w+):(\w+)/(.*)$#', $tpl_name, $parts);
559 9
        if ($matched) {
560 8
            $names = array('tpl_name', 'type', 'module', 'file');
561 8
            $ret = array();
562 8
            for ($i=0; $i<4; ++$i) {
563 8
                $ret[$names[$i]] = $parts[$i];
564
            }
565
        } else {
566
            // this should be eliminated
567 1
            $this->events()->triggerEvent('debug.log', "Sloppy template: " . $tpl_name);
568 1
            $ret = array();
569 1
            $ret['type'] = $this->isAdminSide ? 'admin' : 'module';
570 1
            $info = explode(':', $tpl_name);
571 1
            if (count($info) == 2) {
572 1
                $ret['type'] = $info[0];
573 1
                $tpl_name = str_replace($ret['type'] . ':', '', $tpl_name);
574
            }
575
576 1
            if ($ret['type'] === 'db') {
577
                //For legacy compatibility
578 1
                $ret['type'] = $this->isAdminSide ? 'admin' : 'module';
579
            }
580
581 1
            $info = explode('|', $tpl_name);
582 1
            if (count($info) == 2) {
583
                $ret['module'] = $info[0];
584
                $ret['file'] = $info[1];
585
            } else {
586 1
                $ret['module'] = 'system';
587 1
                $ret['file'] = $tpl_name;
588 1
                if ($this->isModule()) {
589
                    $ret['module'] = $this->module->getVar('dirname', 'n');
590
                }
591
            }
592 1
            $ret['tpl_name'] = $ret['type'] . ':' . $ret['module'] . '/' . $ret['file'];
593
        }
594
595 9
        return $ret;
596
    }
597
598
    /**
599
     * Render Header
600
     *
601
     * @param string|null $tpl_name template name
602
     *
603
     * @return null|boolean
604
     */
605
    public function header($tpl_name = null)
606
    {
607
        static $included = false;
608
        if ($included) {
609
            return false;
610
        }
611
        $included = true;
612
613
        $this->events()->triggerEvent('core.header.start');
614
615
        //For legacy
616
        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...
617
            $tpl_name = $this->option['template_main'];
618
            $this->deprecated(
619
                'XoopsOption \'template_main\' is deprecated, please use $xoops->header(\'templatename.tpl\') instead'
620
            );
621
        }
622
        $this->theme($tpl_name);
623
        $this->tpl()->assign('xoops', $this);
624
625
        if ($this->isAdminSide) {
626
            $this->events()->triggerEvent('system.class.gui.header');
627
            include_once $this->path('modules/system/themes/default/default.php');
628
            $gui = new XoopsGuiDefault();
629
            $gui->header();
630
        } else {
631
            $this->events()->triggerEvent('core.header.addmeta');
632
            // Temporary solution for start page redirection
633
            if (defined("XOOPS_STARTPAGE_REDIRECTED")) {
634
                $smarty = $repeat = null;
635
                $this->theme()->headContent(
636
                    null,
637
                    "<base href='" . \XoopsBaseConfig::get('url') . '/modules/'
638
                    . $this->getConfig('startpage') . "/' />",
639
                    $smarty,
640
                    $repeat
641
                );
642
            }
643
644
            // Sets cache time
645
            if ($this->isModule()) {
646
                $cache_times = $this->getConfig('module_cache');
647
                $this->theme()->contentCacheLifetime =
648
                    isset($cache_times[$this->module->getVar('mid')]) ? $cache_times[$this->module->getVar('mid')] : 0;
649
                // Tricky solution for setting cache time for homepage
650
            } else {
651
                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...
652
                    // $this->theme->contentCacheLifetime = 604800;
653
                }
654
            }
655
            $this->events()->triggerEvent('core.header.checkcache');
656
            if ($this->theme()->checkCache()) {
657
                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...
658
            }
659
        }
660
661
        if (!isset($this->tpl_name) && $this->isModule()) {
662
            ob_start();
663
        }
664
665
        $this->events()->triggerEvent('core.header.end');
666
        return true;
667
    }
668
669
    /**
670
     * Render Footer
671
     *
672
     * @return false|null
673
     */
674
    public function footer()
675
    {
676
        static $included = false;
677
        if ($included) {
678
            return false;
679
        }
680
        $included = true;
681
682
        $this->events()->triggerEvent('core.footer.start');
683
684
        if (!headers_sent()) {
685
            header('Content-Type:text/html; charset=' . XoopsLocale::getCharset());
686
            header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
687
            header('Cache-Control: private, no-cache');
688
            header('Pragma: no-cache');
689
        }
690
691
        if (isset($this->option['template_main'])
692
            && $this->option['template_main'] != $this->theme()->contentTemplate
693
        ) {
694
            trigger_error("xoopsOption[template_main] should be defined before including header.php", E_USER_WARNING);
695
            $this->theme()->contentTemplate = $this->tpl_name;
696
        }
697
        $this->theme()->render();
698
        $this->events()->triggerEvent('core.footer.end');
699
        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...
700
    }
701
702
    /**
703
     * Check if a module is set
704
     *
705
     * @return bool
706
     */
707 12
    public function isModule()
708
    {
709 12
        return $this->module instanceof XoopsModule ? true : false;
710
    }
711
712
    /**
713
     * Check if a user is set
714
     *
715
     * @return bool
716
     */
717 7
    public function isUser()
718
    {
719 7
        return $this->user instanceof XoopsUser ? true : false;
720
    }
721
722
    /**
723
     * Check if user is admin
724
     *
725
     * @return bool
726
     */
727 1
    public function isAdmin()
728
    {
729 1
        return $this->userIsAdmin;
730
    }
731
732
    /**
733
     * Get handler of Block
734
     *
735
     * @param boolean $optional true if failure to load handler should be considered a warning, not an error
736
     *
737
     * @return \Xoops\Core\Kernel\Handlers\XoopsBlockHandler
738
     */
739 4
    public function getHandlerBlock($optional = false)
740
    {
741 4
        return $this->getHandler('Block', $optional);
742
    }
743
744
    /**
745
     * Get handler of Block Module Link
746
     *
747
     * @param boolean $optional true if failure to load handler should be considered a warning, not an error
748
     *
749
     * @return \Xoops\Core\Kernel\Handlers\XoopsBlockModuleLinkHandler
750
     */
751 1
    public function getHandlerBlockModuleLink($optional = false)
752
    {
753 1
        return $this->getHandler('BlockModuleLink', $optional);
754
    }
755
756
    /**
757
     * Get handler of Config
758
     *
759
     * @param boolean $optional true if failure to load handler should be considered a warning, not an error
760
     *
761
     * @return \Xoops\Core\Kernel\Handlers\XoopsConfigHandler
762
     */
763 1
    public function getHandlerConfig($optional = false)
764
    {
765 1
        return $this->getHandler('Config', $optional);
766
    }
767
768
    /**
769
     * Get handler of Config  Item
770
     *
771
     * @param boolean $optional true if failure to load handler should be considered a warning, not an error
772
     *
773
     * @return \Xoops\Core\Kernel\Handlers\XoopsConfigItemHandler
774
     */
775 18
    public function getHandlerConfigItem($optional = false)
776
    {
777 18
        return $this->getHandler('ConfigItem', $optional);
778
    }
779
780
    /**
781
     * Get handler of Config Option
782
     *
783
     * @param boolean $optional true if failure to load handler should be considered a warning, not an error
784
     *
785
     * @return \Xoops\Core\Kernel\Handlers\XoopsConfigOptionHandler
786
     */
787 18
    public function getHandlerConfigOption($optional = false)
788
    {
789 18
        return $this->getHandler('ConfigOption', $optional);
790
    }
791
792
    /**
793
     * Get handler of Group
794
     *
795
     * @param boolean $optional true if failure to load handler should be considered a warning, not an error
796
     *
797
     * @return \Xoops\Core\Kernel\Handlers\XoopsGroupHandler
798
     */
799 2
    public function getHandlerGroup($optional = false)
800
    {
801 2
        return $this->getHandler('Group', $optional);
802
    }
803
804
    /**
805
     * Get handler of Group Permission
806
     *
807
     * @param boolean $optional true if failure to load handler should be considered a warning, not an error
808
     *
809
     * @return \Xoops\Core\Kernel\Handlers\XoopsGroupPermHandler
810
     */
811 4
    public function getHandlerGroupPermission($optional = false)
812
    {
813 4
        return $this->getHandler('GroupPerm', $optional);
814
    }
815
816
    /**
817
     * Get handler of Member
818
     *
819
     * @param boolean $optional true if failure to load handler should be considered a warning, not an error
820
     *
821
     * @return \Xoops\Core\Kernel\Handlers\XoopsMemberHandler
822
     */
823 15
    public function getHandlerMember($optional = false)
824
    {
825 15
        return $this->getHandler('Member', $optional);
826
    }
827
828
    /**
829
     * Get handler of Membership
830
     *
831
     * @param boolean $optional true if failure to load handler should be considered a warning, not an error
832
     *
833
     * @return \Xoops\Core\Kernel\Handlers\XoopsMembershipHandler
834
     */
835 2
    public function getHandlerMembership($optional = false)
836
    {
837 2
        return $this->getHandler('Membership', $optional);
838
    }
839
840
    /**
841
     * Get handler of Module
842
     *
843
     * @param boolean $optional true if failure to load handler should be considered a warning, not an error
844
     *
845
     * @return \Xoops\Core\Kernel\Handlers\XoopsModuleHandler
846
     */
847 10
    public function getHandlerModule($optional = false)
848
    {
849 10
        return $this->getHandler('Module', $optional);
850
    }
851
852
    /**
853
     * Get handler of Online
854
     *
855
     * @param boolean $optional true if failure to load handler should be considered a warning, not an error
856
     *
857
     * @return \Xoops\Core\Kernel\Handlers\XoopsOnlineHandler
858
     */
859 2
    public function getHandlerOnline($optional = false)
860
    {
861 2
        return $this->getHandler('Online', $optional);
862
    }
863
864
    /**
865
     * Get handler of Private Message
866
     *
867
     * @param boolean $optional true if failure to load handler should be considered a warning, not an error
868
     *
869
     * @return \Xoops\Core\Kernel\Handlers\XoopsPrivateMessageHandler
870
     */
871 1
    public function getHandlerPrivateMessage($optional = false)
872
    {
873 1
        return $this->getHandler('Privmessage', $optional);
874
    }
875
876
    /**
877
     * Get the session manager
878
     *
879
     * @return Xoops\Core\Session\Manager
880
     */
881 1
    public function session()
882
    {
883 1
        if ($this->sessionManager === null) {
884 1
            $this->sessionManager = new \Xoops\Core\Session\Manager();
885
        }
886 1
        return $this->sessionManager;
887
    }
888
889
    /**
890
     * Get handler of Template File
891
     *
892
     * @param boolean $optional true if failure to load handler should be considered a warning, not an error
893
     *
894
     * @return \Xoops\Core\Kernel\Handlers\XoopsTplFileHandler
895
     */
896 2
    public function getHandlerTplFile($optional = false)
897
    {
898 2
        return $this->getHandler('tplfile', $optional);
899
    }
900
901
    /**
902
     * Get handler of Template Set
903
     *
904
     * @param boolean $optional true if failure to load handler should be considered a warning, not an error
905
     *
906
     * @return \Xoops\Core\Kernel\Handlers\XoopsTplSetHandler
907
     */
908 1
    public function getHandlerTplSet($optional = false)
909
    {
910 1
        return $this->getHandler('Tplset', $optional);
911
    }
912
913
    /**
914
     * Get handler of User
915
     *
916
     * @param boolean $optional true if failure to load handler should be considered a warning, not an error
917
     *
918
     * @return \Xoops\Core\Kernel\Handlers\XoopsUserHandler
919
     */
920 2
    public function getHandlerUser($optional = false)
921
    {
922 2
        return $this->getHandler('user', $optional);
923
    }
924
925
    /**
926
     * Get handler
927
     *
928
     * @param string  $name     name of handler
929
     * @param boolean $optional true if failure to load handler should be considered a warning, not an error
930
     *
931
     * @return XoopsObjectHandler|XoopsPersistableObjectHandler|null
932
     */
933 59
    protected function getHandler($name, $optional = false)
934
    {
935 59
        if (!isset($this->kernelHandlers[$name])) {
936 6
            if (!isset($this->handlerFactory)) {
937
                $this->handlerFactory = HandlerFactory::getInstance();
938
            }
939 6
            $handler = $this->handlerFactory->newSpec()->scheme('kernel')->name($name)->optional($optional)->build();
940 6
            if ($handler === null) {
941
                $this->logger()->log(
942
                    \Psr\Log\LogLevel::WARNING,
943
                    sprintf('A handler for %s is not available', $name)
944
                );
945
            }
946 6
            $this->kernelHandlers[$name] = $handler;
947
        }
948
949 59
        return $this->kernelHandlers[$name];
950
    }
951
952
    /**
953
     * Get Module Handler
954
     *
955
     * @param string|null $name       name of handler
956
     * @param string|null $module_dir dirname of module
957
     * @param boolean     $optional   true if failure to load handler should be considered a warning, not an error
958
     *
959
     * @return XoopsObjectHandler|XoopsPersistableObjectHandler|bool
960
     */
961 2
    public function getModuleHandler($name = null, $module_dir = null, $optional = false)
962
    {
963
        // if $module_dir is not specified
964 2
        if (!isset($module_dir)) {
965
            // if a module is loaded
966
            if ($this->module instanceof XoopsModule) {
967
                $module_dir = $this->module->getVar('dirname', 'n');
968
            } else {
969
                trigger_error('No Module is loaded', E_USER_ERROR);
970
            }
971
        } else {
972 2
            $module_dir = trim($module_dir);
973
        }
974 2
        $name = (!isset($name)) ? $module_dir : trim($name);
975 2
        if (!isset($this->moduleHandlers[$module_dir][$name])) {
976 2
            if (!isset($this->handlerFactory)) {
977
                $this->handlerFactory = HandlerFactory::getInstance();
978
            }
979 2
            $handler = $this->handlerFactory->create($name, $module_dir, $optional);
980 2
            if ($handler === null) {
981
                $this->logger()->log(
982
                    LogLevel::WARNING,
983
                    sprintf('No handler for %s exists in module %s', $name, $module_dir)
984
                );
985
            }
986 2
            $this->moduleHandlers[$module_dir][$name] = $handler;
987
        }
988 2
        return $this->moduleHandlers[$module_dir][$name];
989
    }
990
991
    /**
992
     * Get Module Form
993
     *
994
     * @param XoopsObject $obj        object to populate form
995
     * @param string      $name       name of form
996
     * @param string      $module_dir dirname of associated module
997
     *
998
     * @return Xoops\Form\Form|bool
999
     */
1000 1
    public function getModuleForm($obj, $name, $module_dir = null)
1001
    {
1002 1
        if (empty($name)) {
1003 1
            return false;
1004
        }
1005
        if (empty($module_dir)) {
1006
            if ($this->isModule()) {
1007
                $module_dir = $this->module->getVar('dirname', 'n');
1008
            } else {
1009
                return false;
1010
            }
1011
        }
1012
        if (XoopsLoad::fileExists(
1013
            $hnd_file = \XoopsBaseConfig::get('root-path') . "/modules/{$module_dir}/class/form/{$name}.php"
1014
        )) {
1015
            include_once $hnd_file;
1016
            $class = ucfirst(strtolower($module_dir)) . ucfirst($name) . 'Form';
1017
            if (class_exists($class)) {
1018
                $instance = new $class($obj);
1019
                if ($instance instanceof \Xoops\Form\Form) {
1020
                    return $instance;
1021
                }
1022
            }
1023
        }
1024
        return false;
1025
    }
1026
1027
    /**
1028
     * Get Module Helper
1029
     *
1030
     * @param string $dirname dirname of module
1031
     *
1032
     * @return bool|Xoops\Module\Helper\HelperAbstract
1033
     */
1034 1
    public static function getModuleHelper($dirname)
1035
    {
1036 1
        return \Xoops\Module\Helper::getHelper($dirname);
1037
    }
1038
1039
    /**
1040
     * XOOPS language loader wrapper
1041
     * Temporary solution, not encouraged to use
1042
     *
1043
     * @param string $name     Name of language file to be loaded, without extension
1044
     * @param mixed  $domain   string: Module dirname; global language file will be loaded if
1045
     *                           $domain is set to 'global' or not specified
1046
     *                          array:  example; array('Frameworks/moduleclasses/moduleadmin')
1047
     * @param string $language Language to be loaded, current language content will be loaded if not specified
1048
     *
1049
     * @return  boolean
1050
     */
1051 7
    public function loadLanguage($name, $domain = '', $language = null)
1052
    {
1053 7
        if (empty($name)) {
1054 1
            return false;
1055
        }
1056
1057 7
        $language = empty($language) ? XoopsLocale::getLegacyLanguage() : $language;
1058
        // expanded domain to multiple categories, e.g. module:Fsystem, framework:filter, etc.
1059 7 View Code Duplication
        if ((empty($domain) || 'global' === $domain)) {
1060 1
            $path = '';
1061
        } else {
1062 6
            $path = (is_array($domain)) ? array_shift($domain) . '/' : "modules/{$domain}/";
1063
        }
1064 7
        $path .= 'language';
1065
1066 7
        if (!XoopsLoad::fileExists($file = $this->path("{$path}/{$language}/{$name}.php"))) {
1067 6
            if (!XoopsLoad::fileExists($file = $this->path("{$path}/english/{$name}.php"))) {
1068 6
                return false;
1069
            }
1070
        }
1071 1
        $ret = include_once $file;
1072 1
        return $ret;
1073
    }
1074
1075
    /**
1076
     * loadLocale
1077
     *
1078
     * @param string $domain Module dirname; global language file will be loaded if set to 'global' or not specified
1079
     * @param string $locale Locale to be loaded, current language content will be loaded if not specified
1080
     *
1081
     * @return  boolean
1082
     */
1083 4
    public static function loadLocale($domain = null, $locale = null)
1084
    {
1085 4
        return \Xoops\Locale::loadLocale($domain, $locale);
1086
    }
1087
1088
    /**
1089
     * Translate a key value
1090
     *
1091
     * @param string $key     constant name
1092
     * @param string $dirname dirname of module (domain)
1093
     *
1094
     * @return string
1095
     */
1096 1
    public function translate($key, $dirname = 'xoops')
1097
    {
1098 1
        return \Xoops\Locale::translate($key, $dirname);
1099
    }
1100
1101
    /**
1102
     * Get active modules from cache file
1103
     *
1104
     * @return array
1105
     */
1106 9
    public function getActiveModules()
1107
    {
1108 9
        if (is_array($this->activeModules)) {
1109 9
            return $this->activeModules;
1110
        }
1111
1112
        try {
1113
            if (!$this->activeModules = $this->cache()->read('system/modules/active')) {
1114
                $this->setActiveModules();
1115
            }
1116
        } catch (\Exception $e) {
1117
            $this->activeModules = array();
1118
        }
1119
        return $this->activeModules;
1120
    }
1121
1122
    /**
1123
     * Write active modules to cache file
1124
     *
1125
     * @return array
1126
     */
1127 1
    public function setActiveModules()
1128
    {
1129 1
        $module_handler = $this->getHandlerModule();
1130 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...
1131 1
        $modules_active = array();
1132 1
        foreach ($modules_array as $module) {
1133 1
            $modules_active[$module['mid']] = $module['dirname'];
1134
        }
1135 1
        $this->cache()->write('system/modules/active', $modules_active);
1136 1
        $this->activeModules = $modules_active;
1137 1
        return $modules_active;
1138
    }
1139
1140
    /**
1141
     * Checks is module is installed and active
1142
     *
1143
     * @param string $dirname module directory
1144
     *
1145
     * @return bool
1146
     */
1147 7
    public function isActiveModule($dirname)
1148
    {
1149 7
        if (isset($dirname) && in_array($dirname, $this->getActiveModules())) {
1150 2
            return true;
1151
        }
1152 6
        return false;
1153
    }
1154
1155
    /**
1156
     * get module object from module name (dirname)
1157
     *
1158
     * @param string $dirname dirname of the module
1159
     *
1160
     * @return bool|XoopsModule
1161
     */
1162 4 View Code Duplication
    public function getModuleByDirname($dirname)
1163
    {
1164 4
        $key = "system/module/dirname/{$dirname}";
1165 4
        if (!$module = $this->cache()->read($key)) {
1166 4
            $module = $this->getHandlerModule()->getByDirname($dirname);
1167 4
            $this->cache()->write($key, $module);
1168
        }
1169 4
        return $module;
1170
    }
1171
1172
    /**
1173
     * Get Module By Id
1174
     *
1175
     * @param int $id Id of the module
1176
     *
1177
     * @return bool|XoopsModule
1178
     */
1179 1 View Code Duplication
    public function getModuleById($id)
1180
    {
1181 1
        $key = "system/module/id/{$id}";
1182 1
        if (!$module = $this->cache()->read($key)) {
1183 1
            $module = $this->getHandlerModule()->getById($id);
1184 1
            $this->cache()->write($key, $module);
1185
        }
1186 1
        return $module;
1187
    }
1188
1189
    /**
1190
     * Render Simple Header
1191
     *
1192
     * @param bool $closehead true to close the HTML head element
1193
     *
1194
     * @return void
1195
     */
1196 1
    public function simpleHeader($closehead = true)
1197
    {
1198 1
        $this->events()->triggerEvent('core.header.start');
1199 1
        $this->theme();
1200 1
        $xoopsConfigMetaFooter = $this->getConfigs();
1201
1202 1
        if (!headers_sent()) {
1203
            header('Content-Type:text/html; charset=' . XoopsLocale::getCharset());
1204
            header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
1205
            header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
1206
            header(
1207
                'Cache-Control: no-store, no-cache, max-age=1, s-maxage=1, must-revalidate, post-check=0, pre-check=0'
1208
            );
1209
            header("Pragma: no-cache");
1210
        }
1211
1212 1
        echo "<!DOCTYPE html>\n";
1213 1
        $xoops_url = \XoopsBaseConfig::get('url');
1214 1
        echo '<html lang="' . XoopsLocale::getLangCode() . '">
1215
              <head>
1216
              <meta charset="utf-8">
1217
              <meta http-equiv="X-UA-Compatible" content="IE=edge">
1218
              <meta name="viewport" content="width=device-width, initial-scale=1">
1219 1
              <meta name="robots" content="' . htmlspecialchars($xoopsConfigMetaFooter['meta_robots']) . '" />
1220 1
              <meta name="keywords" content="' . htmlspecialchars($xoopsConfigMetaFooter['meta_keywords']) . '" />
1221 1
              <meta name="description" content="' . htmlspecialchars($xoopsConfigMetaFooter['meta_description']) . '" />
1222 1
              <meta name="rating" content="' . htmlspecialchars($xoopsConfigMetaFooter['meta_rating']) . '" />
1223 1
              <meta name="author" content="' . htmlspecialchars($xoopsConfigMetaFooter['meta_author']) . '" />
1224
              <meta name="generator" content="XOOPS" />
1225 1
              <title>' . htmlspecialchars($this->getConfig('sitename')) . '</title>'
1226 1
            . $this->theme->renderBaseAssets();
1227
1228 1
        $locale = $this->getConfig('locale');
1229 1
        if (XoopsLoad::fileExists($this->path('locale/' . $locale . '/style.css'))) {
1230
            echo '<link rel="stylesheet" type="text/css" media="all" href="' . $xoops_url
1231
                . '/locale/' . $locale . '/style.css" />';
1232
        }
1233 1
        if ($themecss) {
1234
            echo '<link rel="stylesheet" type="text/css" media="all" href="' . $themecss . '" />';
0 ignored issues
show
Bug introduced by
The variable $themecss does not exist. Did you forget to declare it?

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

Loading history...
1235
            echo '<link rel="stylesheet" type="text/css" media="screen" href="' .
1236
                $this->url('themes/' . $this->getConfig('theme_set') . '/media/bootstrap/css/xoops.bootstrap.css')
1237
                .'" />';
1238
        }
1239 1
        if ($closehead) {
1240 1
            echo '</head><body>';
1241
        }
1242 1
    }
1243
1244
    /**
1245
     * Render simpleFooter
1246
     *
1247
     * @return void
1248
     */
1249 2
    public function simpleFooter()
1250
    {
1251 2
        $this->events()->triggerEvent('core.header.footer');
1252 2
        echo '</body></html>';
1253 2
        ob_end_flush();
1254 2
    }
1255
    /**
1256
     * render an alert message to a string
1257
     *
1258
     * @param string $type  alert type, one of 'info', 'error', 'success' or 'warning'
1259
     * @param mixed  $msg   string or array of strings
1260
     * @param string $title title for alert
1261
     *
1262
     * @return string
1263
     */
1264 1
    public function alert($type, $msg, $title = '/')
1265
    {
1266 1
        $tpl = new XoopsTpl();
1267
        switch ($type) {
1268 1
            case 'info':
1269
            default:
1270 1
                $tpl->assign('alert_type', 'alert-info');
1271 1
                if ($title === '/') {
1272 1
                    $title = XoopsLocale::INFORMATION;
1273
                }
1274 1
                break;
1275
1276 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...
1277 1
                $tpl->assign('alert_type', 'alert-danger');
1278 1
                if ($title === '/') {
1279 1
                    $title = XoopsLocale::ERROR;
1280
                }
1281 1
                break;
1282
1283 1
            case 'success':
1284 1
                $tpl->assign('alert_type', 'alert-success');
1285 1
                if ($title === '/') {
1286 1
                    $title = XoopsLocale::SUCCESS;
1287
                }
1288 1
                break;
1289
1290 1
            case 'warning':
1291 1
                $tpl->assign('alert_type', 'alert-warning');
1292 1
                if ($title === '/') {
1293 1
                    $title = XoopsLocale::WARNING;
1294
                }
1295 1
                break;
1296
        }
1297
1298 1
        if ($title != '') {
1299 1
            $tpl->assign('alert_title', $title);
1300
        }
1301 1
        if (!is_scalar($msg) && !is_array($msg)) {
1302 1
            $msg = ''; // don't know what to do with this, so make it blank
1303
        }
1304 1
        $alert_msg = (is_array($msg)) ? @implode("<br />", $msg) : $msg;
1305
1306 1
        if (empty($alert_msg)) {
1307 1
            return '';
1308
        }
1309 1
        $tpl->assign('alert_msg', $alert_msg);
1310 1
        $ret = $tpl->fetch('module:system/system_alert.tpl');
1311 1
        return $ret;
1312
1313
    }
1314
1315
    /**
1316
     * Render a confirmation form to a string
1317
     *
1318
     * @param array   $hiddens  associative array of values used to complete confirmed action
1319
     * @param string  $action   form action (URL)
1320
     * @param string  $msg      message to display
1321
     * @param string  $submit   submit button message
1322
     * @param boolean $addtoken true to add CSRF token
1323
     *
1324
     * @return string rendered confirm message
1325
     */
1326 1
    public function confirm($hiddens, $action, $msg, $submit = '', $addtoken = true)
1327
    {
1328 1
        $tpl = new XoopsTpl();
1329 1
        $submit = ($submit != '') ? trim($submit) : XoopsLocale::A_SUBMIT;
1330 1
        $tpl->assign('msg', $msg);
1331 1
        $tpl->assign('action', $action);
1332 1
        $tpl->assign('submit', $submit);
1333 1
        $str_hiddens = '';
1334 1
        foreach ($hiddens as $name => $value) {
1335 1
            if (is_array($value)) {
1336 1
                foreach ($value as $caption => $newvalue) {
1337 1
                    $str_hiddens .= '<input type="radio" name="' . $name . '" value="'
1338 1
                        . htmlspecialchars($newvalue) . '" > ' . $caption . NWLINE;
1339
                }
1340 1
                $str_hiddens .= '<br />' . NWLINE;
1341
            } else {
1342 1
                $str_hiddens .= '<input type="hidden" name="' . $name . '" value="'
1343 1
                    . htmlspecialchars($value) . '" />' . NWLINE;
1344
            }
1345
        }
1346 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...
1347 1
            $tpl->assign('token', $this->security()->getTokenHTML());
1348
        }
1349 1
        $tpl->assign('hiddens', $str_hiddens);
1350 1
        return $tpl->fetch('module:system/system_confirm.tpl');
1351
    }
1352
1353
    /**
1354
     * Get User Timestamp (kind of pointless, since timestamps are UTC?)
1355
     *
1356
     * @param \DateTime|int $time DateTime object or unix timestamp
1357
     *
1358
     * @return int unix timestamp
1359
     */
1360 1
    public function getUserTimestamp($time)
1361
    {
1362 1
        $dt = \Xoops\Core\Locale\Time::cleanTime($time);
1363 1
        return $dt->getTimestamp();
1364
    }
1365
1366
    /**
1367
     * Function to calculate server timestamp from user entered time (timestamp)
1368
     *
1369
     * @param int  $timestamp time stamp
1370
     * @param null $userTZ    timezone
1371
     *
1372
     * @return int
1373
     */
1374 1
    public function userTimeToServerTime($timestamp, $userTZ = null)
1375
    {
1376 1
        if (!isset($userTZ)) {
1377 1
            $userTZ = $this->getConfig('default_TZ');
1378
        }
1379 1
        $timestamp = $timestamp - (($userTZ - $this->getConfig('server_TZ')) * 3600);
1380 1
        return (int)$timestamp;
1381
    }
1382
1383
    /**
1384
     * get the groups associated with the current user
1385
     *
1386
     * @return int[]
1387
     */
1388 3
    public function getUserGroups()
1389
    {
1390 3
        $groups = $this->isUser() ? $this->user->getGroups() : array(FixedGroups::ANONYMOUS);
1391
1392 3
        return $groups;
1393
    }
1394
1395
    /**
1396
     * generate a temporary password
1397
     *
1398
     * @return string
1399
     *
1400
     * @todo make better passwords
1401
     */
1402 1
    public function makePass()
1403
    {
1404 1
        $makepass = '';
1405
        $syllables = array(
1406 1
            'er', 'in', 'tia', 'wol', 'fe', 'pre', 'vet', 'jo', 'nes', 'al', 'len', 'son', 'cha', 'ir', 'ler', 'bo',
1407
            'ok', 'tio', 'nar', 'sim', 'ple', 'bla', 'ten', 'toe', 'cho', 'co', 'lat', 'spe', 'ak', 'er', 'po', 'co',
1408
            'lor', 'pen', 'cil', 'li', 'ght', 'wh', 'at', 'the', 'he', 'ck', 'is', 'mam', 'bo', 'no', 'fi', 've', 'any',
1409
            'way', 'pol', 'iti', 'cs', 'ra', 'dio', 'sou', 'rce', 'sea', 'rch', 'pa', 'per', 'com', 'bo', 'sp', 'eak',
1410
            'st', 'fi', 'rst', 'gr', 'oup', 'boy', 'ea', 'gle', 'tr', 'ail', 'bi', 'ble', 'brb', 'pri', 'dee', 'kay',
1411
            'en', 'be', 'se'
1412
        );
1413 1
        for ($count = 1; $count <= 4; ++$count) {
1414 1
            if (1 == mt_rand() % 10) {
1415 1
                $makepass .= sprintf('%0.0f', (rand() % 50) + 1);
1416
            } else {
1417 1
                $makepass .= sprintf('%s', $syllables[rand() % 62]);
1418
            }
1419
        }
1420 1
        return $makepass;
1421
    }
1422
1423
    /**
1424
     * Check Email
1425
     *
1426
     * @param string $email    check email
1427
     * @param bool   $antispam true if returned email should be have anti-SPAM measures applied
1428
     *
1429
     * @return false|string email address if valid, otherwise false
1430
     */
1431 2
    public function checkEmail($email, $antispam = false)
1432
    {
1433 2
        if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
1434 1
            return false;
1435
        }
1436 2
        if ($antispam) {
1437 1
            $email = str_replace("@", " at ", $email);
1438 1
            $email = str_replace(".", " dot ", $email);
1439
        }
1440 2
        return $email;
1441
    }
1442
1443
    /**
1444
     * formatURL - add default http:// if no valid protocol specified
1445
     *
1446
     * @param string $url full or partial url
1447
     *
1448
     * @return string
1449
     */
1450 1
    public function formatURL($url)
1451
    {
1452 1
        $url = trim($url);
1453 1
        if ($url != '') {
1454 1
            if (!preg_match('/^(https?|ftps?|ed2k)\:\/\//i', $url)) {
1455 1
                $url = 'http://' . $url;
1456
            }
1457
        }
1458 1
        return $url;
1459
    }
1460
1461
    /**
1462
     * Function to get banner html tags for use in templates
1463
     *
1464
     * @return string
1465
     */
1466 3
    public function getBanner()
1467
    {
1468 3
        $options = '';
1469 3
        $this->events()->triggerEvent('core.banner.display', array(&$options));
1470 3
        return $options;
1471
    }
1472
1473
    /**
1474
     * Function to redirect a user to certain pages
1475
     *
1476
     * @param string $url               URL to redirect to
1477
     * @param int    $time              time to wait (to allow reading message display)
1478
     * @param string $message           message to display
1479
     * @param bool   $addredirect       add xoops_redirect parameter with current URL to the redirect
1480
     *                                   URL -  used for return from login redirect
1481
     * @param bool   $allowExternalLink allow redirect to external URL
1482
     *
1483
     * @return void
1484
     */
1485
    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...
1486
    {
1487
        $this->events()->triggerEvent('core.redirect.start', array(
1488
            $url, $time, $message, $addredirect, $allowExternalLink
1489
        ));
1490
        // if conditions are right, system preloads will exit on this call
1491
        // so don't use it if you want to be called, use start version above.
1492
        $this->events()->triggerEvent('core.include.functions.redirectheader', array(
1493
            $url, $time, $message, $addredirect, $allowExternalLink
1494
        ));
1495
1496
        $xoops_url = \XoopsBaseConfig::get('url');
1497
1498
        if (preg_match("/[\\0-\\31]|about:|script:/i", $url)) {
1499
            if (!preg_match('/^\b(java)?script:([\s]*)history\.go\(-[0-9]*\)([\s]*[;]*[\s]*)$/si', $url)) {
1500
                $url = $xoops_url;
1501
            }
1502
        }
1503 View Code Duplication
        if (!$allowExternalLink && $pos = strpos($url, '://')) {
1504
            $xoopsLocation = substr($xoops_url, strpos($xoops_url, '://') + 3);
1505
            if (strcasecmp(substr($url, $pos + 3, strlen($xoopsLocation)), $xoopsLocation)) {
1506
                $url = $xoops_url;
1507
            }
1508
        }
1509
        if (!defined('XOOPS_CPFUNC_LOADED')) {
1510
            $theme = 'default';
1511
        } else {
1512
            $theme = $this->getConfig('theme_set');
1513
        }
1514
1515
        $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...
1516
        $xoopsThemeFactory = new \Xoops\Core\Theme\Factory();
1517
        $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...
1518
        $xoopsThemeFactory->defaultTheme = $theme;
1519
        $this->setTheme($xoopsThemeFactory->createInstance(array(
1520
            "plugins" => array(), "renderBanner" => false
1521
        )));
1522
        $this->setTpl($this->theme()->template);
1523
        $this->tpl()->assign(array(
1524
            'xoops_theme'      => $theme, 'xoops_imageurl' => \XoopsBaseConfig::get('themes-url') . '/' . $theme . '/',
1525
            'xoops_themecss'   => $this->getCss($theme),
1526
            'xoops_requesturi' => htmlspecialchars($_SERVER['REQUEST_URI'], ENT_QUOTES),
1527
            'xoops_sitename'   => htmlspecialchars($this->getConfig('sitename'), ENT_QUOTES),
1528
            'xoops_slogan'     => htmlspecialchars($this->getConfig('slogan'), ENT_QUOTES),
1529
            'xoops_dirname'    => $this->isModule() ? $this->module->getVar('dirname') : 'system',
1530
            'xoops_pagetitle'  => $this->isModule() ? $this->module->getVar('name')
1531
                : htmlspecialchars($this->getConfig('slogan'), ENT_QUOTES)
1532
        ));
1533
1534
        $this->tpl()->assign('time', (int)($time));
1535
        if (!empty($_SERVER['REQUEST_URI']) && $addredirect && strstr($url, 'user.php')) {
1536
            $joiner = (false===strpos($url, '?')) ? '?' : '&amp;';
1537
            $url .= $joiner . 'xoops_redirect=' . urlencode($_SERVER['REQUEST_URI']);
1538
        }
1539
        $url = preg_replace("/&amp;/i", '&', htmlspecialchars($url, ENT_QUOTES));
1540
        $this->tpl()->assign('url', $url);
1541
        $message = trim($message) != '' ? $message : XoopsLocale::E_TAKING_YOU_BACK;
1542
        $this->tpl()->assign('message', $message);
1543
        $this->tpl()->assign('lang_ifnotreload', sprintf(XoopsLocale::F_IF_PAGE_NOT_RELOAD_CLICK_HERE, $url));
1544
1545
        $this->events()->triggerEvent('core.include.functions.redirectheader.end');
1546
        $this->tpl()->display('module:system/system_redirect.tpl');
1547
        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...
1548
    }
1549
1550
    /**
1551
     * Do an immediate redirect to the specified url. Use this instead of using PHP's header()
1552
     * directly so that a core.redirect.start event is triggered. An example is debugbar, that
1553
     * stacks data so the details for both original and redirected scripts data are available.
1554
     *
1555
     * @param string $url URL to redirect to
1556
     *
1557
     * @return void
1558
     */
1559
    public static function simpleRedirect($url)
1560
    {
1561
        header("location: {$url}");
1562
        $xoops = \Xoops::getInstance();
1563
        $xoops->events()->triggerEvent('core.redirect.start', array($url));
1564
        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...
1565
    }
1566
1567
    /**
1568
     * Get Environment Value
1569
     *
1570
     * @param string $key key (name) in the environment
1571
     *
1572
     * @return string
1573
     */
1574 6
    public function getEnv($key)
1575
    {
1576 6
        return HttpRequest::getInstance()->getEnv($key, '');
1577
    }
1578
1579
    /**
1580
     * Function to get css file for a certain themeset
1581
     *
1582
     * @param string $theme theme name
1583
     *
1584
     * @return string
1585
     */
1586 4
    public function getCss($theme = '')
1587
    {
1588 4
        if ($theme == '') {
1589
            $theme = $this->getConfig('theme_set');
1590
        }
1591 4
        $userAgent = $this->getEnv('HTTP_USER_AGENT');
1592 4
        if (stristr($userAgent, 'mac')) {
1593
            $str_css = 'styleMAC.css';
1594 4
        } elseif (preg_match("/MSIE ([0-9]\.[0-9]{1,2})/i", $userAgent)) {
1595
            $str_css = 'style.css';
1596
        } else {
1597 4
            $str_css = 'styleNN.css';
1598
        }
1599 4
        $xoops_theme_path = \XoopsBaseConfig::get('themes-path');
1600 4
        $xoops_theme_url = \XoopsBaseConfig::get('themes-url');
1601 4 View Code Duplication
        if (is_dir($xoops_theme_path . '/' . $theme)) {
1602 4
            if (XoopsLoad::fileExists($xoops_theme_path . '/' . $theme . '/' . $str_css)) {
1603
                return $xoops_theme_url . '/' . $theme . '/' . $str_css;
1604 4
            } elseif (XoopsLoad::fileExists($xoops_theme_path . '/' . $theme . '/style.css')) {
1605
                return $xoops_theme_url . '/' . $theme . '/style.css';
1606
            }
1607
        }
1608 4 View Code Duplication
        if (is_dir($xoops_theme_path . '/' . $theme . '/css')) {
1609
            if (XoopsLoad::fileExists($xoops_theme_path . '/' . $theme . '/css/' . $str_css)) {
1610
                return $xoops_theme_url . '/' . $theme . '/css/' . $str_css;
1611
            } elseif (XoopsLoad::fileExists($xoops_theme_path . '/' . $theme . '/css/style.css')) {
1612
                return $xoops_theme_url . '/' . $theme . '/css/style.css';
1613
            }
1614
        }
1615 4 View Code Duplication
        if (is_dir($xoops_theme_path . '/' . $theme . '/assets/css')) {
1616 4
            if (XoopsLoad::fileExists($xoops_theme_path . '/' . $theme . '/assets/css/' . $str_css)) {
1617
                return $xoops_theme_url . '/' . $theme . '/assets/css/' . $str_css;
1618 4
            } elseif (XoopsLoad::fileExists($xoops_theme_path . '/' . $theme . '/assets/css/style.css')) {
1619 4
                return $xoops_theme_url . '/' . $theme . '/assets/css/style.css';
1620
            }
1621
        }
1622
        return '';
1623
    }
1624
1625
    /**
1626
     * Get Mailer
1627
     *
1628
     * @return XoopsMailer|XoopsMailerLocale
1629
     */
1630 1
    public function getMailer()
1631
    {
1632 1
        static $mailer;
1633 1
        if (is_object($mailer)) {
1634
            return $mailer;
1635
        }
1636 1
        \Xoops\Locale::loadMailerLocale();
1637 1
        if (class_exists('XoopsMailerLocale')) {
1638 1
            $mailer = new XoopsMailerLocale();
1639
        } else {
1640
            $mailer = new XoopsMailer();
1641
        }
1642 1
        return $mailer;
1643
    }
1644
1645
    /**
1646
     * Get Option
1647
     *
1648
     * @param string $key key (name) of option
1649
     *
1650
     * @return string
1651
     */
1652 4
    public function getOption($key)
1653
    {
1654 4
        $ret = '';
1655 4
        if (isset($this->option[$key])) {
1656 1
            $ret = $this->option[$key];
1657
        }
1658 4
        return $ret;
1659
    }
1660
1661
    /**
1662
     * Set Option
1663
     *
1664
     * @param string $key   key (name) of option
1665
     * @param null   $value value for option
1666
     *
1667
     * @return void
1668
     */
1669 1
    public function setOption($key, $value = null)
1670
    {
1671 1
        if (!is_null($value)) {
1672 1
            $this->option[$key] = $value;
1673
        }
1674 1
    }
1675
1676
    /**
1677
     * Get Config value
1678
     *
1679
     * @param string $key key (name) of configuration
1680
     *
1681
     * @return mixed
1682
     */
1683 59
    public function getConfig($key)
1684
    {
1685 59
        return $this->getModuleConfig($key, 'system');
1686
    }
1687
1688
    /**
1689
     * Get all Config Values
1690
     *
1691
     * @return array
1692
     */
1693 13
    public function getConfigs()
1694
    {
1695 13
        return $this->getModuleConfigs('system');
1696
    }
1697
1698
    /**
1699
     * Add Config Values
1700
     *
1701
     * @param array  $configs array of configs
1702
     * @param string $dirname module name
1703
     *
1704
     * @return void
1705
     */
1706 1 View Code Duplication
    public function addConfigs($configs, $dirname = 'system')
1707
    {
1708 1
        $dirname = trim(strtolower($dirname));
1709 1
        if (empty($dirname)) {
1710 1
            $dirname = $this->isModule() ? $this->module->getVar('dirname') : 'system';
1711
        }
1712 1
        if (!empty($dirname)) {
1713 1
            $this->moduleConfigs[$dirname] = array_merge($this->moduleConfigs[$dirname], (array)$configs);
1714
        }
1715 1
    }
1716
1717
    /**
1718
     * Set Config Value
1719
     *
1720
     * @param string $key     key (name) of the configuration item
1721
     * @param mixed  $value   configuration value
1722
     * @param string $dirname dirname of module
1723
     *
1724
     * @return void
1725
     */
1726 9 View Code Duplication
    public function setConfig($key, $value = null, $dirname = 'system')
1727
    {
1728 9
        if (!is_null($value)) {
1729 9
            $dirname = trim(strtolower($dirname));
1730 9
            if (empty($dirname)) {
1731
                $dirname = $this->isModule() ? $this->module->getVar('dirname') : 'system';
1732
            }
1733 9
            $this->moduleConfigs[$dirname][$key] =& $value;
1734
        }
1735 9
    }
1736
1737
    /**
1738
     * Unset Config Value
1739
     *
1740
     * @param string $key     key (name) of the configuration item
1741
     * @param string $dirname dirname of module
1742
     *
1743
     * @return void
1744
     */
1745 3
    public function unsetConfig($key, $dirname = 'system')
1746
    {
1747 3
        $dirname = trim(strtolower($dirname));
1748 3
        if (empty($dirname)) {
1749
            $dirname = $this->isModule() ? $this->module->getVar('dirname') : 'system';
1750
        }
1751 3
        unset($this->moduleConfigs[$dirname][$key]);
1752 3
        if (empty($this->moduleConfigs[$dirname])) {
1753 1
            unset($this->moduleConfigs[$dirname]);
1754
        }
1755 3
    }
1756
1757
    /**
1758
     * Unset all module configs
1759
     *
1760
     * @return void
1761
     */
1762
    public function clearModuleConfigsCache()
1763
    {
1764
        $this->moduleConfigs = array();
1765
    }
1766
1767
    /**
1768
     * getModuleConfig
1769
     *
1770
     * @param string $key     config name
1771
     * @param string $dirname module directory
1772
     *
1773
     * @return mixed the value for the named config
1774
     */
1775 61
    public function getModuleConfig($key, $dirname = '')
1776
    {
1777 61
        $dirname = trim(strtolower($dirname));
1778 61
        if (empty($dirname)) {
1779 1
            $dirname = $this->isModule() ? $this->module->getVar('dirname') : 'system';
1780
        }
1781
1782 61
        if (isset($this->moduleConfigs[$dirname][$key])) {
1783 58
            return $this->moduleConfigs[$dirname][$key];
1784
        }
1785
1786 5
        $this->getModuleConfigs($dirname);
1787
1788 5
        if (!isset($this->moduleConfigs[$dirname][$key])) {
1789 5
            $this->moduleConfigs[$dirname][$key] = '';
1790
        }
1791 5
        return $this->moduleConfigs[$dirname][$key];
1792
    }
1793
1794
    /**
1795
     * Get Module Configs
1796
     *
1797
     * @param string $dirname dirname of module
1798
     *
1799
     * @return array
1800
     */
1801 21
    public function getModuleConfigs($dirname = '')
1802
    {
1803 21
        $dirname = trim($dirname);
1804 21
        if (empty($dirname)) {
1805 2
            $dirname = $this->isModule() ? $this->module->getVar('dirname') : 'system';
1806
        }
1807 21
        if (isset($this->moduleConfigs[$dirname])) {
1808 20
            return $this->moduleConfigs[$dirname];
1809
        }
1810 1
        $this->moduleConfigs[$dirname] = array();
1811 1
        $key = "system/module/configs/{$dirname}";
1812 1
        if (!$configs = $this->cache()->read($key)) {
1813 1
            $module = $this->getModuleByDirname($dirname);
1814 1
            if (is_object($module)) {
1815
                $configs = $this->getHandlerConfig()->getConfigsByModule($module->getVar('mid'));
1816
                $this->cache()->write($key, $configs);
1817 1
                $this->moduleConfigs[$dirname] =& $configs;
1818
            }
1819
        } else {
1820
            $this->moduleConfigs[$dirname] =& $configs;
1821
        }
1822
1823 1
        if ($this->isModule()) {
1824
            //for legacy
1825 1
            $this->moduleConfig =& $this->moduleConfigs[$this->module->getVar('dirname')];
1826
        }
1827 1
        if ($dirname === 'system') {
1828
            $this->config =& $this->moduleConfigs['system'];
1829
        }
1830 1
        return $this->moduleConfigs[$dirname];
1831
    }
1832
1833
    /**
1834
     * Append Config Value
1835
     *
1836
     * @param string $key           key (name) of the configuration item
1837
     * @param array  $values        array of configuration value
1838
     * @param bool   $appendWithKey true to add each $value element with associative value
1839
     *                               false to add $values as a single index element
1840
     * @param string $dirname       dirname of module
1841
     *
1842
     * @return void
1843
     */
1844 3
    public function appendConfig($key, array $values, $appendWithKey = false, $dirname = 'system')
1845
    {
1846 3
        $dirname = trim(strtolower($dirname));
1847 3
        if (empty($dirname)) {
1848
            $dirname = $this->isModule() ? $this->module->getVar('dirname') : 'system';
1849
        }
1850 3
        if (!isset($this->moduleConfigs[$dirname][$key]) || !is_array($this->moduleConfigs[$dirname][$key])) {
1851 2
            $this->moduleConfigs[$dirname][$key] = array();
1852
        }
1853 3
        if ($appendWithKey) {
1854 3
            foreach ($values as $key2 => $value) {
1855 3
                $this->moduleConfigs[$dirname][$key][$key2] =& $value;
1856
            }
1857
        } else {
1858 1
            $this->moduleConfigs[$dirname][$key][] =& $values;
1859
        }
1860 3
    }
1861
1862
    /**
1863
     * Disables page cache by overriding module cache settings
1864
     *
1865
     * @return void
1866
     */
1867 1
    public function disableModuleCache()
1868
    {
1869 1
        if ($this->isModule()) {
1870 1
            $this->appendConfig('module_cache', array($this->module->getVar('mid') => 0), true);
1871
        }
1872 1
    }
1873
1874
    /**
1875
     * getBaseDomain
1876
     *
1877
     * Get domain name from a URL. This will check that the domain is valid for registering,
1878
     * preventing return of constructs like 'co.uk' as the domain. See https://publicsuffix.org/
1879
     *
1880
     * @param string  $url              URL
1881
     * @param boolean $includeSubdomain true to include include subdomains,
1882
     *                                  default is false registerable domain only
1883
     * @param boolean $returnObject     true to return Pdp\Uri\Url\Host object
1884
     *                                  false returns domain as string
1885
     *
1886
     * @return Pdp\Uri\Url\Host|string|null domain, or null if domain is invalid
1887
     */
1888 1
    public function getBaseDomain($url, $includeSubdomain = false, $returnObject = false)
1889
    {
1890 1
        $pslManager = new \Pdp\PublicSuffixListManager();
1891 1
        $parser = new \Pdp\Parser($pslManager->getList());
1892
1893 1
        $url=mb_strtolower($url, 'UTF-8');
1894
1895
        try {
1896
            // use php-domain-parser to give us just the domain
1897 1
            $pdp = $parser->parseUrl($url);
1898 1
            $host = $pdp->host->host;
1899
        } catch (\Exception $e) {
1900
            $this->events()->triggerEvent('core.exception', $e);
1901
            return null;
1902
        }
1903
        // check for exceptions, localhost and ip address (v4 & v6)
1904 1
        if (!empty($host)) {
1905
            // localhost exception
1906 1
            if ($host==='localhost') {
1907 1
                return $returnObject ? $pdp->host : $host;
1908
            }
1909
            // Check for IPV6 URL (see http://www.ietf.org/rfc/rfc2732.txt)
1910
            // strip brackets before validating
1911 1
            if (substr($host, 0, 1)==='[' && substr($host, -1)===']') {
1912 1
                $host = substr($host, 1, (strlen($host)-2));
1913
            }
1914
            // ip address exception
1915 1
            if (filter_var($host, FILTER_VALIDATE_IP)) {
1916 1
                return $returnObject ? new \Pdp\Uri\Url\Host(null, null, null, $host) : $host;
1917
            }
1918
        }
1919
1920 1
        $host = $pdp->host->registerableDomain;
1921 1
        if (!empty($host) && $includeSubdomain) {
1922 1
            $host = $pdp->host->host;
1923
        }
1924 1
        return $returnObject ? $pdp->host : $host;
1925
    }
1926
1927
    /**
1928
     * function to update compiled template file in cache folder
1929
     *
1930
     * @param string $tpl_id template id
1931
     *
1932
     * @return boolean
1933
     */
1934 1
    public function templateTouch($tpl_id)
1935
    {
1936 1
        $tplfile = $this->getHandlerTplFile()->get($tpl_id);
1937
1938 1
        if (is_object($tplfile)) {
1939 1
            $file = $tplfile->getVar('tpl_file', 'n');
1940 1
            $module = $tplfile->getVar('tpl_module', 'n');
1941 1
            $type = $tplfile->getVar('tpl_type', 'n');
1942 1
            $tpl = new XoopsTpl();
1943 1
            return $tpl->touch($type . ':' . $module . '/' . $file);
1944
        }
1945
        return false;
1946
    }
1947
1948
    /**
1949
     * Clear the module cache
1950
     *
1951
     * @param int $mid Module ID
1952
     *
1953
     * @return void
1954
     */
1955
    public function templateClearModuleCache($mid)
1956
    {
1957
        $module = $this->getModuleById($mid);
1958
        $xoopsTpl = new XoopsTpl();
1959
        $xoopsTpl->clearModuleCompileCache($module->getVar('dirname'));
1960
    }
1961
1962
    /**
1963
     * Support for deprecated messages events
1964
     *
1965
     * @param string $message message
1966
     *
1967
     * @return void
1968
     */
1969 15
    public function deprecated($message)
1970
    {
1971 15
        $message = $this->logger()->sanitizePath($message);
1972 15
        $this->events()->triggerEvent('core.deprecated', array($message));
1973 15
    }
1974
1975
    /**
1976
     * Support for disabling error reporting
1977
     *
1978
     * @return void
1979
     */
1980 3
    public function disableErrorReporting()
1981
    {
1982
        //error_reporting(0);
1983 3
        $this->events()->triggerEvent('core.disableerrorreporting');
1984 3
    }
1985
}
1986