1: <?php
2: /**
3: * Wrapper around backtraces providing utility methods.
4: *
5: * Copyright 1999-2012 Horde LLC (http://www.horde.org/)
6: *
7: * @category Horde
8: * @package Support
9: * @license http://www.horde.org/licenses/bsd
10: */
11: class Horde_Support_Backtrace
12: {
13: /**
14: * Backtrace.
15: *
16: * @var array
17: */
18: protected $_backtrace;
19:
20: public function __construct($backtrace = null)
21: {
22: if ($backtrace instanceof Exception) {
23: $this->createFromException($backtrace);
24: } elseif ($backtrace) {
25: $this->createFromDebugBacktrace($backtrace);
26: } else {
27: $this->createFromDebugBacktrace(debug_backtrace(), 1);
28: }
29: }
30:
31: /**
32: * Wraps the result of debug_backtrace().
33: *
34: * By specifying a non-zero $nestingLevel, levels of the backtrace can be
35: * ignored. For instance, when Horde_Support_Backtrace creates a backtrace
36: * for you, it ignores the Horde_Backtrace constructor in the wrapped
37: * trace.
38: *
39: * @param array $backtrace The debug_backtrace() result.
40: * @param integer $nestingLevel The number of levels of the backtrace to
41: * ignore.
42: */
43: public function createFromDebugBacktrace($backtrace, $nestingLevel = 0)
44: {
45: while ($nestingLevel > 0) {
46: array_shift($backtrace);
47: --$nestingLevel;
48: }
49:
50: $this->_backtrace = $backtrace;
51: }
52:
53: /**
54: * Wraps an Exception object's backtrace.
55: *
56: * @param Exception $e The exception to wrap.
57: */
58: public function createFromException(Exception $e)
59: {
60: $this->_backtrace = $e->getTrace();
61: }
62:
63: /**
64: * Returns the nesting level (number of calls deep) of the current context.
65: *
66: * @return integer Nesting level.
67: */
68: public function getNestingLevel()
69: {
70: return count($this->_backtrace);
71: }
72:
73: /**
74: * Returns the context at a specific nesting level.
75: *
76: * @param integer $nestingLevel 0 == current level, 1 == caller, and so on
77: *
78: * @return array The requested context.
79: */
80: public function getContext($nestingLevel)
81: {
82: if (!isset($this->_backtrace[$nestingLevel])) {
83: throw new Horde_Exception('Unknown nesting level');
84: }
85: return $this->_backtrace[$nestingLevel];
86: }
87:
88: /**
89: * Returns details about the routine where the exception occurred.
90: *
91: * @return array $caller
92: */
93: public function getCurrentContext()
94: {
95: return $this->getContext(0);
96: }
97:
98: /**
99: * Returns details about the caller of the routine where the exception
100: * occurred.
101: *
102: * @return array $caller
103: */
104: public function getCallingContext()
105: {
106: return $this->getContext(1);
107: }
108:
109: /**
110: * Returns a simple, human-readable list of the complete backtrace.
111: *
112: * @return string The backtrace map.
113: */
114: public function __toString()
115: {
116: $count = count($this->_backtrace);
117: $pad = strlen($count);
118: $map = '';
119: for ($i = $count - 1; $i >= 0; $i--) {
120: $map .= str_pad($count - $i, $pad, ' ', STR_PAD_LEFT) . '. ';
121: if (isset($this->_backtrace[$i]['class'])) {
122: $map .= $this->_backtrace[$i]['class']
123: . $this->_backtrace[$i]['type'];
124: }
125: $map .= $this->_backtrace[$i]['function'] . '()';
126: if (isset($this->_backtrace[$i]['file'])) {
127: $map .= ' ' . $this->_backtrace[$i]['file']
128: . ':' . $this->_backtrace[$i]['line'];
129: }
130: $map .= "\n";
131: }
132: return $map;
133: }
134: }
135: