/** * Static callback that does the minification. * The method is called from within the compiled template. * * @param array $files List of files that need to minified. * @param string $type Is it a js or a css minification in question. * @param Htpl $htpl Current htpl instance. * * @throws HtplException */ public static function minifyCallback($files, $type, Htpl $htpl) { // get minify driver instance $options = $htpl->getOptions()['minify']; if (empty($options)) { throw new HtplException('Missing options for w-minify function.'); } // get driver $driver = isset($options['driver']) ? $options['driver'] : '\\Webiny\\Htpl\\Functions\\WMinify\\WMinify'; if (!is_object($driver)) { $driver = new $driver($htpl); } if (!$driver instanceof \Webiny\Htpl\Functions\WMinify\WMinifyAbstract) { throw new HtplException('Minify driver must implement \\Webiny\\Htpl\\Functions\\WMinify\\WMinifyAbstract.'); } if ($type == 'js') { $minifiedFile = $driver->minifyJavaScript($files); echo '<script type="text/javascript" src="' . $minifiedFile . '"/>'; } else { if ($type == 'css') { $minifiedFile = $driver->minifyCss($files); echo '<link rel="stylesheet" href="' . $minifiedFile . '"/>'; } else { throw new HtplException(sprintf('Unknown $type value for minify callback: %s', $type)); } } }
public function testGetSource() { $provider = new ArrayProvider(['test.htpl' => '{var}']); $htpl = new Htpl($provider); $htpl->assign('var', 'FooBar'); $expectedResult = '<?php echo htmlspecialchars($this->getVar(\'var\', $this->vars), ENT_QUOTES | ENT_SUBSTITUTE, \'utf-8\');?>'; $this->assertSame($expectedResult, trim($htpl->build('test.htpl')->getSource())); }
/** * Static callback that includes a Htpl template. * * @param string $file Path to the Htpl template. * @param Htpl $htpl Current Htpl instance. * * @throws HtplException */ public static function htpl($file, Htpl $htpl) { // validate the variable value // only htpl templates are allowed if (substr($file, -5) != '.htpl') { throw new HtplException(sprintf('Failed to include %s. Only .htpl templates can be included.', $file)); } // use the same htpl instance so we benefit from the internal cache and already initialized provider and so we // also pass the current assigned variables $htpl->display($file); }
/** * Method that does the actual compiling. * * @param string $templateName Template name that should be compiled. * * @return Layout Compiled template in form of a string. * @throws HtplException */ private function compileLayout($templateName) { // before we can do the template compile, we need to solve the template inheritance $layout = LayoutTree::getLayout($this->htpl->getTemplateProvider(), $templateName); $template = $layout->getSource(); // validate that the raw template doesn't contain any PHP code if (strpos($template, '<?') !== false) { throw new HtplException(sprintf('Template "%s" contains PHP tags which are not allowed.', $templateName)); } // strip out w-literal content before parsing any tags or variables $literals = TagLexer::parse($template)->select('w-literal'); $literalReplacements = []; foreach ($literals as $l) { $id = '<!-- htpl: w-literal => ' . uniqid() . ' -->'; $literalReplacements[$id] = $l['content']; $template = str_replace($l['outerHtml'], $id, $template); } // parse the variables $template = VarLexer::parse($template, $this->htpl); // get a list of possible functions (tags) that we support $functions = $this->htpl->getFunctions(); $lexedTemplate = TagLexer::parse($template); foreach ($functions as $tag => $callback) { $tags = $lexedTemplate->select($tag); foreach ($tags as $t) { $lexedTemplate = TagLexer::parse($template); $currentMatch = $lexedTemplate->select($tag); if (count($currentMatch) < 1) { continue; } else { $currentMatch = $currentMatch[0]; } $content = $currentMatch['content']; $attributes = isset($currentMatch['attributes']) ? $currentMatch['attributes'] : []; try { // extract the opening and closing tag $outerContent = str_replace($currentMatch['content'], '', $currentMatch['outerHtml']); $closingTag = '</' . $tag . '>'; $openingTag = str_replace($closingTag, '', $outerContent); $instance = new $callback(); $result = $instance->parseTag($content, $attributes, $this->htpl); if (!$result) { continue; } // check if we have context defined $contextStart = ''; $contextEnd = ''; if (isset($result['contexts'])) { foreach ($result['contexts'] as $c) { $contextStart .= '<!-- htpl-context-start:' . $c . ' -->' . "\n"; $contextEnd = '<!-- htpl-context-end:' . $c . ' -->' . "\n" . $contextEnd; } } // do the replacement if (isset($result['content'])) { $replacement = $contextStart . $result['openingTag'] . $result['content'] . $result['closingTag'] . $contextEnd; // we replace with offset 1 cause, we always do the replacement on the current template instance //$template = str_replace($currentMatch['outerHtml'], $replacement, $template); $template = preg_replace('/(\\s+|)' . preg_quote($currentMatch['outerHtml'], '/') . '(\\s+|)/', $replacement, $template); } else { $replacement = $contextStart . $result['openingTag'] . $currentMatch['content'] . $result['closingTag'] . $contextEnd; $template = preg_replace('/(\\s+|)' . preg_quote($currentMatch['outerHtml'], '/') . '(\\s+|)/', $replacement, $template); /* //$template = str_replace($openingTag, $result['openingTag'], $template); $template = preg_replace('/(\s+|)' . preg_quote($openingTag, '/') . '(\s+|)/', $result['openingTag'], $template); if (isset($result['closingTag'])) { //$template = str_replace($closingTag, $result['closingTag'], $template); $template = preg_replace('/(\s+|)' . preg_quote($closingTag, '/') . '(\s+|)/', $result['closingTag'], $template); } */ } } catch (HtplException $e) { throw new HtplException('Htpl in unable to parse your template near: ' . $openingTag . "\n\n " . $e->getMessage()); } } } // adjust contexts $template = $this->adjustContexts($template); // optimize template execution /*$template = preg_replace('/\?>(\s+|)\<\?php/', "\n", $template);*/ // put back the literals foreach ($literalReplacements as $lrId => $lrVal) { $template = str_replace($lrId, $lrVal, $template); } // save the new source $layout->setSource($template); return $layout; }
public function testSetGetLexerTags() { $provider = new ArrayProvider(['test.htpl' => '{var}']); $htpl = new Htpl($provider); $this->assertSame(['varStartFlag' => '{', 'varEndFlag' => '}'], $htpl->getLexerFlags()); $htpl->setLexerFlags('{{', '}}'); $this->assertSame(['varStartFlag' => '{{', 'varEndFlag' => '}}'], $htpl->getLexerFlags()); }