Completed
Pull Request — master (#133)
by Goffy
16:45
created

xos_opal_Theme::headContent()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 3
nc 2
nop 4
dl 0
loc 6
rs 9.4285
c 0
b 0
f 0
1
<?php
0 ignored issues
show
Coding Style Compatibility introduced by
For compatibility and reusability of your code, PSR1 recommends that a file should introduce either new symbols (like classes, functions, etc.) or have side-effects (like outputting something, or including other files), but not both at the same time. The first symbol is defined on line 31 and the first side effect is on line 21.

The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.

The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.

To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.

Loading history...
2
/**
3
 * xos_opal_Theme component class file
4
 *
5
 * You may not change or alter any portion of this comment or credits
6
 * of supporting developers from this source code or any supporting source code
7
 * which is considered copyrighted (c) material of the original comment or credit authors.
8
 * This program is distributed in the hope that it will be useful,
9
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11
 *
12
 * @copyright       (c) 2000-2016 XOOPS Project (www.xoops.org)
13
 * @license             GNU GPL 2 (http://www.gnu.org/licenses/gpl-2.0.html)
14
 * @author              Skalpa Keo <[email protected]>
15
 * @author              Taiwen Jiang <[email protected]>
16
 * @since               2.3.0
17
 * @package             kernel
18
 * @subpackage          xos_opal_Theme
19
 */
20
21
defined('XOOPS_ROOT_PATH') || exit('Restricted access');
22
23
/**
24
 * xos_opal_ThemeFactory
25
 *
26
 * @author     Skalpa Keo
27
 * @package    xos_opal
28
 * @subpackage xos_opal_Theme
29
 * @since      2.3.0
30
 */
31
class xos_opal_ThemeFactory
32
{
33
    public $xoBundleIdentifier = 'xos_opal_ThemeFactory';
34
    /**
35
     * Currently enabled themes (if empty, all the themes in themes/ are allowed)
36
     *
37
     * @var array
38
     */
39
    public $allowedThemes = array();
40
    /**
41
     * Default theme to instanciate if none specified
42
     *
43
     * @var string
44
     */
45
    public $defaultTheme = 'default';
46
    /**
47
     * If users are allowed to choose a custom theme
48
     *
49
     * @var bool
50
     */
51
    public $allowUserSelection = true;
52
53
    /**
54
     * Instanciate the specified theme
55
     * @param  array $options
56
     * @param  array $initArgs
57
     * @return null|xos_opal_Theme
58
     */
59
    public function &createInstance($options = array(), $initArgs = array())
60
    {
61
        // Grab the theme folder from request vars if present
62
        if (empty($options['folderName'])) {
63
            if (($req = @$_REQUEST['xoops_theme_select']) && $this->isThemeAllowed($req)) {
64
                $options['folderName'] = $req;
65
                if (isset($_SESSION) && $this->allowUserSelection) {
66
                    $_SESSION[$this->xoBundleIdentifier]['defaultTheme'] = $req;
67
                }
68
            } elseif (isset($_SESSION[$this->xoBundleIdentifier]['defaultTheme'])) {
69
                $options['folderName'] = $_SESSION[$this->xoBundleIdentifier]['defaultTheme'];
70
            } elseif (empty($options['folderName']) || !$this->isThemeAllowed($options['folderName'])) {
71
                $options['folderName'] = $this->defaultTheme;
72
            }
73
            $GLOBALS['xoopsConfig']['theme_set'] = $options['folderName'];
74
        }
75
        $options['path'] = XOOPS_THEME_PATH . '/' . $options['folderName'];
76
        $inst            = null;
0 ignored issues
show
Unused Code introduced by
$inst 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...
77
        $inst            = new xos_opal_Theme();
78
        foreach ($options as $k => $v) {
79
            $inst->$k = $v;
80
        }
81
        $inst->xoInit();
82
83
        return $inst;
84
    }
85
86
    /**
87
     * Checks if the specified theme is enabled or not
88
     *
89
     * @param  string $name
90
     * @return bool
91
     */
92
    public function isThemeAllowed($name)
93
    {
94
        return (empty($this->allowedThemes) || in_array($name, $this->allowedThemes));
95
    }
96
}
97
98
/**
99
 * xos_opal_AdminThemeFactory
100
 *
101
 * @author     Andricq Nicolas (AKA MusS)
102
 * @author     trabis
103
 * @package    xos_opal
104
 * @subpackage xos_opal_Theme
105
 * @since      2.4.0
106
 */
107
class xos_opal_AdminThemeFactory extends xos_opal_ThemeFactory
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
108
{
109
    /**
110
     * @param array $options
111
     * @param array $initArgs
112
     *
113
     * @return null|xos_opal_Theme
114
     */
115
    public function &createInstance($options = array(), $initArgs = array())
116
    {
117
        $options['plugins']      = array();
118
        $options['renderBanner'] = false;
119
        $inst                    =& parent::createInstance($options, $initArgs);
120
        $inst->path              = XOOPS_ADMINTHEME_PATH . '/' . $inst->folderName;
121
        $inst->url               = XOOPS_ADMINTHEME_URL . '/' . $inst->folderName;
122
        $inst->template->assign(array(
123
                                    'theme_path'  => $inst->path,
124
                                    'theme_tpl'   => $inst->path . '/xotpl',
125
                                    'theme_url'   => $inst->url,
126
                                    'theme_img'   => $inst->url . '/img',
127
                                    'theme_icons' => $inst->url . '/icons',
128
                                    'theme_css'   => $inst->url . '/css',
129
                                    'theme_js'    => $inst->url . '/js',
130
                                    'theme_lang'  => $inst->url . '/language'));
131
132
        return $inst;
133
    }
134
}
135
136
/**
137
 * Class xos_opal_Theme
138
 */
139
class xos_opal_Theme
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
140
{
141
    /**
142
     * Should we render banner? Not for redirect pages or admin side
143
     *
144
     * @var bool
145
     */
146
    public $renderBanner = true;
147
    /**
148
     * The name of this theme
149
     *
150
     * @var string
151
     */
152
    public $folderName = '';
153
    /**
154
     * Physical path of this theme folder
155
     *
156
     * @var string
157
     */
158
    public $path = '';
159
    public $url  = '';
160
161
    /**
162
     * Whether or not the theme engine should include the output generated by php
163
     *
164
     * @var string
165
     */
166
    public $bufferOutput = true;
167
    /**
168
     * Canvas-level template to use
169
     *
170
     * @var string
171
     */
172
    public $canvasTemplate = 'theme.html';
173
174
    /**
175
     * Theme folder path
176
     *
177
     * @var string
178
     */
179
    public $themesPath = 'themes';
180
181
    /**
182
     * Content-level template to use
183
     *
184
     * @var string
185
     */
186
    public $contentTemplate = '';
187
188
    public $contentCacheLifetime = 0;
189
    public $contentCacheId;
190
191
    /**
192
     * Text content to display right after the contentTemplate output
193
     *
194
     * @var string
195
     */
196
    public $content = '';
197
    /**
198
     * Page construction plug-ins to use
199
     *
200
     * @var array
201
     * @access public
202
     */
203
    public $plugins     = array(
204
        'xos_logos_PageBuilder');
205
    public $renderCount = 0;
206
    /**
207
     * Pointer to the theme template engine
208
     *
209
     * @var XoopsTpl
210
     */
211
    public $template = false;
212
213
    /**
214
     * Array containing the document meta-information
215
     *
216
     * @var array
217
     */
218
    public $metas = array(
219
        //'http' => array(
220
        //    'Content-Script-Type' => 'text/javascript' ,
221
        //    'Content-Style-Type' => 'text/css') ,
222
        'meta'   => array(),
223
        'link'   => array(),
224
        'script' => array());
225
226
    /**
227
     * Array of strings to be inserted in the head tag of HTML documents
228
     *
229
     * @var array
230
     */
231
    public $htmlHeadStrings = array();
232
    /**
233
     * Custom variables that will always be assigned to the template
234
     *
235
     * @var array
236
     */
237
    public $templateVars = array();
238
239
    /**
240
     * User extra information for cache id, like language, user groups
241
     *
242
     * @var boolean
243
     */
244
    public $use_extra_cache_id = true;
245
246
    /**
247
     * *#@-
248
     */
249
250
    /**
251
     * *#@+
252
     *
253
     * @tasktype 10 Initialization
254
     */
255
    /**
256
     * Initializes this theme
257
     *
258
     * Upon initialization, the theme creates its template engine and instanciates the
259
     * plug-ins from the specified {@link $plugins} list. If the theme is a 2.0 theme, that does not
260
     * display redirection messages, the HTTP redirections system is disabled to ensure users will
261
     * see the redirection screen.
262
     *
263
     * @param  array $options
264
     * @return bool
265
     */
266
    public function xoInit($options = array())
0 ignored issues
show
Unused Code introduced by
The parameter $options is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
267
    {
268
        $this->path                   = XOOPS_THEME_PATH . '/' . $this->folderName;
269
        $this->url                    = XOOPS_THEME_URL . '/' . $this->folderName;
270
        $this->template               = null;
271
        $this->template               = new XoopsTpl();
272
        $this->template->currentTheme =& $this;
0 ignored issues
show
Bug introduced by
The property currentTheme does not seem to exist in XoopsTpl.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
273
        $this->template->assign_by_ref('xoTheme', $this);
274
        $this->template->assign(array(
275
                                    'xoops_theme'      => $GLOBALS['xoopsConfig']['theme_set'],
276
                                    'xoops_imageurl'   => XOOPS_THEME_URL . '/' . $GLOBALS['xoopsConfig']['theme_set'] . '/',
277
                                    'xoops_themecss'   => xoops_getcss($GLOBALS['xoopsConfig']['theme_set']),
278
                                    'xoops_requesturi' => htmlspecialchars($_SERVER['REQUEST_URI'], ENT_QUOTES),
279
                                    'xoops_sitename'   => htmlspecialchars($GLOBALS['xoopsConfig']['sitename'], ENT_QUOTES),
280
                                    'xoops_slogan'     => htmlspecialchars($GLOBALS['xoopsConfig']['slogan'], ENT_QUOTES),
281
                                    'xoops_dirname'    => isset($GLOBALS['xoopsModule']) && is_object($GLOBALS['xoopsModule']) ? $GLOBALS['xoopsModule']->getVar('dirname') : 'system',
282
                                    'xoops_banner'     => ($GLOBALS['xoopsConfig']['banners'] && $this->renderBanner) ? xoops_getbanner() : '&nbsp;',
283
                                    'xoops_pagetitle'  => isset($GLOBALS['xoopsModule']) && is_object($GLOBALS['xoopsModule']) ? $GLOBALS['xoopsModule']->getVar('name') : htmlspecialchars($GLOBALS['xoopsConfig']['slogan'], ENT_QUOTES)));
284
285
        if (isset($GLOBALS['xoopsUser']) && is_object($GLOBALS['xoopsUser'])) {
286
            $this->template->assign(array(
287
                                        'xoops_isuser'     => true,
288
                                        'xoops_avatar'     => XOOPS_UPLOAD_URL . '/' . $GLOBALS['xoopsUser']->getVar('user_avatar'),
289
                                        'xoops_userid'     => $GLOBALS['xoopsUser']->getVar('uid'),
290
                                        'xoops_uname'      => $GLOBALS['xoopsUser']->getVar('uname'),
291
                                        'xoops_name'       => $GLOBALS['xoopsUser']->getVar('name'),
292
                                        'xoops_isadmin'    => $GLOBALS['xoopsUserIsAdmin'],
293
                                        'xoops_usergroups' => $GLOBALS['xoopsUser']->getGroups()));
294
        } else {
295
            $this->template->assign(array(
296
                                        'xoops_isuser'     => false,
297
                                        'xoops_isadmin'    => false,
298
                                        'xoops_usergroups' => array(XOOPS_GROUP_ANONYMOUS)));
299
        }
300
301
        // Meta tags
302
        $config_handler = xoops_getHandler('config');
303
        $criteria       = new CriteriaCompo(new Criteria('conf_modid', 0));
304
        $criteria->add(new Criteria('conf_catid', XOOPS_CONF_METAFOOTER));
305
        $config = $config_handler->getConfigs($criteria, true);
306
        foreach (array_keys($config) as $i) {
307
            $name  = $config[$i]->getVar('conf_name', 'n');
308
            $value = $config[$i]->getVar('conf_value', 'n');
309
            if (substr($name, 0, 5) === 'meta_') {
310
                $this->addMeta('meta', substr($name, 5), $value);
311
            } else {
312
                // prefix each tag with 'xoops_'
313
                $this->template->assign("xoops_$name", $value);
314
            }
315
        }
316
        // Load global javascript
317
        $this->addScript('include/xoops.js');
318
        $this->loadLocalization();
319
320
        if ($this->bufferOutput) {
321
            ob_start();
322
        }
323
        $GLOBALS['xoTheme']  =& $this;
324
        $GLOBALS['xoopsTpl'] =& $this->template;
325
        // Instanciate and initialize all the theme plugins
326
        foreach ($this->plugins as $k => $bundleId) {
327
            if (!is_object($bundleId)) {
328
                $this->plugins[$bundleId]        = null;
329
                $this->plugins[$bundleId]        = new $bundleId();
330
                $this->plugins[$bundleId]->theme =& $this;
331
                $this->plugins[$bundleId]->xoInit();
332
                unset($this->plugins[$k]);
333
            }
334
        }
335
336
        return true;
337
    }
338
339
    /**
340
     * Generate cache id based on extra information of language and user groups
341
     *
342
     * User groups other than anonymous should be detected to avoid disclosing group sensitive contents
343
     *
344
     * @param  string $cache_id    raw cache id
345
     * @param  string $extraString extra string
346
     * @return string complete cache id
347
     */
348
    public function generateCacheId($cache_id, $extraString = '')
349
    {
350
        static $extra_string;
351
        if (!$this->use_extra_cache_id) {
352
            return $cache_id;
353
        }
354
355
        if (empty($extraString)) {
356
            if (empty($extra_string)) {
357
                // Generate language section
358
                $extra_string = $GLOBALS['xoopsConfig']['language'];
359
                // Generate group section
360
                if (!isset($GLOBALS['xoopsUser']) || !is_object($GLOBALS['xoopsUser'])) {
361
                    $extra_string .= '-' . XOOPS_GROUP_ANONYMOUS;
362
                } else {
363
                    $groups = $GLOBALS['xoopsUser']->getGroups();
364
                    sort($groups);
365
                    // Generate group string for non-anonymous groups,
366
                    // XOOPS_DB_PASS and XOOPS_DB_NAME (before we find better variables) are used to protect group sensitive contents
367
                    $extra_string .= '-' . substr(md5(implode('-', $groups)), 0, 8) . '-' . substr(md5(XOOPS_DB_PASS . XOOPS_DB_NAME . XOOPS_DB_USER), 0, 8);
368
                }
369
            }
370
            $extraString = $extra_string;
371
        }
372
        $cache_id .= '-' . $extraString;
373
374
        return $cache_id;
375
    }
376
377
    /**
378
     * xos_opal_Theme::checkCache()
379
     *
380
     * @return bool
381
     */
382
    public function checkCache()
383
    {
384
        if ($_SERVER['REQUEST_METHOD'] !== 'POST' && $this->contentCacheLifetime) {
385
            $template                       = $this->contentTemplate ?: 'db:system_dummy.tpl';
386
            $this->template->caching        = 2;
387
            $this->template->cache_lifetime = $this->contentCacheLifetime;
388
            $uri                            = str_replace(XOOPS_URL, '', $_SERVER['REQUEST_URI']);
389
            // Clean uri by removing session id
390
            if (defined('SID') && SID && strpos($uri, SID)) {
391
                $uri = preg_replace("/([\?&])(" . SID . "$|" . SID . '&)/', "\\1", $uri);
392
            }
393
            $this->contentCacheId = $this->generateCacheId('page_' . substr(md5($uri), 0, 8));
394
            if ($this->template->is_cached($template, $this->contentCacheId)) {
395
                $xoopsLogger = XoopsLogger::getInstance();
396
                $xoopsLogger->addExtra($template, sprintf('Cached (regenerates every %d seconds)', $this->contentCacheLifetime));
397
                $this->render(null, null, $template);
398
399
                return true;
400
            }
401
        }
402
403
        return false;
404
    }
405
406
    /**
407
     * Render the page
408
     *
409
     * The theme engine builds pages from 2 templates: canvas and content.
410
     *
411
     * A module can call this method directly and specify what templates the theme engine must use.
412
     * If render() hasn't been called before, the theme defaults will be used for the canvas and
413
     * page template (and xoopsOption['template_main'] for the content).
414
     *
415
     * @param string $canvasTpl  The canvas template, if different from the theme default
416
     * @param string $pageTpl    The page template, if different from the theme default (unsupported, 2.3+ only)
417
     * @param string $contentTpl The content template
418
     * @param array  $vars       Template variables to send to the template engine
419
     *
420
     * @return bool
421
     */
422
    public function render($canvasTpl = null, $pageTpl = null, $contentTpl = null, $vars = array())
0 ignored issues
show
Unused Code introduced by
The parameter $pageTpl is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
423
    {
424
        if ($this->renderCount) {
425
            return false;
426
        }
427
        $xoopsLogger = XoopsLogger::getInstance();
428
        $xoopsLogger->startTime('Page rendering');
429
430
        xoops_load('xoopscache');
431
        $cache = XoopsCache::getInstance();
432
433
        //Get meta information for cached pages
434
        if ($this->contentCacheLifetime && $this->contentCacheId && $content = $cache->read($this->contentCacheId)) {
435
            //we need to merge metas set by blocks ) with the module cached meta
436
            $this->htmlHeadStrings = array_merge($this->htmlHeadStrings, $content['htmlHeadStrings']);
437
            foreach ($content['metas'] as $type => $value) {
438
                $this->metas[$type] = array_merge($this->metas[$type], $content['metas'][$type]);
439
            }
440
            $GLOBALS['xoopsOption']['xoops_pagetitle']     = $content['xoops_pagetitle'];
441
            $GLOBALS['xoopsOption']['xoops_module_header'] = $content['header'];
442
        }
443
444
        if (!empty($GLOBALS['xoopsOption']['xoops_pagetitle'])) {
445
            $this->template->assign('xoops_pagetitle', $GLOBALS['xoopsOption']['xoops_pagetitle']);
446
        }
447
        $header = empty($GLOBALS['xoopsOption']['xoops_module_header']) ? $this->template->get_template_vars('xoops_module_header') : $GLOBALS['xoopsOption']['xoops_module_header'];
448
449
        //save meta information of cached pages
450
        if ($this->contentCacheLifetime && $this->contentCacheId && !$contentTpl) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $contentTpl 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...
451
            $content['htmlHeadStrings'] = $this->htmlHeadStrings;
0 ignored issues
show
Bug introduced by
The variable $content does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
452
            $content['metas']           = $this->metas;
453
            $content['xoops_pagetitle'] =& $this->template->get_template_vars('xoops_pagetitle');
454
            $content['header']          = $header;
455
            $cache->write($this->contentCacheId, $content);
456
        }
457
458
        //  @internal : Lame fix to ensure the metas specified in the xoops config page don't appear twice
459
        $old = array(
460
            'robots',
461
            'keywords',
462
            'description',
463
            'rating',
464
            'author',
465
            'copyright');
466
        foreach ($this->metas['meta'] as $name => $value) {
467
            if (in_array($name, $old)) {
468
                $this->template->assign("xoops_meta_$name", htmlspecialchars($value, ENT_QUOTES));
469
                unset($this->metas['meta'][$name]);
470
            }
471
        }
472
473
        // We assume no overlap between $GLOBALS['xoopsOption']['xoops_module_header'] and $this->template->get_template_vars( 'xoops_module_header' ) ?
474
        $this->template->assign('xoops_module_header', $this->renderMetas(null, true) . "\n" . $header);
475
476
        if ($canvasTpl) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $canvasTpl of type string|null 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...
477
            $this->canvasTemplate = $canvasTpl;
478
        }
479
        if ($contentTpl) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $contentTpl of type string|null 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...
480
            $this->contentTemplate = $contentTpl;
481
        }
482
        if (!empty($vars)) {
483
            $this->template->assign($vars);
484
        }
485
        if ($this->contentTemplate) {
486
            $this->content = $this->template->fetch($this->contentTemplate, $this->contentCacheId);
487
        }
488
        if ($this->bufferOutput) {
489
            $this->content .= ob_get_contents();
490
            ob_end_clean();
491
        }
492
493
        $this->template->assign_by_ref('xoops_contents', $this->content);
494
495
        // Do not cache the main (theme.html) template output
496
        $this->template->caching = 0;
497
        //mb -------------------------
498
//        $this->template->display($this->path . '/' . $this->canvasTemplate);
499
        if (file_exists($this->path . '/' . $this->canvasTemplate)) {
500
            $this->template->display($this->path . '/' . $this->canvasTemplate);
501
        } else {
502
            $this->template->display($this->path . '/theme.tpl');
503
        }
504
        //mb -------------------------
505
        $this->renderCount++;
506
        $xoopsLogger->stopTime('Page rendering');
507
508
        return true;
509
    }
510
511
    /**
512
     * Load localization information
513
     *
514
     * Folder structure for localization:
515
     * <ul>themes/themefolder/english
516
     *     <li>main.php - language definitions</li>
517
     *     <li>style.css - localization stylesheet</li>
518
     *     <li>script.js - localization script</li>
519
     * </ul>
520
     * @param  string $type
521
     * @return bool
522
     */
523
    public function loadLocalization($type = 'main')
524
    {
525
        $language = $GLOBALS['xoopsConfig']['language'];
526
        // Load global localization stylesheet if available
527
        if (file_exists($GLOBALS['xoops']->path('language/' . $language . '/style.css'))) {
528
            $this->addStylesheet($GLOBALS['xoops']->url('language/' . $language . '/style.css'));
529
        }
530
        $this->addLanguage($type, $language);
531
        // Load theme localization stylesheet and scripts if available
532 View Code Duplication
        if (file_exists($this->path . '/language/' . $language . '/script.js')) {
533
            $this->addScript($this->url . '/language/' . $language . '/script.js');
534
        }
535 View Code Duplication
        if (file_exists($this->path . '/language/' . $language . '/style.css')) {
536
            $this->addStylesheet($this->url . '/language/' . $language . '/style.css');
537
        }
538
539
        return true;
540
    }
541
542
    /**
543
     * Load theme specific language constants
544
     *
545
     * @param string $type     language type, like 'main', 'admin'; Needs to be declared in theme xo-info.php
546
     * @param string $language specific language
547
     *
548
     * @return bool|mixed
549
     */
550
    public function addLanguage($type = 'main', $language = null)
551
    {
552
        $language = (null === $language) ? $GLOBALS['xoopsConfig']['language'] : $language;
553
        if (!file_exists($fileinc = $this->path . "/language/{$language}/{$type}.php")) {
554
            if (!file_exists($fileinc = $this->path . "/language/english/{$type}.php")) {
555
                return false;
556
            }
557
        }
558
        $ret = include_once $fileinc;
559
560
        return $ret;
561
    }
562
563
    /**
564
     * *#@+
565
     *
566
     * @tasktype 20 Manipulating page meta-information
567
     */
568
    /**
569
     * Adds script code to the document head
570
     *
571
     * This methods allows the insertion of an external script file (if $src is provided), or
572
     * of a script snippet. The file URI is parsed to take benefit of the theme resource
573
     * overloading system.
574
     *
575
     * The $attributes parameter allows you to specify the attributes that will be added to the
576
     * inserted <script> tag. If unspecified, the <var>type</var> attribute value will default to
577
     * 'text/javascript'.
578
     *
579
     * <code>
580
     * // Add an external script using a physical path
581
     * $theme->addScript( 'www/script.js', null, '' );
582
     * $theme->addScript( 'modules/newbb/script.js', null, '' );
583
     * // Specify attributes for the <script> tag
584
     * $theme->addScript( 'mod_xoops_SiteManager#common.js', array( 'type' => 'application/x-javascript' ), '', 'mod_xoops_Sitemanager' );
585
     * // Insert a code snippet
586
     * $theme->addScript( null, array( 'type' => 'application/x-javascript' ), 'window.open("Hello world");', 'hello' );
587
     * </code>
588
     *
589
     * @param  string $src        path to an external script file
590
     * @param  array  $attributes hash of attributes to add to the <script> tag
591
     * @param  string $content    Code snippet to output within the <script> tag
592
     * @param  string $name       Element Name in array scripts are stored in.
593
     * @return void
594
     */
595 View Code Duplication
    public function addScript($src = '', $attributes = array(), $content = '', $name = '')
596
    {
597
        if (empty($attributes)) {
598
            $attributes = array();
599
        }
600
        if (!empty($src)) {
601
            $src               = $GLOBALS['xoops']->url($this->resourcePath($src));
602
            $attributes['src'] = $src;
603
        }
604
        if (!empty($content)) {
605
            $attributes['_'] = $content;
606
        }
607
        if (!isset($attributes['type'])) {
608
            $attributes['type'] = 'text/javascript';
609
        }
610
        if (empty($name)) {
611
            $name = md5(serialize($attributes));
612
        }
613
        $this->addMeta('script', $name, $attributes);
614
    }
615
616
    /**
617
     * Add StyleSheet or CSS code to the document head
618
     *
619
     * @param  string $src        path to .css file
620
     * @param  array  $attributes name => value paired array of attributes such as title
621
     * @param  string $content    CSS code to output between the <style> tags (in case $src is empty)
622
     * @param  string $name       Element Name in array stylesheets are stored in.
623
     * @return void
624
     */
625 View Code Duplication
    public function addStylesheet($src = '', $attributes = array(), $content = '', $name = '')
626
    {
627
        if (empty($attributes)) {
628
            $attributes = array();
629
        }
630
        if (!empty($src)) {
631
            $src                = $GLOBALS['xoops']->url($this->resourcePath($src));
632
            $attributes['href'] = $src;
633
        }
634
        if (!isset($attributes['type'])) {
635
            $attributes['type'] = 'text/css';
636
        }
637
        if (!empty($content)) {
638
            $attributes['_'] = $content;
639
        }
640
        if (empty($name)) {
641
            $name = md5(serialize($attributes));
642
        }
643
        $this->addMeta('stylesheet', $name, $attributes);
644
    }
645
646
    /**
647
     * Add a <link> to the header
648
     *
649
     * @param string $rel        Relationship from the current doc to the anchored one
650
     * @param string $href       URI of the anchored document
651
     * @param array  $attributes Additional attributes to add to the <link> element
652
     * @param string $name       Element Name in array links are stored in.
653
     */
654
    public function addLink($rel, $href = '', $attributes = array(), $name = '')
655
    {
656
        if (empty($attributes)) {
657
            $attributes = array();
658
        }
659
        if (!empty($href)) {
660
            $attributes['href'] = $href;
661
        }
662
        $attributes['rel'] = $rel;
663
        if (empty($name)) {
664
            $name = md5(serialize($attributes));
665
        }
666
        $this->addMeta('link', $name, $attributes);
667
    }
668
669
    /**
670
     * Set a meta http-equiv value
671
     * @param         $name
672
     * @param  null   $value
673
     * @return string
0 ignored issues
show
Documentation introduced by
Should the return type not be string|null?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
674
     */
675
    public function addHttpMeta($name, $value = null)
676
    {
677
        if (isset($value)) {
678
            return $this->addMeta('http', $name, $value);
679
        }
680
        unset($this->metas['http'][$name]);
681
        return null;
682
    }
683
684
    /**
685
     * Change output page meta-information
686
     * @param  string $type
687
     * @param  string $name
688
     * @param  string $value
689
     * @return string
690
     */
691
    public function addMeta($type = 'meta', $name = '', $value = '')
692
    {
693
        if (!isset($this->metas[$type])) {
694
            $this->metas[$type] = array();
695
        }
696
        if (!empty($name)) {
697
            $this->metas[$type][$name] = $value;
698
        } else {
699
            $this->metas[$type][md5(serialize(array($value)))] = $value;
700
        }
701
702
        return $value;
703
    }
704
705
    /**
706
     * xos_opal_Theme::headContent()
707
     *
708
     * @param mixed $params
709
     * @param mixed $content
710
     * @param mixed $smarty
711
     * @param mixed $repeat
712
     *
713
     * @return void
714
     */
715
    public function headContent($params, $content, &$smarty, &$repeat)
0 ignored issues
show
Unused Code introduced by
The parameter $params is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $smarty is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
716
    {
717
        if (!$repeat) {
718
            $this->htmlHeadStrings[] = $content;
719
        }
720
    }
721
722
    /**
723
     * xos_opal_Theme::renderMetas()
724
     *
725
     * @param  mixed $type
726
     * @param  mixed $return
727
     * @return bool|string
728
     */
729
    public function renderMetas($type = null, $return = false)
730
    {
731
        $str = '';
732
        if (!isset($type)) {
733
            foreach (array_keys($this->metas) as $type) {
734
                $str .= $this->renderMetas($type, true);
735
            }
736
            $str .= implode("\n", $this->htmlHeadStrings);
737
        } else {
738
            switch ($type) {
739 View Code Duplication
                case 'script':
740
                    foreach ($this->metas[$type] as $attrs) {
741
                        $str .= '<script' . $this->renderAttributes($attrs) . '>';
742
                        if (@$attrs['_']) {
743
                            $str .= "\n//<![CDATA[\n" . $attrs['_'] . "\n//]]>";
744
                        }
745
                        $str .= "</script>\n";
746
                    }
747
                    break;
748
                case 'link':
749
                    foreach ($this->metas[$type] as $attrs) {
750
                        $rel = $attrs['rel'];
751
                        unset($attrs['rel']);
752
                        $str .= '<link rel="' . $rel . '"' . $this->renderAttributes($attrs) . " />\n";
753
                    }
754
                    break;
755 View Code Duplication
                case 'stylesheet':
756
                    foreach ($this->metas[$type] as $attrs) {
757
                        if (@$attrs['_']) {
758
                            $str .= '<style' . $this->renderAttributes($attrs) . ">\n/* <![CDATA[ */\n" . $attrs['_'] . "\n/* //]]> */\n</style>";
759
                        } else {
760
                            $str .= '<link rel="stylesheet"' . $this->renderAttributes($attrs) . " />\n";
761
                        }
762
                    }
763
                    break;
764 View Code Duplication
                case 'http':
765
                    foreach ($this->metas[$type] as $name => $content) {
766
                        $str .= '<meta http-equiv="' . htmlspecialchars($name, ENT_QUOTES) . '" content="' . htmlspecialchars($content, ENT_QUOTES) . "\" />\n";
767
                    }
768
                    break;
769 View Code Duplication
                default:
770
                    foreach ($this->metas[$type] as $name => $content) {
771
                        $str .= '<meta name="' . htmlspecialchars($name, ENT_QUOTES) . '" content="' . htmlspecialchars($content, ENT_QUOTES) . "\" />\n";
772
                    }
773
                    break;
774
            }
775
        }
776
        if ($return) {
777
            return $str;
778
        }
779
        echo $str;
780
781
        return true;
782
    }
783
784
    /**
785
     * Generates a unique element ID
786
     *
787
     * @param  string $tagName
788
     * @return string
789
     */
790
    public function genElementId($tagName = 'xos')
791
    {
792
        static $cache = array();
793
        if (!isset($cache[$tagName])) {
794
            $cache[$tagName] = 1;
795
        }
796
797
        return $tagName . '-' . $cache[$tagName]++;
798
    }
799
800
    /**
801
     * Transform an attributes collection to an XML string
802
     *
803
     * @param  array $coll
804
     * @return string
805
     */
806
    public function renderAttributes($coll)
807
    {
808
        $str = '';
809
        foreach ($coll as $name => $val) {
810
            if ($name !== '_') {
811
                $str .= ' ' . $name . '="' . htmlspecialchars($val, ENT_QUOTES) . '"';
812
            }
813
        }
814
815
        return $str;
816
    }
817
818
    /**
819
     * Return a themable file resource path
820
     *
821
     * @param  string $path
822
     * @return string
823
     */
824
    public function resourcePath($path)
825
    {
826
        if (substr($path, 0, 1) === '/') {
827
            $path = substr($path, 1);
828
        }
829
830
        if (file_exists(XOOPS_ROOT_PATH . "/{$this->themesPath}/{$this->folderName}/{$path}")) {
831
            return "{$this->themesPath}/{$this->folderName}/{$path}";
832
        }
833
834
        if (file_exists(XOOPS_ROOT_PATH . "/themes/{$this->folderName}/{$path}")) {
835
            return "themes/{$this->folderName}/{$path}";
836
        }
837
838
        return $path;
839
    }
840
}
841