Source for file dumper.php

Documentation is available at dumper.php

  1. <?php
  2. /**
  3.  *  base include file for SimpleTest
  4.  *  @package    SimpleTest
  5.  *  @subpackage UnitTester
  6.  *  @version    $Id: dumper.php 1909 2009-07-29 15:58:11Z dgheath $
  7.  */
  8. /**
  9.  * does type matter
  10.  */
  11. if (defined('TYPE_MATTERS')) {
  12.     define('TYPE_MATTERS'true);
  13. }
  14.  
  15. /**
  16.  *    Displays variables as text and does diffs.
  17.  *    @package  SimpleTest
  18.  *    @subpackage   UnitTester
  19.  */
  20. class SimpleDumper {
  21.  
  22.     /**
  23.      *    Renders a variable in a shorter form than print_r().
  24.      *    @param mixed $value      Variable to render as a string.
  25.      *    @return string           Human readable string form.
  26.      *    @access public
  27.      */
  28.     function describeValue($value{
  29.         $type $this->getType($value);
  30.         switch($type{
  31.             case "Null":
  32.                 return "NULL";
  33.             case "Boolean":
  34.                 return "Boolean: " ($value "true" "false");
  35.             case "Array":
  36.                 return "Array: " count($value" items";
  37.             case "Object":
  38.                 return "Object: of " get_class($value);
  39.             case "String":
  40.                 return "String: " $this->clipString($value200);
  41.             default:
  42.                 return "$type$value";
  43.         }
  44.         return "Unknown";
  45.     }
  46.  
  47.     /**
  48.      *    Gets the string representation of a type.
  49.      *    @param mixed $value    Variable to check against.
  50.      *    @return string         Type.
  51.      *    @access public
  52.      */
  53.     function getType($value{
  54.         if (isset($value)) {
  55.             return "Null";
  56.         elseif (is_bool($value)) {
  57.             return "Boolean";
  58.         elseif (is_string($value)) {
  59.             return "String";
  60.         elseif (is_integer($value)) {
  61.             return "Integer";
  62.         elseif (is_float($value)) {
  63.             return "Float";
  64.         elseif (is_array($value)) {
  65.             return "Array";
  66.         elseif (is_resource($value)) {
  67.             return "Resource";
  68.         elseif (is_object($value)) {
  69.             return "Object";
  70.         }
  71.         return "Unknown";
  72.     }
  73.  
  74.     /**
  75.      *    Creates a human readable description of the
  76.      *    difference between two variables. Uses a
  77.      *    dynamic call.
  78.      *    @param mixed $first        First variable.
  79.      *    @param mixed $second       Value to compare with.
  80.      *    @param boolean $identical  If true then type anomolies count.
  81.      *    @return string             Description of difference.
  82.      *    @access public
  83.      */
  84.     function describeDifference($first$second$identical false{
  85.         if ($identical{
  86.             if ($this->isTypeMatch($first$second)) {
  87.                 return "with type mismatch as [" $this->describeValue($first.
  88.                     "] does not match [" $this->describeValue($second"]";
  89.             }
  90.         }
  91.         $type $this->getType($first);
  92.         if ($type == "Unknown"{
  93.             return "with unknown type";
  94.         }
  95.         $method 'describe' $type 'Difference';
  96.         return $this->$method($first$second$identical);
  97.     }
  98.  
  99.     /**
  100.      *    Tests to see if types match.
  101.      *    @param mixed $first        First variable.
  102.      *    @param mixed $second       Value to compare with.
  103.      *    @return boolean            True if matches.
  104.      *    @access private
  105.      */
  106.     protected function isTypeMatch($first$second{
  107.         return ($this->getType($first== $this->getType($second));
  108.     }
  109.  
  110.     /**
  111.      *    Clips a string to a maximum length.
  112.      *    @param string $value         String to truncate.
  113.      *    @param integer $size         Minimum string size to show.
  114.      *    @param integer $position     Centre of string section.
  115.      *    @return string               Shortened version.
  116.      *    @access public
  117.      */
  118.     function clipString($value$size$position 0{
  119.         $length strlen($value);
  120.         if ($length <= $size{
  121.             return $value;
  122.         }
  123.         $position min($position$length);
  124.         $start ($size/$position $position $size/2);
  125.         if ($start $size $length{
  126.             $start $length $size;
  127.         }
  128.         $value substr($value$start$size);
  129.         return ($start "..." ""$value ($start $size $length "..." "");
  130.     }
  131.  
  132.     /**
  133.      *    Creates a human readable description of the
  134.      *    difference between two variables. The minimal
  135.      *    version.
  136.      *    @param null $first          First value.
  137.      *    @param mixed $second        Value to compare with.
  138.      *    @return string              Human readable description.
  139.      *    @access private
  140.      */
  141.     protected function describeGenericDifference($first$second{
  142.         return "as [" $this->describeValue($first.
  143.                 "] does not match [" .
  144.                 $this->describeValue($second"]";
  145.     }
  146.  
  147.     /**
  148.      *    Creates a human readable description of the
  149.      *    difference between a null and another variable.
  150.      *    @param null $first          First null.
  151.      *    @param mixed $second        Null to compare with.
  152.      *    @param boolean $identical   If true then type anomolies count.
  153.      *    @return string              Human readable description.
  154.      *    @access private
  155.      */
  156.     protected function describeNullDifference($first$second$identical{
  157.         return $this->describeGenericDifference($first$second);
  158.     }
  159.  
  160.     /**
  161.      *    Creates a human readable description of the
  162.      *    difference between a boolean and another variable.
  163.      *    @param boolean $first       First boolean.
  164.      *    @param mixed $second        Boolean to compare with.
  165.      *    @param boolean $identical   If true then type anomolies count.
  166.      *    @return string              Human readable description.
  167.      *    @access private
  168.      */
  169.     protected function describeBooleanDifference($first$second$identical{
  170.         return $this->describeGenericDifference($first$second);
  171.     }
  172.  
  173.     /**
  174.      *    Creates a human readable description of the
  175.      *    difference between a string and another variable.
  176.      *    @param string $first        First string.
  177.      *    @param mixed $second        String to compare with.
  178.      *    @param boolean $identical   If true then type anomolies count.
  179.      *    @return string              Human readable description.
  180.      *    @access private
  181.      */
  182.     protected function describeStringDifference($first$second$identical{
  183.         if (is_object($second|| is_array($second)) {
  184.             return $this->describeGenericDifference($first$second);
  185.         }
  186.         $position $this->stringDiffersAt($first$second);
  187.         $message "at character $position";
  188.         $message .= " with [" .
  189.                 $this->clipString($first200$position"] and [" .
  190.                 $this->clipString($second200$position"]";
  191.         return $message;
  192.     }
  193.  
  194.     /**
  195.      *    Creates a human readable description of the
  196.      *    difference between an integer and another variable.
  197.      *    @param integer $first       First number.
  198.      *    @param mixed $second        Number to compare with.
  199.      *    @param boolean $identical   If true then type anomolies count.
  200.      *    @return string              Human readable description.
  201.      *    @access private
  202.      */
  203.     protected function describeIntegerDifference($first$second$identical{
  204.         if (is_object($second|| is_array($second)) {
  205.             return $this->describeGenericDifference($first$second);
  206.         }
  207.         return "because [" $this->describeValue($first.
  208.                 "] differs from [" .
  209.                 $this->describeValue($second"] by " .
  210.                 abs($first $second);
  211.     }
  212.  
  213.     /**
  214.      *    Creates a human readable description of the
  215.      *    difference between two floating point numbers.
  216.      *    @param float $first         First float.
  217.      *    @param mixed $second        Float to compare with.
  218.      *    @param boolean $identical   If true then type anomolies count.
  219.      *    @return string              Human readable description.
  220.      *    @access private
  221.      */
  222.     protected function describeFloatDifference($first$second$identical{
  223.         if (is_object($second|| is_array($second)) {
  224.             return $this->describeGenericDifference($first$second);
  225.         }
  226.         return "because [" $this->describeValue($first.
  227.                 "] differs from [" .
  228.                 $this->describeValue($second"] by " .
  229.                 abs($first $second);
  230.     }
  231.  
  232.     /**
  233.      *    Creates a human readable description of the
  234.      *    difference between two arrays.
  235.      *    @param array $first         First array.
  236.      *    @param mixed $second        Array to compare with.
  237.      *    @param boolean $identical   If true then type anomolies count.
  238.      *    @return string              Human readable description.
  239.      *    @access private
  240.      */
  241.     protected function describeArrayDifference($first$second$identical{
  242.         if (is_array($second)) {
  243.             return $this->describeGenericDifference($first$second);
  244.         }
  245.         if ($this->isMatchingKeys($first$second$identical)) {
  246.             return "as key list [" .
  247.                     implode(", "array_keys($first)) "] does not match key list [" .
  248.                     implode(", "array_keys($second)) "]";
  249.         }
  250.         foreach (array_keys($firstas $key{
  251.             if ($identical && ($first[$key=== $second[$key])) {
  252.                 continue;
  253.             }
  254.             if ($identical && ($first[$key== $second[$key])) {
  255.                 continue;
  256.             }
  257.             return "with member [$key$this->describeDifference(
  258.                     $first[$key],
  259.                     $second[$key],
  260.                     $identical);
  261.         }
  262.         return "";
  263.     }
  264.  
  265.     /**
  266.      *    Compares two arrays to see if their key lists match.
  267.      *    For an identical match, the ordering and types of the keys
  268.      *    is significant.
  269.      *    @param array $first         First array.
  270.      *    @param array $second        Array to compare with.
  271.      *    @param boolean $identical   If true then type anomolies count.
  272.      *    @return boolean             True if matching.
  273.      *    @access private
  274.      */
  275.     protected function isMatchingKeys($first$second$identical{
  276.         $first_keys array_keys($first);
  277.         $second_keys array_keys($second);
  278.         if ($identical{
  279.             return ($first_keys === $second_keys);
  280.         }
  281.         sort($first_keys);
  282.         sort($second_keys);
  283.         return ($first_keys == $second_keys);
  284.     }
  285.  
  286.     /**
  287.      *    Creates a human readable description of the
  288.      *    difference between a resource and another variable.
  289.      *    @param resource $first       First resource.
  290.      *    @param mixed $second         Resource to compare with.
  291.      *    @param boolean $identical    If true then type anomolies count.
  292.      *    @return string              Human readable description.
  293.      *    @access private
  294.      */
  295.     protected function describeResourceDifference($first$second$identical{
  296.         return $this->describeGenericDifference($first$second);
  297.     }
  298.  
  299.     /**
  300.      *    Creates a human readable description of the
  301.      *    difference between two objects.
  302.      *    @param object $first        First object.
  303.      *    @param mixed $second        Object to compare with.
  304.      *    @param boolean $identical   If true then type anomolies count.
  305.      *    @return string              Human readable description.
  306.      */
  307.     protected function describeObjectDifference($first$second$identical{
  308.         if (is_object($second)) {
  309.             return $this->describeGenericDifference($first$second);
  310.         }
  311.         return $this->describeArrayDifference(
  312.                 $this->getMembers($first),
  313.                 $this->getMembers($second),
  314.                 $identical);
  315.     }
  316.  
  317.     /**
  318.      *    Get all members of an object including private and protected ones.
  319.      *    A safer form of casting to an array.
  320.      *    @param object $object     Object to list members of,
  321.      *                               including private ones.
  322.      *    @return array             Names and values in the object.
  323.      */
  324.     protected function getMembers($object{
  325.         $reflection new ReflectionObject($object);
  326.         $members array();
  327.         foreach ($reflection->getProperties(as $property{
  328.             if (method_exists($property'setAccessible')) {
  329.                 $property->setAccessible(true);
  330.             }
  331.             try {
  332.                 $members[$property->getName()$property->getValue($object);
  333.             catch (ReflectionException $e{
  334.                 $members[$property->getName()=
  335.                     $this->getPrivatePropertyNoMatterWhat($property->getName()$object);
  336.             }
  337.         }
  338.         return $members;
  339.     }
  340.  
  341.     /**
  342.      *    Extracts a private member's value when reflection won't play ball.
  343.      *    @param string $name        Property name.
  344.      *    @param object $object      Object to read.
  345.      *    @return mixed              Value of property.
  346.      */
  347.     private function getPrivatePropertyNoMatterWhat($name$object{
  348.         foreach ((array)$object as $mangled_name => $value{
  349.             if ($this->unmangle($mangled_name== $name{
  350.                 return $value;
  351.             }
  352.         }
  353.     }
  354.  
  355.     /**
  356.      *    Removes crud from property name after it's been converted
  357.      *    to an array.
  358.      *    @param string $mangled     Name from array cast.
  359.      *    @return string             Cleaned up name.
  360.      */
  361.     function unmangle($mangled{
  362.         $parts preg_split('/[^a-zA-Z0-9_\x7f-\xff]+/'$mangled);
  363.         return array_pop($parts);
  364.     }
  365.  
  366.     /**
  367.      *    Find the first character position that differs
  368.      *    in two strings by binary chop.
  369.      *    @param string $first        First string.
  370.      *    @param string $second       String to compare with.
  371.      *    @return integer             Position of first differing
  372.      *                                 character.
  373.      *    @access private
  374.      */
  375.     protected function stringDiffersAt($first$second{
  376.         if ($first || $second{
  377.             return 0;
  378.         }
  379.         if (strlen($firststrlen($second)) {
  380.             list($first$secondarray($second$first);
  381.         }
  382.         $position 0;
  383.         $step strlen($first);
  384.         while ($step 1{
  385.             $step = (integer)(($step 12);
  386.             if (strncmp($first$second$position $step== 0{
  387.                 $position += $step;
  388.             }
  389.         }
  390.         return $position;
  391.     }
  392.  
  393.     /**
  394.      *    Sends a formatted dump of a variable to a string.
  395.      *    @param mixed $variable    Variable to display.
  396.      *    @return string            Output from print_r().
  397.      *    @access public
  398.      */
  399.     function dump($variable{
  400.         ob_start();
  401.         print_r($variable);
  402.         $formatted ob_get_contents();
  403.         ob_end_clean();
  404.         return $formatted;
  405.     }
  406. }
  407. ?>

Documentation generated on Thu, 01 Oct 2009 20:54:38 -0500 by phpDocumentor 1.4.2