/** * Constructor * * @param string $markup * @return LiquidVariable */ public function __construct($markup) { $this->markup = $markup; $quoted_fragment_regexp = new LiquidRegexp('/\\s*(' . LIQUID_QUOTED_FRAGMENT . ')/'); $filter_seperator_regexp = new LiquidRegexp('/' . LIQUID_FILTER_SEPARATOR . '\\s*(.*)/'); $filter_split_regexp = new LiquidRegexp('/' . LIQUID_FILTER_SEPARATOR . '/'); $filter_name_regexp = new LiquidRegexp('/\\s*(\\w+)/'); $filter_argument_regexp = new LiquidRegexp('/(?:' . LIQUID_FILTER_ARGUMENT_SEPARATOR . '|' . LIQUID_ARGUMENT_SEPARATOR . ')\\s*(' . LIQUID_QUOTED_FRAGMENT . ')/'); $quoted_fragment_regexp->match($markup); //$this->_name = $quoted_fragment_regexp->matches[1]; $this->_name = isset($quoted_fragment_regexp->matches[1]) ? $quoted_fragment_regexp->matches[1] : null; // harry if ($filter_seperator_regexp->match($markup)) { $filters = $filter_split_regexp->split($filter_seperator_regexp->matches[1]); foreach ($filters as $filter) { $filter_name_regexp->match($filter); $filtername = $filter_name_regexp->matches[1]; $filter_argument_regexp->match_all($filter); //$matches = array_flatten($filter_argument_regexp->matches[1]); $matches = Liquid::array_flatten($filter_argument_regexp->matches[1]); $this->filters[] = array($filtername, $matches); } } else { $this->filters = array(); } }
/** * Constructor * * @param string $markup * @param array $tokens * @param LiquidFileSystem $file_system * @return AssignLiquidTag */ public function __construct($markup, &$tokens, &$file_system) { $syntax_regexp = new LiquidRegexp('/(\\w+)\\s*=\\s*(' . LIQUID_QUOTED_FRAGMENT . '+)/'); $filter_seperator_regexp = new LiquidRegexp('/' . LIQUID_FILTER_SEPARATOR . '\\s*(.*)/'); $filter_split_regexp = new LiquidRegexp('/' . LIQUID_FILTER_SEPARATOR . '/'); $filter_name_regexp = new LiquidRegexp('/\\s*(\\w+)/'); $filter_argument_regexp = new LiquidRegexp('/(?:' . LIQUID_FILTER_ARGUMENT_SEPARATOR . '|' . LIQUID_ARGUMENT_SEPARATOR . ')\\s*(' . LIQUID_QUOTED_FRAGMENT . ')/'); $this->filters = array(); if ($filter_seperator_regexp->match($markup)) { $filters = $filter_split_regexp->split($filter_seperator_regexp->matches[1]); foreach ($filters as $filter) { $filter_name_regexp->match($filter); $filtername = $filter_name_regexp->matches[1]; $filter_argument_regexp->match_all($filter); $matches = Liquid::array_flatten($filter_argument_regexp->matches[1]); array_push($this->filters, array($filtername, $matches)); } } if ($syntax_regexp->match($markup)) { $this->_to = $syntax_regexp->matches[1]; $this->_from = $syntax_regexp->matches[2]; } else { throw new LiquidException("Syntax Error in 'assign' - Valid syntax: assign [var] = [source]"); } }
/** * Unknown tag handler * * @param string $tag * @param array $params * @param array $tokens */ function unknown_tag($tag, $params, &$tokens) { $when_syntax_regexp = new LiquidRegexp('/' . LIQUID_QUOTED_FRAGMENT . '/'); switch ($tag) { case 'when': // push the current nodelist onto the stack and prepare for a new one if ($when_syntax_regexp->match($params)) { $this->push_nodelist(); $this->right = $when_syntax_regexp->matches[0]; $this->_nodelist = array(); } else { throw new LiquidException("Syntax Error in tag 'case' - Valid when condition: when [condition]"); // harry } break; case 'else': // push the last nodelist onto the stack and prepare to recieve the else nodes $this->push_nodelist(); $this->right = null; $this->else_nodelist =& $this->_nodelist; $this->_nodelist = array(); break; default: parent::unknown_tag($tag, $params, $tokens); } }
/** * Constructor * * @param string $markup * @param array $tokens * @param LiquidFileSystem $file_system * @return AssignLiquidTag */ public function __construct($markup, &$tokens, &$file_system) { $syntax = new LiquidRegexp("/(" . LIQUID_ALLOWED_VARIABLE_CHARS . "+)/"); if ($syntax->match($markup)) { $this->_toDecrement = $syntax->matches[0]; } else { throw new LiquidException("Syntax Error in 'decrement' - Valid syntax: decrement [var]"); } }
/** * Constructor * * @param string $markup * @param Array $tokens * @param LiquidFileSystem $fileSystem * @return CaptureLiquidTag */ public function __construct($markup, &$tokens, &$fileSystem) { $syntaxRegexp = new LiquidRegexp('/(\\w+)/'); if ($syntaxRegexp->match($markup)) { $this->_block = $syntaxRegexp->matches[1]; parent::__construct($markup, $tokens, $fileSystem); } else { throw new LiquidException("Syntax Error in 'block' - Valid syntax: block [name]"); } }
/** * Constructor * * @param string $markup * @param array $tokens * @param LiquidFileSystem $file_system * @return AssignLiquidTag */ public function __construct($markup, &$tokens, &$file_system) { //$syntax_regexp = new LiquidRegexp('/(\w+)\s*=\s*('.LIQUID_ALLOWED_VARIABLE_CHARS.'+)/'); $syntax_regexp = new LiquidRegexp('/(\\w+)\\s*=\\s*(' . LIQUID_QUOTED_FRAGMENT . '+)/'); if ($syntax_regexp->match($markup)) { $this->_to = $syntax_regexp->matches[1]; $this->_from = $syntax_regexp->matches[2]; } else { throw new LiquidException("Syntax Error in 'assign' - Valid syntax: assign [var] = [source]"); } }
/** * Constructor * * @param string $markup * @param Array $tokens * @param LiquidFileSystem $file_system * @return CaptureLiquidTag */ public function __construct($markup, &$tokens, &$file_system) { $syntax_regexp = new LiquidRegexp('/(\\w+)/'); if ($syntax_regexp->match($markup)) { $this->_to = $syntax_regexp->matches[1]; parent::__construct($markup, $tokens, $file_system); } else { throw new LiquidException("Syntax Error in 'capture' - Valid syntax: assign [var] = [source]"); // harry } }
/** * Constructor * * @param string $markup * @param array $tokens * @param LiquidFileSystem $file_system * @return TableRowLiquidTag */ public function __construct($markup, &$tokens, &$file_system) { parent::__construct($markup, $tokens, $file_system); $syntax = new LiquidRegexp("/(\\w+)\\s+in\\s+(" . LIQUID_ALLOWED_VARIABLE_CHARS . "+)/"); if ($syntax->match($markup)) { $this->variable_name = $syntax->matches[1]; $this->collection_name = $syntax->matches[2]; $this->extract_attributes($markup); } else { throw new LiquidException("Syntax Error in 'table_row loop' - Valid syntax: table_row [item] in [collection] cols=3"); } }
/** * Constructor * * @param string $markup * @param array $tokens * @param LiquidFileSystem $file_system * @return TableRowLiquidTag */ function TableRowLiquidTag($markup, &$tokens, &$file_system) { parent::LiquidTag($markup, $tokens, $file_system); $syntax = new LiquidRegexp("/(\\w+)\\s+in\\s+(" . LIQUID_ALLOWED_VARIABLE_CHARS . "+)/"); if ($syntax->match($markup)) { $this->variable_name = $syntax->matches[1]; $this->collection_name = $syntax->matches[2]; $this->extract_attributes($markup); } else { trigger_error("Syntax Error in 'table_row loop' - Valid syntax: table_row [item] in [collection] cols=3", E_USER_ERROR); } }
/** * Render the tag * * @param LiquidContext $context */ public function render(&$context) { $context->push(); $logicalRegex = new LiquidRegexp('/\\s+(and|or)\\s+/'); $conditionalRegex = new LiquidRegexp('/(' . LIQUID_QUOTED_FRAGMENT . ')\\s*([=!<>a-z_]+)?\\s*(' . LIQUID_QUOTED_FRAGMENT . ')?/'); $result = ''; foreach ($this->_blocks as $i => $block) { if ($block[0] == 'else') { $result = $this->render_all($block[2], $context); break; } if ($block[0] == 'if' || $block[0] == 'elsif') { /* Extract logical operators */ $logicalRegex->match($block[1]); $logicalOperators = $logicalRegex->matches; array_shift($logicalOperators); /* Extract individual conditions */ $temp = $logicalRegex->split($block[1]); $conditions = array(); foreach ($temp as $condition) { if ($conditionalRegex->match($condition)) { $left = isset($conditionalRegex->matches[1]) ? $conditionalRegex->matches[1] : null; $operator = isset($conditionalRegex->matches[2]) ? $conditionalRegex->matches[2] : null; $right = isset($conditionalRegex->matches[3]) ? $conditionalRegex->matches[3] : null; array_push($conditions, array('left' => $left, 'operator' => $operator, 'right' => $right)); } else { throw new LiquidException("Syntax Error in tag 'if' - Valid syntax: if [condition]"); } } if (count($logicalOperators)) { /* If statement contains and/or */ $display = true; foreach ($logicalOperators as $k => $logicalOperator) { if ($logicalOperator == 'and') { $display = $this->interpret_condition($conditions[$k]['left'], $conditions[$k]['right'], $conditions[$k]['operator'], $context) && $this->interpret_condition($conditions[$k + 1]['left'], $conditions[$k + 1]['right'], $conditions[$k + 1]['operator'], $context); } else { $display = $this->interpret_condition($conditions[$k]['left'], $conditions[$k]['right'], $conditions[$k]['operator'], $context) || $this->interpret_condition($conditions[$k + 1]['left'], $conditions[$k + 1]['right'], $conditions[$k + 1]['operator'], $context); } } } else { /* If statement is a single condition */ $display = $this->interpret_condition($conditions[0]['left'], $conditions[0]['right'], $conditions[0]['operator'], $context); } if ($display) { $result = $this->render_all($block[2], $context); break; } } } $context->pop(); return $result; }
/** * Constructor * * @param string $markup * @param array $tokens * @param LiquidFileSystem $fileSystem * @return ForLiquidTag */ public function __construct($markup, &$tokens, &$fileSystem) { parent::__construct($markup, $tokens, $fileSystem); $syntaxRegexp = new LiquidRegexp('/(\\w+)\\s+in\\s+(' . LIQUID_ALLOWED_VARIABLE_CHARS . '+)/'); if ($syntaxRegexp->match($markup)) { $this->_variableName = $syntaxRegexp->matches[1]; $this->_collectionName = $syntaxRegexp->matches[2]; $this->_name = $syntaxRegexp->matches[1] . '-' . $syntaxRegexp->matches[2]; $this->extractAttributes($markup); } else { throw new LiquidException("Syntax Error in 'for loop' - Valid syntax: for [item] in [collection]"); } }
/** * Constructor * * @param string $markup * @param array $tokens * @param LiquidFileSystem $fileSystem * @return ForLiquidTag */ public function __construct($markup, &$tokens, &$fileSystem) { parent::__construct($markup, $tokens, $fileSystem); $syntax = new LiquidRegexp('/(' . LIQUID_ALLOWED_VARIABLE_CHARS . '+)\\s+by\\s+(\\w+)/'); if ($syntax->match($markup)) { $this->_collectionName = $syntax->matches[1]; $this->_numberItems = $syntax->matches[2]; $this->_currentPage = is_numeric($_GET['page']) ? $_GET['page'] : 1; $this->_currentOffset = ($this->_currentPage - 1) * $this->_numberItems; $this->extractAttributes($markup); } else { throw new LiquidException("Syntax Error - Valid syntax: paginate [collection] by [items]"); } }
/** * Constructor * * @param string $markup * @param array $tokens * @param LiquidFileSystem $fileSystem * @return IncludeLiquidTag */ public function __construct($markup, &$tokens, &$fileSystem) { $regex = new LiquidRegexp('/("[^"]+"|\'[^\']+\')(\\s+(with|for)\\s+(' . LIQUID_QUOTED_FRAGMENT . '+))?/'); if ($regex->match($markup)) { $this->_templateName = substr($regex->matches[1], 1, strlen($regex->matches[1]) - 2); if (isset($regex->matches[1])) { $this->_collection = isset($regex->matches[3]) ? $regex->matches[3] == "for" : null; $this->_variable = isset($regex->matches[4]) ? $regex->matches[4] : null; } $this->extractAttributes($markup); } else { throw new LiquidException("Error in tag 'include' - Valid syntax: include '[template]' (with|for) [object|collection]"); } parent::__construct($markup, $tokens, $fileSystem); }
/** * Resolves a given path to a full template file path, making sure it's valid * * @param string $templatePath * @return string */ public function fullPath($templatePath) { $nameRegex = LIQUID_INCLUDE_ALLOW_EXT ? new LiquidRegexp('/^[^.\\/][a-zA-Z0-9_\\.\\/]+$/') : new LiquidRegexp('/^[^.\\/][a-zA-Z0-9_\\/]+$/'); if (!$nameRegex->match($templatePath)) { throw new LiquidException("Illegal template name '{$templatePath}'"); } if (strpos($templatePath, '/') !== false) { //LIQUID_INCLUDE_ALLOW_EXT $fullPath = LIQUID_INCLUDE_ALLOW_EXT ? $this->_root . dirname($templatePath) . '/' . basename($templatePath) : $this->_root . dirname($templatePath) . '/' . LIQUID_INCLUDE_PREFIX . basename($templatePath) . '.' . LIQUID_INCLUDE_SUFFIX; } else { $fullPath = LIQUID_INCLUDE_ALLOW_EXT ? $this->_root . $templatePath : $this->_root . LIQUID_INCLUDE_PREFIX . $templatePath . '.' . LIQUID_INCLUDE_SUFFIX; } $rootRegex = new LiquidRegexp('/' . preg_quote(realpath($this->_root), '/') . '/'); if (!$rootRegex->match(realpath($fullPath))) { throw new LiquidException("Illegal template path '" . realpath($fullPath) . "'"); } return $fullPath; }
/** * Constructor * * @param string $markup * @param array $tokens * @param LiquidFileSystem $file_system * @return ForLiquidTag */ public function __construct($markup, &$tokens, &$file_system) { parent::__construct($markup, $tokens, $file_system); $syntax_regexp = new LiquidRegexp('/(\\w+)\\s+in\\s+(' . LIQUID_ALLOWED_VARIABLE_CHARS . '+)/'); if ($syntax_regexp->match($markup)) { $this->_variableName = $syntax_regexp->matches[1]; $this->_collectionName = $syntax_regexp->matches[2]; $this->_name = $syntax_regexp->matches[1] . '-' . $syntax_regexp->matches[2]; $this->extractAttributes($markup); } else { $syntax_regexp = new LiquidRegexp('/(\\w+)\\s+in\\s+\\((\\d|' . LIQUID_ALLOWED_VARIABLE_CHARS . '+)\\s*..\\s*(\\d|' . LIQUID_ALLOWED_VARIABLE_CHARS . '+)\\)/'); if ($syntax_regexp->match($markup)) { $this->_type = 'digit'; $this->_variableName = $syntax_regexp->matches[1]; $this->_start = $syntax_regexp->matches[2]; $this->_collectionName = $syntax_regexp->matches[3]; $this->_name = $syntax_regexp->matches[1] . '-digit'; $this->extractAttributes($markup); } else { throw new LiquidException("Syntax Error in 'for loop' - Valid syntax: for [item] in [collection] OR for [int] in ([start]..[end])"); } } }
/** * Constructor * * @param string $markup * @return LiquidVariable */ function LiquidVariable($markup) { $this->markup = $markup; $quoted_fragment_regexp = new LiquidRegexp('/\\s*(' . LIQUID_QUOTED_FRAGMENT . ')/'); $filter_seperator_regexp = new LiquidRegexp('/' . LIQUID_FILTER_SEPERATOR . '\\s*(.*)/'); $filter_split_regexp = new LiquidRegexp('/' . LIQUID_FILTER_SEPERATOR . '/'); $filter_name_regexp = new LiquidRegexp('/\\s*(\\w+)/'); $filter_argument_regexp = new LiquidRegexp('/(?:' . LIQUID_FILTER_ARGUMENT_SEPERATOR . '|' . LIQUID_ARGUMENT_SPERATOR . ')\\s*(' . LIQUID_QUOTED_FRAGMENT . ')/'); $quoted_fragment_regexp->match($markup); $this->name = $quoted_fragment_regexp->matches[1]; if ($filter_seperator_regexp->match($markup)) { $filters = $filter_split_regexp->split($filter_seperator_regexp->matches[1]); foreach ($filters as $filter) { $filter_name_regexp->match($filter); $filtername = $filter_name_regexp->matches[1]; $filter_argument_regexp->match_all($filter); $matches = array_flatten($filter_argument_regexp->matches[1]); $this->filters[] = array($filtername, $matches); } } else { $this->filters = array(); } }
/** * Extract variables from a string of markup * * @param string $markup * @return array; */ private function _variablesFromString($markup) { $regexp = new LiquidRegexp('/\\s*(' . LIQUID_QUOTED_FRAGMENT . ')\\s*/'); $parts = explode(',', $markup); $result = array(); foreach ($parts as $part) { $regexp->match($part); if ($regexp->matches[1]) { $result[] = $regexp->matches[1]; } } return $result; }
/** * Resolves a given path to a full template file path, making sure it's valid * * @param string $template_path * @return string */ function full_path($template_path) { $name_regex = new LiquidRegexp('/^[^.\\/][a-zA-Z0-9_\\/]+$/'); if (!$name_regex->match($template_path)) { trigger_error("Illegal template name '{$template_path}'", E_USER_ERROR); return false; } if (strpos($template_path, '/') !== false) { $full_path = $this->root . dirname($template_path) . '/' . "_" . basename($template_path) . ".liquid"; } else { $full_path = $this->root . "_" . $template_path . ".liquid"; } $root_regex = new LiquidRegexp(realpath($root)); if (!$root_regex->match(realpath($full_path))) { trigger_error("Illegal template path '" . realpath($full_path) . "'", E_USER_ERROR); } else { return $full_path; } }
/** * Parses the tokens * * @param array $tokens */ public function parse(&$tokens) { if (!isset($this->_fileSystem)) { throw new LiquidException("No file system"); } // read the source of the template and create a new sub document $source = $this->_fileSystem->readTemplateFile($this->_templateName); // tokens in this new document $maintokens = LiquidTemplate::tokenize($source); $eRegexp = new LiquidRegexp('/^' . LIQUID_TAG_START . '\\s*extends (.*)?' . LIQUID_TAG_END . '$/'); foreach ($maintokens as $maintoken) { if ($eRegexp->match($maintoken)) { $m = $eRegexp->matches[1]; break; } } if (isset($m)) { $rest = array_merge($maintokens, $tokens); } else { $childtokens = $this->_findBlocks($tokens); $blockstartRegexp = new LiquidRegexp('/^' . LIQUID_TAG_START . '\\s*block (\\w+)\\s*(.*)?' . LIQUID_TAG_END . '$/'); $blockendRegexp = new LiquidRegexp('/^' . LIQUID_TAG_START . '\\s*endblock\\s*?' . LIQUID_TAG_END . '$/'); $b = array(); $name = null; $rest = array(); $aufzeichnen = false; for ($i = 0; $i < count($maintokens); $i++) { if ($blockstartRegexp->match($maintokens[$i])) { $name = $blockstartRegexp->matches[1]; if (isset($childtokens[$name])) { $aufzeichnen = true; array_push($rest, $maintokens[$i]); foreach ($childtokens[$name] as $item) { array_push($rest, $item); } } } if (!$aufzeichnen) { array_push($rest, $maintokens[$i]); } if ($blockendRegexp->match($maintokens[$i]) && $aufzeichnen === true) { $aufzeichnen = false; array_push($rest, $maintokens[$i]); } } } $this->_hash = md5($source); $cache = LiquidTemplate::getCache(); if (isset($cache)) { if (($this->_document = $cache->read($this->_hash)) != false && $this->_document->checkIncludes() != true) { } else { $this->_document = new LiquidDocument($rest, $this->_fileSystem); $cache->write($this->_hash, $this->_document); } } else { $this->_document = new LiquidDocument($rest, $this->_fileSystem); } }
/** * Create a variable for the given token * * @param string $token * @return LiquidVariable */ function create_variable($token) { $variable_regexp = new LiquidRegexp('/^' . LIQUID_VARIABLE_START . '(.*)' . LIQUID_VARIABLE_END . '$/'); if ($variable_regexp->match($token)) { return new LiquidVariable($variable_regexp->matches[1]); } throw new LiquidException("Variable {$token} was not properly terminated"); }
/** * Constructor * * @param string $markup * @param array $tokens * @param LiquidFileSystem $file_system * @return IncludeLiquidTag */ function IncludeLiquidTag($markup, &$tokens, &$file_system) { $regex = new LiquidRegexp('/("[^"]+"|\'[^\']+\')(\\s+(with|for)\\s+(' . LIQUID_QUOTED_FRAGMENT . '+))?/'); if ($regex->match($markup)) { $this->template_name = substr($regex->matches[1], 1, strlen($regex->matches[1]) - 2); if (isset($regex->matches[1])) { $this->collection = $regex->matches[3] == "for"; $this->variable = $regex->matches[4]; } $this->extract_attributes($markup); } else { trigger_error("Error in tag 'include' - Valid syntax: include '[template]' (with|for) [object|collection]", E_USER_ERROR); } parent::LiquidTag($markup, $tokens, $file_system); }