Наследование: extends Flags
Пример #1
0
 /**
  *
  */
 public function renderView($viewCode, $viewContext = null, $viewRoot = null)
 {
     // Fix the view root
     if (empty($viewRoot) === true) {
         $viewRoot = PATH_APP . '/Views';
     }
     // Check whether the view exists
     $pathToView = $viewRoot . '/' . $viewCode;
     if (file_exists($pathToView) === false) {
         \z\e(EXCEPTION_VIEW_NOT_FOUND, ['pathToView' => $pathToView, 'viewCode' => $viewCode, 'viewContext' => $viewContext]);
     }
     // Load the view
     $view = file_get_contents($pathToView);
     // Compile the view
     $code = \LightnCandy\LightnCandy::compile($view, ['basedir' => [PATH_APP . '/Views'], 'fileext' => [''], 'flags' => \LightnCandy\LightnCandy::FLAG_ERROR_EXCEPTION | \LightnCandy\LightnCandy::FLAG_HANDLEBARS | \LightnCandy\LightnCandy::FLAG_RENDER_DEBUG | \LightnCandy\LightnCandy::FLAG_RUNTIMEPARTIAL | \LightnCandy\LightnCandy::FLAG_THIS, 'helpers' => ['locale' => function () {
         return \z\service('manager/culture')->localeCode;
     }, 'str' => function ($indexed, $associative) {
         // Build arguments
         $arguments = $this->buildArguments(['stringCode'], $indexed, $associative);
         // Get the string
         $result = \z\str($arguments['stringCode']);
         return $result;
     }]]);
     // Build path to code
     $pathToCode = '/tmp/' . sha1('fbenard/zero_' . $pathToView) . '.php';
     // Get the view renderer
     file_put_contents($pathToCode, $code);
     $renderer = (require $pathToCode);
     // Render the view
     $result = $renderer($viewContext);
     return $result;
 }
Пример #2
0
 public function __construct($config)
 {
     $this->config = $config;
     $str = LightnCandy::compile(file_get_contents($this->config['template']));
     $this->path = sprintf('%s.php', tempnam($config['tmp'], 'tpl'));
     file_put_contents($this->path, sprintf("<?php\n%s", $str));
     $this->renderer = (require_once $this->path);
 }
 /**
  * Setup token delimiter by default or provided string
  *
  * @param array<string,array|string|integer> $context Current context
  * @param string $left left string of a token
  * @param string $right right string of a token
  */
 protected static function setupToken(&$context, $left = '{{', $right = '}}')
 {
     parent::setupToken($context, $left, $right);
     if (self::$compileHelpersOnly) {
         $helperTokens = array();
         foreach ($context['helpers'] as $helper => $value) {
             $helperTokens[] = $helper . '.*?';
         }
         $helperTokens = implode('|', $helperTokens);
         $context['tokens']['search'] = "/^(.*?)(\\s*)({$left})(~?)([\\^#\\/!&>]?)(" . $helperTokens . ")(~?)({$right})(\\s*)(.*)\$/s";
     }
 }
Пример #4
0
 /**
  * @dataProvider issueProvider
  */
 public function testIssues($issue)
 {
     global $tmpdir;
     $php = LightnCandy::compile($issue['template'], isset($issue['options']) ? $issue['options'] : null);
     $context = LightnCandy::getContext();
     $parsed = print_r(LightnCandy::$lastParsed, true);
     if (count($context['error'])) {
         $this->fail('Compile failed due to:' . print_r($context['error'], true) . "\nPARSED: {$parsed}");
     }
     $renderer = LightnCandy::prepare($php);
     $this->assertEquals($issue['expected'], $renderer($issue['data'], array('debug' => $issue['debug'])), "PHP CODE:\n{$php}\n{$parsed}");
 }
 public function compile($name)
 {
     $source = $this->getLoader()->getSource($name);
     $cacheKey = $this->getCacheFilename($name);
     $phpStr = '';
     try {
         $this->partials->exchangeArray([new FileResource($this->getLoader()->getCacheKey($name))]);
         $phpStr = LightnCandy::compile($source, $this->options);
     } catch (\Exception $e) {
         throw new LoaderException($e->getMessage());
     }
     $this->cache->write($cacheKey, '<?php // ' . $name . PHP_EOL . $phpStr, $this->partials->getArrayCopy());
     return $phpStr;
 }
Пример #6
0
 public function renderWidget($widget)
 {
     $filename = get_class($widget) . '.hbs';
     $filename = str_replace('\\', '/', $filename);
     $filename = $this->themePath . '/' . $filename;
     if (!file_exists($filename)) {
         throw new RuntimeException("Can't find widget template: " . $filename);
     }
     $template = file_get_contents($filename);
     $helper = new Helper();
     $phpStr = LightnCandy::compile($template, ['flags' => LightnCandy::FLAG_INSTANCE | LightnCandy::FLAG_METHOD, 'helpers' => ['route' => 'Materia\\Helper::route']]);
     $renderer = LightnCandy::prepare($phpStr);
     $data = ['widget' => $widget];
     $data['urlGenerator'] = $this->urlGenerator;
     $data['materia'] = $this;
     return $renderer($data);
 }
Пример #7
0
 /**
  * @dataProvider jsonSpecProvider
  */
 public function testSpecs($spec)
 {
     global $tmpdir;
     $flag = LightnCandy::FLAG_MUSTACHE | LightnCandy::FLAG_ERROR_EXCEPTION;
     if ($spec['name'] == 'Interpolation - Expansion' || $spec['name'] == 'Interpolation - Alternate Delimiters' || $spec['desc'] == 'Lambdas used for sections should receive the raw section string.' || $spec['name'] == 'Section - Expansion' || $spec['name'] == 'Section - Alternate Delimiters' || $spec['name'] == 'Section - Multiple Calls' || $spec['name'] == 'Inverted Section') {
         $this->markTestIncomplete('Not supported case: complex mustache lambdas');
     }
     if (isset($spec['data']['lambda']['php'])) {
         $spec['data']['lambda'] = getFunctionCode('function ($text = null) {' . $spec['data']['lambda']['php'] . '}');
     }
     foreach (array($flag, $flag | LightnCandy::FLAG_STANDALONEPHP) as $f) {
         global $calls;
         $calls = 0;
         $php = LightnCandy::compile($spec['template'], array('flags' => $f, 'partials' => isset($spec['partials']) ? $spec['partials'] : null, 'basedir' => $tmpdir));
         $parsed = print_r(LightnCandy::$lastParsed, true);
         $renderer = LightnCandy::prepare($php);
         $this->assertEquals($spec['expected'], $renderer($spec['data'], array('debug' => 0)), "SPEC:\n" . print_r($spec, true) . "\nPHP CODE: {$php}\nPARSED: {$parsed}");
     }
 }
Пример #8
0
 /**
  * @dataProvider jsonSpecProvider
  */
 public function testSpecs($spec)
 {
     global $tmpdir;
     global $tested;
     global $test_flags;
     recursive_unset($spec, '!sparsearray');
     recursive_lambda_fix($spec['data']);
     if (isset($spec['options']['data'])) {
         recursive_lambda_fix($spec['options']['data']);
     }
     //// Skip bad specs
     // 1. No expected nor exception in spec
     if (!isset($spec['expected']) && !isset($spec['exception'])) {
         $this->markTestIncomplete("Skip [{$spec['file']}#{$spec['description']}]#{$spec['no']} , no expected result in spec, skip.");
     }
     // 2. Not supported case: foo/bar path
     if ($spec['it'] === 'literal paths' && $spec['no'] === 58 || $spec['it'] === 'literal paths' && $spec['no'] === 59 || $spec['it'] === 'this keyword nested inside path' || $spec['it'] === 'this keyword nested inside helpers param' || $spec['it'] === 'should handle invalid paths' || $spec['it'] === 'parameter data throws when using complex scope references' || $spec['it'] === 'block with complex lookup using nested context') {
         $this->markTestIncomplete('Not supported case: foo/bar path');
     }
     // 3. Different API, no need to test
     if ($spec['it'] === 'registering undefined partial throws an exception') {
         $this->markTestIncomplete('Not supported case: just skip it');
     }
     // 4. block parameters, special case now do not support
     if ($spec['it'] === 'should not take presedence over pathed values') {
         $this->markTestIncomplete('Not supported case: just skip it');
     }
     // 5. Not supported case: helperMissing and blockHelperMissing
     if ($spec['it'] === 'if a context is not found, helperMissing is used' || $spec['it'] === 'if a context is not found, custom helperMissing is used' || $spec['it'] === 'if a value is not found, custom helperMissing is used' || $spec['it'] === 'should include in simple block calls' || $spec['it'] === 'should include full id' || $spec['it'] === 'should include full id if a hash is passed' || $spec['it'] === 'lambdas resolved by blockHelperMissing are bound to the context') {
         $this->markTestIncomplete('Not supported case: just skip it');
     }
     // 6. Not supported case: misc
     if ($spec['description'] === 'compat mode' || $spec['description'] === 'directives' || $spec['file'] === 'specs/handlebars/spec/track-ids.json' || $spec['it'] === 'knows how to report the correct line number in errors' || $spec['it'] === 'knows how to report the correct line number in errors when the first character is a newline' || $spec['it'] === 'should allow block params on chained helpers' || $spec['it'] === 'chained inverted sections' || $spec['description'] === 'decorators' || $spec['it'] === 'helper for raw block gets parameters' || $spec['template'] === '{{foo}') {
         $this->markTestIncomplete('Not supported case: just skip it');
     }
     // TODO: require fix
     if ($spec['template'] === '{{#with .}}{{#*inline "myPartial"}}success{{/inline}}{{/with}}{{> myPartial}}' || $spec['it'] === 'functions returning safestrings shouldn\'t be escaped' || $spec['it'] === 'rendering function partial in vm mode' || $spec['it'] === 'provides each nested helper invocation its own options hash' || $spec['template'] === '{{echo (header)}}' || $spec['it'] === 'block functions without context argument' || $spec['it'] === 'depthed block functions with context argument' || $spec['it'] === 'block functions with context argument') {
         $this->markTestIncomplete('TODO: require fix');
     }
     // FIX SPEC
     if ($spec['it'] === 'should take presednece over parent block params') {
         $spec['helpers']['goodbyes']['php'] = 'function($options) { static $value; if($value === null) { $value = 1; } return $options->fn(array("value" => "bar"), array("blockParams" => ($options["fn.blockParams"] === 1) ? array($value++, $value++) : null));}';
     }
     if ($spec['it'] === 'should handle undefined and null' && $spec['expected'] === 'true true object') {
         $spec['expected'] = 'true true array';
     }
     foreach ($test_flags as $f) {
         // setup helpers
         $tested++;
         $helpers = array();
         $helpersList = '';
         foreach (array_merge(isset($spec['globalHelpers']) && is_array($spec['globalHelpers']) ? $spec['globalHelpers'] : array(), isset($spec['helpers']) && is_array($spec['helpers']) ? $spec['helpers'] : array()) as $name => $func) {
             if (!isset($func['php'])) {
                 $this->markTestIncomplete("Skip [{$spec['file']}#{$spec['description']}]#{$spec['no']} , no PHP helper code provided for this case.");
             }
             $hname = preg_replace('/\\.|\\//', '_', "custom_helper_{$spec['no']}_{$tested}_{$name}");
             $helpers[$name] = $hname;
             $helper = preg_replace('/\\$options->(\\w+)/', '$options[\'$1\']', patch_this(preg_replace('/\\$block\\/\\*\\[\'(.+?)\'\\]\\*\\/->(.+?)\\(/', '$block[\'$2\'](', patch_safestring(preg_replace('/function/', "function {$hname}", $func['php'], 1)))));
             if ($spec['it'] === 'helper block with complex lookup expression' && $name === 'goodbyes') {
                 $helper = preg_replace('/\\[\'fn\'\\]\\(\\)/', '[\'fn\'](array())', $helper);
             }
             $helpersList .= "{$helper}\n";
             eval($helper);
         }
         try {
             $partials = isset($spec['globalPartials']) ? $spec['globalPartials'] : array();
             // Do not use array_merge() here because it destories numeric key
             if (isset($spec['partials'])) {
                 foreach ($spec['partials'] as $k => $v) {
                     $partials[$k] = $v;
                 }
             }
             if (isset($spec['compileOptions']['preventIndent'])) {
                 if ($spec['compileOptions']['preventIndent']) {
                     $f = $f | LightnCandy::FLAG_PREVENTINDENT;
                 }
             }
             if (isset($spec['compileOptions']['explicitPartialContext'])) {
                 if ($spec['compileOptions']['explicitPartialContext']) {
                     $f = $f | LightnCandy::FLAG_PARTIALNEWCONTEXT;
                 }
             }
             if (isset($spec['compileOptions']['ignoreStandalone'])) {
                 if ($spec['compileOptions']['ignoreStandalone']) {
                     $f = $f | LightnCandy::FLAG_IGNORESTANDALONE;
                 }
             }
             if (isset($spec['compileOptions']['stringParams'])) {
                 if ($spec['compileOptions']['stringParams']) {
                     $f = $f | LightnCandy::FLAG_STRINGPARAMS;
                 }
             }
             if (isset($spec['compileOptions']['knownHelpersOnly'])) {
                 if ($spec['compileOptions']['knownHelpersOnly']) {
                     $f = $f | LightnCandy::FLAG_KNOWNHELPERSONLY;
                 }
             }
             $php = LightnCandy::compile($spec['template'], array('flags' => $f, 'hbhelpers' => $helpers, 'basedir' => $tmpdir, 'partials' => $partials));
             $parsed = print_r(LightnCandy::$lastParsed, true);
         } catch (Exception $e) {
             // Exception as expected, pass!
             if (isset($spec['exception'])) {
                 continue;
             }
             // Failed this case
             $this->fail('Exception:' . $e->getMessage());
         }
         $renderer = LightnCandy::prepare($php);
         if ($spec['description'] === 'Tokenizer') {
             // no compile error means passed
             continue;
         }
         try {
             $ropt = array('debug' => Runtime::DEBUG_ERROR_EXCEPTION);
             if (isset($spec['options']['data'])) {
                 $ropt['data'] = $spec['options']['data'];
             }
             $result = $renderer($spec['data'], $ropt);
         } catch (Exception $e) {
             if (!isset($spec['expected'])) {
                 // expected error and catched here, so passed
                 continue;
             }
             $this->fail("Rendering Error in {$spec['file']}#{$spec['description']}]#{$spec['no']}:{$spec['it']} PHP CODE: {$php}\nPARSED: {$parsed}\n" . $e->getMessage());
         }
         if (!isset($spec['expected'])) {
             $this->fail('Should Fail:' . print_r($spec, true) . "PHP CODE: {$php}\nPARSED: {$parsed}\nHELPERS:{$helpersList}");
         }
         $this->assertEquals($spec['expected'], $result, "[{$spec['file']}#{$spec['description']}]#{$spec['no']}:{$spec['it']} PHP CODE: {$php}\nPARSED: {$parsed}\nHELPERS:{$helpersList}");
     }
 }
Пример #9
0
 /**
  * Render the template using the mustache engine
  *
  * @args
  * 		template: The template uri for render
  * 		args: The args that used for render
  */
 public function render($template, $args = array())
 {
     if (func_num_args() > 2) {
         // They must using the variable args method
         $args = func_get_args();
         $template = array_shift($args);
         return $this->render($template, $args);
     }
     // Get the cache file name by md5 it
     $hash = md5($template);
     $cacheDir = $this->filecache->cacheDir();
     if (!file_exists($cacheDir)) {
         // Create the directory if not exists
         mkdir($cacheDir, 0755, true);
     }
     $phpname = \Clips\path_join($cacheDir, 'tpl_' . $hash . '.php');
     $debug = \Clips\config('debug_template');
     // Check if we can found the compiled php
     if (!file_exists($phpname) || $debug) {
         // Can't found this template in cache, read it from resource
         $resource = new \Clips\Resource($template);
         $str = $resource->contents();
         $flags = \Clips\context('template_flags');
         if (!$flags) {
             $flags = \Clips\config('template_flags');
             if ($flags) {
                 $flags = $flags[0];
             } else {
                 $flags = LightnCandy::FLAG_ERROR_EXCEPTION | LightnCandy::FLAG_HANDLEBARS | LightnCandy::FLAG_HANDLEBARSJS;
             }
         }
         $opts = array('flags' => $flags);
         $partials = \Clips\context('template_partials');
         if ($partials) {
             $opts['partials'] = $partials;
         }
         $default_helpers = array('site_url' => '\\Clips\\Libraries\\site_url', 'static_url' => '\\Clips\\Libraries\\static_url', 'php' => '\\Clips\\Libraries\\php_call');
         $default_block_helpers = array('times' => '\\Clips\\Libraries\\times', 'randtimes' => '\\Clips\\Libraries\\randtimes');
         $helpers = \Clips\context('template_helpers');
         if ($helpers) {
             $opts['helpers'] = array_merge($default_helpers, $helpers);
         } else {
             $opts['helpers'] = $default_helpers;
         }
         $block_helpers = \Clips\context('template_block_helpers');
         if ($block_helpers) {
             $opts['hbhelpers'] = array_merge($default_block_helpers, $block_helpers);
         } else {
             $opts['hbhelpers'] = $default_block_helpers;
         }
         if ($str) {
             $php = "<?php " . PHP_EOL . LightnCandy::compile($str, $opts);
             // Save it to php file
             file_put_contents($phpname, $php);
         }
     }
     if (file_exists($phpname)) {
         $renderer = (include $phpname);
         return $renderer((array) $args);
     }
     return '';
 }
Пример #10
0
 /**
  * @dataProvider errorProvider
  */
 public function testErrors($test)
 {
     global $tmpdir;
     $php = LightnCandy::compile($test['template'], $test['options']);
     $context = LightnCandy::getContext();
     // This case should be compiled without error
     if (!isset($test['expected'])) {
         return;
     }
     $this->assertEquals($test['expected'], $context['error'], "Code: {$php}");
 }
Пример #11
0
<?php

use LightnCandy\LightnCandy;
$template = '{{> (partial_name_helper type)}}';
$data = array('type' => 'dog', 'name' => 'Lucky', 'age' => 5);
function partial_name_helper($type)
{
    switch ($type[0]) {
        case 'man':
        case 'woman':
            return 'people';
        case 'dog':
        case 'cat':
            return 'animal';
        default:
            return 'default';
    }
}
$php = LightnCandy::compile($template, array('flags' => LightnCandy::FLAG_HANDLEBARSJS | LightnCandy::FLAG_RUNTIMEPARTIAL | LightnCandy::FLAG_ERROR_EXCEPTION, 'helpers' => array('partial_name_helper'), 'partials' => array('people' => 'This is {{name}}, he is {{age}} years old.', 'animal' => 'This is {{name}}, it is {{age}} years old.', 'default' => 'This is {{name}}.')));
$renderer = LightnCandy::prepare($php);
echo "Data:\n";
print_r($data);
echo "\nTemplate:\n{$template}\n";
echo "\nCode:\n{$php}\n\n";
echo "\nOutput:\n";
echo $renderer($data);
echo "\n";
Пример #12
0
 /**
  * @dataProvider compileProvider
  */
 public function testUsedFeature($test)
 {
     LightnCandy::compile($test['template'], $test['options']);
     $context = LightnCandy::getContext();
     $this->assertEquals($test['expected'], $context['usedFeature']);
 }
Пример #13
0
 /**
  * Fetch rendered template
  *
  * @param  string $template Template pathname relative to templates directory
  * @param  array  $data     Associative array of template variables
  *
  * @return string
  */
 public function fetch($template, $data = [])
 {
     $data = array_merge($this->defaultVariables, $data);
     $php = Engine::compile($this->getTemplate($template), array('flags' => Engine::FLAG_ERROR_EXCEPTION | Engine::FLAG_ERROR_LOG | Engine::FLAG_INSTANCE | Engine::FLAG_MUSTACHE | Engine::FLAG_HANDLEBARS, 'basedir' => $this->directories, 'fileext' => $this->extensions, 'helpers' => $this->helpers, 'hbhelpers' => $this->block_helpers));
     $renderer = Engine::prepare($php);
     return $renderer(array_merge($data ?: array()), LCRun3::DEBUG_ERROR_LOG);
 }