Completed
Push — master ( fe4c2e...b05117 )
by Michael
12s
created

Xoops::registry()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

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