Authored by hf

do modify nginx.reg and test render template

<?php return function ($in, $debugopt = 1) {
$cx = array(
'flags' => array(
'jstrue' => false,
'jsobj' => false,
'spvar' => true,
'prop' => false,
'method' => false,
'mustlok' => true,
'echo' => false,
'debug' => $debugopt,
),
'constants' => array(),
'helpers' => array(),
'blockhelpers' => array(),
'hbhelpers' => array(),
'partials' => array(),
'scopes' => array(),
'sp_vars' => array('root' => $in),
'lcrun' => 'Plugin\LCRun3',
);
return '
This is a test '.htmlentities((string)Plugin\LCRun3::v($cx, $in, array('test')), ENT_QUOTES, 'UTF-8').'
';
}
?>
\ No newline at end of file
... ...
<?php
namespace Plugin;
/**
* LightnCandy static class for compiled template runtime methods.
*/
class LCRun3 {
const DEBUG_ERROR_LOG = 1;
const DEBUG_ERROR_EXCEPTION = 2;
const DEBUG_TAGS = 4;
const DEBUG_TAGS_ANSI = 12;
const DEBUG_TAGS_HTML = 20;
/**
* LightnCandy runtime method for output debug info.
*
* @param string $v expression
* @param string $f runtime function name
* @param array<string,array|string|integer> $cx render time context
*
* @expect '{{123}}' when input '123', 'miss', array('flags' => array('debug' => LCRun3::DEBUG_TAGS), 'lcrun' => 'LCRun3'), ''
* @expect '<!--MISSED((-->{{#123}}<!--))--><!--SKIPPED--><!--MISSED((-->{{/123}}<!--))-->' when input '123', 'wi', array('flags' => array('debug' => LCRun3::DEBUG_TAGS_HTML), 'lcrun' => 'LCRun3'), false, false, function () {return 'A';}
*/
public static function debug($v, $f, $cx) {
$params = array_slice(func_get_args(), 2);
$r = call_user_func_array((isset($cx['funcs'][$f]) ? $cx['funcs'][$f] : "{$cx['lcrun']}::$f"), $params);
if ($cx['flags']['debug'] & self::DEBUG_TAGS) {
$ansi = $cx['flags']['debug'] & (self::DEBUG_TAGS_ANSI - self::DEBUG_TAGS);
$html = $cx['flags']['debug'] & (self::DEBUG_TAGS_HTML - self::DEBUG_TAGS);
$cs = ($html ? (($r !== '') ? '<!!--OK((-->' : '<!--MISSED((-->') : '')
. ($ansi ? (($r !== '') ? "\033[0;32m" : "\033[0;31m") : '');
$ce = ($html ? '<!--))-->' : '')
. ($ansi ? "\033[0m" : '');
switch ($f) {
case 'sec':
case 'ifv':
case 'unl':
case 'wi':
if ($r == '') {
if ($ansi) {
$r = "\033[0;33mSKIPPED\033[0m";
}
if ($html) {
$r = '<!--SKIPPED-->';
}
}
return "$cs{{#{$v}}}$ce{$r}$cs{{/{$v}}}$ce";
default:
return "$cs{{{$v}}}$ce";
}
} else {
return $r;
}
}
/**
* LightnCandy runtime method for missing data error.
*
* @param array<string,array|string|integer> $cx render time context
* @param string $v expression
*/
public static function miss($cx, $v) {
$e = "LCRun3: $v is not exist";
if ($cx['flags']['debug'] & self::DEBUG_ERROR_LOG) {
error_log($e);
return;
}
if ($cx['flags']['debug'] & self::DEBUG_ERROR_EXCEPTION) {
throw new Exception($e);
}
}
/**
* LightnCandy runtime method for variable lookup. It is slower and only be used for instance property or method detection.
*
* @param array<string,array|string|integer> $cx render time context
* @param array<array|string|integer> $base current variable context
* @param array<string|integer> $path array of names for path
*
* @return null|string Return the value or null when not found
*
* @expect null when input array('scopes' => array(), 'flags' => array('prop' => 0, 'method' => 0, 'mustlok' => 0)), 0, array('a', 'b')
* @expect 3 when input array('scopes' => array(), 'flags' => array('prop' => 0, 'method' => 0), 'mustlok' => 0), array('a' => array('b' => 3)), array('a', 'b')
* @expect null when input array('scopes' => array(), 'flags' => array('prop' => 0, 'method' => 0, 'mustlok' => 0)), (Object) array('a' => array('b' => 3)), array('a', 'b')
* @expect 3 when input array('scopes' => array(), 'flags' => array('prop' => 1, 'method' => 0, 'mustlok' => 0)), (Object) array('a' => array('b' => 3)), array('a', 'b')
*/
public static function v($cx, $base, $path) {
$count = count($cx['scopes']);
while ($base) {
$v = $base;
foreach ($path as $name) {
if (is_array($v) && isset($v[$name])) {
$v = $v[$name];
continue;
}
if (is_object($v)) {
if ($cx['flags']['prop'] && isset($v->$name)) {
$v = $v->$name;
continue;
}
if ($cx['flags']['method'] && is_callable(array($v, $name))) {
$v = $v->$name();
continue;
}
}
if ($cx['flags']['mustlok']) {
unset($v);
break;
}
return null;
}
if (isset($v)) {
return $v;
}
$count--;
switch ($count) {
case -1:
$base = $cx['sp_vars']['root'];
break;
case -2:
return null;
default:
$base = $cx['scopes'][$count];
}
}
}
/**
* LightnCandy runtime method for {{#if var}}.
*
* @param array<string,array|string|integer> $cx render time context
* @param array<array|string|integer>|string|integer|null $v value to be tested
*
* @return boolean Return true when the value is not null nor false.
*
* @expect false when input array(), null
* @expect false when input array(), 0
* @expect false when input array(), false
* @expect true when input array(), true
* @expect true when input array(), 1
* @expect false when input array(), ''
* @expect false when input array(), array()
* @expect true when input array(), array('')
* @expect true when input array(), array(0)
*/
public static function ifvar($cx, $v) {
return !is_null($v) && ($v !== false) && ($v !== 0) && ($v !== 0.0) && ($v !== '') && (is_array($v) ? (count($v) > 0) : true);
}
/**
* LightnCandy runtime method for {{#if var}} when {{../var}} used.
*
* @param array<string,array|string|integer> $cx render time context
* @param array<array|string|integer>|string|integer|null $v value to be tested
* @param array<array|string|integer> $in input data with current scope
* @param Closure|null $truecb callback function when test result is true
* @param Closure|null $falsecb callback function when test result is false
*
* @return string The rendered string of the section
*
* @expect '' when input array('scopes' => array()), null, array(), null
* @expect '' when input array('scopes' => array()), null, array(), function () {return 'Y';}
* @expect 'Y' when input array('scopes' => array()), 1, array(), function () {return 'Y';}
* @expect 'N' when input array('scopes' => array()), null, array(), function () {return 'Y';}, function () {return 'N';}
*/
public static function ifv($cx, $v, $in, $truecb, $falsecb = null) {
$ret = '';
if (self::ifvar($cx, $v)) {
if ($truecb) {
$cx['scopes'][] = $in;
$ret = $truecb($cx, $in);
array_pop($cx['scopes']);
}
} else {
if ($falsecb) {
$cx['scopes'][] = $in;
$ret = $falsecb($cx, $in);
array_pop($cx['scopes']);
}
}
return $ret;
}
/**
* LightnCandy runtime method for {{#unless var}} when {{../var}} used.
*
* @param array<string,array|string|integer> $cx render time context
* @param array<array|string|integer>|string|integer|null $var value be tested
* @param array<array|string|integer>|string|integer|null $in input data with current scope
* @param Closure $truecb callback function when test result is true
* @param Closure|null $falsecb callback function when test result is false
*
* @return string Return rendered string when the value is not null nor false.
*
* @expect '' when input array('scopes' => array()), null, array(), null
* @expect 'Y' when input array('scopes' => array()), null, array(), function () {return 'Y';}
* @expect '' when input array('scopes' => array()), 1, array(), function () {return 'Y';}
* @expect 'Y' when input array('scopes' => array()), null, array(), function () {return 'Y';}, function () {return 'N';}
* @expect 'N' when input array('scopes' => array()), true, array(), function () {return 'Y';}, function () {return 'N';}
*/
public static function unl($cx, $var, $in, $truecb, $falsecb = null) {
return self::ifv($cx, $var, $in, $falsecb, $truecb);
}
/**
* LightnCandy runtime method for {{^var}} inverted section.
*
* @param array<string,array|string|integer> $cx render time context
* @param array<array|string|integer>|string|integer|null $v value to be tested
*
* @return boolean Return true when the value is not null nor false.
*
* @expect true when input array(), null
* @expect false when input array(), 0
* @expect true when input array(), false
* @expect false when input array(), 'false'
* @expect true when input array(), array()
* @expect false when input array(), array('1')
*/
public static function isec($cx, $v) {
return is_null($v) || ($v === false) || (is_array($v) && (count($v) === 0));
}
/**
* LightnCandy runtime method for {{{var}}} .
*
* @param array<string,array|string|integer> $cx render time context
* @param array<array|string|integer>|string|integer|null $v value to be output
*
* @return string The raw value of the specified variable
*
* @expect true when input array('flags' => array('jstrue' => 0)), true
* @expect 'true' when input array('flags' => array('jstrue' => 1)), true
* @expect '' when input array('flags' => array('jstrue' => 0)), false
* @expect 'false' when input array('flags' => array('jstrue' => 1)), false
* @expect 'false' when input array('flags' => array('jstrue' => 1)), false, true
* @expect 'Array' when input array('flags' => array('jstrue' => 1, 'jsobj' => 0)), array('a', 'b')
* @expect 'a,b' when input array('flags' => array('jstrue' => 1, 'jsobj' => 1)), array('a', 'b')
* @expect '[object Object]' when input array('flags' => array('jstrue' => 1, 'jsobj' => 1)), array('a', 'c' => 'b')
* @expect '[object Object]' when input array('flags' => array('jstrue' => 1, 'jsobj' => 1)), array('c' => 'b')
* @expect 'a,true' when input array('flags' => array('jstrue' => 1, 'jsobj' => 1)), array('a', true)
* @expect 'a,1' when input array('flags' => array('jstrue' => 0, 'jsobj' => 1)), array('a',true)
* @expect 'a,' when input array('flags' => array('jstrue' => 0, 'jsobj' => 1)), array('a',false)
* @expect 'a,false' when input array('flags' => array('jstrue' => 1, 'jsobj' => 1)), array('a',false)
*/
public static function raw($cx, $v) {
if ($v === true) {
if ($cx['flags']['jstrue']) {
return 'true';
}
}
if (($v === false)) {
if ($cx['flags']['jstrue']) {
return 'false';
}
}
if (is_array($v)) {
if ($cx['flags']['jsobj']) {
if (count(array_diff_key($v, array_keys(array_keys($v)))) > 0) {
return '[object Object]';
} else {
$ret = array();
foreach ($v as $k => $vv) {
$ret[] = self::raw($cx, $vv);
}
return join(',', $ret);
}
} else {
return 'Array';
}
}
return "$v";
}
/**
* LightnCandy runtime method for {{var}} .
*
* @param array<string,array|string|integer> $cx render time context
* @param array<array|string|integer>|string|integer|null $var value to be htmlencoded
*
* @return string The htmlencoded value of the specified variable
*
* @expect 'a' when input array(), 'a'
* @expect 'a&amp;b' when input array(), 'a&b'
* @expect 'a&#039;b' when input array(), 'a\'b'
*/
public static function enc($cx, $var) {
return htmlentities(self::raw($cx, $var), ENT_QUOTES, 'UTF-8');
}
/**
* LightnCandy runtime method for {{var}} , and deal with single quote to same as handlebars.js .
*
* @param array<string,array|string|integer> $cx render time context
* @param array<array|string|integer>|string|integer|null $var value to be htmlencoded
*
* @return string The htmlencoded value of the specified variable
*
* @expect 'a' when input array(), 'a'
* @expect 'a&amp;b' when input array(), 'a&b'
* @expect 'a&#x27;b' when input array(), 'a\'b'
* @expect '&#x60;a&#x27;b' when input array(), '`a\'b'
*/
public static function encq($cx, $var) {
return preg_replace('/`/', '&#x60;', preg_replace('/&#039;/', '&#x27;', htmlentities(self::raw($cx, $var), ENT_QUOTES, 'UTF-8')));
}
/**
* LightnCandy runtime method for {{#var}} section.
*
* @param array<string,array|string|integer> $cx render time context
* @param array<array|string|integer>|string|integer|null $v value for the section
* @param array<array|string|integer>|string|integer|null $in input data with current scope
* @param boolean $each true when rendering #each
* @param Closure $cb callback function to render child context
* @param Closure|null $else callback function to render child context when {{else}}
*
* @return string The rendered string of the section
*
* @expect '' when input array('flags' => array('spvar' => 0)), false, false, false, function () {return 'A';}
* @expect '' when input array('flags' => array('spvar' => 0)), null, null, false, function () {return 'A';}
* @expect 'A' when input array('flags' => array('spvar' => 0)), true, true, false, function () {return 'A';}
* @expect 'A' when input array('flags' => array('spvar' => 0)), 0, 0, false, function () {return 'A';}
* @expect '-a=' when input array('flags' => array('spvar' => 0)), array('a'), array('a'), false, function ($c, $i) {return "-$i=";}
* @expect '-a=-b=' when input array('flags' => array('spvar' => 0)), array('a','b'), array('a','b'), false, function ($c, $i) {return "-$i=";}
* @expect '' when input array('flags' => array('spvar' => 0)), 'abc', 'abc', true, function ($c, $i) {return "-$i=";}
* @expect '-b=' when input array('flags' => array('spvar' => 0)), array('a' => 'b'), array('a' => 'b'), true, function ($c, $i) {return "-$i=";}
* @expect '1' when input array('flags' => array('spvar' => 0)), 'b', 'b', false, function ($c, $i) {return count($i);}
* @expect '1' when input array('flags' => array('spvar' => 0)), 1, 1, false, function ($c, $i) {return print_r($i, true);}
* @expect '0' when input array('flags' => array('spvar' => 0)), 0, 0, false, function ($c, $i) {return print_r($i, true);}
* @expect '{"b":"c"}' when input array('flags' => array('spvar' => 0)), array('b' => 'c'), array('b' => 'c'), false, function ($c, $i) {return json_encode($i);}
* @expect 'inv' when input array('flags' => array('spvar' => 0)), array(), 0, true, function ($c, $i) {return 'cb';}, function ($c, $i) {return 'inv';}
* @expect 'inv' when input array('flags' => array('spvar' => 0)), array(), 0, false, function ($c, $i) {return 'cb';}, function ($c, $i) {return 'inv';}
* @expect 'inv' when input array('flags' => array('spvar' => 0)), false, 0, true, function ($c, $i) {return 'cb';}, function ($c, $i) {return 'inv';}
* @expect 'inv' when input array('flags' => array('spvar' => 0)), false, 0, false, function ($c, $i) {return 'cb';}, function ($c, $i) {return 'inv';}
* @expect 'inv' when input array('flags' => array('spvar' => 0)), '', 0, true, function ($c, $i) {return 'cb';}, function ($c, $i) {return 'inv';}
* @expect 'cb' when input array('flags' => array('spvar' => 0)), '', 0, false, function ($c, $i) {return 'cb';}, function ($c, $i) {return 'inv';}
* @expect 'inv' when input array('flags' => array('spvar' => 0)), 0, 0, true, function ($c, $i) {return 'cb';}, function ($c, $i) {return 'inv';}
* @expect 'cb' when input array('flags' => array('spvar' => 0)), 0, 0, false, function ($c, $i) {return 'cb';}, function ($c, $i) {return 'inv';}
* @expect 'inv' when input array('flags' => array('spvar' => 0)), new stdClass, 0, true, function ($c, $i) {return 'cb';}, function ($c, $i) {return 'inv';}
* @expect 'cb' when input array('flags' => array('spvar' => 0)), new stdClass, 0, false, function ($c, $i) {return 'cb';}, function ($c, $i) {return 'inv';}
* @expect '268' when input array('flags' => array('spvar' => 1), 'sp_vars'=>array('root' => 0)), array(1,3,4), 0, false, function ($c, $i) {return $i * 2;}
* @expect '038' when input array('flags' => array('spvar' => 1), 'sp_vars'=>array('root' => 0)), array(1,3,'a'=>4), 0, true, function ($c, $i) {return $i * $c['sp_vars']['index'];}
*/
public static function sec($cx, $v, $in, $each, $cb, $else = null) {
$isAry = is_array($v) || ($v instanceof ArrayObject);
$isTrav = $v instanceof Traversable;
$loop = $each;
$keys = null;
$last = null;
$isObj = false;
if ($isAry && $else !== null && count($v) === 0) {
$cx['scopes'][] = $in;
$ret = $else($cx, $in);
array_pop($cx['scopes']);
return $ret;
}
// #var, detect input type is object or not
if (!$loop && $isAry) {
$keys = array_keys($v);
$loop = (count(array_diff_key($v, array_keys($keys))) == 0);
$isObj = !$loop;
}
if (($loop && $isAry) || $isTrav) {
if ($each && !$isTrav) {
// Detect input type is object or not when never done once
if ($keys == null) {
$keys = array_keys($v);
$isObj = (count(array_diff_key($v, array_keys($keys))) > 0);
}
}
$ret = array();
$cx['scopes'][] = $in;
$i = 0;
if ($cx['flags']['spvar']) {
$old_spvar = $cx['sp_vars'];
$cx['sp_vars'] = array(
'_parent' => $old_spvar,
'root' => $old_spvar['root'],
);
if (!$isTrav) {
$last = count($keys) - 1;
}
}
foreach ($v as $index => $raw) {
if ($cx['flags']['spvar']) {
$cx['sp_vars']['first'] = ($i === 0);
$cx['sp_vars']['last'] = ($i == $last);
$cx['sp_vars']['key'] = $index;
$cx['sp_vars']['index'] = $i;
$i++;
}
$ret[] = $cb($cx, $raw);
}
if ($cx['flags']['spvar']) {
if ($isObj) {
unset($cx['sp_vars']['key']);
} else {
unset($cx['sp_vars']['last']);
}
unset($cx['sp_vars']['index']);
unset($cx['sp_vars']['first']);
$cx['sp_vars'] = $old_spvar;
}
array_pop($cx['scopes']);
return join('', $ret);
}
if ($each) {
if ($else !== null) {
$cx['scopes'][] = $in;
$ret = $else($cx, $v);
array_pop($cx['scopes']);
return $ret;
}
return '';
}
if ($isAry) {
$cx['scopes'][] = $in;
$ret = $cb($cx, $v);
array_pop($cx['scopes']);
return $ret;
}
if ($v === true) {
return $cb($cx, $in);
}
if (!is_null($v) && ($v !== false)) {
return $cb($cx, $v);
}
if ($else !== null) {
$cx['scopes'][] = $in;
$ret = $else($cx, $in);
array_pop($cx['scopes']);
return $ret;
}
return '';
}
/**
* LightnCandy runtime method for {{#with var}} .
*
* @param array<string,array|string|integer> $cx render time context
* @param array<array|string|integer>|string|integer|null $v value to be the new context
* @param array<array|string|integer>|string|integer|null $in input data with current scope
* @param Closure $cb callback function to render child context
* @param Closure|null $else callback function to render child context when {{else}}
*
* @return string The rendered string of the token
*
* @expect '' when input array(), false, false, function () {return 'A';}
* @expect '' when input array(), null, null, function () {return 'A';}
* @expect '{"a":"b"}' when input array(), array('a'=>'b'), array('a'=>'c'), function ($c, $i) {return json_encode($i);}
* @expect '-b=' when input array(), 'b', array('a'=>'b'), function ($c, $i) {return "-$i=";}
*/
public static function wi($cx, $v, $in, $cb, $else = null) {
if (($v === false) || ($v === null)) {
return $else ? $else($cx, $in) : '';
}
$cx['scopes'][] = $in;
$ret = $cb($cx, $v);
array_pop($cx['scopes']);
return $ret;
}
/**
* LightnCandy runtime method for {{> partial}} .
*
* @param array<string,array|string|integer> $cx render time context
* @param string $p partial name
* @param array<array|string|integer>|string|integer|null $v value to be the new context
*
* @return string The rendered string of the partial
*
*/
public static function p($cx, $p, $v, $sp = '') {
$param = $v[0][0];
if (is_array($v[1])) {
if (is_array($v[0][0])) {
$param = array_merge($v[0][0], $v[1]);
} else if (($cx['flags']['method'] || $cx['flags']['prop']) && is_object($v[0][0])) {
foreach ($v[1] as $i => $v) {
$param->$i = $v;
}
}
}
return call_user_func($cx['partials'][$p], $cx, $param, $sp);
}
/**
* LightnCandy runtime method for custom helpers.
*
* @param array<string,array|string|integer> $cx render time context
* @param string $ch the name of custom helper to be executed
* @param array<array> $vars variables for the helper
* @param string $op the name of variable resolver. should be one of: 'raw', 'enc', or 'encq'.
*
* @return string The rendered string of the token
*
* @expect '=-=' when input array('helpers' => array('a' => function ($i) {return "=$i[0]=";})), 'a', array(array('-'),array()), 'raw'
* @expect '=&amp;=' when input array('helpers' => array('a' => function ($i) {return "=$i[0]=";})), 'a', array(array('&'),array()), 'enc'
* @expect '=&#x27;=' when input array('helpers' => array('a' => function ($i) {return "=$i[0]=";})), 'a', array(array('\''),array()), 'encq'
* @expect '=b=' when input array('helpers' => array('a' => function ($i,$j) {return "={$j['a']}=";})), 'a', array(array(),array('a' => 'b')), 'raw'
*/
public static function ch($cx, $ch, $vars, $op) {
return self::chret(call_user_func_array($cx['helpers'][$ch], $vars), $op);
}
/**
* LightnCandy runtime method to handle response of custom helpers.
*
* @param string|array<string,array|string|integer> $ret return value from custom helper
* @param string $op the name of variable resolver. should be one of: 'raw', 'enc', or 'encq'.
*
* @return string The rendered string of the token
*
* @expect '=&=' when input '=&=', 'raw'
* @expect '=&amp;&#039;=' when input '=&\'=', 'enc'
* @expect '=&amp;&#x27;=' when input '=&\'=', 'encq'
* @expect '=&amp;&#039;=' when input array('=&\'='), 'enc'
* @expect '=&amp;&#x27;=' when input array('=&\'='), 'encq'
* @expect '=&amp;=' when input array('=&=', false), 'enc'
* @expect '=&=' when input array('=&=', false), 'raw'
* @expect '=&=' when input array('=&=', 'raw'), 'enc'
* @expect '=&amp;&#x27;=' when input array('=&\'=', 'encq'), 'raw'
*/
public static function chret($ret, $op) {
if (is_array($ret)) {
if (isset($ret[1]) && $ret[1]) {
$op = $ret[1];
}
$ret = $ret[0];
}
switch ($op) {
case 'enc':
return htmlentities($ret, ENT_QUOTES, 'UTF-8');
case 'encq':
return preg_replace('/&#039;/', '&#x27;', htmlentities($ret, ENT_QUOTES, 'UTF-8'));
}
return $ret;
}
/**
* LightnCandy runtime method for Handlebars.js style custom helpers.
*
* @param array<string,array|string|integer> $cx render time context
* @param string $ch the name of custom helper to be executed
* @param array<array|string|integer>|string|integer|null $vars variables for the helper
* @param string $op the name of variable resolver. should be one of: 'raw', 'enc', or 'encq'.
* @param boolean $inverted the logic will be inverted
* @param Closure|null $cb callback function to render child context
* @param Closure|null $else callback function to render child context when {{else}}
*
* @return string The rendered string of the token
*/
public static function hbch($cx, $ch, $vars, $op, $inverted, $cb = null, $else = null) {
$isBlock = (is_object($cb) && ($cb instanceof Closure));
$args = $vars[0];
$options = array(
'name' => $ch,
'hash' => $vars[1],
'_this' => $isBlock ? $op : $inverted,
);
// $invert the logic
if ($inverted) {
$tmp = $else;
$else = $cb;
$cb = $tmp;
}
if ($isBlock) {
$options['fn'] = function ($context = '_NO_INPUT_HERE_') use ($cx, $op, $cb) {
if ($cx['flags']['echo']) {
ob_start();
}
if ($context === '_NO_INPUT_HERE_') {
$cx['scopes'][] = $op;
$ret = $cb($cx, $op);
} else {
$cx['scopes'][] = $op;
$ret = $cb($cx, $context);
}
array_pop($cx['scopes']);
return $cx['flags']['echo'] ? ob_get_clean() : $ret;
};
}
if ($else) {
$options['inverse'] = function ($context = '_NO_INPUT_HERE_') use ($cx, $op, $else) {
if ($cx['flags']['echo']) {
ob_start();
}
if ($context === '_NO_INPUT_HERE_') {
$ret = $else($cx, $op);
} else {
$cx['scopes'][] = $op;
$ret = $else($cx, $context);
array_pop($cx['scopes']);
}
return $cx['flags']['echo'] ? ob_get_clean() : $ret;
};
}
// prepare $options['data']
if ($cx['flags']['spvar']) {
$options['data'] = $cx['sp_vars'];
}
$args[] = $options;
$e = null;
$r = true;
try {
$r = call_user_func_array($cx['hbhelpers'][$ch], $args);
} catch (Exception $E) {
$e = "LCRun3: call custom helper '$ch' error: " . $E->getMessage();
}
if($e !== null) {
if ($cx['flags']['debug'] & self::DEBUG_ERROR_LOG) {
error_log($e);
}
if ($cx['flags']['debug'] & self::DEBUG_ERROR_EXCEPTION) {
throw new Exception($e);
}
}
return self::chret($r, $isBlock ? 'raw' : $op);
}
/**
* LightnCandy runtime method for block custom helpers.
*
* @param array<string,array|string|integer> $cx render time context
* @param string $ch the name of custom helper to be executed
* @param array<array|string|integer>|string|integer|null $vars variables for the helper
* @param array<array|string|integer>|string|integer|null $in input data with current scope
* @param boolean $inverted the logic will be inverted
* @param Closure $cb callback function to render child context
* @param Closure|null $else callback function to render child context when {{else}}
*
* @return string The rendered string of the token
*
* @expect '4.2.3' when input array('blockhelpers' => array('a' => function ($cx) {return array($cx,2,3);})), 'a', array(0, 0), 4, false, function($cx, $i) {return implode('.', $i);}
* @expect '2.6.5' when input array('blockhelpers' => array('a' => function ($cx,$in) {return array($cx,$in[0],5);})), 'a', array('6', 0), 2, false, function($cx, $i) {return implode('.', $i);}
* @expect '' when input array('blockhelpers' => array('a' => function ($cx,$in) {})), 'a', array('6', 0), 2, false, function($cx, $i) {return implode('.', $i);}
*/
public static function bch($cx, $ch, $vars, $in, $inverted, $cb, $else = null) {
$r = call_user_func($cx['blockhelpers'][$ch], $in, $vars[0], $vars[1]);
// $invert the logic
if ($inverted) {
$tmp = $else;
$else = $cb;
$cb = $tmp;
}
$ret = '';
if (is_null($r)) {
if ($else) {
$cx['scopes'][] = $in;
$ret = $else($cx, $r);
array_pop($cx['scopes']);
}
} else {
if ($cb) {
$cx['scopes'][] = $in;
$ret = $cb($cx, $r);
array_pop($cx['scopes']);
}
}
return $ret;
}
}
\ No newline at end of file
... ...
... ... @@ -72,14 +72,14 @@ class TemplateLayout implements View_Interface
{
$request = Dispatcher::getInstance()->getRequest();
$config = Application::app()->getConfig()->get('application');
$tplExt = '.' . $config->view->ext;
$viewPath = $this->getScriptPath() . '/' . $request->module;
$viewName = $viewPath . '/' . $request->controller . '/' . $tpl . $tplExt;
$tplExt = $config->template->ext;
$viewPath = $config->template->path;
$viewName = $viewPath . '/' . $request->module . '/' . $request->controller . '/' . $tpl . '.' . $tplExt;
// 判断视图模板文件是否存在, 不存在则直接返回空
if (!file_exists($viewName)) {
return '';
}
$tpl_vars = array_merge($this->tpl_vars, $tpl_vars);
// 取得模板的最后修改时间戳
$lastModifyTime = filemtime($viewName);
... ... @@ -97,12 +97,14 @@ class TemplateLayout implements View_Interface
}
// 第一次渲染该模板的流程:取得模板内容 => 预编译成PHP函数 => 写入服务器生成PHP文件
else {
echo $config->template->partials;
$template = file_get_contents($viewName, false, null);
$phpStr = LightnCandy::compile($template, array(
// DEBUG: LightnCandy::FLAG_RENDER_DEBUG | LightnCandy::FLAG_ERROR_EXCEPTION
'flags' => LightnCandy::FLAG_MUSTACHE | LightnCandy::FLAG_HANDLEBARS, // 使用MUSTACHE和HANDLEBARS的模板格式
'basedir' => array($viewPath . '/partials'), // 模板里使用 {{> partial_name}} 时查找的目录
'basedir' => array($config->template->partials), // 模板里使用 {{> partial_name}} 时查找的目录
'fileext' => array($tplExt), // 允许查找文件的后缀
'lcrun' => 'Plugin\LCRun3', // 指定编译模板的runtime
));
// 文件流方式读取PHP方法
$renderer = LightnCandy::prepare($phpStr);
... ... @@ -112,7 +114,7 @@ class TemplateLayout implements View_Interface
// 装载内容,调用PHP函数
try {
$result = $renderer($this->_tpl_vars);
$result = $renderer($tpl_vars);
} catch (Exception $e) {
$result = '';
}
... ... @@ -129,7 +131,7 @@ class TemplateLayout implements View_Interface
public function setScriptPath($path)
{
$result = false;
if (is_readable($path)) {
if (is_dir($path)) {
$this->tpl_dir = $path;
$result = true;
}
... ...
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\NGINX\Parameters]
"Application"="E:\\nginx\\nginx.exe"
"Application"="D:\\workspace\\yohobuy.git.dev.yoho.cn\\script\\nginx\\nginx.exe"
"AppParameters"=""
"AppDirectory"="E:\\nginx\\"
\ No newline at end of file
"AppDirectory"="D:\\workspace\\"
\ No newline at end of file
... ...
... ... @@ -5,7 +5,7 @@ E:
cd nginx
nginx.exe
@echo off
echo Starting PHP FastCGI...
RunHiddenConsole.exe D:\php\php-cgi.exe -b 127.0.0.1:9000 -c D:\php\php.ini
#@echo off
#echo Starting PHP FastCGI...
#RunHiddenConsole.exe D:\php\php-cgi.exe -b 127.0.0.1:9000 -c D:\php\php.ini
EXIT
\ No newline at end of file
... ...
该目录用于存放前端相关的模板
\ No newline at end of file
... ...
{{>layout/header}}
This is a test {{test}}
{{>layout/footer}}
\ No newline at end of file
... ...
</body>
</html>
\ No newline at end of file
... ...
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>{{title}}</title>
<meta name="keywords" content="{{keywords}}">
<meta name="description" content="{{description}}">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
<meta http-equiv="cleartype" content="on">
<meta name="apple-mobile-web-app-status-bar-style" content="black" />
<meta content="telephone=no" name="format-detection" />
<meta content="email=no" name="format-detection" />
</head>
<body>
\ No newline at end of file
... ...
该目录用于存放前端相关的模板
\ No newline at end of file
... ...
... ... @@ -76,16 +76,15 @@ class Bootstrap extends Bootstrap_Abstract
*/
public function _initLayout(Dispatcher $dispatcher)
{
// 关闭自动渲染模板
$dispatcher->autoRender(false);
// 判断到不是AJAX请求时, 使用自定义的模板渲染 (Mustache or Handlebars)
if (!$dispatcher->getRequest()->isXmlHttpRequest()) {
$layout = new TemplateLayout();
$layout->setScriptPath($this->_config->application->layout->path);
$layout->setScriptPath($this->_config->application->template->path);
$dispatcher->setView($layout);
}
// 关闭自动渲染模板
else {
$dispatcher->autoRender(false);
}
}
/**
... ...
... ... @@ -7,6 +7,7 @@ class IndexController extends AbstractAction
{
public function indexAction()
{
echo 'hello world';
$this->_view->assign('title', 'YOHO!有货');
$this->_view->display('index', array('test' => 'hello world'));
}
}
\ No newline at end of file
... ...
... ... @@ -4,7 +4,7 @@ application.directory = APPLICATION_PATH "/application"
;;website library
application.library = ROOT_PATH "/library"
;;默认模块
application.modules = "index,default"
application.modules = "Index"
;;加载
application.bootstrap = APPLICATION_PATH "/application/Bootstrap.php"
;;view文件的扩展名
... ... @@ -19,7 +19,7 @@ application.dispatcher.defaultController = "index"
application.dispatcher.defaultAction = "index"
;;初始化命名空间
application.namespaces = "Action,Plugin"
application.namespaces = "Action,Configs,Plugin"
;;使用composer
composer.autoload = 0
... ... @@ -41,4 +41,7 @@ application.dispatcher.throwException = True
application.dispatcher.catchException = True
;模板预编译目录,该目录需要有读写权限
application.template.compile = ROOT_PATH "/compile/m.yohobuy.com"
\ No newline at end of file
application.template.compile = ROOT_PATH "/compile/m.yohobuy.com"
application.template.path = ROOT_PATH "/template/m.yohobuy.com/actions"
application.template.partials = ROOT_PATH "/template/m.yohobuy.com/partials"
application.template.ext = "phtml"
\ No newline at end of file
... ...
... ... @@ -4,7 +4,7 @@ application.directory = APPLICATION_PATH "/application"
;;website library
application.library = ROOT_PATH "/library"
;;默认模块
application.modules = "Default,Test"
application.modules = "Index"
;;加载
application.bootstrap = APPLICATION_PATH "/application/Bootstrap.php"
;;view文件的扩展名
... ... @@ -41,4 +41,7 @@ application.dispatcher.throwException = False
application.dispatcher.catchException = False
;模板预编译目录,该目录需要有读写权限
application.template.compile = ROOT_PATH "/compile/m.yohobuy.com"
\ No newline at end of file
application.template.compile = ROOT_PATH "/compile/m.yohobuy.com"
application.template.path = ROOT_PATH "/template/m.yohobuy.com/actions"
application.template.partials = ROOT_PATH "/template/m.yohobuy.com/partials"
application.template.ext = "phtml"
\ No newline at end of file
... ...
... ... @@ -4,7 +4,7 @@ application.directory = APPLICATION_PATH "/application"
;;website library
application.library = ROOT_PATH "/library"
;;默认模块
application.modules = "Default,Test"
application.modules = "Index"
;;加载
application.bootstrap = APPLICATION_PATH "/application/Bootstrap.php"
;;view文件的扩展名
... ... @@ -41,4 +41,7 @@ application.dispatcher.throwException = True
application.dispatcher.catchException = True
;模板预编译目录,该目录需要有读写权限
application.template.compile = ROOT_PATH "/compile/m.yohobuy.com"
\ No newline at end of file
application.template.compile = ROOT_PATH "/compile/m.yohobuy.com"
application.template.path = ROOT_PATH "/template/m.yohobuy.com/actions"
application.template.partials = ROOT_PATH "/template/m.yohobuy.com/partials"
application.template.ext = "phtml"
\ No newline at end of file
... ...