/** * Handles CONTEXT_TAG. */ private function contextTag() { $matches = $this->match('~ (?P<end>/?>)(?P<tagnewline>[\\ \\t]*(?=\\r|\\n))?| ## end of HTML tag ' . $this->macroRe . '| ## curly tag \\s*(?P<attr>[^\\s/>={]+)(?:\\s*=\\s*(?P<value>["\']|[^\\s/>{]+))? ## begin of HTML attribute ~xsi'); if (!$matches || !empty($matches['macro'])) { // EOF or {macro} } elseif (!empty($matches['end'])) { // end of HTML tag /> $tag = end($this->tags); $isEmpty = !$tag->closing && ($matches['end'][0] === '/' || isset(Html::$emptyElements[strtolower($tag->name)])); if ($tag->isMacro || !empty($tag->attrs)) { if ($tag->isMacro) { $code = $this->handler->tagMacro(substr($tag->name, strlen(self::HTML_PREFIX)), $tag->attrs, $tag->closing); if ($code === NULL) { throw new InvalidStateException("Unknown tag-macro <{$tag->name}> on line {$this->line}."); } if ($isEmpty) { $code .= $this->handler->tagMacro(substr($tag->name, strlen(self::HTML_PREFIX)), $tag->attrs, TRUE); } } else { $code = substr($this->output, $tag->pos) . $matches[0] . (isset($matches['tagnewline']) ? "\n" : ''); $code = $this->handler->attrsMacro($code, $tag->attrs, $tag->closing); if ($code === NULL) { throw new InvalidStateException("Unknown macro-attribute " . self::HTML_PREFIX . implode(' or ' . self::HTML_PREFIX, array_keys($tag->attrs)) . " on line {$this->line}."); } if ($isEmpty) { $code = $this->handler->attrsMacro($code, $tag->attrs, TRUE); } } $this->output = substr_replace($this->output, $code, $tag->pos); $matches[0] = ''; // remove from output } if ($isEmpty) { $tag->closing = TRUE; } if (!$tag->closing && (strcasecmp($tag->name, 'script') === 0 || strcasecmp($tag->name, 'style') === 0)) { $this->context = self::CONTEXT_CDATA; $this->escape = strcasecmp($tag->name, 'style') ? 'TemplateHelpers::escapeJs' : 'TemplateHelpers::escapeCss'; } else { $this->context = self::CONTEXT_TEXT; $this->escape = 'TemplateHelpers::escapeHtml'; if ($tag->closing) { array_pop($this->tags); } } } else { // HTML attribute $name = $matches['attr']; $value = empty($matches['value']) ? TRUE : $matches['value']; // special attribute? if ($isSpecial = String::startsWith($name, self::HTML_PREFIX)) { $name = substr($name, strlen(self::HTML_PREFIX)); } $tag = end($this->tags); if ($isSpecial || $tag->isMacro) { if ($value === '"' || $value === "'") { if ($matches = $this->match('~(.*?)' . $value . '~xsi')) { // overwrites $matches $value = $matches[1]; } } $tag->attrs[$name] = $value; $matches[0] = ''; // remove from output } elseif ($value === '"' || $value === "'") { // attribute = "' $this->context = self::CONTEXT_ATTRIBUTE; $this->quote = $value; $this->escape = strncasecmp($name, 'on', 2) ? strcasecmp($name, 'style') ? 'TemplateHelpers::escapeHtml' : 'TemplateHelpers::escapeHtmlCss' : 'TemplateHelpers::escapeHtmlJs'; } } return $matches; }