Spike PHPCoverage Details: dumper.php

Line #FrequencySource Line
1 <?php
2     /**
3      *  base include file for SimpleTest
4      *  @package    SimpleTest
5      *  @subpackage UnitTester
6      *  @version    $Id: dumper.php 1672 2008-03-02 04:47:34Z edwardzyang $
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) {
291            $type = $this->getType($value);
30             switch($type) {
311                case "Null":
32                     return "NULL";
331                case "Boolean":
341                    return "Boolean: " . ($value ? "true" : "false");
351                case "Array":
36                     return "Array: " . count($value) . " items";
371                case "Object":
381                    return "Object: of " . get_class($value);
391                case "String":
401                    return "String: " . $this->clipString($value, 200);
411                default:
421                    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) {
541            if (! isset($value)) {
55                 return "Null";
561            } elseif (is_bool($value)) {
571                return "Boolean";
581            } elseif (is_string($value)) {
591                return "String";
601            } elseif (is_integer($value)) {
611                return "Integer";
621            } elseif (is_float($value)) {
63                 return "Float";
641            } elseif (is_array($value)) {
65                 return "Array";
661            } elseif (is_resource($value)) {
67                 return "Resource";
681            } elseif (is_object($value)) {
691                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         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) {
1191            $length = strlen($value);
1201            if ($length <= $size) {
121                 return $value;
122             }
1231            $position = min($position, $length);
1241            $start = ($size/2 > $position ? 0 : $position - $size/2);
1251            if ($start + $size > $length) {
126                 $start = $length - $size;
127             }
1281            $value = substr($value, $start, $size);
1291            return ($start > 0 ? "..." : "") . $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         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         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         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         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($first, 200, $position) . "] and [" .
190                     $this->clipString($second, 200, $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         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         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         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($first) as $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         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         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          *    @access private
307          */
308         function _describeObjectDifference($first, $second, $identical) {
309             if (! is_object($second)) {
310                 return $this->_describeGenericDifference($first, $second);
311             }
312             return $this->_describeArrayDifference(
313                     get_object_vars($first),
314                     get_object_vars($second),
315                     $identical);
316         }
317         
318         /**
319          *    Find the first character position that differs
320          *    in two strings by binary chop.
321          *    @param string $first        First string.
322          *    @param string $second       String to compare with.
323          *    @return integer             Position of first differing
324          *                                character.
325          *    @access private
326          */
327         function _stringDiffersAt($first, $second) {
328             if (! $first || ! $second) {
329                 return 0;
330             }
331             if (strlen($first) < strlen($second)) {
332                 list($first, $second) = array($second, $first);
333             }
334             $position = 0;
335             $step = strlen($first);
336             while ($step > 1) {
337                 $step = (integer)(($step + 1) / 2);
338                 if (strncmp($first, $second, $position + $step) == 0) {
339                     $position += $step;
340                 }
341             }
342             return $position;
343         }
344         
345         /**
346          *    Sends a formatted dump of a variable to a string.
347          *    @param mixed $variable    Variable to display.
348          *    @return string            Output from print_r().
349          *    @access public
350          *    @static
351          */
352         function dump($variable) {
353             ob_start();
354             print_r($variable);
355             $formatted = ob_get_contents();
356             ob_end_clean();
357             return $formatted;
358         }
359     }
360 ?