Completed
Push — master ( 28e496...caa3d6 )
by Richard
22s queued 10s
created

xos_opal_ThemeFactory::createInstance()   C

Complexity

Conditions 12
Paths 24

Size

Total Lines 32
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 22
c 1
b 0
f 0
dl 0
loc 32
rs 6.9666
cc 12
nc 24
nop 2

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
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
use Xmf\Request;
22
23
defined('XOOPS_ROOT_PATH') || exit('Restricted access');
24
25
/**
26
 * xos_opal_ThemeFactory
27
 *
28
 * @author     Skalpa Keo
29
 * @package    xos_opal
30
 * @subpackage xos_opal_Theme
31
 * @since      2.3.0
32
 */
33
class xos_opal_ThemeFactory
34
{
35
    public $xoBundleIdentifier = 'xos_opal_ThemeFactory';
36
    /**
37
     * Currently enabled themes (if empty, all the themes in themes/ are allowed)
38
     *
39
     * @var array
40
     */
41
    public $allowedThemes = array();
42
    /**
43
     * Default theme to instantiate if none specified
44
     *
45
     * @var string
46
     */
47
    public $defaultTheme = 'default';
48
    /**
49
     * If users are allowed to choose a custom theme
50
     *
51
     * @var bool
52
     */
53
    public $allowUserSelection = true;
54
55
    /**
56
     * Instantiate the specified theme
57
     * @param  array $options
58
     * @param  array $initArgs
59
     * @return null|xos_opal_Theme
60
     */
61
    public function createInstance($options = array(), $initArgs = array())
62
    {
63
        // Grab the theme folder from request vars if present
64
        if (empty($options['folderName'])) {
65
            if (($req = @$_REQUEST['xoops_theme_select']) && $this->isThemeAllowed($req)) {
66
                $options['folderName'] = $req;
67
                if (isset($_SESSION) && $this->allowUserSelection) {
68
                    $_SESSION[$this->xoBundleIdentifier]['defaultTheme'] = $req;
69
                }
70
            } elseif (isset($_SESSION[$this->xoBundleIdentifier]['defaultTheme'])) {
71
                $options['folderName'] = $_SESSION[$this->xoBundleIdentifier]['defaultTheme'];
72
            } elseif (empty($options['folderName']) || !$this->isThemeAllowed($options['folderName'])) {
73
                $options['folderName'] = $this->defaultTheme;
74
            }
75
            $GLOBALS['xoopsConfig']['theme_set'] = $options['folderName'];
76
        }
77
        if (!(file_exists(XOOPS_THEME_PATH . '/' . $options['folderName'] .'/theme.tpl')
78
            || file_exists(XOOPS_THEME_PATH . '/' . $options['folderName'] .'/theme.html'))
79
        ) {
80
            trigger_error('Theme not found -- ' . $options['folderName']);
81
            $this->defaultTheme = 'default';
82
            $options['folderName'] = $this->defaultTheme;
83
            $GLOBALS['xoopsConfig']['theme_set'] = $options['folderName'];
84
        }
85
        $options['path'] = XOOPS_THEME_PATH . '/' . $options['folderName'];
86
        $inst            = new xos_opal_Theme();
87
        foreach ($options as $k => $v) {
88
            $inst->$k = $v;
89
        }
90
        $inst->xoInit();
91
92
        return $inst;
93
    }
94
95
    /**
96
     * Checks if the specified theme is enabled or not
97
     *
98
     * @param  string $name
99
     * @return bool
100
     */
101
    public function isThemeAllowed($name)
102
    {
103
        return (empty($this->allowedThemes) || in_array($name, $this->allowedThemes));
104
    }
105
}
106
107
/**
108
 * xos_opal_AdminThemeFactory
109
 *
110
 * @author     Andricq Nicolas (AKA MusS)
111
 * @author     trabis
112
 * @package    xos_opal
113
 * @subpackage xos_opal_Theme
114
 * @since      2.4.0
115
 */
116
class xos_opal_AdminThemeFactory extends xos_opal_ThemeFactory
117
{
118
    /**
119
     * @param array $options
120
     * @param array $initArgs
121
     *
122
     * @return null|xos_opal_Theme
123
     */
124
    public function &createInstance($options = array(), $initArgs = array())
125
    {
126
        $options['plugins']      = array();
127
        $options['renderBanner'] = false;
128
        $inst                    = parent::createInstance($options, $initArgs);
129
        $inst->path              = XOOPS_ADMINTHEME_PATH . '/' . $inst->folderName;
130
        $inst->url               = XOOPS_ADMINTHEME_URL . '/' . $inst->folderName;
131
        $inst->template->assign(array(
132
                                    'theme_path'  => $inst->path,
133
                                    'theme_tpl'   => $inst->path . '/xotpl',
134
                                    'theme_url'   => $inst->url,
135
                                    'theme_img'   => $inst->url . '/img',
136
                                    'theme_icons' => $inst->url . '/icons',
137
                                    'theme_css'   => $inst->url . '/css',
138
                                    'theme_js'    => $inst->url . '/js',
139
                                    'theme_lang'  => $inst->url . '/language'));
140
141
        return $inst;
142
    }
143
}
144
145
/**
146
 * Class xos_opal_Theme
147
 */
148
class xos_opal_Theme
149
{
150
    /**
151
     * Should we render banner? Not for redirect pages or admin side
152
     *
153
     * @var bool
154
     */
155
    public $renderBanner = true;
156
    /**
157
     * The name of this theme
158
     *
159
     * @var string
160
     */
161
    public $folderName = '';
162
    /**
163
     * Physical path of this theme folder
164
     *
165
     * @var string
166
     */
167
    public $path = '';
168
    public $url  = '';
169
170
    /**
171
     * Whether or not the theme engine should include the output generated by php
172
     *
173
     * @var string
174
     */
175
    public $bufferOutput = true;
176
    /**
177
     * Canvas-level template to use
178
     *
179
     * @var string
180
     */
181
    public $canvasTemplate = 'theme.tpl';
182
183
    /**
184
     * Theme folder path
185
     *
186
     * @var string
187
     */
188
    public $themesPath = 'themes';
189
190
    /**
191
     * Content-level template to use
192
     *
193
     * @var string
194
     */
195
    public $contentTemplate = '';
196
197
    public $contentCacheLifetime = 0;
198
    public $contentCacheId;
199
200
    /**
201
     * Text content to display right after the contentTemplate output
202
     *
203
     * @var string
204
     */
205
    public $content = '';
206
    /**
207
     * Page construction plug-ins to use
208
     *
209
     * @var array
210
     * @access public
211
     */
212
    public $plugins     = array(
213
        'xos_logos_PageBuilder');
214
    public $renderCount = 0;
215
    /**
216
     * Pointer to the theme template engine
217
     *
218
     * @var XoopsTpl
219
     */
220
    public $template = false;
221
222
    /**
223
     * Array containing the document meta-information
224
     *
225
     * @var array
226
     */
227
    public $metas = array(
228
        //'http' => array(
229
        //    'Content-Script-Type' => 'text/javascript' ,
230
        //    'Content-Style-Type' => 'text/css') ,
231
        'meta'   => array(),
232
        'link'   => array(),
233
        'script' => array());
234
235
    /**
236
     * Array of strings to be inserted in the head tag of HTML documents
237
     *
238
     * @var array
239
     */
240
    public $htmlHeadStrings = array();
241
    /**
242
     * Custom variables that will always be assigned to the template
243
     *
244
     * @var array
245
     */
246
    public $templateVars = array();
247
248
    /**
249
     * User extra information for cache id, like language, user groups
250
     *
251
     * @var boolean
252
     */
253
    public $use_extra_cache_id = true;
254
255
    /**
256
     * *#@-
257
     */
258
259
    /**
260
     * *#@+
261
     *
262
     * @tasktype 10 Initialization
263
     */
264
    /**
265
     * Initializes this theme
266
     *
267
     * Upon initialization, the theme creates its template engine and instantiates the
268
     * plug-ins from the specified {@link $plugins} list. If the theme is a 2.0 theme, that does not
269
     * display redirection messages, the HTTP redirections system is disabled to ensure users will
270
     * see the redirection screen.
271
     *
272
     * @param  array $options
273
     * @return bool
274
     */
275
    public function xoInit($options = array())
0 ignored issues
show
Unused Code introduced by
The parameter $options is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

275
    public function xoInit(/** @scrutinizer ignore-unused */ $options = array())

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

Loading history...
276
    {
277
        /** @var XoopsConfigHandler $configHandler */
278
        $configHandler = xoops_getHandler('config');
279
280
        $this->path                   = XOOPS_THEME_PATH . '/' . $this->folderName;
281
        $this->url                    = XOOPS_THEME_URL . '/' . $this->folderName;
282
        $this->template               = null;
283
        $this->template               = new XoopsTpl();
284
        $this->template->currentTheme = $this;
0 ignored issues
show
Bug introduced by
The property currentTheme does not seem to exist on XoopsTpl.
Loading history...
285
        $this->template->assign_by_ref('xoTheme', $this);
286
        $GLOBALS['xoTheme']  = $this;
287
        $GLOBALS['xoopsTpl'] = $this->template;
288
        $tempPath = str_replace('\\', '/', realpath(XOOPS_ROOT_PATH) . '/');
289
        $tempName = str_replace('\\', '/', realpath($_SERVER['SCRIPT_FILENAME']));
290
        $xoops_page = str_replace($tempPath, '', $tempName);
291
        if (strpos($xoops_page, 'modules') !== false) {
292
            $xoops_page = str_replace('modules/', '', $xoops_page);
293
        }
294
        $tempScriptname = str_replace('\\', '/', $_SERVER['SCRIPT_NAME']);
295
        $tempRequesturi = str_replace('\\', '/', Request::getString('REQUEST_URI', '', 'SERVER'));
296
        if (strlen($tempRequesturi) > strlen($tempScriptname)) {
297
            $xoops_modulepage =  $xoops_page . str_replace($tempScriptname, '', $tempRequesturi);
298
        } else {
299
            $xoops_modulepage =  '';
300
        }
301
        $xoops_page = str_replace('.php', '', $xoops_page);
302
        if (isset($GLOBALS['xoopsConfig']['startpage'])) {
303
            $xoops_startpage = $GLOBALS['xoopsConfig']['startpage'];
304
            if ($xoops_startpage == '--') {
305
                $xoops_startpage = 'system';
306
            }
307
        } else {
308
            $xoops_startpage = 'system';
309
        }
310
        // call the theme_autorun.php if the theme has one
311
        if (file_exists($this->path . "/theme_autorun.php")) {
312
            include_once($this->path . "/theme_autorun.php");
313
        }
314
315
        $searchConfig = $configHandler->getConfigsByCat(XOOPS_CONF_SEARCH);
316
        $xoops_search = (bool) (isset($searchConfig['enable_search']) && $searchConfig['enable_search'] === 1);
317
        $this->template->assign(array(
318
            'xoops_theme'      => $GLOBALS['xoopsConfig']['theme_set'],
319
            'xoops_imageurl'   => XOOPS_THEME_URL . '/' . $GLOBALS['xoopsConfig']['theme_set'] . '/',
320
            'xoops_themecss'   => xoops_getcss($GLOBALS['xoopsConfig']['theme_set']),
321
            'xoops_requesturi' => htmlspecialchars($_SERVER['REQUEST_URI'], ENT_QUOTES),
322
            'xoops_sitename'   => htmlspecialchars($GLOBALS['xoopsConfig']['sitename'], ENT_QUOTES),
323
            'xoops_slogan'     => htmlspecialchars($GLOBALS['xoopsConfig']['slogan'], ENT_QUOTES),
324
            'xoops_dirname'    => isset($GLOBALS['xoopsModule']) && is_object($GLOBALS['xoopsModule'])
325
                ? $GLOBALS['xoopsModule']->getVar('dirname') : 'system',
326
            'xoops_page'       => $xoops_page,
327
            'xoops_startpage'  => $xoops_startpage,
328
            'xoops_modulepage' => $xoops_modulepage,
329
            'xoops_banner'     => ($GLOBALS['xoopsConfig']['banners'] && $this->renderBanner)
330
                ? xoops_getbanner() : '&nbsp;',
331
            'xoops_pagetitle'  => isset($GLOBALS['xoopsModule']) && is_object($GLOBALS['xoopsModule'])
332
                ? $GLOBALS['xoopsModule']->getVar('name')
333
                : htmlspecialchars($GLOBALS['xoopsConfig']['slogan'], ENT_QUOTES),
334
            'xoops_search'     => $xoops_search,
335
        ));
336
        if (isset($GLOBALS['xoopsUser']) && is_object($GLOBALS['xoopsUser'])) {
337
            $this->template->assign(array(
338
                'xoops_isuser'     => true,
339
                'xoops_avatar'     => XOOPS_UPLOAD_URL . '/' . $GLOBALS['xoopsUser']->getVar('user_avatar'),
340
                'xoops_userid'     => $GLOBALS['xoopsUser']->getVar('uid'),
341
                'xoops_uname'      => $GLOBALS['xoopsUser']->getVar('uname'),
342
                'xoops_name'       => $GLOBALS['xoopsUser']->getVar('name'),
343
                'xoops_isadmin'    => $GLOBALS['xoopsUserIsAdmin'],
344
                'xoops_usergroups' => $GLOBALS['xoopsUser']->getGroups(),
345
            ));
346
        } else {
347
            $this->template->assign(array(
348
                'xoops_isuser'     => false,
349
                'xoops_isadmin'    => false,
350
                'xoops_usergroups' => array(XOOPS_GROUP_ANONYMOUS),
351
            ));
352
        }
353
354
        // Meta tags
355
        $criteria       = new CriteriaCompo(new Criteria('conf_modid', 0));
356
        $criteria->add(new Criteria('conf_catid', XOOPS_CONF_METAFOOTER));
357
        $config = $configHandler->getConfigs($criteria, true);
358
        foreach (array_keys($config) as $i) {
359
            $name  = $config[$i]->getVar('conf_name', 'n');
360
            $value = $config[$i]->getVar('conf_value', 'n');
361
            if (substr($name, 0, 5) === 'meta_') {
362
                $this->addMeta('meta', substr($name, 5), $value);
363
            } else {
364
                // prefix each tag with 'xoops_'
365
                $this->template->assign("xoops_$name", $value);
366
            }
367
        }
368
        // Load global javascript
369
        $this->addScript('include/xoops.js');
370
        $this->loadLocalization();
371
372
        if ($this->bufferOutput) {
373
            ob_start();
374
        }
375
        // Instantiate and initialize all the theme plugins
376
        foreach ($this->plugins as $k => $bundleId) {
377
            if (!is_object($bundleId)) {
378
                $this->plugins[$bundleId]        = null;
379
                $this->plugins[$bundleId]        = new $bundleId();
380
                $this->plugins[$bundleId]->theme =& $this;
381
                $this->plugins[$bundleId]->xoInit();
382
                unset($this->plugins[$k]);
383
            }
384
        }
385
386
        return true;
387
    }
388
389
    /**
390
     * Generate cache id based on extra information of language and user groups
391
     *
392
     * User groups other than anonymous should be detected to avoid disclosing group sensitive contents
393
     *
394
     * @param  string $cache_id    raw cache id
395
     * @param  string $extraString extra string
396
     * @return string complete cache id
397
     */
398
    public function generateCacheId($cache_id, $extraString = '')
399
    {
400
        static $extra_string;
401
        if (!$this->use_extra_cache_id) {
402
            return $cache_id;
403
        }
404
405
        if (empty($extraString)) {
406
            if (empty($extra_string)) {
407
                // Generate language section
408
                $extra_string = $GLOBALS['xoopsConfig']['language'];
409
                // Generate group section
410
                if (!isset($GLOBALS['xoopsUser']) || !is_object($GLOBALS['xoopsUser'])) {
411
                    $extra_string .= '-' . XOOPS_GROUP_ANONYMOUS;
412
                } else {
413
                    $groups = $GLOBALS['xoopsUser']->getGroups();
414
                    sort($groups);
415
                    // Generate group string for non-anonymous groups,
416
                    // XOOPS_DB_PASS and XOOPS_DB_NAME (before we find better variables) are used to protect group sensitive contents
417
                    $extra_string .= '-' . substr(md5(implode('-', $groups)), 0, 8) . '-' . substr(md5(XOOPS_DB_PASS . XOOPS_DB_NAME . XOOPS_DB_USER), 0, 8);
418
                }
419
            }
420
            $extraString = $extra_string;
421
        }
422
        $cache_id .= '-' . $extraString;
423
424
        return $cache_id;
425
    }
426
427
    /**
428
     * xos_opal_Theme::checkCache()
429
     *
430
     * @return bool
431
     */
432
    public function checkCache()
433
    {
434
        if ($_SERVER['REQUEST_METHOD'] !== 'POST' && $this->contentCacheLifetime) {
435
            $template                       = $this->contentTemplate ?: 'db:system_dummy.tpl';
436
            $this->template->caching        = 2;
437
            $this->template->cache_lifetime = $this->contentCacheLifetime;
438
            $uri                            = str_replace(XOOPS_URL, '', $_SERVER['REQUEST_URI']);
439
            // Clean uri by removing session id
440
            if (defined('SID') && SID && strpos($uri, SID)) {
441
                $uri = preg_replace("/([\?&])(" . SID . "$|" . SID . '&)/', "\\1", $uri);
442
            }
443
            $this->contentCacheId = $this->generateCacheId('page_' . substr(md5($uri), 0, 8));
444
            if ($this->template->is_cached($template, $this->contentCacheId)) {
445
                $xoopsLogger = XoopsLogger::getInstance();
446
                $xoopsLogger->addExtra($template, sprintf('Cached (regenerates every %d seconds)', $this->contentCacheLifetime));
447
                $this->render(null, null, $template);
448
449
                return true;
450
            }
451
        }
452
453
        return false;
454
    }
455
456
    /**
457
     * Render the page
458
     *
459
     * The theme engine builds pages from 2 templates: canvas and content.
460
     *
461
     * A module can call this method directly and specify what templates the theme engine must use.
462
     * If render() hasn't been called before, the theme defaults will be used for the canvas and
463
     * page template (and xoopsOption['template_main'] for the content).
464
     *
465
     * @param string $canvasTpl  The canvas template, if different from the theme default
466
     * @param string $pageTpl    The page template, if different from the theme default (unsupported, 2.3+ only)
467
     * @param string $contentTpl The content template
468
     * @param array  $vars       Template variables to send to the template engine
469
     *
470
     * @return bool
471
     */
472
    public function render($canvasTpl = null, $pageTpl = null, $contentTpl = null, $vars = array())
473
    {
474
        if ($this->renderCount) {
475
            return false;
476
        }
477
        $xoopsLogger = XoopsLogger::getInstance();
478
        $xoopsLogger->startTime('Page rendering');
479
480
        xoops_load('xoopscache');
481
        $cache = XoopsCache::getInstance();
482
483
        //Get meta information for cached pages
484
        if ($this->contentCacheLifetime && $this->contentCacheId && $content = $cache->read($this->contentCacheId)) {
485
            //we need to merge metas set by blocks ) with the module cached meta
486
            $this->htmlHeadStrings = array_merge($this->htmlHeadStrings, $content['htmlHeadStrings']);
487
            foreach ($content['metas'] as $type => $value) {
488
                $this->metas[$type] = array_merge($this->metas[$type], $content['metas'][$type]);
489
            }
490
            $GLOBALS['xoopsOption']['xoops_pagetitle']     = $content['xoops_pagetitle'];
491
            $GLOBALS['xoopsOption']['xoops_module_header'] = $content['header'];
492
        }
493
494
        if (!empty($GLOBALS['xoopsOption']['xoops_pagetitle'])) {
495
            $this->template->assign('xoops_pagetitle', $GLOBALS['xoopsOption']['xoops_pagetitle']);
496
        }
497
        $header = empty($GLOBALS['xoopsOption']['xoops_module_header']) ? $this->template->get_template_vars('xoops_module_header') : $GLOBALS['xoopsOption']['xoops_module_header'];
498
499
        //save meta information of cached pages
500
        if ($this->contentCacheLifetime && $this->contentCacheId && !$contentTpl) {
501
            $content['htmlHeadStrings'] = $this->htmlHeadStrings;
502
            $content['metas']           = $this->metas;
503
            $content['xoops_pagetitle'] =& $this->template->get_template_vars('xoops_pagetitle');
504
            $content['header']          = $header;
505
            $cache->write($this->contentCacheId, $content);
506
        }
507
508
        //  @internal : Lame fix to ensure the metas specified in the xoops config page don't appear twice
509
        $old = array(
510
            'robots',
511
            'keywords',
512
            'description',
513
            'rating',
514
            'author',
515
            'copyright');
516
        foreach ($this->metas['meta'] as $name => $value) {
517
            if (in_array($name, $old)) {
518
                $this->template->assign("xoops_meta_$name", htmlspecialchars($value, ENT_QUOTES));
519
                unset($this->metas['meta'][$name]);
520
            }
521
        }
522
523
        // We assume no overlap between $GLOBALS['xoopsOption']['xoops_module_header'] and $this->template->get_template_vars( 'xoops_module_header' ) ?
524
        $this->template->assign('xoops_module_header', $this->renderMetas(null, true) . "\n" . $header);
0 ignored issues
show
Bug introduced by
Are you sure $header of type array|mixed can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

524
        $this->template->assign('xoops_module_header', $this->renderMetas(null, true) . "\n" . /** @scrutinizer ignore-type */ $header);
Loading history...
525
526
        if ($canvasTpl) {
527
            $this->canvasTemplate = $canvasTpl;
528
        }
529
        if ($contentTpl) {
530
            $this->contentTemplate = $contentTpl;
531
        }
532
        if (!empty($vars)) {
533
            $this->template->assign($vars);
534
        }
535
        if ($this->contentTemplate) {
536
            $this->content = $this->template->fetch($this->contentTemplate, $this->contentCacheId);
537
        }
538
        if ($this->bufferOutput) {
539
            $this->content .= ob_get_contents();
540
            ob_end_clean();
541
        }
542
543
        $this->template->assign_by_ref('xoops_contents', $this->content);
544
545
        // Do not cache the main (theme.html) template output
546
        $this->template->caching = 0;
547
        if (file_exists($this->path . '/' . $this->canvasTemplate)) {
548
            $this->template->display($this->path . '/' . $this->canvasTemplate);
549
        } else {
550
            $this->template->display($this->path . '/theme.html');
551
        }
552
        $this->renderCount++;
553
        $xoopsLogger->stopTime('Page rendering');
554
555
        return true;
556
    }
557
558
    /**
559
     * Load localization information
560
     *
561
     * Folder structure for localization:
562
     * <ul>themes/themefolder/english
563
     *     <li>main.php - language definitions</li>
564
     *     <li>style.css - localization stylesheet</li>
565
     *     <li>script.js - localization script</li>
566
     * </ul>
567
     * @param  string $type
568
     * @return bool
569
     */
570
    public function loadLocalization($type = 'main')
571
    {
572
        $language = $GLOBALS['xoopsConfig']['language'];
573
        // Load global localization stylesheet if available
574
        if (file_exists($GLOBALS['xoops']->path('language/' . $language . '/style.css'))) {
575
            $this->addStylesheet($GLOBALS['xoops']->url('language/' . $language . '/style.css'));
576
        }
577
        $this->addLanguage($type, $language);
578
        // Load theme localization stylesheet and scripts if available
579
        if (file_exists($this->path . '/language/' . $language . '/script.js')) {
580
            $this->addScript($this->url . '/language/' . $language . '/script.js');
581
        }
582
        if (file_exists($this->path . '/language/' . $language . '/style.css')) {
583
            $this->addStylesheet($this->url . '/language/' . $language . '/style.css');
584
        }
585
586
        return true;
587
    }
588
589
    /**
590
     * Load theme specific language constants
591
     *
592
     * @param string $type     language type, like 'main', 'admin'; Needs to be declared in theme xo-info.php
593
     * @param string $language specific language
594
     *
595
     * @return bool|mixed
596
     */
597
    public function addLanguage($type = 'main', $language = null)
598
    {
599
        $language = (null === $language) ? $GLOBALS['xoopsConfig']['language'] : $language;
600
        if (!file_exists($fileinc = $this->path . "/language/{$language}/{$type}.php")) {
601
            if (!file_exists($fileinc = $this->path . "/language/english/{$type}.php")) {
602
                return false;
603
            }
604
        }
605
        $ret = include_once $fileinc;
606
607
        return $ret;
608
    }
609
610
    /**
611
     * *#@+
612
     *
613
     * @tasktype 20 Manipulating page meta-information
614
     */
615
    /**
616
     * Adds script code to the document head
617
     *
618
     * This methods allows the insertion of an external script file (if $src is provided), or
619
     * of a script snippet. The file URI is parsed to take benefit of the theme resource
620
     * overloading system.
621
     *
622
     * The $attributes parameter allows you to specify the attributes that will be added to the
623
     * inserted <script> tag. If unspecified, the <var>type</var> attribute value will default to
624
     * 'text/javascript'.
625
     *
626
     * <code>
627
     * // Add an external script using a physical path
628
     * $theme->addScript( 'www/script.js', null, '' );
629
     * $theme->addScript( 'modules/newbb/script.js', null, '' );
630
     * // Specify attributes for the <script> tag
631
     * $theme->addScript( 'mod_xoops_SiteManager#common.js', array( 'type' => 'application/x-javascript' ), '', 'mod_xoops_Sitemanager' );
632
     * // Insert a code snippet
633
     * $theme->addScript( null, array( 'type' => 'application/x-javascript' ), 'window.open("Hello world");', 'hello' );
634
     * </code>
635
     *
636
     * @param  string $src        path to an external script file
637
     * @param  array  $attributes hash of attributes to add to the <script> tag
638
     * @param  string $content    Code snippet to output within the <script> tag
639
     * @param  string $name       Element Name in array scripts are stored in.
640
     * @return void
641
     */
642
    public function addScript($src = '', $attributes = array(), $content = '', $name = '')
643
    {
644
        if (empty($attributes)) {
645
            $attributes = array();
646
        }
647
        if (!empty($src)) {
648
            $src               = $GLOBALS['xoops']->url($this->resourcePath($src));
649
            $attributes['src'] = $src;
650
        }
651
        if (!empty($content)) {
652
            $attributes['_'] = $content;
653
        }
654
        if (!isset($attributes['type'])) {
655
            $attributes['type'] = 'text/javascript';
656
        }
657
        if (empty($name)) {
658
            $name = md5(serialize($attributes));
659
        }
660
        $this->addMeta('script', $name, $attributes);
0 ignored issues
show
Bug introduced by
$attributes of type array is incompatible with the type string expected by parameter $value of xos_opal_Theme::addMeta(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

660
        $this->addMeta('script', $name, /** @scrutinizer ignore-type */ $attributes);
Loading history...
661
    }
662
663
    /**
664
     * Add StyleSheet or CSS code to the document head
665
     *
666
     * @param  string $src        path to .css file
667
     * @param  array  $attributes name => value paired array of attributes such as title
668
     * @param  string $content    CSS code to output between the <style> tags (in case $src is empty)
669
     * @param  string $name       Element Name in array stylesheets are stored in.
670
     * @return void
671
     */
672
    public function addStylesheet($src = '', $attributes = array(), $content = '', $name = '')
673
    {
674
        if (empty($attributes)) {
675
            $attributes = array();
676
        }
677
        if (!empty($src)) {
678
            $src                = $GLOBALS['xoops']->url($this->resourcePath($src));
679
            $attributes['href'] = $src;
680
        }
681
        if (!isset($attributes['type'])) {
682
            $attributes['type'] = 'text/css';
683
        }
684
        if (!empty($content)) {
685
            $attributes['_'] = $content;
686
        }
687
        if (empty($name)) {
688
            $name = md5(serialize($attributes));
689
        }
690
        $this->addMeta('stylesheet', $name, $attributes);
0 ignored issues
show
Bug introduced by
$attributes of type array is incompatible with the type string expected by parameter $value of xos_opal_Theme::addMeta(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

690
        $this->addMeta('stylesheet', $name, /** @scrutinizer ignore-type */ $attributes);
Loading history...
691
    }
692
693
    /**
694
     * Add a <link> to the header
695
     *
696
     * @param string $rel        Relationship from the current doc to the anchored one
697
     * @param string $href       URI of the anchored document
698
     * @param array  $attributes Additional attributes to add to the <link> element
699
     * @param string $name       Element Name in array links are stored in.
700
     */
701
    public function addLink($rel, $href = '', $attributes = array(), $name = '')
702
    {
703
        if (empty($attributes)) {
704
            $attributes = array();
705
        }
706
        if (!empty($href)) {
707
            $attributes['href'] = $href;
708
        }
709
        $attributes['rel'] = $rel;
710
        if (empty($name)) {
711
            $name = md5(serialize($attributes));
712
        }
713
        $this->addMeta('link', $name, $attributes);
0 ignored issues
show
Bug introduced by
$attributes of type array is incompatible with the type string expected by parameter $value of xos_opal_Theme::addMeta(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

713
        $this->addMeta('link', $name, /** @scrutinizer ignore-type */ $attributes);
Loading history...
714
    }
715
716
    /**
717
     * Set a meta http-equiv value
718
     * @param         $name
719
     * @param  null   $value
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $value is correct as it would always require null to be passed?
Loading history...
720
     * @return string
721
     */
722
    public function addHttpMeta($name, $value = null)
723
    {
724
        if (isset($value)) {
725
            return $this->addMeta('http', $name, $value);
726
        }
727
        unset($this->metas['http'][$name]);
728
        return null;
729
    }
730
731
    /**
732
     * Change output page meta-information
733
     * @param  string $type
734
     * @param  string $name
735
     * @param  string $value
736
     * @return string
737
     */
738
    public function addMeta($type = 'meta', $name = '', $value = '')
739
    {
740
        if (!isset($this->metas[$type])) {
741
            $this->metas[$type] = array();
742
        }
743
        if (!empty($name)) {
744
            $this->metas[$type][$name] = $value;
745
        } else {
746
            $this->metas[$type][md5(serialize(array($value)))] = $value;
747
        }
748
749
        return $value;
750
    }
751
752
    /**
753
     * xos_opal_Theme::headContent()
754
     *
755
     * @param mixed $params
756
     * @param mixed $content
757
     * @param mixed $smarty
758
     * @param mixed $repeat
759
     *
760
     * @return void
761
     */
762
    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. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

762
    public function headContent(/** @scrutinizer ignore-unused */ $params, $content, &$smarty, &$repeat)

This check looks for 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. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

762
    public function headContent($params, $content, /** @scrutinizer ignore-unused */ &$smarty, &$repeat)

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

Loading history...
763
    {
764
        if (!$repeat) {
765
            $this->htmlHeadStrings[] = $content;
766
        }
767
    }
768
769
    /**
770
     * xos_opal_Theme::renderMetas()
771
     *
772
     * @param  mixed $type
773
     * @param  mixed $return
774
     * @return bool|string
775
     */
776
    public function renderMetas($type = null, $return = false)
777
    {
778
        $str = '';
779
        if (!isset($type)) {
780
            foreach (array_keys($this->metas) as $type) {
781
                $str .= $this->renderMetas($type, true);
782
            }
783
            $str .= implode("\n", $this->htmlHeadStrings);
784
        } else {
785
            switch ($type) {
786
                case 'script':
787
                    foreach ($this->metas[$type] as $attrs) {
788
                        $str .= '<script' . $this->renderAttributes($attrs) . '>';
789
                        if (@$attrs['_']) {
790
                            $str .= "\n//<![CDATA[\n" . $attrs['_'] . "\n//]]>";
791
                        }
792
                        $str .= "</script>\n";
793
                    }
794
                    break;
795
                case 'link':
796
                    foreach ($this->metas[$type] as $attrs) {
797
                        $rel = $attrs['rel'];
798
                        unset($attrs['rel']);
799
                        $str .= '<link rel="' . $rel . '"' . $this->renderAttributes($attrs) . " />\n";
800
                    }
801
                    break;
802
                case 'stylesheet':
803
                    foreach ($this->metas[$type] as $attrs) {
804
                        if (@$attrs['_']) {
805
                            $str .= '<style' . $this->renderAttributes($attrs) . ">\n/* <![CDATA[ */\n" . $attrs['_'] . "\n/* //]]> */\n</style>";
806
                        } else {
807
                            $str .= '<link rel="stylesheet"' . $this->renderAttributes($attrs) . " />\n";
808
                        }
809
                    }
810
                    break;
811
                case 'http':
812
                    foreach ($this->metas[$type] as $name => $content) {
813
                        $str .= '<meta http-equiv="' . htmlspecialchars($name, ENT_QUOTES) . '" content="' . htmlspecialchars($content, ENT_QUOTES) . "\" />\n";
814
                    }
815
                    break;
816
                default:
817
                    foreach ($this->metas[$type] as $name => $content) {
818
                        $str .= '<meta name="' . htmlspecialchars($name, ENT_QUOTES) . '" content="' . htmlspecialchars($content, ENT_QUOTES) . "\" />\n";
819
                    }
820
                    break;
821
            }
822
        }
823
        if ($return) {
824
            return $str;
825
        }
826
        echo $str;
827
828
        return true;
829
    }
830
831
    /**
832
     * Generates a unique element ID
833
     *
834
     * @param  string $tagName
835
     * @return string
836
     */
837
    public function genElementId($tagName = 'xos')
838
    {
839
        static $cache = array();
840
        if (!isset($cache[$tagName])) {
841
            $cache[$tagName] = 1;
842
        }
843
844
        return $tagName . '-' . $cache[$tagName]++;
845
    }
846
847
    /**
848
     * Transform an attributes collection to an XML string
849
     *
850
     * @param  array $coll
851
     * @return string
852
     */
853
    public function renderAttributes($coll)
854
    {
855
        $str = '';
856
        foreach ($coll as $name => $val) {
857
            if ($name !== '_') {
858
                $str .= ' ' . $name . '="' . htmlspecialchars($val, ENT_QUOTES) . '"';
859
            }
860
        }
861
862
        return $str;
863
    }
864
865
    /**
866
     * Return a themable file resource path
867
     *
868
     * @param  string $path
869
     * @return string
870
     */
871
    public function resourcePath($path)
872
    {
873
        if (substr($path, 0, 1) === '/') {
874
            $path = substr($path, 1);
875
        }
876
877
        if (file_exists(XOOPS_ROOT_PATH . "/{$this->themesPath}/{$this->folderName}/{$path}")) {
878
            return "{$this->themesPath}/{$this->folderName}/{$path}";
879
        }
880
881
        if (file_exists(XOOPS_ROOT_PATH . "/themes/{$this->folderName}/{$path}")) {
882
            return "themes/{$this->folderName}/{$path}";
883
        }
884
885
        return $path;
886
    }
887
}
888