/** * Resolves a given path to a full template file path, making sure it's valid * * @param string $templatePath * * @throws LiquidException * @return string */ public function fullPath($templatePath) { $nameRegex = Liquid::get('INCLUDE_ALLOW_EXT') ? new Regexp('/^[^.\\/][a-zA-Z0-9_\\.\\/]+$/') : new Regexp('/^[^.\\/][a-zA-Z0-9_\\/]+$/'); if (!$nameRegex->match($templatePath)) { throw new LiquidException("Illegal template name '{$templatePath}'"); } if (strpos($templatePath, '/') !== false) { $fullPath = Liquid::get('INCLUDE_ALLOW_EXT') ? $this->root . dirname($templatePath) . '/' . basename($templatePath) : $this->root . dirname($templatePath) . '/' . Liquid::get('INCLUDE_PREFIX') . basename($templatePath) . '.' . Liquid::get('INCLUDE_SUFFIX'); } else { $fullPath = Liquid::get('INCLUDE_ALLOW_EXT') ? $this->root . $templatePath : $this->root . Liquid::get('INCLUDE_PREFIX') . $templatePath . '.' . Liquid::get('INCLUDE_SUFFIX'); } $rootRegex = new Regexp('/' . preg_quote(realpath($this->root), '/') . '/'); if (!$rootRegex->match(realpath($fullPath))) { throw new LiquidException("Illegal template path '" . realpath($fullPath) . "'"); } return $fullPath; }
/** * Constructor * * @param string $markup */ public function __construct($markup) { $this->markup = $markup; $quotedFragmentRegexp = new Regexp('/\\s*(' . Liquid::get('QUOTED_FRAGMENT') . ')/'); $filterSeperatorRegexp = new Regexp('/' . Liquid::get('FILTER_SEPARATOR') . '\\s*(.*)/'); $filterSplitRegexp = new Regexp('/' . Liquid::get('FILTER_SEPARATOR') . '/'); $filterNameRegexp = new Regexp('/\\s*(\\w+)/'); $filterArgumentRegexp = new Regexp('/(?:' . Liquid::get('FILTER_ARGUMENT_SEPARATOR') . '|' . Liquid::get('ARGUMENT_SEPARATOR') . ')\\s*(' . Liquid::get('QUOTED_FRAGMENT_FILTER_ARGUMENT') . ')/'); $quotedFragmentRegexp->match($markup); $this->name = isset($quotedFragmentRegexp->matches[1]) ? $quotedFragmentRegexp->matches[1] : null; if ($filterSeperatorRegexp->match($markup)) { $filters = $filterSplitRegexp->split($filterSeperatorRegexp->matches[1]); foreach ($filters as $filter) { $filterNameRegexp->match($filter); $filtername = $filterNameRegexp->matches[1]; $filterArgumentRegexp->matchAll($filter); $matches = Liquid::arrayFlatten($filterArgumentRegexp->matches[1]); $this->filters[] = array($filtername, $matches); } } else { $this->filters = array(); } }
/** * @param string * @return void */ public function parse($text) { $this->texy->invokeHandlers('beforeBlockParse', [$this, &$text]); // parser initialization $this->text = $text; $this->offset = 0; // parse loop $matches = []; $priority = 0; foreach ($this->patterns as $name => $pattern) { $ms = Regexp::match($text, $pattern['pattern'], Regexp::OFFSET_CAPTURE | Regexp::ALL); foreach ((array) $ms as $m) { $offset = $m[0][1]; foreach ($m as $k => $v) { $m[$k] = $v[0]; } $matches[] = [$offset, $name, $m, $priority]; } $priority++; } unset($name, $pattern, $ms, $m, $k, $v); usort($matches, function ($a, $b) { if ($a[0] === $b[0]) { return $a[3] < $b[3] ? -1 : 1; } if ($a[0] < $b[0]) { return -1; } return 1; }); $matches[] = [strlen($text), NULL, NULL]; // terminal cap // process loop $el = $this->element; $cursor = 0; do { do { list($mOffset, $mName, $mMatches) = $matches[$cursor]; $cursor++; if ($mName === NULL || $mOffset >= $this->offset) { break; } } while (1); // between-matches content if ($mOffset > $this->offset) { $s = trim(substr($text, $this->offset, $mOffset - $this->offset)); if ($s !== '') { $this->texy->paragraphModule->process($this, $s, $el); } } if ($mName === NULL) { break; // finito } $this->offset = $mOffset + strlen($mMatches[0]) + 1; // 1 = \n $res = call_user_func_array($this->patterns[$mName]['handler'], [$this, $mMatches, $mName]); if ($res === FALSE || $this->offset <= $mOffset) { // module rejects text // asi by se nemelo stat, rozdeli generic block $this->offset = $mOffset; // turn offset back continue; } elseif ($res instanceof HtmlElement) { $el->insert(NULL, $res); } elseif (is_string($res)) { $el->insert(NULL, $res); } } while (1); }
/** * Create a variable for the given token * * @param string $token * * @throws \Liquid\LiquidException * @return Variable */ private function createVariable($token) { $variableRegexp = new Regexp('/^' . Liquid::get('VARIABLE_START') . '(.*)' . Liquid::get('VARIABLE_END') . '$/'); if ($variableRegexp->match($token)) { return new Variable($variableRegexp->matches[1]); } throw new LiquidException("Variable {$token} was not properly terminated"); }