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
|
|
|
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; |
|
|
|
|
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 |
|
|
|
|
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 |
|
|
|
|
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()) |
|
|
|
|
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; |
|
|
|
|
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() : ' ', |
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()) |
|
|
|
|
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) { |
|
|
|
|
451
|
|
|
$content['htmlHeadStrings'] = $this->htmlHeadStrings; |
|
|
|
|
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) { |
|
|
|
|
477
|
|
|
$this->canvasTemplate = $canvasTpl; |
478
|
|
|
} |
479
|
|
|
if ($contentTpl) { |
|
|
|
|
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 |
|
|
|
|
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) |
|
|
|
|
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
|
|
|
|
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.