Completed
Pull Request — master (#462)
by Richard
11:15
created

Xoops::getHandlerBlock()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

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

Let’s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let’s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
13
use 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 129
    public function events()
218
    {
219 129
        return \Xoops\Core\Events::getInstance();
220
    }
221
222
    /**
223
     * Deprecated - use events() instead
224
     *
225
     * @return XoopsPreload
226
     */
227 16
    public function preload()
228
    {
229 16
        return $this->events();
230
    }
231
232
    /**
233
     * get the asset utility
234
     *
235
     * @return Xoops\Core\Assets instance
236
     */
237 4
    public function assets()
238
    {
239 4
        static $instance;
240 4
        if (!isset($instance)) {
241 1
            $instance = new \Xoops\Core\Assets;
242 1
        }
243 4
        return $instance;
244
    }
245
246
    /**
247
     * get the service manager
248
     *
249
     * @param string $service - service name
250
     *
251
     * @return Xoops\Core\Service\Provider instance
252
     */
253 4
    public function service($service)
254 1
    {
255 4
        static $instance;
256 4
        if (!isset($instance)) {
257 1
            $instance = \Xoops\Core\Service\Manager::getInstance();
258 1
        }
259 4
        return $instance->locate($service);
260
    }
261
262
    /**
263
     * provide a common registry instance
264
     *
265
     * @return Xoops\Core\Registry
266
     */
267 3
    public function registry()
268
    {
269 3
        static $instance;
270 3
        if (!isset($instance)) {
271 1
            $instance = new \Xoops\Core\Registry();
272 2
        }
273 3
        return $instance;
274
    }
275
276
    /**
277
     * get security instance
278
     *
279
     * @return XoopsSecurity
280
     */
281 4
    public function security()
282
    {
283 4
        static $instance;
284 4
        if (!isset($instance)) {
285
            $instance = new \Xoops\Core\Security();
286
        }
287 4
        return $instance;
288
    }
289
290
    /**
291
     * get current template engine
292
     *
293
     * @return null|XoopsTpl
294
     */
295 9
    public function tpl()
296
    {
297 9
        return $this->tpl;
298
    }
299
300
    /**
301
     * set current template engine
302
     *
303
     * @param XoopsTpl $tpl template engine
304
     *
305
     * @return XoopsTpl
306
     */
307 6
    public function setTpl(XoopsTpl $tpl)
308
    {
309 6
        return $this->tpl = $tpl;
310
    }
311
312
    /**
313
     * establish the theme
314
     *
315
     * @param null|string $tpl_name base template
316
     *
317
     * @return null|XoopsTheme
318
     */
319 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...
320
    {
321 6
        if (!isset($this->theme)) {
322
            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...
323
                $tpl_info = $this->getTplInfo($tpl_name);
324
                $this->tpl_name = $tpl_info['tpl_name'];
325
            } else {
326
                $tpl_name = 'module:system/system_dummy.tpl';
327
                $tpl_info = $this->getTplInfo($tpl_name);
328
                $this->tpl_name = $tpl_info['tpl_name'];
329
            }
330
            if (!$this->isAdminSide) {
331
                $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...
332
                $xoopsThemeFactory = new \Xoops\Core\Theme\Factory();
333
                $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...
334
                $xoopsThemeFactory->defaultTheme = $this->getConfig('theme_set');
335
                $this->setTheme($xoopsThemeFactory->createInstance(array('contentTemplate' => $this->tpl_name)));
336
            } else {
337
                $adminThemeFactory = new \Xoops\Core\Theme\AdminFactory();
338
                $this->setTheme($adminThemeFactory->createInstance(array(
339
                    'folderName'      => 'default', 'themesPath' => 'modules/system/themes',
340
                    'contentTemplate' => $this->tpl_name
341
                )));
342
                //$this->theme()->loadLocalization('admin');
343
                list($cssAssets, $jsAssets) = $this->theme()->getLocalizationAssets('admin');
344
                if (!empty($cssAssets)) {
345
                    $this->theme()->addBaseStylesheetAssets($cssAssets);
346
                }
347
                if (!empty($jsAssets)) {
348
                    $this->theme()->addBaseScriptAssets($jsAssets);
349
                }
350
            }
351
        } else {
352 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...
353
                $tpl_info = $this->getTplInfo($tpl_name);
354
                $this->tpl_name = $tpl_info['tpl_name'];
355
                $this->theme->contentTemplate = $this->tpl_name;
356
            }
357
        }
358 6
        $GLOBALS['xoTheme'] = $this->theme;
359 6
        return $this->theme;
360
    }
361
362
    /**
363
     * set theme
364
     *
365
     * @param XoopsTheme $theme theme
366
     *
367
     * @return XoopsTheme
368
     */
369 4
    public function setTheme(XoopsTheme $theme)
370
    {
371 4
        return $this->theme = $theme;
372
    }
373
374
    /**
375
     * Convert a XOOPS path to a physical one
376
     *
377
     * @param string $url     url to derive path from
378
     * @param bool   $virtual virtual
379
     *
380
     * @return string
381
     */
382 32
    public function path($url, $virtual = false)
383
    {
384 32
        $url = $this->normalizePath($url);
385 32
        $rootPath = $this->normalizePath(\XoopsBaseConfig::get('root-path') . '/');
386 32
        if (0 === strpos($url, $rootPath)) {
387
            $url = substr($url, strlen($rootPath));
388
        }
389
        //$url = ltrim($url, '/');
390 32
        $parts = explode('/', $url, 2);
391 32
        $root = isset($parts[0]) ? $parts[0] : '';
392 32
        $path = isset($parts[1]) ? $parts[1] : '';
393 32
        if (!isset($this->paths[$root])) {
394 6
            list($root, $path) = array('www', $url);
395 6
        }
396 32
        if (!$virtual) { // Returns a physical path
397 30
            $path = $this->paths[$root][0] . '/' . $path;
398
            //$path = str_replace('/', DIRECTORY_SEPARATOR, $path);
399 30
            return $path;
400
        }
401 5
        return !isset($this->paths[$root][1]) ? '' : ($this->paths[$root][1] . '/' . $path);
402
    }
403
404
    /**
405
     * Convert path separators to unix style
406
     *
407
     * @param string $path path to normalize
408
     *
409
     * @return string normalized path
410
     */
411 32
    public function normalizePath($path)
412
    {
413 32
        return str_replace('\\', '/', $path);
414
    }
415
416
    /**
417
     * Convert a XOOPS path to an URL
418
     *
419
     * @param string $url path (or url)
420
     *
421
     * @return string
422
     */
423 5
    public function url($url)
424
    {
425 5
        return (false !== strpos($url, '://') ? $url : $this->path($url, true));
426
    }
427
428
    /**
429
     * Build an URL with the specified request params
430
     *
431
     * @param string $url    base url
432
     * @param array  $params parameters to add to the url
433
     *
434
     * @return string
435
     */
436 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...
437
    {
438 1
        if ($url === '.') {
439 1
            $url = $_SERVER['REQUEST_URI'];
440 1
        }
441 1
        $split = explode('?', $url);
442 1
        if (count($split) > 1) {
443 1
            list($url, $query) = $split;
444 1
            parse_str($query, $query);
445 1
            $params = array_merge($query, $params);
446 1
        }
447 1
        if (!empty($params)) {
448 1
            foreach ($params as $k => $v) {
449 1
                $params[$k] = $k . '=' . rawurlencode($v);
450 1
            }
451 1
            $url .= '?' . implode('&', $params);
452 1
        }
453 1
        return $url;
454
    }
455
456
    /**
457
     * Check if a path exists
458
     *
459
     * @param string $path       filesystem path
460
     * @param string $error_type error level i.e. Psr\Log\LogLevel
461
     *
462
     * @return string|false
463
     */
464 2
    public function pathExists($path, $error_type)
465
    {
466 2
        if (XoopsLoad::fileExists($path)) {
467 1
            return $path;
468
        } else {
469 1
            $this->logger()->log(
470 1
                LogLevel::WARNING,
471 1
                \XoopsLocale::E_FILE_NOT_FOUND,
472 1
                array($path, $error_type)
473 1
            );
474
475
            //trigger_error(XoopsLocale::E_FILE_NOT_FOUND, $error_type);
476 1
            return false;
477
        }
478
    }
479
480
    /**
481
     * Start gzipCompression output buffer
482
     *
483
     * @return void
484
     */
485 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...
486
    {
487
        /**
488
         * Disable gzip compression if PHP is run under CLI mode and needs refactored to work correctly
489
         */
490 1
        if (empty($_SERVER['SERVER_NAME']) || substr(PHP_SAPI, 0, 3) === 'cli') {
491 1
            $this->setConfig('gzip_compression', 0);
492 1
        }
493
494 1
        if ($this->getConfig('gzip_compression') == 1
495 1
            && extension_loaded('zlib')
496 1
            && !ini_get('zlib.output_compression')
497 1
        ) {
498
            if (@ini_get('zlib.output_compression_level') < 0) {
499
                ini_set('zlib.output_compression_level', 6);
500
            }
501
            ob_start('ob_gzhandler');
502
        }
503 1
    }
504
505
    /**
506
     * Translate a path
507
     *
508
     * @return void
509
     */
510 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...
511
    {
512
        /**
513
         * *#@+
514
         * Host abstraction layer
515
         */
516 1
        if (!isset($_SERVER['PATH_TRANSLATED']) && isset($_SERVER['SCRIPT_FILENAME'])) {
517 1
            $_SERVER['PATH_TRANSLATED'] = $_SERVER['SCRIPT_FILENAME']; // For Apache CGI
518 1
        } else {
519 1
            if (isset($_SERVER['PATH_TRANSLATED']) && !isset($_SERVER['SCRIPT_FILENAME'])) {
520 1
                $_SERVER['SCRIPT_FILENAME'] = $_SERVER['PATH_TRANSLATED']; // For IIS/2K now I think :-(
521 1
            }
522
        }
523
        /**
524
         * User Mulitbytes
525
         */
526 1 View Code Duplication
        if (empty($_SERVER['REQUEST_URI'])) { // Not defined by IIS
527
            // Under some configs, IIS makes SCRIPT_NAME point to php.exe :-(
528 1
            if (!($_SERVER['REQUEST_URI'] = @$_SERVER['PHP_SELF'])) {
529 1
                $_SERVER['REQUEST_URI'] = $_SERVER['SCRIPT_NAME'];
530 1
            }
531 1
            if (isset($_SERVER['QUERY_STRING'])) {
532 1
                $_SERVER['REQUEST_URI'] .= '?' . $_SERVER['QUERY_STRING'];
533 1
            }
534 1
        }
535 1
    }
536
537
    /**
538
     * Select Theme
539
     *
540
     * @return void
541
     */
542 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...
543
    {
544 1
        $xoopsThemeSelect = Request::getString('xoops_theme_select', '', 'POST');
545 1
        if (!empty($xoopsThemeSelect) && in_array($xoopsThemeSelect, $this->getConfig('theme_set_allowed'))) {
546 1
            $this->setConfig('theme_set', $xoopsThemeSelect);
547 1
            $_SESSION['xoopsUserTheme'] = $xoopsThemeSelect;
548 1
        } else {
549 1
            if (!empty($_SESSION['xoopsUserTheme'])
550 1
                && in_array($_SESSION['xoopsUserTheme'], $this->getConfig('theme_set_allowed'))
551 1
            ) {
552 1
                $this->setConfig('theme_set', $_SESSION['xoopsUserTheme']);
553 1
            }
554
        }
555 1
    }
556
557
    /**
558
     * Gets module, type and file from a tpl name
559
     *
560
     * @param string $tpl_name in form type:module/filename.tpl
561
     *
562
     * @return array|false associative array of 'tpl_name', 'type', 'module', 'file'
563
     *                     or false on error
564
     */
565 9
    public function getTplInfo($tpl_name)
566
    {
567 9
        $parts = array();
568 9
        $matched = preg_match('#(\w+):(\w+)/(.*)$#', $tpl_name, $parts);
569 9
        if ($matched) {
570 8
            $names = array('tpl_name', 'type', 'module', 'file');
571 8
            $ret = array();
572 8
            for ($i=0; $i<4; ++$i) {
573 8
                $ret[$names[$i]] = $parts[$i];
574 8
            }
575 8
        } else {
576
            // this should be eliminated
577 1
            $this->events()->triggerEvent('debug.log', "Sloppy template: " . $tpl_name);
578 1
            $ret = array();
579 1
            $ret['type'] = $this->isAdminSide ? 'admin' : 'module';
580 1
            $info = explode(':', $tpl_name);
581 1
            if (count($info) == 2) {
582 1
                $ret['type'] = $info[0];
583 1
                $tpl_name = str_replace($ret['type'] . ':', '', $tpl_name);
584 1
            }
585
586 1
            if ($ret['type'] === 'db') {
587
                //For legacy compatibility
588 1
                $ret['type'] = $this->isAdminSide ? 'admin' : 'module';
589 1
            }
590
591 1
            $info = explode('|', $tpl_name);
592 1
            if (count($info) == 2) {
593
                $ret['module'] = $info[0];
594
                $ret['file'] = $info[1];
595
            } else {
596 1
                $ret['module'] = 'system';
597 1
                $ret['file'] = $tpl_name;
598 1
                if ($this->isModule()) {
599
                    $ret['module'] = $this->module->getVar('dirname', 'n');
600
                }
601
            }
602 1
            $ret['tpl_name'] = $ret['type'] . ':' . $ret['module'] . '/' . $ret['file'];
603
        }
604
605 9
        return $ret;
606
    }
607
608
    /**
609
     * Render Header
610
     *
611
     * @param string|null $tpl_name template name
612
     *
613
     * @return null|boolean
614
     */
615
    public function header($tpl_name = null)
616
    {
617
        static $included = false;
618
        if ($included) {
619
            return false;
620
        }
621
        $included = true;
622
623
        $this->events()->triggerEvent('core.header.start');
624
625
        //For legacy
626
        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...
627
            $tpl_name = $this->option['template_main'];
628
            $this->deprecated(
629
                'XoopsOption \'template_main\' is deprecated, please use $xoops->header(\'templatename.tpl\') instead'
630
            );
631
        }
632
        $this->theme($tpl_name);
633
        $this->tpl()->assign('xoops', $this);
634
635
        if ($this->isAdminSide) {
636
            $this->events()->triggerEvent('system.class.gui.header');
637
            include_once $this->path('modules/system/themes/default/default.php');
638
            $gui = new XoopsGuiDefault();
639
            $gui->header();
640
        } else {
641
            $this->events()->triggerEvent('core.header.addmeta');
642
            // Temporary solution for start page redirection
643
            if (defined("XOOPS_STARTPAGE_REDIRECTED")) {
644
                $smarty = $repeat = null;
645
                $this->theme()->headContent(
646
                    null,
647
                    "<base href='" . \XoopsBaseConfig::get('url') . '/modules/'
648
                    . $this->getConfig('startpage') . "/' />",
649
                    $smarty,
650
                    $repeat
651
                );
652
            }
653
654
            // Sets cache time
655
            if ($this->isModule()) {
656
                $cache_times = $this->getConfig('module_cache');
657
                $this->theme()->contentCacheLifetime =
658
                    isset($cache_times[$this->module->getVar('mid')]) ? $cache_times[$this->module->getVar('mid')] : 0;
659
                // Tricky solution for setting cache time for homepage
660
            } else {
661
                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...
662
                    // $this->theme->contentCacheLifetime = 604800;
663
                }
664
            }
665
            $this->events()->triggerEvent('core.header.checkcache');
666
            if ($this->theme()->checkCache()) {
667
                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...
668
            }
669
        }
670
671
        if (!isset($this->tpl_name) && $this->isModule()) {
672
            ob_start();
673
        }
674
675
        $this->events()->triggerEvent('core.header.end');
676
        return true;
677
    }
678
679
    /**
680
     * Render Footer
681
     *
682
     * @return false|null
683
     */
684
    public function footer()
685
    {
686
        static $included = false;
687
        if ($included) {
688
            return false;
689
        }
690
        $included = true;
691
692
        $this->events()->triggerEvent('core.footer.start');
693
694
        if (!headers_sent()) {
695
            header('Content-Type:text/html; charset=' . XoopsLocale::getCharset());
696
            header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
697
            header('Cache-Control: private, no-cache');
698
            header('Pragma: no-cache');
699
        }
700
701
        if (isset($this->option['template_main'])
702
            && $this->option['template_main'] != $this->theme()->contentTemplate
703
        ) {
704
            trigger_error("xoopsOption[template_main] should be defined before including header.php", E_USER_WARNING);
705
            $this->theme()->contentTemplate = $this->tpl_name;
706
        }
707
        $this->theme()->render();
708
        $this->events()->triggerEvent('core.footer.end');
709
        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...
710
    }
711
712
    /**
713
     * Check if a module is set
714
     *
715
     * @return bool
716
     */
717 12
    public function isModule()
718
    {
719 12
        return $this->module instanceof XoopsModule ? true : false;
720
    }
721
722
    /**
723
     * Check if a user is set
724
     *
725
     * @return bool
726
     */
727 7
    public function isUser()
728
    {
729 7
        return $this->user instanceof XoopsUser ? true : false;
730
    }
731
732
    /**
733
     * Check if user is admin
734
     *
735
     * @return bool
736
     */
737 1
    public function isAdmin()
738
    {
739 1
        return $this->userIsAdmin;
740
    }
741
742
    /**
743
     * Get handler of Block
744
     *
745
     * @param boolean $optional true if failure to load handler should be considered a warning, not an error
746
     *
747
     * @return \Xoops\Core\Kernel\Handlers\XoopsBlockHandler
748
     */
749 4
    public function getHandlerBlock($optional = false)
750
    {
751 4
        return $this->getHandler('Block', $optional);
752
    }
753
754
    /**
755
     * Get handler of Block Module Link
756
     *
757
     * @param boolean $optional true if failure to load handler should be considered a warning, not an error
758
     *
759
     * @return \Xoops\Core\Kernel\Handlers\XoopsBlockModuleLinkHandler
760
     */
761 1
    public function getHandlerBlockModuleLink($optional = false)
762
    {
763 1
        return $this->getHandler('BlockModuleLink', $optional);
764
    }
765
766
    /**
767
     * Get handler of Config
768
     *
769
     * @param boolean $optional true if failure to load handler should be considered a warning, not an error
770
     *
771
     * @return \Xoops\Core\Kernel\Handlers\XoopsConfigHandler
772
     */
773 1
    public function getHandlerConfig($optional = false)
774
    {
775 1
        return $this->getHandler('Config', $optional);
776
    }
777
778
    /**
779
     * Get handler of Config  Item
780
     *
781
     * @param boolean $optional true if failure to load handler should be considered a warning, not an error
782
     *
783
     * @return \Xoops\Core\Kernel\Handlers\XoopsConfigItemHandler
784
     */
785 18
    public function getHandlerConfigItem($optional = false)
786
    {
787 18
        return $this->getHandler('ConfigItem', $optional);
788
    }
789
790
    /**
791
     * Get handler of Config Option
792
     *
793
     * @param boolean $optional true if failure to load handler should be considered a warning, not an error
794
     *
795
     * @return \Xoops\Core\Kernel\Handlers\XoopsConfigOptionHandler
796
     */
797 18
    public function getHandlerConfigOption($optional = false)
798
    {
799 18
        return $this->getHandler('ConfigOption', $optional);
800
    }
801
802
    /**
803
     * Get handler of Group
804
     *
805
     * @param boolean $optional true if failure to load handler should be considered a warning, not an error
806
     *
807
     * @return \Xoops\Core\Kernel\Handlers\XoopsGroupHandler
808
     */
809 2
    public function getHandlerGroup($optional = false)
810
    {
811 2
        return $this->getHandler('Group', $optional);
812
    }
813
814
    /**
815
     * Get handler of Group Permission
816
     *
817
     * @param boolean $optional true if failure to load handler should be considered a warning, not an error
818
     *
819
     * @return \Xoops\Core\Kernel\Handlers\XoopsGroupPermHandler
820
     */
821 4
    public function getHandlerGroupPermission($optional = false)
822
    {
823 4
        return $this->getHandler('GroupPerm', $optional);
824
    }
825
826
    /**
827
     * Get handler of Member
828
     *
829
     * @param boolean $optional true if failure to load handler should be considered a warning, not an error
830
     *
831
     * @return \Xoops\Core\Kernel\Handlers\XoopsMemberHandler
832
     */
833 15
    public function getHandlerMember($optional = false)
834
    {
835 15
        return $this->getHandler('Member', $optional);
836
    }
837
838
    /**
839
     * Get handler of Membership
840
     *
841
     * @param boolean $optional true if failure to load handler should be considered a warning, not an error
842
     *
843
     * @return \Xoops\Core\Kernel\Handlers\XoopsMembershipHandler
844
     */
845 2
    public function getHandlerMembership($optional = false)
846
    {
847 2
        return $this->getHandler('Membership', $optional);
848
    }
849
850
    /**
851
     * Get handler of Module
852
     *
853
     * @param boolean $optional true if failure to load handler should be considered a warning, not an error
854
     *
855
     * @return \Xoops\Core\Kernel\Handlers\XoopsModuleHandler
856
     */
857 10
    public function getHandlerModule($optional = false)
858
    {
859 10
        return $this->getHandler('Module', $optional);
860
    }
861
862
    /**
863
     * Get handler of Online
864
     *
865
     * @param boolean $optional true if failure to load handler should be considered a warning, not an error
866
     *
867
     * @return \Xoops\Core\Kernel\Handlers\XoopsOnlineHandler
868
     */
869 2
    public function getHandlerOnline($optional = false)
870
    {
871 2
        return $this->getHandler('Online', $optional);
872
    }
873
874
    /**
875
     * Get handler of Private Message
876
     *
877
     * @param boolean $optional true if failure to load handler should be considered a warning, not an error
878
     *
879
     * @return \Xoops\Core\Kernel\Handlers\XoopsPrivateMessageHandler
880
     */
881 1
    public function getHandlerPrivateMessage($optional = false)
882
    {
883 1
        return $this->getHandler('Privmessage', $optional);
884
    }
885
886
    /**
887
     * Get the session manager
888
     *
889
     * @return Xoops\Core\Session\Manager
890
     */
891 1
    public function session()
892
    {
893 1
        if ($this->sessionManager === null) {
894 1
            $this->sessionManager = new \Xoops\Core\Session\Manager();
895 1
        }
896 1
        return $this->sessionManager;
897
    }
898
899
    /**
900
     * Get handler of Template File
901
     *
902
     * @param boolean $optional true if failure to load handler should be considered a warning, not an error
903
     *
904
     * @return \Xoops\Core\Kernel\Handlers\XoopsTplFileHandler
905
     */
906 2
    public function getHandlerTplFile($optional = false)
907
    {
908 2
        return $this->getHandler('tplfile', $optional);
909
    }
910
911
    /**
912
     * Get handler of Template Set
913
     *
914
     * @param boolean $optional true if failure to load handler should be considered a warning, not an error
915
     *
916
     * @return \Xoops\Core\Kernel\Handlers\XoopsTplSetHandler
917
     */
918 1
    public function getHandlerTplSet($optional = false)
919
    {
920 1
        return $this->getHandler('Tplset', $optional);
921
    }
922
923
    /**
924
     * Get handler of User
925
     *
926
     * @param boolean $optional true if failure to load handler should be considered a warning, not an error
927
     *
928
     * @return \Xoops\Core\Kernel\Handlers\XoopsUserHandler
929
     */
930 2
    public function getHandlerUser($optional = false)
931
    {
932 2
        return $this->getHandler('user', $optional);
933
    }
934
935
    /**
936
     * Get handler
937
     *
938
     * @param string  $name     name of handler
939
     * @param boolean $optional true if failure to load handler should be considered a warning, not an error
940
     *
941
     * @return XoopsObjectHandler|XoopsPersistableObjectHandler|null
942
     */
943 59
    protected function getHandler($name, $optional = false)
944
    {
945 59
        if (!isset($this->kernelHandlers[$name])) {
946 6
            if (!isset($this->handlerFactory)) {
947
                $this->handlerFactory = HandlerFactory::getInstance();
948
            }
949 6
            $handler = $this->handlerFactory->newSpec()->scheme('kernel')->name($name)->optional($optional)->build();
950 6
            if ($handler === null) {
951
                $this->logger()->log(
952
                    \Psr\Log\LogLevel::WARNING,
953
                    sprintf('A handler for %s is not available', $name)
954
                );
955
            }
956 6
            $this->kernelHandlers[$name] = $handler;
957 6
        }
958
959 59
        return $this->kernelHandlers[$name];
960
    }
961
962
    /**
963
     * Get Module Handler
964
     *
965
     * @param string|null $name       name of handler
966
     * @param string|null $module_dir dirname of module
967
     * @param boolean     $optional   true if failure to load handler should be considered a warning, not an error
968
     *
969
     * @return XoopsObjectHandler|XoopsPersistableObjectHandler|bool
970
     */
971 2
    public function getModuleHandler($name = null, $module_dir = null, $optional = false)
972
    {
973
        // if $module_dir is not specified
974 2
        if (!isset($module_dir)) {
975
            // if a module is loaded
976
            if ($this->module instanceof XoopsModule) {
977
                $module_dir = $this->module->getVar('dirname', 'n');
978
            } else {
979
                trigger_error('No Module is loaded', E_USER_ERROR);
980
            }
981
        } else {
982 2
            $module_dir = trim($module_dir);
983
        }
984 2
        $name = (!isset($name)) ? $module_dir : trim($name);
985 2
        if (!isset($this->moduleHandlers[$module_dir][$name])) {
986 2
            if (!isset($this->handlerFactory)) {
987
                $this->handlerFactory = HandlerFactory::getInstance();
988
            }
989 2
            $handler = $this->handlerFactory->create($name, $module_dir, $optional);
990 2
            if ($handler === null) {
991
                $this->logger()->log(
992
                    LogLevel::WARNING,
993
                    sprintf('No handler for %s exists in module %s', $name, $module_dir)
994
                );
995
            }
996 2
            $this->moduleHandlers[$module_dir][$name] = $handler;
997 2
        }
998 2
        return $this->moduleHandlers[$module_dir][$name];
999
    }
1000
1001
    /**
1002
     * Get Module Form
1003
     *
1004
     * @param XoopsObject $obj        object to populate form
1005
     * @param string      $name       name of form
1006
     * @param string      $module_dir dirname of associated module
1007
     *
1008
     * @return Xoops\Form\Form|bool
1009
     */
1010 1
    public function getModuleForm($obj, $name, $module_dir = null)
1011
    {
1012 1
        if (empty($name)) {
1013 1
            return false;
1014
        }
1015
        if (empty($module_dir)) {
1016
            if ($this->isModule()) {
1017
                $module_dir = $this->module->getVar('dirname', 'n');
1018
            } else {
1019
                return false;
1020
            }
1021
        }
1022
        if (XoopsLoad::fileExists(
1023
            $hnd_file = \XoopsBaseConfig::get('root-path') . "/modules/{$module_dir}/class/form/{$name}.php"
1024
        )) {
1025
            include_once $hnd_file;
1026
            $class = ucfirst(strtolower($module_dir)) . ucfirst($name) . 'Form';
1027
            if (class_exists($class)) {
1028
                $instance = new $class($obj);
1029
                if ($instance instanceof \Xoops\Form\Form) {
1030
                    return $instance;
1031
                }
1032
            }
1033
        }
1034
        return false;
1035
    }
1036
1037
    /**
1038
     * Get Module Helper
1039
     *
1040
     * @param string $dirname dirname of module
1041
     *
1042
     * @return bool|Xoops\Module\Helper\HelperAbstract
1043
     */
1044 1
    public static function getModuleHelper($dirname)
1045
    {
1046 1
        return \Xoops\Module\Helper::getHelper($dirname);
1047
    }
1048
1049
    /**
1050
     * XOOPS language loader wrapper
1051
     * Temporary solution, not encouraged to use
1052
     *
1053
     * @param string $name     Name of language file to be loaded, without extension
1054
     * @param mixed  $domain   string: Module dirname; global language file will be loaded if
1055
     *                           $domain is set to 'global' or not specified
1056
     *                          array:  example; array('Frameworks/moduleclasses/moduleadmin')
1057
     * @param string $language Language to be loaded, current language content will be loaded if not specified
1058
     *
1059
     * @return  boolean
1060
     */
1061 7
    public function loadLanguage($name, $domain = '', $language = null)
1062
    {
1063 7
        if (empty($name)) {
1064 1
            return false;
1065
        }
1066
1067 7
        $language = empty($language) ? XoopsLocale::getLegacyLanguage() : $language;
1068
        // expanded domain to multiple categories, e.g. module:Fsystem, framework:filter, etc.
1069 7 View Code Duplication
        if ((empty($domain) || 'global' === $domain)) {
1070 1
            $path = '';
1071 1
        } else {
1072 6
            $path = (is_array($domain)) ? array_shift($domain) . '/' : "modules/{$domain}/";
1073
        }
1074 7
        $path .= 'language';
1075
1076 7
        if (!XoopsLoad::fileExists($file = $this->path("{$path}/{$language}/{$name}.php"))) {
1077 6
            if (!XoopsLoad::fileExists($file = $this->path("{$path}/english/{$name}.php"))) {
1078 6
                return false;
1079
            }
1080
        }
1081 1
        $ret = include_once $file;
1082 1
        return $ret;
1083
    }
1084
1085
    /**
1086
     * loadLocale
1087
     *
1088
     * @param string $domain Module dirname; global language file will be loaded if set to 'global' or not specified
1089
     * @param string $locale Locale to be loaded, current language content will be loaded if not specified
1090
     *
1091
     * @return  boolean
1092
     */
1093 4
    public static function loadLocale($domain = null, $locale = null)
1094
    {
1095 4
        return \Xoops\Locale::loadLocale($domain, $locale);
1096
    }
1097
1098
    /**
1099
     * Translate a key value
1100
     *
1101
     * @param string $key     constant name
1102
     * @param string $dirname dirname of module (domain)
1103
     *
1104
     * @return string
1105
     */
1106 1
    public function translate($key, $dirname = 'xoops')
1107
    {
1108 1
        return \Xoops\Locale::translate($key, $dirname);
1109
    }
1110
1111
    /**
1112
     * Get active modules from cache file
1113
     *
1114
     * @return array
1115
     */
1116 10
    public function getActiveModules()
1117
    {
1118 10
        if (is_array($this->activeModules)) {
1119 10
            return $this->activeModules;
1120
        }
1121
1122
        try {
1123
            if (!$this->activeModules = $this->cache()->read('system/modules/active')) {
1124
                $this->activeModules = $this->setActiveModules();
1125
            }
1126
        } catch (\Exception $e) {
1127
            $this->activeModules = array();
1128
        }
1129
        return $this->activeModules;
1130
    }
1131
1132
    /**
1133
     * Write active modules to cache file
1134
     *
1135
     * @return array
1136
     */
1137 1
    public function setActiveModules()
1138
    {
1139 1
        $module_handler = $this->getHandlerModule();
1140 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...
1141 1
        $modules_active = array();
1142 1
        foreach ($modules_array as $module) {
1143 1
            $modules_active[$module['mid']] = $module['dirname'];
1144 1
        }
1145 1
        $this->cache()->write('system/modules/active', $modules_active);
1146 1
        return $modules_active;
1147
    }
1148
1149
    /**
1150
     * Checks is module is installed and active
1151
     *
1152
     * @param string $dirname module directory
1153
     *
1154
     * @return bool
1155
     */
1156 8
    public function isActiveModule($dirname)
1157
    {
1158 8
        if (isset($dirname) && in_array($dirname, $this->getActiveModules())) {
1159 3
            return true;
1160
        }
1161 6
        return false;
1162
    }
1163
1164
    /**
1165
     * get module object from module name (dirname)
1166
     *
1167
     * @param string $dirname dirname of the module
1168
     *
1169
     * @return bool|XoopsModule
1170
     */
1171 4 View Code Duplication
    public function getModuleByDirname($dirname)
1172
    {
1173 4
        $key = "system/module/dirname/{$dirname}";
1174 4
        if (!$module = $this->cache()->read($key)) {
1175 4
            $module = $this->getHandlerModule()->getByDirname($dirname);
1176 4
            $this->cache()->write($key, $module);
1177 4
        }
1178 4
        return $module;
1179
    }
1180
1181
    /**
1182
     * Get Module By Id
1183
     *
1184
     * @param int $id Id of the module
1185
     *
1186
     * @return bool|XoopsModule
1187
     */
1188 1 View Code Duplication
    public function getModuleById($id)
1189
    {
1190 1
        $key = "system/module/id/{$id}";
1191 1
        if (!$module = $this->cache()->read($key)) {
1192 1
            $module = $this->getHandlerModule()->getById($id);
1193 1
            $this->cache()->write($key, $module);
1194 1
        }
1195 1
        return $module;
1196
    }
1197
1198
    /**
1199
     * Render Simple Header
1200
     *
1201
     * @param bool $closehead true to close the HTML head element
1202
     *
1203
     * @return void
1204
     */
1205 1
    public function simpleHeader($closehead = true)
1206
    {
1207 1
        $this->events()->triggerEvent('core.header.start');
1208 1
        $this->theme();
1209 1
        $xoopsConfigMetaFooter = $this->getConfigs();
1210
1211 1
        if (!headers_sent()) {
1212
            header('Content-Type:text/html; charset=' . XoopsLocale::getCharset());
1213
            header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
1214
            header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
1215
            header(
1216
                'Cache-Control: no-store, no-cache, max-age=1, s-maxage=1, must-revalidate, post-check=0, pre-check=0'
1217
            );
1218
            header("Pragma: no-cache");
1219
        }
1220
1221 1
        echo "<!DOCTYPE html>\n";
1222 1
        $xoops_url = \XoopsBaseConfig::get('url');
1223 1
        echo '<html lang="' . XoopsLocale::getLangCode() . '">
1224
              <head>
1225 1
              <meta http-equiv="content-type" content="text/html; charset=' . XoopsLocale::getCharset() . '" />
1226 1
              <meta name="robots" content="' . htmlspecialchars($xoopsConfigMetaFooter['meta_robots']) . '" />
1227 1
              <meta name="keywords" content="' . htmlspecialchars($xoopsConfigMetaFooter['meta_keywords']) . '" />
1228 1
              <meta name="description" content="' . htmlspecialchars($xoopsConfigMetaFooter['meta_description']) . '" />
1229 1
              <meta name="rating" content="' . htmlspecialchars($xoopsConfigMetaFooter['meta_rating']) . '" />
1230 1
              <meta name="author" content="' . htmlspecialchars($xoopsConfigMetaFooter['meta_author']) . '" />
1231
              <meta name="generator" content="XOOPS" />
1232 1
              <title>' . htmlspecialchars($this->getConfig('sitename')) . '</title>
1233 1
              <script type="text/javascript" src="' . $xoops_url . '/include/xoops.js"></script>
1234 1
              <script type="text/javascript" src="' . $xoops_url . '/media/jquery/jquery.js"></script>
1235 1
              <script type="text/javascript" src="' . $xoops_url . '/media/bootstrap/js/bootstrap.min.js"></script>';
1236 1
        $themecss = $this->getCss($this->getConfig('theme_set'));
1237 1
        echo '<link rel="stylesheet" type="text/css" media="all" href="' . $xoops_url . '/xoops.css" />';
1238 1
        $locale = $this->getConfig('locale');
1239 1
        if (XoopsLoad::fileExists($this->path('locale/' . $locale . '/style.css'))) {
1240
            echo '<link rel="stylesheet" type="text/css" media="all" href="' . $xoops_url
1241
                . '/locale/' . $locale . '/style.css" />';
1242
        }
1243 1
        if ($themecss) {
1244 1
            echo '<link rel="stylesheet" type="text/css" media="all" href="' . $themecss . '" />';
1245
            echo '<link rel="stylesheet" type="text/css" media="screen" href="' .
1246 1
                $this->url('themes/' . $this->getConfig('theme_set') . '/media/bootstrap/css/xoops.bootstrap.css')
1247 1
                .'" />';
1248 1
        }
1249 1
        if ($closehead) {
1250 1
            echo '</head><body>';
1251 1
        }
1252 1
    }
1253
1254
    /**
1255
     * Render simpleFooter
1256
     *
1257
     * @return void
1258
     */
1259 2
    public function simpleFooter()
1260
    {
1261 2
        $this->events()->triggerEvent('core.header.footer');
1262 2
        echo '</body></html>';
1263 2
        ob_end_flush();
1264 2
    }
1265
    /**
1266
     * render an alert message to a string
1267
     *
1268
     * @param string $type  alert type, one of 'info', 'error', 'success' or 'warning'
1269
     * @param mixed  $msg   string or array of strings
1270
     * @param string $title title for alert
1271
     *
1272
     * @return string
1273
     */
1274 1
    public function alert($type, $msg, $title = '/')
1275
    {
1276 1
        $tpl = new XoopsTpl();
1277
        switch ($type) {
1278 1
            case 'info':
1279 1
            default:
1280 1
                $tpl->assign('alert_type', 'alert-info');
1281 1
                if ($title === '/') {
1282 1
                    $title = XoopsLocale::INFORMATION;
1283 1
                }
1284 1
                break;
1285
1286 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...
1287 1
                $tpl->assign('alert_type', 'alert-error');
1288 1
                if ($title === '/') {
1289 1
                    $title = XoopsLocale::ERROR;
1290 1
                }
1291 1
                break;
1292
1293 1
            case 'success':
1294 1
                $tpl->assign('alert_type', 'alert-success');
1295 1
                if ($title === '/') {
1296 1
                    $title = XoopsLocale::SUCCESS;
1297 1
                }
1298 1
                break;
1299
1300 1
            case 'warning':
1301 1
                $tpl->assign('alert_type', '');
1302 1
                if ($title === '/') {
1303 1
                    $title = XoopsLocale::WARNING;
1304 1
                }
1305 1
                break;
1306 1
        }
1307
1308 1
        if ($title != '') {
1309 1
            $tpl->assign('alert_title', $title);
1310 1
        }
1311 1
        if (!is_scalar($msg) && !is_array($msg)) {
1312 1
            $msg = ''; // don't know what to do with this, so make it blank
1313 1
        }
1314 1
        if (is_array($msg)) {
1315
            // if this is not a simple array of strings, this might not work
1316 1
            $alert_msg = @implode("<br />", $msg);
1317 1
        } else {
1318 1
            $alert_msg = $msg;
1319
        }
1320 1
        if ($alert_msg == '') {
1321 1
            return '';
1322
        } else {
1323 1
            $tpl->assign('alert_msg', $alert_msg);
1324 1
            $ret = $tpl->fetch('module:system/system_alert.tpl');
1325 1
            return $ret;
1326
        }
1327
    }
1328
1329
    /**
1330
     * Render a confirmation form to a string
1331
     *
1332
     * @param array   $hiddens  associative array of values used to complete confirmed action
1333
     * @param string  $action   form action (URL)
1334
     * @param string  $msg      message to display
1335
     * @param string  $submit   submit button message
1336
     * @param boolean $addtoken true to add CSRF token
1337
     *
1338
     * @return string rendered confirm message
1339
     */
1340 1
    public function confirm($hiddens, $action, $msg, $submit = '', $addtoken = true)
1341
    {
1342 1
        $tpl = new XoopsTpl();
1343 1
        $submit = ($submit != '') ? trim($submit) : XoopsLocale::A_SUBMIT;
1344 1
        $tpl->assign('msg', $msg);
1345 1
        $tpl->assign('action', $action);
1346 1
        $tpl->assign('submit', $submit);
1347 1
        $str_hiddens = '';
1348 1
        foreach ($hiddens as $name => $value) {
1349 1
            if (is_array($value)) {
1350 1
                foreach ($value as $caption => $newvalue) {
1351 1
                    $str_hiddens .= '<input type="radio" name="' . $name . '" value="'
1352 1
                        . htmlspecialchars($newvalue) . '" > ' . $caption . NWLINE;
1353 1
                }
1354 1
                $str_hiddens .= '<br />' . NWLINE;
1355 1
            } else {
1356 1
                $str_hiddens .= '<input type="hidden" name="' . $name . '" value="'
1357 1
                    . htmlspecialchars($value) . '" />' . NWLINE;
1358
            }
1359 1
        }
1360 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...
1361 1
            $tpl->assign('token', $this->security()->getTokenHTML());
1362 1
        }
1363 1
        $tpl->assign('hiddens', $str_hiddens);
1364 1
        return $tpl->fetch('module:system/system_confirm.tpl');
1365
    }
1366
1367
    /**
1368
     * Get User Timestamp (kind of pointless, since timestamps are UTC?)
1369
     *
1370
     * @param \DateTime|int $time DateTime object or unix timestamp
1371
     *
1372
     * @return int unix timestamp
1373
     */
1374 1
    public function getUserTimestamp($time)
1375
    {
1376 1
        $dt = \Xoops\Core\Locale\Time::cleanTime($time);
1377 1
        return $dt->getTimestamp();
1378
    }
1379
1380
    /**
1381
     * Function to calculate server timestamp from user entered time (timestamp)
1382
     *
1383
     * @param int  $timestamp time stamp
1384
     * @param null $userTZ    timezone
1385
     *
1386
     * @return int
1387
     */
1388 1
    public function userTimeToServerTime($timestamp, $userTZ = null)
1389
    {
1390 1
        if (!isset($userTZ)) {
1391 1
            $userTZ = $this->getConfig('default_TZ');
1392 1
        }
1393 1
        $timestamp = $timestamp - (($userTZ - $this->getConfig('server_TZ')) * 3600);
1394 1
        return (int)$timestamp;
1395
    }
1396
1397
    /**
1398
     * get the groups associated with the current user
1399
     *
1400
     * @return int[]
1401
     */
1402 3
    public function getUserGroups()
1403
    {
1404 3
        $groups = $this->isUser() ? $this->user->getGroups() : array(FixedGroups::ANONYMOUS);
1405
1406 3
        return $groups;
1407
    }
1408
1409
    /**
1410
     * generate a temporary password
1411
     *
1412
     * @return string
1413
     *
1414
     * @todo make better passwords
1415
     */
1416 1
    public function makePass()
1417
    {
1418 1
        $makepass = '';
1419
        $syllables = array(
1420 1
            'er', 'in', 'tia', 'wol', 'fe', 'pre', 'vet', 'jo', 'nes', 'al', 'len', 'son', 'cha', 'ir', 'ler', 'bo',
1421 1
            'ok', 'tio', 'nar', 'sim', 'ple', 'bla', 'ten', 'toe', 'cho', 'co', 'lat', 'spe', 'ak', 'er', 'po', 'co',
1422 1
            'lor', 'pen', 'cil', 'li', 'ght', 'wh', 'at', 'the', 'he', 'ck', 'is', 'mam', 'bo', 'no', 'fi', 've', 'any',
1423 1
            'way', 'pol', 'iti', 'cs', 'ra', 'dio', 'sou', 'rce', 'sea', 'rch', 'pa', 'per', 'com', 'bo', 'sp', 'eak',
1424 1
            'st', 'fi', 'rst', 'gr', 'oup', 'boy', 'ea', 'gle', 'tr', 'ail', 'bi', 'ble', 'brb', 'pri', 'dee', 'kay',
1425 1
            'en', 'be', 'se'
1426 1
        );
1427 1
        for ($count = 1; $count <= 4; ++$count) {
1428 1
            if (1 == mt_rand() % 10) {
1429 1
                $makepass .= sprintf('%0.0f', (rand() % 50) + 1);
1430 1
            } else {
1431 1
                $makepass .= sprintf('%s', $syllables[rand() % 62]);
1432
            }
1433 1
        }
1434 1
        return $makepass;
1435
    }
1436
1437
    /**
1438
     * Check Email
1439
     *
1440
     * @param string $email    check email
1441
     * @param bool   $antispam true if returned email should be have anti-SPAM measures applied
1442
     *
1443
     * @return false|string email address if valid, otherwise false
1444
     */
1445 2
    public function checkEmail($email, $antispam = false)
1446
    {
1447 2
        if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
1448 1
            return false;
1449
        }
1450 2
        if ($antispam) {
1451 1
            $email = str_replace("@", " at ", $email);
1452 1
            $email = str_replace(".", " dot ", $email);
1453 1
        }
1454 2
        return $email;
1455
    }
1456
1457
    /**
1458
     * formatURL - add default http:// if no valid protocol specified
1459
     *
1460
     * @param string $url full or partial url
1461
     *
1462
     * @return string
1463
     */
1464 1
    public function formatURL($url)
1465
    {
1466 1
        $url = trim($url);
1467 1
        if ($url != '') {
1468 1
            if (!preg_match('/^(https?|ftps?|ed2k)\:\/\//i', $url)) {
1469 1
                $url = 'http://' . $url;
1470 1
            }
1471 1
        }
1472 1
        return $url;
1473
    }
1474
1475
    /**
1476
     * Function to get banner html tags for use in templates
1477
     *
1478
     * @return string
1479
     */
1480 3
    public function getBanner()
1481
    {
1482 3
        $options = '';
1483 3
        $this->events()->triggerEvent('core.banner.display', array(&$options));
1484 3
        return $options;
1485
    }
1486
1487
    /**
1488
     * Function to redirect a user to certain pages
1489
     *
1490
     * @param string $url               URL to redirect to
1491
     * @param int    $time              time to wait (to allow reading message display)
1492
     * @param string $message           message to display
1493
     * @param bool   $addredirect       add xoops_redirect parameter with current URL to the redirect
1494
     *                                   URL -  used for return from login redirect
1495
     * @param bool   $allowExternalLink allow redirect to external URL
1496
     *
1497
     * @return void
1498
     */
1499
    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...
1500
    {
1501
        $this->events()->triggerEvent('core.redirect.start', array(
1502
            $url, $time, $message, $addredirect, $allowExternalLink
1503
        ));
1504
        // if conditions are right, system preloads will exit on this call
1505
        // so don't use it if you want to be called, use start version above.
1506
        $this->events()->triggerEvent('core.include.functions.redirectheader', array(
1507
            $url, $time, $message, $addredirect, $allowExternalLink
1508
        ));
1509
1510
        $xoops_url = \XoopsBaseConfig::get('url');
1511
1512
        if (preg_match("/[\\0-\\31]|about:|script:/i", $url)) {
1513
            if (!preg_match('/^\b(java)?script:([\s]*)history\.go\(-[0-9]*\)([\s]*[;]*[\s]*)$/si', $url)) {
1514
                $url = $xoops_url;
1515
            }
1516
        }
1517 View Code Duplication
        if (!$allowExternalLink && $pos = strpos($url, '://')) {
1518
            $xoopsLocation = substr($xoops_url, strpos($xoops_url, '://') + 3);
1519
            if (strcasecmp(substr($url, $pos + 3, strlen($xoopsLocation)), $xoopsLocation)) {
1520
                $url = $xoops_url;
1521
            }
1522
        }
1523
        if (!defined('XOOPS_CPFUNC_LOADED')) {
1524
            $theme = 'default';
1525
        } else {
1526
            $theme = $this->getConfig('theme_set');
1527
        }
1528
1529
        $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...
1530
        $xoopsThemeFactory = new \Xoops\Core\Theme\Factory();
1531
        $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...
1532
        $xoopsThemeFactory->defaultTheme = $theme;
1533
        $this->setTheme($xoopsThemeFactory->createInstance(array(
1534
            "plugins" => array(), "renderBanner" => false
1535
        )));
1536
        $this->setTpl($this->theme()->template);
1537
        $this->tpl()->assign(array(
1538
            'xoops_theme'      => $theme, 'xoops_imageurl' => \XoopsBaseConfig::get('themes-url') . '/' . $theme . '/',
1539
            'xoops_themecss'   => $this->getCss($theme),
1540
            'xoops_requesturi' => htmlspecialchars($_SERVER['REQUEST_URI'], ENT_QUOTES),
1541
            'xoops_sitename'   => htmlspecialchars($this->getConfig('sitename'), ENT_QUOTES),
1542
            'xoops_slogan'     => htmlspecialchars($this->getConfig('slogan'), ENT_QUOTES),
1543
            'xoops_dirname'    => $this->isModule() ? $this->module->getVar('dirname') : 'system',
1544
            'xoops_pagetitle'  => $this->isModule() ? $this->module->getVar('name')
1545
                : htmlspecialchars($this->getConfig('slogan'), ENT_QUOTES)
1546
        ));
1547
1548
        $this->tpl()->assign('time', (int)($time));
1549
        if (!empty($_SERVER['REQUEST_URI']) && $addredirect && strstr($url, 'user.php')) {
1550
            $joiner = (false===strpos($url, '?')) ? '?' : '&amp;';
1551
            $url .= $joiner . 'xoops_redirect=' . urlencode($_SERVER['REQUEST_URI']);
1552
        }
1553
        $url = preg_replace("/&amp;/i", '&', htmlspecialchars($url, ENT_QUOTES));
1554
        $this->tpl()->assign('url', $url);
1555
        $message = trim($message) != '' ? $message : XoopsLocale::E_TAKING_YOU_BACK;
1556
        $this->tpl()->assign('message', $message);
1557
        $this->tpl()->assign('lang_ifnotreload', sprintf(XoopsLocale::F_IF_PAGE_NOT_RELOAD_CLICK_HERE, $url));
1558
1559
        $this->events()->triggerEvent('core.include.functions.redirectheader.end');
1560
        $this->tpl()->display('module:system/system_redirect.tpl');
1561
        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...
1562
    }
1563
1564
    /**
1565
     * Do an immediate redirect to the specified url. Use this instead of using PHP's header()
1566
     * directly so that a core.redirect.start event is triggered. An example is debugbar, that
1567
     * stacks data so the details for both original and redirected scripts data are available.
1568
     *
1569
     * @param string $url URL to redirect to
1570
     *
1571
     * @return void
1572
     */
1573
    public static function simpleRedirect($url)
1574
    {
1575
        header("location: {$url}");
1576
        $xoops = \Xoops::getInstance();
1577
        $xoops->events()->triggerEvent('core.redirect.start', array($url));
1578
        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...
1579
    }
1580
1581
    /**
1582
     * Get Environment Value
1583
     *
1584
     * @param string $key key (name) in the environment
1585
     *
1586
     * @return string
1587
     */
1588 8
    public function getEnv($key)
1589
    {
1590 8
        return HttpRequest::getInstance()->getEnv($key, '');
1591
    }
1592
1593
    /**
1594
     * Function to get css file for a certain themeset
1595
     *
1596
     * @param string $theme theme name
1597
     *
1598
     * @return string
1599
     */
1600 6
    public function getCss($theme = '')
1601
    {
1602 6
        if ($theme == '') {
1603 1
            $theme = $this->getConfig('theme_set');
1604 1
        }
1605 6
        $userAgent = $this->getEnv('HTTP_USER_AGENT');
1606 6
        if (stristr($userAgent, 'mac')) {
1607 1
            $str_css = 'styleMAC.css';
1608 6
        } elseif (preg_match("/MSIE ([0-9]\.[0-9]{1,2})/i", $userAgent)) {
1609 1
            $str_css = 'style.css';
1610 1
        } else {
1611 6
            $str_css = 'styleNN.css';
1612
        }
1613 6
        $xoops_theme_path = \XoopsBaseConfig::get('themes-path');
1614 6
        $xoops_theme_url = \XoopsBaseConfig::get('themes-url');
1615 6 View Code Duplication
        if (is_dir($xoops_theme_path . '/' . $theme)) {
1616 6
            if (XoopsLoad::fileExists($xoops_theme_path . '/' . $theme . '/' . $str_css)) {
1617 1
                return $xoops_theme_url . '/' . $theme . '/' . $str_css;
1618 6
            } elseif (XoopsLoad::fileExists($xoops_theme_path . '/' . $theme . '/style.css')) {
1619 1
                return $xoops_theme_url . '/' . $theme . '/style.css';
1620
            }
1621 6
        }
1622 6 View Code Duplication
        if (is_dir($xoops_theme_path . '/' . $theme . '/css')) {
1623 6
            if (XoopsLoad::fileExists($xoops_theme_path . '/' . $theme . '/css/' . $str_css)) {
1624 1
                return $xoops_theme_url . '/' . $theme . '/css/' . $str_css;
1625 6
            } elseif (XoopsLoad::fileExists($xoops_theme_path . '/' . $theme . '/css/style.css')) {
1626 6
                return $xoops_theme_url . '/' . $theme . '/css/style.css';
1627
            }
1628
        }
1629 1
        return '';
1630
    }
1631
1632
    /**
1633
     * Get Mailer
1634
     *
1635
     * @return XoopsMailer|XoopsMailerLocale
1636
     */
1637 1
    public function getMailer()
1638
    {
1639 1
        static $mailer;
1640 1
        if (is_object($mailer)) {
1641
            return $mailer;
1642
        }
1643 1
        \Xoops\Locale::loadMailerLocale();
1644 1
        if (class_exists('XoopsMailerLocale')) {
1645 1
            $mailer = new XoopsMailerLocale();
1646 1
        } else {
1647
            $mailer = new XoopsMailer();
1648
        }
1649 1
        return $mailer;
1650
    }
1651
1652
    /**
1653
     * Get Option
1654
     *
1655
     * @param string $key key (name) of option
1656
     *
1657
     * @return string
1658
     */
1659 4
    public function getOption($key)
1660
    {
1661 4
        $ret = '';
1662 4
        if (isset($this->option[$key])) {
1663 1
            $ret = $this->option[$key];
1664 1
        }
1665 4
        return $ret;
1666
    }
1667
1668
    /**
1669
     * Set Option
1670
     *
1671
     * @param string $key   key (name) of option
1672
     * @param null   $value value for option
1673
     *
1674
     * @return void
1675
     */
1676 1
    public function setOption($key, $value = null)
1677
    {
1678 1
        if (!is_null($value)) {
1679 1
            $this->option[$key] = $value;
1680 1
        }
1681 1
    }
1682
1683
    /**
1684
     * Get Config value
1685
     *
1686
     * @param string $key key (name) of configuration
1687
     *
1688
     * @return mixed
1689
     */
1690 60
    public function getConfig($key)
1691
    {
1692 60
        return $this->getModuleConfig($key, 'system');
1693
    }
1694
1695
    /**
1696
     * Get all Config Values
1697
     *
1698
     * @return array
1699
     */
1700 13
    public function getConfigs()
1701
    {
1702 13
        return $this->getModuleConfigs('system');
1703
    }
1704
1705
    /**
1706
     * Add Config Values
1707
     *
1708
     * @param array  $configs array of configs
1709
     * @param string $dirname module name
1710
     *
1711
     * @return void
1712
     */
1713 1 View Code Duplication
    public function addConfigs($configs, $dirname = 'system')
1714
    {
1715 1
        $dirname = trim(strtolower($dirname));
1716 1
        if (empty($dirname)) {
1717 1
            $dirname = $this->isModule() ? $this->module->getVar('dirname') : 'system';
1718 1
        }
1719 1
        if (!empty($dirname)) {
1720 1
            $this->moduleConfigs[$dirname] = array_merge($this->moduleConfigs[$dirname], (array)$configs);
1721 1
        }
1722 1
    }
1723
1724
    /**
1725
     * Set Config Value
1726
     *
1727
     * @param string $key     key (name) of the configuration item
1728
     * @param mixed  $value   configuration value
1729
     * @param string $dirname dirname of module
1730
     *
1731
     * @return void
1732
     */
1733 9 View Code Duplication
    public function setConfig($key, $value = null, $dirname = 'system')
1734
    {
1735 9
        if (!is_null($value)) {
1736 9
            $dirname = trim(strtolower($dirname));
1737 9
            if (empty($dirname)) {
1738
                $dirname = $this->isModule() ? $this->module->getVar('dirname') : 'system';
1739
            }
1740 9
            $this->moduleConfigs[$dirname][$key] =& $value;
1741 9
        }
1742 9
    }
1743
1744
    /**
1745
     * Unset Config Value
1746
     *
1747
     * @param string $key     key (name) of the configuration item
1748
     * @param string $dirname dirname of module
1749
     *
1750
     * @return void
1751
     */
1752 3
    public function unsetConfig($key, $dirname = 'system')
1753
    {
1754 3
        $dirname = trim(strtolower($dirname));
1755 3
        if (empty($dirname)) {
1756
            $dirname = $this->isModule() ? $this->module->getVar('dirname') : 'system';
1757
        }
1758 3
        unset($this->moduleConfigs[$dirname][$key]);
1759 3
        if (empty($this->moduleConfigs[$dirname])) {
1760 1
            unset($this->moduleConfigs[$dirname]);
1761 1
        }
1762 3
    }
1763
1764
    /**
1765
     * getModuleConfig
1766
     *
1767
     * @param string $key     config name
1768
     * @param string $dirname module directory
1769
     *
1770
     * @return mixed the value for the named config
1771
     */
1772 63
    public function getModuleConfig($key, $dirname = '')
1773
    {
1774 63
        $dirname = trim(strtolower($dirname));
1775 63
        if (empty($dirname)) {
1776 1
            $dirname = $this->isModule() ? $this->module->getVar('dirname') : 'system';
1777 1
        }
1778
1779 63
        if (isset($this->moduleConfigs[$dirname][$key])) {
1780 60
            return $this->moduleConfigs[$dirname][$key];
1781
        }
1782
1783 5
        $this->getModuleConfigs($dirname);
1784
1785 5
        if (!isset($this->moduleConfigs[$dirname][$key])) {
1786 5
            $this->moduleConfigs[$dirname][$key] = '';
1787 5
        }
1788 5
        return $this->moduleConfigs[$dirname][$key];
1789
    }
1790
1791
    /**
1792
     * Get Module Configs
1793
     *
1794
     * @param string $dirname dirname of module
1795
     *
1796
     * @return array
1797
     */
1798 20
    public function getModuleConfigs($dirname = '')
1799
    {
1800 20
        $dirname = trim($dirname);
1801 20
        if (empty($dirname)) {
1802 2
            $dirname = $this->isModule() ? $this->module->getVar('dirname') : 'system';
1803 2
        }
1804 20
        if (isset($this->moduleConfigs[$dirname])) {
1805 19
            return $this->moduleConfigs[$dirname];
1806
        }
1807 1
        $this->moduleConfigs[$dirname] = array();
1808 1
        $key = "system/module/configs/{$dirname}";
1809 1
        if (!$configs = $this->cache()->read($key)) {
1810 1
            $module = $this->getModuleByDirname($dirname);
1811 1
            if (is_object($module)) {
1812
                $configs = $this->getHandlerConfig()->getConfigsByModule($module->getVar('mid'));
1813
                $this->cache()->write($key, $configs);
1814
                $this->moduleConfigs[$dirname] =& $configs;
1815
            }
1816 1
        } else {
1817
            $this->moduleConfigs[$dirname] =& $configs;
1818
        }
1819
1820 1
        if ($this->isModule()) {
1821
            //for legacy
1822 1
            $this->moduleConfig =& $this->moduleConfigs[$this->module->getVar('dirname')];
1823 1
        }
1824 1
        if ($dirname === 'system') {
1825
            $this->config =& $this->moduleConfigs['system'];
1826
        }
1827 1
        return $this->moduleConfigs[$dirname];
1828
    }
1829
1830
    /**
1831
     * Append Config Value
1832
     *
1833
     * @param string $key           key (name) of the configuration item
1834
     * @param array  $values        array of configuration value
1835
     * @param bool   $appendWithKey true to add each $value element with associative value
1836
     *                               false to add $values as a single index element
1837
     * @param string $dirname       dirname of module
1838
     *
1839
     * @return void
1840
     */
1841 3
    public function appendConfig($key, array $values, $appendWithKey = false, $dirname = 'system')
1842
    {
1843 3
        $dirname = trim(strtolower($dirname));
1844 3
        if (empty($dirname)) {
1845
            $dirname = $this->isModule() ? $this->module->getVar('dirname') : 'system';
1846
        }
1847 3
        if (!isset($this->moduleConfigs[$dirname][$key]) || !is_array($this->moduleConfigs[$dirname][$key])) {
1848 2
            $this->moduleConfigs[$dirname][$key] = array();
1849 2
        }
1850 3
        if ($appendWithKey) {
1851 3
            foreach ($values as $key2 => $value) {
1852 3
                $this->moduleConfigs[$dirname][$key][$key2] =& $value;
1853 3
            }
1854 3
        } else {
1855 1
            $this->moduleConfigs[$dirname][$key][] =& $values;
1856
        }
1857 3
    }
1858
1859
    /**
1860
     * Disables page cache by overriding module cache settings
1861
     *
1862
     * @return void
1863
     */
1864 1
    public function disableModuleCache()
1865
    {
1866 1
        if ($this->isModule()) {
1867 1
            $this->appendConfig('module_cache', array($this->module->getVar('mid') => 0), true);
1868 1
        }
1869 1
    }
1870
1871
    /**
1872
     * getBaseDomain
1873
     *
1874
     * Get domain name from a URL. This will check that the domain is valid for registering,
1875
     * preventing return of constructs like 'co.uk' as the domain. See https://publicsuffix.org/
1876
     *
1877
     * @param string  $url              URL
1878
     * @param boolean $includeSubdomain true to include include subdomains,
1879
     *                                  default is false registerable domain only
1880
     * @param boolean $returnObject     true to return Pdp\Uri\Url\Host object
1881
     *                                  false returns domain as string
1882
     *
1883
     * @return Pdp\Uri\Url\Host|string|null domain, or null if domain is invalid
1884
     */
1885 1
    public function getBaseDomain($url, $includeSubdomain = false, $returnObject = false)
1886
    {
1887 1
        $pslManager = new \Pdp\PublicSuffixListManager();
1888 1
        $parser = new \Pdp\Parser($pslManager->getList());
1889
1890 1
        $url=mb_strtolower($url, 'UTF-8');
1891
1892
        try {
1893
            // use php-domain-parser to give us just the domain
1894 1
            $pdp = $parser->parseUrl($url);
1895 1
            $host = $pdp->host->host;
1896 1
        } catch (\Exception $e) {
1897
            $this->events()->triggerEvent('core.exception', $e);
1898
            return null;
1899
        }
1900
        // check for exceptions, localhost and ip address (v4 & v6)
1901 1
        if (!empty($host)) {
1902
            // localhost exception
1903 1
            if ($host==='localhost') {
1904 1
                return $returnObject ? $pdp->host : $host;
1905
            }
1906
            // Check for IPV6 URL (see http://www.ietf.org/rfc/rfc2732.txt)
1907
            // strip brackets before validating
1908 1
            if (substr($host, 0, 1)==='[' && substr($host, -1)===']') {
1909 1
                $host = substr($host, 1, (strlen($host)-2));
1910 1
            }
1911
            // ip address exception
1912 1
            if (filter_var($host, FILTER_VALIDATE_IP)) {
1913 1
                return $returnObject ? new \Pdp\Uri\Url\Host(null, null, null, $host) : $host;
1914
            }
1915 1
        }
1916
1917 1
        $host = $pdp->host->registerableDomain;
1918 1
        if (!empty($host) && $includeSubdomain) {
1919 1
            $host = $pdp->host->host;
1920 1
        }
1921 1
        return $returnObject ? $pdp->host : $host;
1922
    }
1923
1924
    /**
1925
     * function to update compiled template file in cache folder
1926
     *
1927
     * @param string $tpl_id template id
1928
     *
1929
     * @return boolean
1930
     */
1931 1
    public function templateTouch($tpl_id)
1932
    {
1933 1
        $tplfile = $this->getHandlerTplFile()->get($tpl_id);
1934
1935 1
        if (is_object($tplfile)) {
1936 1
            $file = $tplfile->getVar('tpl_file', 'n');
1937 1
            $module = $tplfile->getVar('tpl_module', 'n');
1938 1
            $type = $tplfile->getVar('tpl_type', 'n');
1939 1
            $tpl = new XoopsTpl();
1940 1
            return $tpl->touch($type . ':' . $module . '/' . $file);
1941
        }
1942
        return false;
1943
    }
1944
1945
    /**
1946
     * Clear the module cache
1947
     *
1948
     * @param int $mid Module ID
1949
     *
1950
     * @return void
1951
     */
1952
    public function templateClearModuleCache($mid)
1953
    {
1954
        $module = $this->getModuleById($mid);
1955
        $xoopsTpl = new XoopsTpl();
1956
        $xoopsTpl->clearModuleCompileCache($module->getVar('dirname'));
1957
    }
1958
1959
    /**
1960
     * Support for deprecated messages events
1961
     *
1962
     * @param string $message message
1963
     *
1964
     * @return void
1965
     */
1966 15
    public function deprecated($message)
1967
    {
1968 15
        $message = $this->logger()->sanitizePath($message);
1969 15
        $this->events()->triggerEvent('core.deprecated', array($message));
1970 15
    }
1971
1972
    /**
1973
     * Support for disabling error reporting
1974
     *
1975
     * @return void
1976
     */
1977 3
    public function disableErrorReporting()
1978
    {
1979
        //error_reporting(0);
1980 3
        $this->events()->triggerEvent('core.disableerrorreporting');
1981 3
    }
1982
}
1983