public static function compile(Compiler $compiler, $file) { list($l, $r) = $compiler->getDelimiters(); self::$l = preg_quote($l, '/'); self::$r = preg_quote($r, '/'); self::$regex = '/ ' . self::$l . 'block\\s(["\']?)(.+?)\\1' . self::$r . '(?:\\r?\\n?) ((?: (?R) | [^' . self::$l . ']* (?: (?! ' . self::$l . '\\/?block\\b ) ' . self::$l . ' [^' . self::$l . ']*+ )* )*) ' . self::$l . '\\/block' . self::$r . ' /six'; if ($compiler->getLooseOpeningHandling()) { self::$l .= '\\s*'; self::$r = '\\s*' . self::$r; } $inheritanceTree = array(array('source' => $compiler->getTemplateSource())); //$curPath = dirname($compiler->getDwoo()->getTemplate()->getResourceIdentifier()) . DIRECTORY_SEPARATOR; $curTpl = $compiler->getDwoo()->getTemplate(); while (!empty($file)) { if ($file === '""' || $file === "''" || substr($file, 0, 1) !== '"' && substr($file, 0, 1) !== '\'') { throw new CompilationException($compiler, 'Extends : The file name must be a non-empty string'); return; } if (preg_match('#^["\']([a-z]{2,}):(.*?)["\']$#i', $file, $m)) { // resource:identifier given, extract them $resource = $m[1]; $identifier = $m[2]; } else { // get the current template's resource $resource = $curTpl->getResourceName(); $identifier = substr($file, 1, -1); } try { $parent = $compiler->getDwoo()->templateFactory($resource, $identifier, null, null, null, $curTpl); } catch (\Dwoo\Exception\SecurityException $e) { throw new CompilationException($compiler, 'Extends : Security restriction : ' . $e->getMessage()); } catch (\Dwoo\Exception $e) { throw new Exception($compiler, 'Extends : ' . $e->getMessage()); } if ($parent === null) { throw new CompilationException($compiler, 'Extends : Resource "' . $resource . ':' . $identifier . '" not found.'); } elseif ($parent === false) { throw new CompilationException($compiler, 'Extends : Resource "' . $resource . '" does not support extends.'); } $curTpl = $parent; $newParent = array('source' => $parent->getSource(), 'resource' => $resource, 'identifier' => $parent->getResourceIdentifier(), 'uid' => $parent->getUid()); if (array_search($newParent, $inheritanceTree, true) !== false) { throw new CompilationException($compiler, 'Extends : Recursive template inheritance detected'); } $inheritanceTree[] = $newParent; if (preg_match('/^' . self::$l . 'extends(?:\\(?\\s*|\\s+)(?:file=)?\\s*((["\']).+?\\2|\\S+?)\\s*\\)?\\s*?' . self::$r . '/i', $parent->getSource(), $match)) { $curPath = dirname($identifier) . DIRECTORY_SEPARATOR; if (isset($match[2]) && $match[2] == '"') { $file = '"' . str_replace('"', '\\"', substr($match[1], 1, -1)) . '"'; } elseif (isset($match[2]) && $match[2] == "'") { $file = '"' . substr($match[1], 1, -1) . '"'; } else { $file = '"' . $match[1] . '"'; } } else { $file = false; } } while (true) { $parent = array_pop($inheritanceTree); $child = end($inheritanceTree); self::$childSource = $child['source']; self::$lastReplacement = count($inheritanceTree) === 1; if (!isset($newSource)) { $newSource = $parent['source']; } $newSource = preg_replace_callback(self::$regex, array(__CLASS__, 'replaceBlock'), $newSource); $newSource = $l . 'do extendsCheck(' . var_export($parent['resource'] . ':' . $parent['identifier'], true) . ')' . $r . $newSource; if (self::$lastReplacement) { break; } } $compiler->setTemplateSource($newSource); $compiler->recompile(); }