1 <?php 2 /** 3 * Wrapper around backtraces providing utility methods. 4 * 5 * Copyright 1999-2017 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 public $backtrace; 19 20 /** 21 * Constructor. 22 * 23 * @param Exception|array $backtrace The backtrace source. Either a 24 * trowable, an exception or an existing 25 * backtrace. 26 * Defaults to the current stack. 27 */ 28 public function __construct($backtrace = null) 29 { 30 if ($backtrace instanceof Throwable) { 31 $this->createFromThrowable($backtrace); 32 } elseif ($backtrace instanceof Exception) { 33 $this->createFromException($backtrace); 34 } elseif ($backtrace) { 35 $this->createFromDebugBacktrace($backtrace); 36 } else { 37 $this->createFromDebugBacktrace(debug_backtrace(), 1); 38 } 39 } 40 41 /** 42 * Wraps the result of debug_backtrace(). 43 * 44 * By specifying a non-zero $nestingLevel, levels of the backtrace can be 45 * ignored. For instance, when Horde_Support_Backtrace creates a backtrace 46 * for you, it ignores the Horde_Backtrace constructor in the wrapped 47 * trace. 48 * 49 * @param array $backtrace The debug_backtrace() result. 50 * @param integer $nestingLevel The number of levels of the backtrace to 51 * ignore. 52 */ 53 public function createFromDebugBacktrace($backtrace, $nestingLevel = 0) 54 { 55 while ($nestingLevel > 0) { 56 array_shift($backtrace); 57 --$nestingLevel; 58 } 59 60 $this->backtrace = $backtrace; 61 } 62 63 /** 64 * Wraps an error object's backtrace. 65 * 66 * @since Horde_Support 2.2.0 67 * 68 * @param Throwable $e The error to wrap. 69 */ 70 public function createFromThrowable(Throwable $e) 71 { 72 $this->_createFromThrowable($e); 73 } 74 75 /** 76 * Wraps an error object's backtrace. 77 * 78 * @todo Merge with createFromThrowable with PHP 7. 79 * 80 * @param Throwable $e The error to wrap. 81 */ 82 protected function _createFromThrowable($e) 83 { 84 $this->backtrace = $e->getTrace(); 85 if ($previous = $e->getPrevious()) { 86 $backtrace = new self($previous); 87 $this->backtrace = array_merge($backtrace->backtrace, 88 $this->backtrace); 89 } 90 } 91 92 /** 93 * Wraps an Exception object's backtrace. 94 * 95 * @todo Remove with PHP 7. 96 * 97 * @param Exception $e The exception to wrap. 98 */ 99 public function createFromException(Exception $e) 100 { 101 $this->_createFromThrowable($e); 102 } 103 104 /** 105 * Returns the nesting level (number of calls deep) of the current context. 106 * 107 * @return integer Nesting level. 108 */ 109 public function getNestingLevel() 110 { 111 return count($this->backtrace); 112 } 113 114 /** 115 * Returns the context at a specific nesting level. 116 * 117 * @param integer $nestingLevel 0 == current level, 1 == caller, and so on 118 * 119 * @return array The requested context. 120 */ 121 public function getContext($nestingLevel) 122 { 123 if (!isset($this->backtrace[$nestingLevel])) { 124 throw new Horde_Exception('Unknown nesting level'); 125 } 126 return $this->backtrace[$nestingLevel]; 127 } 128 129 /** 130 * Returns details about the routine where the exception occurred. 131 * 132 * @return array $caller 133 */ 134 public function getCurrentContext() 135 { 136 return $this->getContext(0); 137 } 138 139 /** 140 * Returns details about the caller of the routine where the exception 141 * occurred. 142 * 143 * @return array $caller 144 */ 145 public function getCallingContext() 146 { 147 return $this->getContext(1); 148 } 149 150 /** 151 * Returns a simple, human-readable list of the complete backtrace. 152 * 153 * @return string The backtrace map. 154 */ 155 public function __toString() 156 { 157 $count = count($this->backtrace); 158 $pad = strlen($count); 159 $map = ''; 160 for ($i = $count - 1; $i >= 0; $i--) { 161 $map .= str_pad($count - $i, $pad, ' ', STR_PAD_LEFT) . '. '; 162 if (isset($this->backtrace[$i]['class'])) { 163 $map .= $this->backtrace[$i]['class'] 164 . $this->backtrace[$i]['type']; 165 } 166 $map .= $this->backtrace[$i]['function'] . '()'; 167 if (isset($this->backtrace[$i]['file'])) { 168 $map .= ' ' . $this->backtrace[$i]['file'] 169 . ':' . $this->backtrace[$i]['line']; 170 } 171 $map .= "\n"; 172 } 173 return $map; 174 } 175 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body