/** * Outputs a stack trace based on the supplied options. * * @param array $options Format for outputting stack trace. Available options are: * - `'args'`: A boolean indicating if arguments should be included. * - `'depth'`: The maximum depth of the trace. * - `'format'`: Either `null`, `'points'` or `'array'`. * - `'includeScope'`: A boolean indicating if items within scope * should be included. * - `'scope'`: Scope for items to include. * - `'start'`: The depth to start with. * - `'trace'`: A trace to use instead of generating one. * @return string Stack trace formatted according to `'format'` option. */ public static function trace(array $options = array()) { $defaults = array('depth' => 999, 'format' => null, 'args' => false, 'start' => 0, 'scope' => array(), 'trace' => array(), 'includeScope' => true, 'closures' => true); $options += $defaults; $backtrace = $options['trace'] ?: debug_backtrace(); $scope = $options['scope']; $count = count($backtrace); $back = array(); $traceDefault = array('line' => '??', 'file' => '[internal]', 'class' => null, 'function' => '[main]'); for ($i = $options['start']; $i < $count && $i < $options['depth']; $i++) { $trace = array_merge(array('file' => '[internal]', 'line' => '??'), $backtrace[$i]); $function = '[main]'; if (isset($backtrace[$i + 1])) { $next = $backtrace[$i + 1] + $traceDefault; $function = $next['function']; if (!empty($next['class'])) { $function = $next['class'] . '::' . $function . '('; if ($options['args'] && isset($next['args'])) { $args = array_map(array('static', 'export'), $next['args']); $function .= join(', ', $args); } $function .= ')'; } } if ($options['closures'] && strpos($function, '{closure}') !== false) { $function = static::_closureDef($backtrace[$i], $function); } if (in_array($function, array('call_user_func_array', 'trigger_error'))) { continue; } $trace['functionRef'] = $function; if ($options['format'] == 'points' && $trace['file'] != '[internal]') { $back[] = array('file' => $trace['file'], 'line' => $trace['line']); } elseif (is_string($options['format']) && $options['format'] != 'array') { $back[] = String\Format::sprintfn($options['format'], array_map(function ($data) { return is_object($data) ? get_class($data) : $data; }, $trace)); } elseif (empty($options['format'])) { $back[] = $function . ' - ' . $trace['file'] . ', line ' . $trace['line']; } else { $back[] = $trace; } if (!empty($scope) && array_intersect_assoc($scope, $trace) == $scope) { if (!$options['includeScope']) { $back = array_slice($back, 0, count($back) - 1); } break; } } if ($options['format'] == 'array' || $options['format'] == 'points') { return $back; } return join("\n", $back); }
static function recognise(URL $url) { $path = $url->getPath()->getPath(true); $match = null; foreach (static::$match as $expr => $class) { $matches = Format::consumeRegex($path, $expr, $match); if ($matches) { if (is_array($class) || is_string($class)) { if (is_array($class)) { $data = isset($class['data']) ? $class['data'] : $match; $class = $class['class']; } else { $data = $match; //matched but no data if ($data === true) { $data = array(); } } if (is_string($class)) { if ($class[0] != '\\') { $class_expr = '\\*\\Web\\Page\\Controller\\' . $class; $class = null; foreach (\Radical\Core\Libraries::get($class_expr) as $class) { //$class set break; } if ($class === null) { return null; } } return new $class($data); } } return $class; } } }
private function match_functor($data) { if (is_string($data)) { $len = strlen($data); if ($len == 0) { throw new \InvalidArgumentException('String must be more than 0B'); } if ($len > 1 && $data[0] == '`') { return function ($url, &$matches) use($data) { return preg_match($data, (string) $url, $matches); }; } else { return function ($url, &$matches) use($data) { $matches = Format::Consume((string) $url, $data); return (bool) $matches; }; } } else { if (is_callable($data)) { return $data; } } throw new \InvalidArgumentException("Invalid argument type:" . gettype($data)); }
function __construct($version) { $this->path = String\Format::sprintfn(static::URL, compact('version')); }