Beispiel #1
0
    function macro($macro, $content = '', $modifiers = '')
    {
        if (func_num_args() === 1) {
            list(, $macro, $content, $modifiers) = NString::match($macro, '#^(/?[a-z0-9.:]+)?(.*?)(\\|[a-z](?:' . NLatteFilter::RE_STRING . '|[^\'"]+)*)?$()#is');
            $content = trim($content);
        }
        if ($macro === '') {
            $macro = substr($content, 0, 2);
            if (!isset($this->macros[$macro])) {
                $macro = substr($content, 0, 1);
                if (!isset($this->macros[$macro])) {
                    return FALSE;
                }
            }
            $content = substr($content, strlen($macro));
        } elseif (!isset($this->macros[$macro])) {
            return FALSE;
        }
        $closing = $macro[0] === '/';
        if ($closing) {
            $node = array_pop($this->nodes);
            if (!$node || "/{$node->name}" !== $macro || $content && !NString::startsWith("{$node->content} ", "{$content} ") || $modifiers) {
                $macro .= $content ? ' ' : '';
                throw new NLatteException("Unexpected macro {{$macro}{$content}{$modifiers}}" . ($node ? ", expecting {/{$node->name}}" . ($content && $node->content ? " or eventually {/{$node->name} {$node->content}}" : '') : ''), 0, $this->filter->line);
            }
            $node->content = $node->modifiers = '';
        } else {
            $node = (object) NULL;
            $node->name = $macro;
            $node->content = $content;
            $node->modifiers = $modifiers;
            if (isset($this->macros["/{$macro}"])) {
                $this->nodes[] = $node;
            }
        }
        $This = $this;
        return NString::replace($this->macros[$macro], '#%(.*?)%#', callback(create_function('$m', 'extract(NClosureFix::$vars[' . NClosureFix::uses(array('This' => $This, 'node' => $node)) . '], EXTR_REFS);
				if ($m[1]) {
					return callback($m[1][0] === \':\' ? array($This, substr($m[1], 1)) : $m[1])
						->invoke($node->content, $node->modifiers);
				} else {
					return $This->formatMacroArgs($node->content);
				}
			')));
    }
Beispiel #2
0
    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'])) {
        } elseif (!empty($matches['end'])) {
            $tag = end($this->tags);
            $isEmpty = !$tag->closing && (strpos($matches['end'], '/') !== FALSE || isset(NHtml::$emptyElements[strtolower($tag->name)]));
            if ($isEmpty) {
                $matches[0] = (NHtml::$xhtml ? ' />' : '>') . (isset($matches['tagnewline']) ? $matches['tagnewline'] : '');
            }
            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] = '';
            }
            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') ? 'NTemplateHelpers::escapeJs' : 'NTemplateHelpers::escapeCss';
            } else {
                $this->context = self::CONTEXT_TEXT;
                $this->escape = 'NTemplateHelpers::escapeHtml';
                if ($tag->closing) {
                    array_pop($this->tags);
                }
            }
        } else {
            $name = $matches['attr'];
            $value = empty($matches['value']) ? TRUE : $matches['value'];
            if ($isSpecial = NString::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')) {
                        $value = $matches[1];
                    }
                }
                $tag->attrs[$name] = $value;
                $matches[0] = '';
            } elseif ($value === '"' || $value === "'") {
                $this->context = self::CONTEXT_ATTRIBUTE;
                $this->quote = $value;
                $this->escape = strncasecmp($name, 'on', 2) ? strcasecmp($name, 'style') ? 'NTemplateHelpers::escapeHtml' : 'NTemplateHelpers::escapeHtmlCss' : 'NTemplateHelpers::escapeHtmlJs';
            }
        }
        return $matches;
    }