start working on Horde_Support_Backtrace, an object to make it easier to get pieces...
authorChuck Hagenbuch <chuck@horde.org>
Fri, 21 Aug 2009 17:48:27 +0000 (13:48 -0400)
committerChuck Hagenbuch <chuck@horde.org>
Fri, 21 Aug 2009 17:48:27 +0000 (13:48 -0400)
framework/Support/lib/Horde/Support/Backtrace.php [new file with mode: 0644]
framework/Support/package.xml
framework/Support/test/Horde/Support/BacktraceTest.php [new file with mode: 0644]

diff --git a/framework/Support/lib/Horde/Support/Backtrace.php b/framework/Support/lib/Horde/Support/Backtrace.php
new file mode 100644 (file)
index 0000000..7d56c44
--- /dev/null
@@ -0,0 +1,111 @@
+<?php
+/**
+ * @category   Horde
+ * @package    Support
+ * @copyright  1999-2009 The Horde Project (http://www.horde.org/)
+ * @license    http://opensource.org/licenses/bsd-license.php
+ */
+
+/**
+ * Wrapper around backtraces providing utility methods.
+ *
+ * @category   Horde
+ * @package    Support
+ * @copyright  1999-2009 The Horde Project (http://www.horde.org/)
+ * @license    http://opensource.org/licenses/bsd-license.php
+ */
+class Horde_Support_Backtrace
+{
+    /**
+     * Backtrace
+     * @var array
+     */
+    protected $_backtrace;
+
+    public function __construct($backtrace = null)
+    {
+        if ($backtrace instanceof Exception) {
+            $this->createFromException($backtrace);
+        } elseif ($backtrace) {
+            $this->createFromDebugBacktrace($backtrace);
+        } else {
+            $this->createFromDebugBacktrace(debug_backtrace(), 1);
+        }
+    }
+
+    /**
+     * Wrap the result of debug_backtrace(). By specifying a non-zero
+     * $nestingLevel, levels of the backtrace can be ignored. For instance, when
+     * Horde_Support_Backtrace creates a backtrace for you, it ignores the
+     * Horde_Backtrace constructor in the wrapped trace.
+     *
+     * @param array $backtrace       The debug_backtrace() result
+     * @param integer $nestingLevel  The number of levels of the backtrace to ignore.
+     */
+    public function createFromDebugBacktrace($backtrace, $nestingLevel = 0)
+    {
+        while ($nestingLevel > 0) {
+            array_shift($backtrace);
+            --$nestingLevel;
+        }
+
+        $this->_backtrace = $backtrace;
+    }
+
+    /**
+     * Wrap an Exception object's backtrace
+     *
+     * @param Exception $e  The exception to wrap
+     */
+    public function createFromException(Exception $e)
+    {
+        $this->_backtrace = $e->getTrace();
+    }
+
+    /**
+     * Return the nesting level (number of calls deep) of the current context.
+     *
+     * @return integer  Nesting level
+     */
+    public function getNestingLevel()
+    {
+        return count($this->_backtrace);
+    }
+
+    /**
+     * Return the context at a specific nesting level.
+     *
+     * @param integer $nestingLevel  0 == current level, 1 == caller, and so on
+     *
+     * @return array  The requested context
+     */
+    public function getContext($nestingLevel)
+    {
+        if (!isset($this->_backtrace[$nestingLevel])) {
+            throw new Horde_Exception('Unknown nesting level');
+        }
+        return $this->_backtrace[$nestingLevel];
+    }
+
+    /**
+     * Return details about the caller of the routine where the exception
+     * occurred
+     *
+     * @return array $caller
+     */
+    public function getCurrentContext()
+    {
+        return $this->getContext(0);
+    }
+
+    /**
+     * Return details about the caller of the routine where the exception
+     * occurred
+     *
+     * @return array $caller
+     */
+    public function getCallingContext()
+    {
+        return $this->getContext(1);
+    }
+}
index d882740..4b6704f 100644 (file)
@@ -27,6 +27,7 @@ http://pear.php.net/dtd/package-2.0.xsd">
  <notes>
    * Initial horde/support package
    * Initial Horde_Support_Array object
+   * Initial Horde_Support_Backtrace object
    * Initial Horde_Support_ConsistentHash object
    * Initial Horde_Support_Inflector object
    * Initial Horde_Support_Stack object
@@ -47,6 +48,7 @@ http://pear.php.net/dtd/package-2.0.xsd">
        </dir> <!-- /lib/Horde/Support/Numerizer/Locale -->
       </dir> <!-- /lib/Horde/Support/Numerizer -->
       <file name="Array.php" role="php" />
+      <file name="Backtrace.php" role="php" />
       <file name="ConsistentHash.php" role="php" />
       <file name="Inflector.php" role="php" />
       <file name="Numerizer.php" role="php" />
@@ -72,6 +74,7 @@ http://pear.php.net/dtd/package-2.0.xsd">
  <phprelease>
   <filelist>
    <install name="lib/Horde/Support/Array.php" as="Horde/Support/Array.php" />
+   <install name="lib/Horde/Support/Backtrace.php" as="Horde/Support/Backtrace.php" />
    <install name="lib/Horde/Support/ConsistentHash.php" as="Horde/Support/ConsistentHash.php" />
    <install name="lib/Horde/Support/Inflector.php" as="Horde/Support/Inflector.php" />
    <install name="lib/Horde/Support/Numerizer/Locale/Base.php" as="Horde/Support/Numerizer/Locale/Base.php" />
diff --git a/framework/Support/test/Horde/Support/BacktraceTest.php b/framework/Support/test/Horde/Support/BacktraceTest.php
new file mode 100644 (file)
index 0000000..5dd4f3b
--- /dev/null
@@ -0,0 +1,82 @@
+<?php
+/**
+ * @category   Horde
+ * @package    Support
+ * @subpackage UnitTests
+ * @copyright  2007-2009 The Horde Project (http://www.horde.org/)
+ * @license    http://opensource.org/licenses/bsd-license.php
+ */
+
+/**
+ * @group      support
+ * @category   Horde
+ * @package    Support
+ * @subpackage UnitTests
+ * @copyright  2007-2009 The Horde Project (http://www.horde.org/)
+ * @license    http://opensource.org/licenses/bsd-license.php
+ */
+class Horde_Support_BacktraceTest extends PHPUnit_Framework_TestCase
+{
+    public function testCreateFromDefaultBacktrace()
+    {
+        $trace = new Horde_Support_Backtrace();
+
+        $caller = $trace->getCurrentContext();
+        $this->assertEquals(__FUNCTION__, $caller['function']);
+
+        $caller = $trace->getCallingContext();
+        $this->assertEquals('invoke', $caller['function']);
+    }
+
+    public function testCreateFromGeneratedBacktrace()
+    {
+        $trace = new Horde_Support_Backtrace($this->returnBacktrace());
+
+        $caller = $trace->getCurrentContext();
+        $this->assertEquals('returnBacktrace', $caller['function']);
+
+        $caller = $trace->getCallingContext();
+        $this->assertEquals(__FUNCTION__, $caller['function']);
+    }
+
+    public function testCreateFromException()
+    {
+        try {
+            $this->throwException();
+        } catch (Exception $e) {
+        }
+
+        $trace = new Horde_Support_Backtrace($e);
+
+        $caller = $trace->getCurrentContext();
+        $this->assertEquals('throwException', $caller['function']);
+
+        $caller = $trace->getCallingContext();
+        $this->assertEquals(__FUNCTION__, $caller['function']);
+    }
+
+    public function testNestingLevelOfDefaultVsGeneratedBacktrace()
+    {
+        $t1 = new Horde_Support_Backtrace();
+        $t2 = new Horde_Support_Backtrace($this->returnBacktrace());
+
+        $this->assertEquals($t1->getCurrentContext(), $t2->getCallingContext());
+    }
+
+    public function testNestingLevel()
+    {
+        $backtrace = new Horde_Support_Backtrace();
+        $dbt = debug_backtrace();
+        $this->assertEquals(count($dbt), $backtrace->getNestingLevel());
+    }
+
+    public function returnBacktrace()
+    {
+        return debug_backtrace();
+    }
+
+    public function throwException()
+    {
+        throw new Exception();
+    }
+}