static function run_script($layout_script, $param = '', $layout_name = '[inline]') { if (!self::$shutdown_function_registered) { register_shutdown_function(function () { if (($e = error_get_last()) && $e['message'] > '') { echo LayoutProcessor::error($e['message'] . "\n* Script crashed with error code " . $e['type'] . ': ' . $e['file'] . ' line ' . $e['line'] . "\n* Scope stack dump:" . print_r(LayoutProcessor::$scope, true)); } }); self::$shutdown_function_registered = true; } $lines = Indentation::blocks($layout_script); $line_no_offset = 0; $output = array(); $scope = array('layout_name' => $layout_name, 'statement_type' => '', 'line_no' => 0, 'vars' => array('_param' => $param), 'if_state' => NULL); if (self::$scope && isset(self::$scope[count(self::$scope) - 1]['statement_type']) && self::$scope[count(self::$scope) - 1]['statement_type'] == 'method command' && isset(self::$scope[count(self::$scope) - 1]['cmd']) && in_array(self::$scope[count(self::$scope) - 1]['cmd'], array('if', 'elseif', 'else', 'loop', 'while'))) { $scope['vars'] =& self::$scope[count(self::$scope) - 1]['vars']; $scope['layout_name'] = self::$scope[count(self::$scope) - 1]['layout_name']; $line_no_offset = self::$scope[count(self::$scope) - 1]['line_no']; } if (count(self::$scope) >= static::MAX_RECURSION_DEPTH) { return static::error('Recursion error when calling ' . $layout_name); } self::$scope[] =& $scope; foreach ($lines as $linedata) { list($scope['line_no'], $line) = $linedata; $scope['line_no'] += $line_no_offset; if (in_array($prefix = substr($line, 0, 1), array_keys(self::$prefix))) { list($statement_type, $callback) = static::resolve_statement_type($prefix); $scope['statement_type'] = $statement_type; if ($statement_type != 'invalid') { $stmt = substr($line, 1); # remove prefix $output[] = forward_static_call($callback, $stmt); } else { $output[] = static::error("Prefix {$prefix} is not callable!"); } } else { list($layout_name, $param) = strpos($line, ':') !== false ? explode(':', $line, 2) : array($line, ''); $scope['statement_type'] = 'layout'; $layout_script = static::get($layout_name); if ($layout_script === false) { if (strlen($layout_name) > static::$layout_name_cap) { # probably indentation error $layout_name = substr($layout_name, 0, static::$layout_name_cap) . '...'; } $output[] = static::error("Undefined layout '{$layout_name}'"); } else { $layout_item = self::$layouts[$layout_name]; $remember_context = self::$context; self::$context = (isset($layout_item['name']) ? $layout_item['name'] : $layout_name) . (isset($layout_item['parent']) ? ' #' . $layout_item['parent'] : '') . (isset($layout_item['id']) ? '/' . $layout_item['id'] : ''); $layout_script = str_replace(static::PARAM_PLACEHOLDER, $param, $layout_script); $param = Indentation::unindent($param); $output[] = static::run_script($layout_script, $param, $layout_name); # ! recursive self::$context = $remember_context; } } if ($scope['statement_type'] == 'method command') { $scope['prev_cmd'] = $scope['cmd']; } elseif ($scope['statement_type'] == 'method comment') { } else { unset($scope['cmd'], $scope['prev_cmd']); } if (self::$error_exit) { if (static::$error_mode & self::ERR_CANCEL) { return array_pop($output); } if (static::$error_mode & self::ERR_RESUME) { if (self::$error_exit != $scope['layout_name']) { self::$error_exit = false; } else { break; } } else { break; } } if (self::$continue_loop || self::$break_counter) { break; } if (self::$return) { if (self::$return != $scope['layout_name']) { self::$return = false; } else { break; } } } array_pop(self::$scope); return implode('', $output); }