public function __construct($appendCustomTags = true) { $this->setStripSpace(false); parent::__construct($appendCustomTags); if (!empty(self::$customTags['no_option'])) { foreach (self::$customTags['no_option'] as $tagname => $taginfo) { if (!isset($this->unparsed_tags[$tagname])) { $this->unparsed_tags[$tagname] = $tagname; } } } if (!empty(self::$customTags['option'])) { foreach (self::$customTags['option'] as $tagname => $taginfo) { if (!isset($this->unparsed_tags[$tagname])) { $this->unparsed_tags[$tagname] = $tagname; } } } // change all unparsable tags to use the unparsable callback foreach ($this->unparsed_tags as $remove) { if (isset($this->tag_list['option']["{$remove}"])) { $this->tag_list['option']["{$remove}"]['callback'] = 'handle_wysiwyg_unparsable'; unset($this->tag_list['option']["{$remove}"]['html'], $this->tag_list['option']["{$remove}"]['strip_space_after']); } if (isset($this->tag_list['no_option']["{$remove}"])) { $this->tag_list['no_option']["{$remove}"]['callback'] = 'handle_wysiwyg_unparsable'; unset($this->tag_list['no_option']["{$remove}"]['html'], $this->tag_list['option']["{$remove}"]['strip_space_after']); } } // make the "pre" tags use the correct handler foreach (array('code', 'php', 'html') as $pre_tag) { if (isset($this->tag_list['no_option']["{$pre_tag}"])) { $this->tag_list['no_option']["{$pre_tag}"]['callback'] = 'handle_preformatted_tag'; unset($this->tag_list['no_option']["{$pre_tag}"]['html'], $this->tag_list['option']["{$pre_tag}"]['strip_space_after']); } } $this->type = vB5_Template_Runtime::isBrowser('ie') ? 'ie' : 'moz_css'; }
/** * Inserts <link>s for CSS in the content * * @param string The content * @param boolean true if we are rendering for a call to /ajax/render/ and we want CSS <link>s separate */ public function insertCss(&$content, $isAjaxTemplateRender) { // register block css templates for blocks that are used in the markup $this->registerBlockCssTemplates($content); if (empty($this->pending)) { return; } $options = vB5_Template_Options::instance(); $storecssasfile = $options->get('options.storecssasfile'); $cssdate = intval($options->get('miscoptions.cssdate')); if (!$cssdate) { $cssdate = time(); // fallback so we get the latest css } $user = vB5_User::instance(); $textdirection = $user['lang_options']['direction'] ? 'ltr' : 'rtl'; // we cannot query user directly for styleid, we need to consider other parameters $styleid = vB5_Template_Stylevar::instance()->getPreferredStyleId(); $vbcsspath = $this->getCssPath($storecssasfile, $textdirection, $styleid); // Used when css is stored as files if ($storecssasfile) { $cssfiledate = $this->getCssFileDate($options, $styleid); } // some css files need to be loaded always from DB $vbcssdbpath = $this->getCssPath(false, $textdirection, $styleid); $replace = ''; $replaceAjax = array(); //if user style customization is enabled we need to hand css_profile specially. It can never come from disk //regardless of the option setting. $userprofilecss = ''; $userprofilecssAjax = ''; // Search for css_additional.css and css_profile.css files, send them to the last in that order (VBV-8781) $additionalToQueue = ''; $profileToQueue = ''; foreach ($this->pending as $key => $css) { if ($css === 'css_additional.css') { $additionalToQueue = $css; unset($this->pending[$key]); continue; } if (substr($css, 0, 15) === 'css_profile.css') { if ($options->get('options.enable_profile_styling')) { $joinChar = strpos($vbcssdbpath . $css, '?') === false ? '?' : '&'; $userprofilecss = '<link rel="stylesheet" type="text/css" href="' . htmlspecialchars($vbcssdbpath . $css) . "{$joinChar}ts={$cssdate} \" />\n"; $userprofilecssAjax = htmlspecialchars($vbcssdbpath . $css) . "{$joinChar}ts={$cssdate}"; unset($this->pending[$key]); } else { $profileToQueue = $css; unset($this->pending[$key]); } } } if (!empty($additionalToQueue)) { $this->pending[] = $additionalToQueue; } if (!empty($profileToQueue)) { $this->pending[] = $profileToQueue; } if ($storecssasfile) { foreach ($this->pending as $css) { $cssfile = $vbcsspath . $cssfiledate . '-' . $css; $replace .= '<link rel="stylesheet" type="text/css" href="' . htmlspecialchars($cssfile) . "\" />\n"; $replaceAjax[] = htmlspecialchars($cssfile); } } else { // Deconstruct bundle logic if ($this->cssBundles == null) { $this->loadCSSBundles(); } $joinChar = strpos($vbcsspath, '?') === false ? '?' : '&'; $templates = array(); //for dupe checking $ieLinks = ''; $nonIeLinks = ''; $ieLinksAjax = array(); $nonIeLinksAjax = array(); // We're using css bunldes instead of combining everything into a single css.php call // to take advantage of client side caching. We're also incoporating the rollup system into // css files stored on the db by linking css.php with all the templates of that bundle in one call. // And we're also avoiding single templates having their own <link> tag if they're already used // in a bundle or elsewhere. foreach ($this->pending as $bundle) { if (isset($this->cssBundles[$bundle])) { $templates = array_merge($templates, $this->cssBundles[$bundle]); // Output the stylesheets twice-- once for IE, once for the rest. // For IE, we split into groups of 5 so we don't exceed IE's limit // on the number of CSS rules in a file. See VBV-7077 $pendingChunks = array_chunk($this->cssBundles[$bundle], 5); foreach ($pendingChunks as $pendingSheets) { $ieLinks .= '<link rel="stylesheet" type="text/css" href="' . htmlspecialchars($vbcsspath . implode(',', $pendingSheets)) . "{$joinChar}ts={$cssdate} \" />\n"; $ieLinksAjax[] = htmlspecialchars($vbcsspath . implode(',', $pendingSheets)) . "{$joinChar}ts={$cssdate}"; } $nonIeLinks .= '<link rel="stylesheet" type="text/css" href="' . htmlspecialchars($vbcsspath . implode(',', $this->cssBundles[$bundle])) . "{$joinChar}ts={$cssdate} \" />\n"; $nonIeLinksAjax[] = htmlspecialchars($vbcsspath . implode(',', $this->cssBundles[$bundle])) . "{$joinChar}ts={$cssdate}"; } else { if (!in_array($bundle, $templates)) { //mark additional css for JS processing. $mark = ' '; if ($bundle == 'css_additional.css') { $mark = ' class="js-additional-css" '; } // we have a single template. that wasn't caught before. link it. $templates[] = $bundle; $link = '<link' . $mark . 'rel="stylesheet" type="text/css" href="' . htmlspecialchars($vbcsspath . $bundle) . "{$joinChar}ts={$cssdate} \" />\n"; $ieLinks .= $link; $nonIeLinks .= $link; $ieLinksAjax[] = htmlspecialchars($vbcsspath . $bundle) . "{$joinChar}ts={$cssdate}"; $nonIeLinksAjax[] = htmlspecialchars($vbcsspath . $bundle) . "{$joinChar}ts={$cssdate}"; } } } unset($templates); $replace .= "\n<!--[if IE]>\n"; $replace .= $ieLinks; $replace .= "<![endif]-->\n<!--[if !IE]><!-->\n"; $replace .= $nonIeLinks; $replace .= "<!--<![endif]-->\n"; if (vB5_Template_Runtime::isBrowser('ie')) { $replaceAjax = array_merge($replaceAjax, $ieLinksAjax); } else { $replaceAjax = array_merge($replaceAjax, $nonIeLinksAjax); } } // Note: This places user profile customized css after css_additional.css. $replace .= $userprofilecss . "\n"; if ($userprofilecssAjax) { $replaceAjax[] = $userprofilecssAjax; } if (!$isAjaxTemplateRender) { // insert the css before the first <script> tag in head element // if there is no script tag in <head>, then insert it at the // end of <head> $scriptPos = stripos($content, '<script'); $headPos = stripos($content, '</head>'); if ($scriptPos !== false && $scriptPos < ($headPos === false ? PHP_INT_MAX : $headPos)) { $top = substr($content, 0, $scriptPos); $bottom = substr($content, $scriptPos); $content = $top . $replace . $bottom; } else { if ($headPos !== false) { $replace .= '</head>'; $content = str_replace('</head>', $replace, $content); } } } else { // We can't use the CDN URL for these, since they will be fetched via AJAX; // fall back to the local URL. VBV-8960 $cdnurl = $options->get('options.cdnurl'); if ($cdnurl) { $baseurl = vB5_Template_Options::instance()->get('options.frontendurl'); $cdnurllen = strlen($cdnurl); foreach ($replaceAjax as $key => $url) { $replaceAjax[$key] = $baseurl . substr($url, $cdnurllen); } } $this->ajaxCssLinks = array_unique(array_merge($this->ajaxCssLinks, $replaceAjax)); } }