Exemplo n.º 1
0
 static function get($layout_name)
 {
     if (DEBUG_MODE) {
         global $logger;
         $parent = isset(static::$layouts[$layout_name]) ? static::$layouts[$layout_name]['parent'] . ':' . static::$layouts[$layout_name]['id'] : $layout_name . SCRIPT_EXTENSION;
         $logger('DEBUG', str_repeat('  ', count(static::$scope)) . $layout_name . ($parent ? " ({$parent})" : ''));
     }
     return parent::get($layout_name);
 }
 static function eval_php($__context, $__code, $__parent = false)
 {
     $part = static::cap($__code);
     $parent = $__parent ? ' in parent scope' : '';
     self::debug("eval_php({$__context},{$part}){$parent}", self::DEBUG_LEVEL_EVALUATIONS);
     return parent::eval_php($__context, $__code, $__parent);
 }
 static function command($stmt)
 {
     # !<cmd>[:]<param>
     list($cmd, $param) = self::split_on_optional_char($stmt);
     $orig_cmd = $cmd;
     list($accepted, $cmd, $param) = static::resolve_alias($cmd, $param);
     if (!$accepted) {
         return static::error('Could not resolve alias for !' . $orig_cmd . ', possibly circular definition');
     }
     $scope =& static::current_scope();
     $scope['cmd'] = $cmd;
     $ColonLF_Exptected = 'colon followed by linefeed and indented code was expected';
     switch ($cmd) {
         case 'php':
             list($status, $return_value, $output) = static::eval_php('!php', $param);
             if ($status != 'ok') {
                 return static::error($return_value);
             }
             # $output is ignored
             if ($return_value === false) {
                 # cancel output
                 return '';
             } elseif (is_null($return_value)) {
                 return $output;
             } else {
                 return $return_value;
             }
             # $output is ignored
         # $output is ignored
         case 'if':
             @(list($expr, $code) = self::split_on_colonLF($param));
             if (is_null($code)) {
                 return static::error('Bad syntax for !if, ' . $ColonLF_Exptected);
             }
             list($status, $return_value, $output) = static::eval_expr('!if expression', $expr);
             if ($status != 'ok') {
                 return static::error($return_value);
             }
             $expr_result = $return_value;
             if ($expr_result) {
                 $scope['if_state'] = true;
                 return static::run_script(Indentation::unindent("\n" . $code), '', '[!if block]');
             } else {
                 $scope['if_state'] = false;
             }
             break;
         case 'elseif':
             if (!isset($scope['prev_cmd']) || !in_array($scope['prev_cmd'], array('if', 'elseif'))) {
                 return static::error('Bad syntax, !elseif only allowed after !if or !elseif');
             }
             if ($scope['if_state'] === true || is_null($scope['if_state'])) {
                 # NULL: error in !if expression
                 return '';
             }
             @(list($expr, $code) = self::split_on_colonLF($param));
             if (is_null($code)) {
                 return static::error('Bad syntax for !elseif, ' . $ColonLF_Exptected);
             }
             list($status, $return_value, $output) = static::eval_expr('!elseif expression', $expr);
             if ($status != 'ok') {
                 return static::error($return_value);
             }
             $expr_result = $return_value;
             if ($expr_result) {
                 $scope['if_state'] = true;
                 return static::run_script(Indentation::unindent("\n" . $code), '', '[!elseif block]');
             } else {
                 $scope['if_state'] = false;
             }
             break;
         case 'else':
             if (!isset($scope['prev_cmd']) || !in_array($scope['prev_cmd'], array('if', 'elseif'))) {
                 return static::error('Bad syntax, !else only allowed after !if or !elseif');
             }
             if ($scope['if_state'] === false) {
                 # !! because leading WS is removed from $param
                 @(list($tmp, $param) = explode(':', $stmt, 2));
                 if (!$param || trim($tmp) != $orig_cmd) {
                     return static::error('Bad syntax for !else, ' . $ColonLF_Exptected);
                 }
                 return static::run_script(Indentation::unindent($param), '', '[!else block]');
             }
             break;
         case 'loop':
             @(list($expr, $code) = self::split_on_colonLF($param));
             if (is_null($code)) {
                 return static::error('Bad syntax for !loop, ' . $ColonLF_Exptected);
             }
             $var_pattern = static::name_pattern('variable');
             if (!preg_match('/^(.+)\\s+as\\s+\\$(' . $var_pattern . ')(\\s*=>\\s*\\$(' . $var_pattern . '))?\\s*$/i', $expr, $m)) {
                 return static::error('Invalid syntax for !loop');
             }
             $expr = trim($m[1]);
             if ($expr && $expr[0] == '[' && substr($expr, -1) == ']') {
                 $expr = 'array(' . trim(substr($expr, 1, -1)) . ')';
             }
             list($status, $return_value, $output) = static::eval_expr('!loop expression', $expr);
             if ($status != 'ok') {
                 return static::error($return_value);
             }
             $arr = $return_value;
             $varname = isset($m[4]) ? $m[4] : $m[2];
             $keyname = isset($m[4]) ? $m[2] : NULL;
             if (!is_array($arr) && !$arr instanceof Traversable) {
                 return static::error('Array or traversable is required for !loop, got ' . gettype($arr));
             }
             $code = Indentation::unindent("\n" . $code);
             $loop_output = array();
             foreach ($arr as $key => $item) {
                 if (!is_null($keyname)) {
                     $scope['vars'][$keyname] = $key;
                 }
                 $scope['vars'][$varname] = $item;
                 $loop_output[] = static::run_script($code, '', '[!loop block]');
                 if (self::$break_counter > 0) {
                     self::$break_counter--;
                     break;
                 }
                 if (self::$continue_loop) {
                     self::$continue_loop = false;
                 }
             }
             return implode('', $loop_output);
         case 'while':
             @(list($expr, $code) = self::split_on_colonLF($param));
             if (is_null($code)) {
                 return static::error('Bad syntax for !while, ' . $ColonLF_Exptected);
             }
             $code = Indentation::unindent("\n" . $code);
             $loop_output = array();
             list($status, $return_value, $output) = static::eval_expr('!while expression', $expr);
             if ($status != 'ok') {
                 return static::error($return_value);
             }
             while ($return_value) {
                 $loop_output[] = static::run_script($code, '', '[!while block]');
                 if (self::$break_counter > 0) {
                     self::$break_counter--;
                     break;
                 }
                 if (self::$continue_loop) {
                     self::$continue_loop = false;
                 }
                 list($status, $return_value, $output) = static::eval_expr('!while expression', $expr);
                 if ($status != 'ok') {
                     return static::error($return_value);
                 }
             }
             return implode('', $loop_output);
         case 'break':
             self::$break_counter = $param && is_numeric($param) ? (int) $param : 1;
             break;
         case 'continue':
             self::$continue_loop = true;
             break;
         case 'return':
             # !return [<num>|to <layout>|with <var-list>]
             self::$return = $scope['layout_name'];
             break;
         case 'scope':
             list($type, $vars) = self::split_on_optional_char($param);
             if (!$vars) {
                 return static::error('Bad syntax for !scope, variable name(s) required');
             }
             $type = strtolower($type);
             switch ($type) {
                 case 'from':
                     list($layout_name, $vars) = array_map('trim', explode(':', $vars, 2));
                     if (!$vars) {
                         return static::error('Bad syntax for !scope, variable name(s) required');
                     }
                     $fscope =& static::find_scope($layout_name);
                     if (is_null($fscope)) {
                         return static::error("Scope '{$layout_name}' was not found");
                     }
                     foreach (array_map('trim', explode(',', $vars)) as $var) {
                         $var = ltrim($var, '$');
                         $scope['vars'][$var] =& $fscope['vars'][$var];
                     }
                     break;
                     #case 'static': # vars stored in $layouts[$layout_name]['vars']
                 #case 'static': # vars stored in $layouts[$layout_name]['vars']
                 case 'caller':
                 case 'parent':
                     if ($type == 'parent') {
                         $layout_name = $scope['layout_name'];
                         if (!isset(self::$layouts[$layout_name])) {
                             return static::error("!scope parent: Did not find layout metadata for '{$layout_name}'");
                         }
                         if (!isset(self::$layouts[$layout_name]['parent'])) {
                             static::error("!scope parent: Did not find parent");
                         }
                         $parent = self::$layouts[$layout_name]['parent'];
                         $pscope =& static::find_scope($parent);
                         if (!$pscope) {
                             return static::error("!scope parent: Did not find scope for '{$parent}'");
                         }
                     } else {
                         # caller
                         if (count(self::$scope) < 2) {
                             return static::error('There is no caller scope!');
                         }
                         $pscope =& static::parent_scope();
                     }
                     foreach (array_map('trim', explode(',', $vars)) as $var) {
                         $var = ltrim($var, '$');
                         $scope['vars'][$var] =& $pscope['vars'][$var];
                     }
                     break;
                 case 'global':
                     foreach (array_map('trim', explode(',', $vars)) as $var) {
                         $var = ltrim($var, '$');
                         $scope['vars'][$var] =& $GLOBALS[$var];
                     }
                     break;
                 default:
                     return static::error("Invalid scope type '{$type}', expected 'from', 'parent', 'caller' or 'global'");
             }
             break;
         case 'param':
             list($accepted, $res) = static::param($param, $scope['vars']['_param']);
             if (!$accepted) {
                 return static::error($res);
             }
             $scope['vars']['_param'] = $res;
             break;
         default:
             if (in_array($cmd, array_keys(self::$custom_commands))) {
                 $callback = self::$custom_commands[$cmd];
                 return call_user_func($callback, $param);
             } else {
                 return static::error("Unknown command '!{$cmd}'");
             }
     }
     return '';
 }