1: <?php
2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19:
20:
21: defined('XOOPS_ROOT_PATH') || exit('Restricted access');
22:
23: 24: 25: 26: 27: 28: 29: 30:
31: class xos_opal_ThemeFactory
32: {
33: public $xoBundleIdentifier = 'xos_opal_ThemeFactory';
34: 35: 36: 37: 38:
39: public $allowedThemes = array();
40: 41: 42: 43: 44:
45: public $defaultTheme = 'default';
46: 47: 48: 49: 50:
51: public $allowUserSelection = true;
52:
53: 54: 55: 56: 57: 58:
59: public function createInstance($options = array(), $initArgs = array())
60: {
61:
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: 88: 89: 90: 91:
92: public function isThemeAllowed($name)
93: {
94: return (empty($this->allowedThemes) || in_array($name, $this->allowedThemes));
95: }
96: }
97:
98: 99: 100: 101: 102: 103: 104: 105: 106:
107: class xos_opal_AdminThemeFactory extends xos_opal_ThemeFactory
108: {
109: 110: 111: 112: 113: 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: 138:
139: class xos_opal_Theme
140: {
141: 142: 143: 144: 145:
146: public $renderBanner = true;
147: 148: 149: 150: 151:
152: public $folderName = '';
153: 154: 155: 156: 157:
158: public $path = '';
159: public $url = '';
160:
161: 162: 163: 164: 165:
166: public $bufferOutput = true;
167: 168: 169: 170: 171:
172: public $canvasTemplate = 'theme.tpl';
173:
174: 175: 176: 177: 178:
179: public $themesPath = 'themes';
180:
181: 182: 183: 184: 185:
186: public $contentTemplate = '';
187:
188: public $contentCacheLifetime = 0;
189: public $contentCacheId;
190:
191: 192: 193: 194: 195:
196: public $content = '';
197: 198: 199: 200: 201: 202:
203: public $plugins = array(
204: 'xos_logos_PageBuilder');
205: public $renderCount = 0;
206: 207: 208: 209: 210:
211: public $template = false;
212:
213: 214: 215: 216: 217:
218: public $metas = array(
219:
220:
221:
222: 'meta' => array(),
223: 'link' => array(),
224: 'script' => array());
225:
226: 227: 228: 229: 230:
231: public $htmlHeadStrings = array();
232: 233: 234: 235: 236:
237: public $templateVars = array();
238:
239: 240: 241: 242: 243:
244: public $use_extra_cache_id = true;
245:
246: 247: 248:
249:
250: 251: 252: 253: 254:
255: 256: 257: 258: 259: 260: 261: 262: 263: 264: 265:
266: public function xoInit($options = array())
267: {
268:
269: $configHandler = xoops_getHandler('config');
270:
271: $this->path = XOOPS_THEME_PATH . '/' . $this->folderName;
272: $this->url = XOOPS_THEME_URL . '/' . $this->folderName;
273: $this->template = null;
274: $this->template = new XoopsTpl();
275: $this->template->currentTheme = $this;
276: $this->template->assign_by_ref('xoTheme', $this);
277: $tempPath = str_replace('\\', '/', realpath(XOOPS_ROOT_PATH) . '/');
278: $tempName = str_replace('\\', '/', realpath($_SERVER['SCRIPT_FILENAME']));
279: $xoops_page = str_replace($tempPath, '', $tempName);
280: if (strpos($xoops_page, 'modules') !== false) {
281: $xoops_page = str_replace('modules/', '', $xoops_page);
282: }
283: $xoops_page = str_replace('.php', '', $xoops_page);
284: if (isset($GLOBALS['xoopsConfig']['startpage'])) {
285: $xoops_startpage = $GLOBALS['xoopsConfig']['startpage'];
286: if ($xoops_startpage == '--') {
287: $xoops_startpage = 'system';
288: }
289: } else {
290: $xoops_startpage = 'system';
291: }
292:
293: if (file_exists($this->path . "/theme_autorun.php")) {
294: include_once($this->path . "/theme_autorun.php");
295: }
296:
297: $searchConfig = $configHandler->getConfigsByCat(XOOPS_CONF_SEARCH);
298: $xoops_search = (bool) (isset($searchConfig['enable_search']) && $searchConfig['enable_search'] === 1);
299: $this->template->assign(array(
300: 'xoops_theme' => $GLOBALS['xoopsConfig']['theme_set'],
301: 'xoops_imageurl' => XOOPS_THEME_URL . '/' . $GLOBALS['xoopsConfig']['theme_set'] . '/',
302: 'xoops_themecss' => xoops_getcss($GLOBALS['xoopsConfig']['theme_set']),
303: 'xoops_requesturi' => htmlspecialchars($_SERVER['REQUEST_URI'], ENT_QUOTES),
304: 'xoops_sitename' => htmlspecialchars($GLOBALS['xoopsConfig']['sitename'], ENT_QUOTES),
305: 'xoops_slogan' => htmlspecialchars($GLOBALS['xoopsConfig']['slogan'], ENT_QUOTES),
306: 'xoops_dirname' => isset($GLOBALS['xoopsModule']) && is_object($GLOBALS['xoopsModule'])
307: ? $GLOBALS['xoopsModule']->getVar('dirname') : 'system',
308: 'xoops_page' => $xoops_page,
309: 'xoops_startpage' => $xoops_startpage,
310: 'xoops_banner' => ($GLOBALS['xoopsConfig']['banners'] && $this->renderBanner)
311: ? xoops_getbanner() : ' ',
312: 'xoops_pagetitle' => isset($GLOBALS['xoopsModule']) && is_object($GLOBALS['xoopsModule'])
313: ? $GLOBALS['xoopsModule']->getVar('name')
314: : htmlspecialchars($GLOBALS['xoopsConfig']['slogan'], ENT_QUOTES),
315: 'xoops_search' => $xoops_search,
316: ));
317: if (isset($GLOBALS['xoopsUser']) && is_object($GLOBALS['xoopsUser'])) {
318: $this->template->assign(array(
319: 'xoops_isuser' => true,
320: 'xoops_avatar' => XOOPS_UPLOAD_URL . '/' . $GLOBALS['xoopsUser']->getVar('user_avatar'),
321: 'xoops_userid' => $GLOBALS['xoopsUser']->getVar('uid'),
322: 'xoops_uname' => $GLOBALS['xoopsUser']->getVar('uname'),
323: 'xoops_name' => $GLOBALS['xoopsUser']->getVar('name'),
324: 'xoops_isadmin' => $GLOBALS['xoopsUserIsAdmin'],
325: 'xoops_usergroups' => $GLOBALS['xoopsUser']->getGroups(),
326: ));
327: } else {
328: $this->template->assign(array(
329: 'xoops_isuser' => false,
330: 'xoops_isadmin' => false,
331: 'xoops_usergroups' => array(XOOPS_GROUP_ANONYMOUS),
332: ));
333: }
334:
335:
336: $criteria = new CriteriaCompo(new Criteria('conf_modid', 0));
337: $criteria->add(new Criteria('conf_catid', XOOPS_CONF_METAFOOTER));
338: $config = $configHandler->getConfigs($criteria, true);
339: foreach (array_keys($config) as $i) {
340: $name = $config[$i]->getVar('conf_name', 'n');
341: $value = $config[$i]->getVar('conf_value', 'n');
342: if (substr($name, 0, 5) === 'meta_') {
343: $this->addMeta('meta', substr($name, 5), $value);
344: } else {
345:
346: $this->template->assign("xoops_$name", $value);
347: }
348: }
349:
350: $this->addScript('include/xoops.js');
351: $this->loadLocalization();
352:
353: if ($this->bufferOutput) {
354: ob_start();
355: }
356: $GLOBALS['xoTheme'] =& $this;
357: $GLOBALS['xoopsTpl'] =& $this->template;
358:
359: foreach ($this->plugins as $k => $bundleId) {
360: if (!is_object($bundleId)) {
361: $this->plugins[$bundleId] = null;
362: $this->plugins[$bundleId] = new $bundleId();
363: $this->plugins[$bundleId]->theme =& $this;
364: $this->plugins[$bundleId]->xoInit();
365: unset($this->plugins[$k]);
366: }
367: }
368:
369: return true;
370: }
371:
372: 373: 374: 375: 376: 377: 378: 379: 380:
381: public function generateCacheId($cache_id, $extraString = '')
382: {
383: static $extra_string;
384: if (!$this->use_extra_cache_id) {
385: return $cache_id;
386: }
387:
388: if (empty($extraString)) {
389: if (empty($extra_string)) {
390:
391: $extra_string = $GLOBALS['xoopsConfig']['language'];
392:
393: if (!isset($GLOBALS['xoopsUser']) || !is_object($GLOBALS['xoopsUser'])) {
394: $extra_string .= '-' . XOOPS_GROUP_ANONYMOUS;
395: } else {
396: $groups = $GLOBALS['xoopsUser']->getGroups();
397: sort($groups);
398:
399:
400: $extra_string .= '-' . substr(md5(implode('-', $groups)), 0, 8) . '-' . substr(md5(XOOPS_DB_PASS . XOOPS_DB_NAME . XOOPS_DB_USER), 0, 8);
401: }
402: }
403: $extraString = $extra_string;
404: }
405: $cache_id .= '-' . $extraString;
406:
407: return $cache_id;
408: }
409:
410: 411: 412: 413: 414:
415: public function checkCache()
416: {
417: if ($_SERVER['REQUEST_METHOD'] !== 'POST' && $this->contentCacheLifetime) {
418: $template = $this->contentTemplate ?: 'db:system_dummy.tpl';
419: $this->template->caching = 2;
420: $this->template->cache_lifetime = $this->contentCacheLifetime;
421: $uri = str_replace(XOOPS_URL, '', $_SERVER['REQUEST_URI']);
422:
423: if (defined('SID') && SID && strpos($uri, SID)) {
424: $uri = preg_replace("/([\?&])(" . SID . "$|" . SID . '&)/', "\\1", $uri);
425: }
426: $this->contentCacheId = $this->generateCacheId('page_' . substr(md5($uri), 0, 8));
427: if ($this->template->is_cached($template, $this->contentCacheId)) {
428: $xoopsLogger = XoopsLogger::getInstance();
429: $xoopsLogger->addExtra($template, sprintf('Cached (regenerates every %d seconds)', $this->contentCacheLifetime));
430: $this->render(null, null, $template);
431:
432: return true;
433: }
434: }
435:
436: return false;
437: }
438:
439: 440: 441: 442: 443: 444: 445: 446: 447: 448: 449: 450: 451: 452: 453: 454:
455: public function render($canvasTpl = null, $pageTpl = null, $contentTpl = null, $vars = array())
456: {
457: if ($this->renderCount) {
458: return false;
459: }
460: $xoopsLogger = XoopsLogger::getInstance();
461: $xoopsLogger->startTime('Page rendering');
462:
463: xoops_load('xoopscache');
464: $cache = XoopsCache::getInstance();
465:
466:
467: if ($this->contentCacheLifetime && $this->contentCacheId && $content = $cache->read($this->contentCacheId)) {
468:
469: $this->htmlHeadStrings = array_merge($this->htmlHeadStrings, $content['htmlHeadStrings']);
470: foreach ($content['metas'] as $type => $value) {
471: $this->metas[$type] = array_merge($this->metas[$type], $content['metas'][$type]);
472: }
473: $GLOBALS['xoopsOption']['xoops_pagetitle'] = $content['xoops_pagetitle'];
474: $GLOBALS['xoopsOption']['xoops_module_header'] = $content['header'];
475: }
476:
477: if (!empty($GLOBALS['xoopsOption']['xoops_pagetitle'])) {
478: $this->template->assign('xoops_pagetitle', $GLOBALS['xoopsOption']['xoops_pagetitle']);
479: }
480: $header = empty($GLOBALS['xoopsOption']['xoops_module_header']) ? $this->template->get_template_vars('xoops_module_header') : $GLOBALS['xoopsOption']['xoops_module_header'];
481:
482:
483: if ($this->contentCacheLifetime && $this->contentCacheId && !$contentTpl) {
484: $content['htmlHeadStrings'] = $this->htmlHeadStrings;
485: $content['metas'] = $this->metas;
486: $content['xoops_pagetitle'] =& $this->template->get_template_vars('xoops_pagetitle');
487: $content['header'] = $header;
488: $cache->write($this->contentCacheId, $content);
489: }
490:
491:
492: $old = array(
493: 'robots',
494: 'keywords',
495: 'description',
496: 'rating',
497: 'author',
498: 'copyright');
499: foreach ($this->metas['meta'] as $name => $value) {
500: if (in_array($name, $old)) {
501: $this->template->assign("xoops_meta_$name", htmlspecialchars($value, ENT_QUOTES));
502: unset($this->metas['meta'][$name]);
503: }
504: }
505:
506:
507: $this->template->assign('xoops_module_header', $this->renderMetas(null, true) . "\n" . $header);
508:
509: if ($canvasTpl) {
510: $this->canvasTemplate = $canvasTpl;
511: }
512: if ($contentTpl) {
513: $this->contentTemplate = $contentTpl;
514: }
515: if (!empty($vars)) {
516: $this->template->assign($vars);
517: }
518: if ($this->contentTemplate) {
519: $this->content = $this->template->fetch($this->contentTemplate, $this->contentCacheId);
520: }
521: if ($this->bufferOutput) {
522: $this->content .= ob_get_contents();
523: ob_end_clean();
524: }
525:
526: $this->template->assign_by_ref('xoops_contents', $this->content);
527:
528:
529: $this->template->caching = 0;
530: if (file_exists($this->path . '/' . $this->canvasTemplate)) {
531: $this->template->display($this->path . '/' . $this->canvasTemplate);
532: } else {
533: $this->template->display($this->path . '/theme.html');
534: }
535: $this->renderCount++;
536: $xoopsLogger->stopTime('Page rendering');
537:
538: return true;
539: }
540:
541: 542: 543: 544: 545: 546: 547: 548: 549: 550: 551: 552:
553: public function loadLocalization($type = 'main')
554: {
555: $language = $GLOBALS['xoopsConfig']['language'];
556:
557: if (file_exists($GLOBALS['xoops']->path('language/' . $language . '/style.css'))) {
558: $this->addStylesheet($GLOBALS['xoops']->url('language/' . $language . '/style.css'));
559: }
560: $this->addLanguage($type, $language);
561:
562: if (file_exists($this->path . '/language/' . $language . '/script.js')) {
563: $this->addScript($this->url . '/language/' . $language . '/script.js');
564: }
565: if (file_exists($this->path . '/language/' . $language . '/style.css')) {
566: $this->addStylesheet($this->url . '/language/' . $language . '/style.css');
567: }
568:
569: return true;
570: }
571:
572: 573: 574: 575: 576: 577: 578: 579:
580: public function addLanguage($type = 'main', $language = null)
581: {
582: $language = (null === $language) ? $GLOBALS['xoopsConfig']['language'] : $language;
583: if (!file_exists($fileinc = $this->path . "/language/{$language}/{$type}.php")) {
584: if (!file_exists($fileinc = $this->path . "/language/english/{$type}.php")) {
585: return false;
586: }
587: }
588: $ret = include_once $fileinc;
589:
590: return $ret;
591: }
592:
593: 594: 595: 596: 597:
598: 599: 600: 601: 602: 603: 604: 605: 606: 607: 608: 609: 610: 611: 612: 613: 614: 615: 616: 617: 618: 619: 620: 621: 622: 623: 624:
625: public function addScript($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['src'] = $src;
633: }
634: if (!empty($content)) {
635: $attributes['_'] = $content;
636: }
637: if (!isset($attributes['type'])) {
638: $attributes['type'] = 'text/javascript';
639: }
640: if (empty($name)) {
641: $name = md5(serialize($attributes));
642: }
643: $this->addMeta('script', $name, $attributes);
644: }
645:
646: 647: 648: 649: 650: 651: 652: 653: 654:
655: public function addStylesheet($src = '', $attributes = array(), $content = '', $name = '')
656: {
657: if (empty($attributes)) {
658: $attributes = array();
659: }
660: if (!empty($src)) {
661: $src = $GLOBALS['xoops']->url($this->resourcePath($src));
662: $attributes['href'] = $src;
663: }
664: if (!isset($attributes['type'])) {
665: $attributes['type'] = 'text/css';
666: }
667: if (!empty($content)) {
668: $attributes['_'] = $content;
669: }
670: if (empty($name)) {
671: $name = md5(serialize($attributes));
672: }
673: $this->addMeta('stylesheet', $name, $attributes);
674: }
675:
676: 677: 678: 679: 680: 681: 682: 683:
684: public function addLink($rel, $href = '', $attributes = array(), $name = '')
685: {
686: if (empty($attributes)) {
687: $attributes = array();
688: }
689: if (!empty($href)) {
690: $attributes['href'] = $href;
691: }
692: $attributes['rel'] = $rel;
693: if (empty($name)) {
694: $name = md5(serialize($attributes));
695: }
696: $this->addMeta('link', $name, $attributes);
697: }
698:
699: 700: 701: 702: 703: 704:
705: public function addHttpMeta($name, $value = null)
706: {
707: if (isset($value)) {
708: return $this->addMeta('http', $name, $value);
709: }
710: unset($this->metas['http'][$name]);
711: return null;
712: }
713:
714: 715: 716: 717: 718: 719: 720:
721: public function addMeta($type = 'meta', $name = '', $value = '')
722: {
723: if (!isset($this->metas[$type])) {
724: $this->metas[$type] = array();
725: }
726: if (!empty($name)) {
727: $this->metas[$type][$name] = $value;
728: } else {
729: $this->metas[$type][md5(serialize(array($value)))] = $value;
730: }
731:
732: return $value;
733: }
734:
735: 736: 737: 738: 739: 740: 741: 742: 743: 744:
745: public function headContent($params, $content, &$smarty, &$repeat)
746: {
747: if (!$repeat) {
748: $this->htmlHeadStrings[] = $content;
749: }
750: }
751:
752: 753: 754: 755: 756: 757: 758:
759: public function renderMetas($type = null, $return = false)
760: {
761: $str = '';
762: if (!isset($type)) {
763: foreach (array_keys($this->metas) as $type) {
764: $str .= $this->renderMetas($type, true);
765: }
766: $str .= implode("\n", $this->htmlHeadStrings);
767: } else {
768: switch ($type) {
769: case 'script':
770: foreach ($this->metas[$type] as $attrs) {
771: $str .= '<script' . $this->renderAttributes($attrs) . '>';
772: if (@$attrs['_']) {
773: $str .= "\n//<![CDATA[\n" . $attrs['_'] . "\n//]]>";
774: }
775: $str .= "</script>\n";
776: }
777: break;
778: case 'link':
779: foreach ($this->metas[$type] as $attrs) {
780: $rel = $attrs['rel'];
781: unset($attrs['rel']);
782: $str .= '<link rel="' . $rel . '"' . $this->renderAttributes($attrs) . " />\n";
783: }
784: break;
785: case 'stylesheet':
786: foreach ($this->metas[$type] as $attrs) {
787: if (@$attrs['_']) {
788: $str .= '<style' . $this->renderAttributes($attrs) . ">\n/* <![CDATA[ */\n" . $attrs['_'] . "\n/* //]]> */\n</style>";
789: } else {
790: $str .= '<link rel="stylesheet"' . $this->renderAttributes($attrs) . " />\n";
791: }
792: }
793: break;
794: case 'http':
795: foreach ($this->metas[$type] as $name => $content) {
796: $str .= '<meta http-equiv="' . htmlspecialchars($name, ENT_QUOTES) . '" content="' . htmlspecialchars($content, ENT_QUOTES) . "\" />\n";
797: }
798: break;
799: default:
800: foreach ($this->metas[$type] as $name => $content) {
801: $str .= '<meta name="' . htmlspecialchars($name, ENT_QUOTES) . '" content="' . htmlspecialchars($content, ENT_QUOTES) . "\" />\n";
802: }
803: break;
804: }
805: }
806: if ($return) {
807: return $str;
808: }
809: echo $str;
810:
811: return true;
812: }
813:
814: 815: 816: 817: 818: 819:
820: public function genElementId($tagName = 'xos')
821: {
822: static $cache = array();
823: if (!isset($cache[$tagName])) {
824: $cache[$tagName] = 1;
825: }
826:
827: return $tagName . '-' . $cache[$tagName]++;
828: }
829:
830: 831: 832: 833: 834: 835:
836: public function renderAttributes($coll)
837: {
838: $str = '';
839: foreach ($coll as $name => $val) {
840: if ($name !== '_') {
841: $str .= ' ' . $name . '="' . htmlspecialchars($val, ENT_QUOTES) . '"';
842: }
843: }
844:
845: return $str;
846: }
847:
848: 849: 850: 851: 852: 853:
854: public function resourcePath($path)
855: {
856: if (substr($path, 0, 1) === '/') {
857: $path = substr($path, 1);
858: }
859:
860: if (file_exists(XOOPS_ROOT_PATH . "/{$this->themesPath}/{$this->folderName}/{$path}")) {
861: return "{$this->themesPath}/{$this->folderName}/{$path}";
862: }
863:
864: if (file_exists(XOOPS_ROOT_PATH . "/themes/{$this->folderName}/{$path}")) {
865: return "themes/{$this->folderName}/{$path}";
866: }
867:
868: return $path;
869: }
870: }
871: