// define('PHPTAL_TALES_DEFAULT_KEYWORD', '_DEFAULT_DEFAULT_DEFAULT_DEFAULT_'); define('PHPTAL_TALES_NOTHING_KEYWORD', '_NOTHING_NOTHING_NOTHING_NOTHING_'); // TALES Specification 1.3 // // Expression ::= [type_prefix ':'] String // type_prefix ::= Name // // Examples: // // a/b/c // path:a/b/c // nothing // path:nothing // python: 1 + 2 // string:Hello, ${username} // // // Builtin Names in Page Templates (for PHPTAL) // // * nothing - special singleton value used by TAL to represent a // non-value (e.g. void, None, Nil, NULL). // // * default - special singleton value used by TAL to specify that // existing text should not be replaced. // // * repeat - the repeat variables (see RepeatVariable). // function _phptal_tale_wrap($array, $nothrow) { if (count($array)==1) return '($ctx->noThrow('.($nothrow?'true':'false').')||1?('. ($array[0]==PHPTAL_TALES_NOTHING_KEYWORD?'NULL':$array[0]). '):"")'; $expr = array_shift($array); return "((\$tmp5=$expr) && (\$ctx->noThrow(false)||1)?\$tmp5:"._phptal_tale_wrap($array, $nothrow).')'; } /** translates array of alternative expressions into single PHP expression. Identical to phptal_tales() for singular expressions. */ function phptal_tale($expression, $nothrow=false) { $r = phptal_tales($expression,true); if (!is_array($r)) return $r; // this weird ternary operator construct is to execute noThrow inside the expression return '($ctx->noThrow(true)||1?'._phptal_tale_wrap($r, $nothrow).':"")'; } function phptal_tales($expression, $nothrow=false) { $expression = trim($expression); // Look for tales modifier (string:, exists:, etc...) //if (preg_match('/^([-a-z]+):(.*?)$/', $expression, $m)) { if (preg_match('/^([a-z][-.a-z]*[a-z]):(.*?)$/i', $expression, $m)) { list(,$typePrefix,$expression) = $m; } // may be a 'string' else if (preg_match('/^\'((?:[^\']|\\\\.)*)\'$/', $expression, $m)) { $expression = stripslashes($m[1]); $typePrefix = 'string'; } // failback to path: else { $typePrefix = 'path'; } // is a registered TALES expression modifier if(PHPTAL_TalesRegistry::getInstance()->isRegistered($typePrefix)) { $callback = PHPTAL_TalesRegistry::getInstance()->getCallback($typePrefix); return call_user_func($callback, $expression, $nothrow); } // class method if (strpos($typePrefix, '.')){ $classCallback = explode('.', $typePrefix, 2); $callbackName = NULL; if(!is_callable($classCallback, FALSE, $callbackName)) { $err = 'Unknown phptal modifier %s function %s does not exists or is not statically callable.'; $err = sprintf($err, $typePrefix, $callbackName); throw new PHPTAL_Exception($err); } $ref = new ReflectionClass($classCallback[0]); if(!$ref->implementsInterface('PHPTAL_Tales')){ $err = 'Unable to use phptal modifier %s as the class %s does not implement the PHPTAL_Tales interface.'; $err = sprintf($err, $typePrefix, $callbackName); throw new PHPTAL_Exception($err); } return call_user_func($classCallback, $expression, $nothrow); } // check if it is implemented via code-generating function $func = 'phptal_tales_'.str_replace('-','_',$typePrefix); if (function_exists($func)) { return $func($expression, $nothrow); } // check if it is implemented via runtime function $runfunc = 'phptal_runtime_tales_'.str_replace('-','_',$typePrefix); if (function_exists($runfunc)) { return "$runfunc(".phptal_tale($expression, $nothrow).")"; } throw new PHPTAL_Exception("Unknown phptal modifier '$typePrefix'. Function '$func' does not exist"); } // Register internal Tales expression modifiers require_once PHPTAL_DIR.'PHPTAL/Php/TalesInternal.php'; PHPTAL_TalesInternal::registerInternalTales(); ?>