| <?php |
| /** |
| * File containing the ezcDebugVariableDumpTool class. |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| * @package Debug |
| * @version //autogentag// |
| * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved. |
| * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0 |
| */ |
| |
| /** |
| * Tool class to dump variables in a way similar to Xdebug. |
| * |
| * This tool class allows to dump variables similar to the way it is done by |
| * Xdebug (@link http://xdebug.org). The class is used in the {@link |
| * ezcDebugPhpStacktraceIterator} to unify the variable dumps with those |
| * generated by {@link ezcDebugXdebugStacktraceIterator}. |
| * |
| * @package Debug |
| * @version //autogen// |
| */ |
| class ezcDebugVariableDumpTool |
| { |
| /** |
| * Returns the string representation of an variable. |
| * |
| * Returns the dump of the given variable, respecting the $maxData and |
| * $maxChildren paramaters when arrays or objects are dumped. $maxDepth is |
| * the maximum recursion depth when dumping arrays and objects. |
| * |
| * @param mixed $arg |
| * @param int $maxData |
| * @param int $maxChildren |
| * @param int $maxDepth |
| * @return string |
| */ |
| public static function dumpVariable( $arg, $maxData, $maxChildren, $maxDepth ) |
| { |
| switch ( gettype( $arg ) ) |
| { |
| case 'boolean': |
| return self::cutString( ( $arg ? 'TRUE' : 'FALSE' ), $maxData ); |
| case 'integer': |
| case 'double': |
| return self::cutString( (string) $arg, $maxData ); |
| case 'string': |
| return sprintf( |
| "'%s'", |
| self::cutString( (string) $arg, $maxData ) |
| ); |
| case 'array': |
| return self::dumpArray( $arg, $maxData, $maxChildren, $maxDepth ); |
| case 'object': |
| return self::dumpObject( $arg, $maxData, $maxChildren, $maxDepth ); |
| case 'resource': |
| return self::dumpResource( $arg, $maxData ); |
| case 'NULL': |
| return 'NULL'; |
| default: |
| return 'unknown type'; |
| } |
| } |
| |
| /** |
| * Returns the string representation of an array. |
| * |
| * Returns the dump of the given array, respecting the $maxData and |
| * $maxChildren paramaters. |
| * |
| * @param array $arg |
| * @param int $maxData |
| * @param int $maxChildren |
| * @param int $maxDepth |
| * @return string |
| */ |
| private static function dumpArray( array $arg, $maxData, $maxChildren, $maxDepth ) |
| { |
| $arrayContent = ''; |
| |
| if ( $maxDepth !== 0 ) |
| { |
| $max = ( |
| $maxChildren === false |
| ? count( $arg ) |
| : min( count( $arg ), $maxChildren ) |
| ); |
| |
| $results = array(); |
| reset( $arg ); |
| for ( $i = 0; $i < $max; ++$i ) |
| { |
| $results[] = |
| self::dumpVariable( |
| key( $arg ), |
| $maxData, |
| $maxChildren, |
| ( $maxDepth === false ? $maxDepth : $maxDepth - 1 ) |
| ) |
| . ' => ' |
| . self::dumpVariable( |
| current( $arg ), |
| $maxData, |
| $maxChildren, |
| ( $maxDepth === false ? $maxDepth : $maxDepth - 1 ) |
| ); |
| next( $arg ); |
| } |
| |
| if ( $max < count( $arg ) ) |
| { |
| $results[] = '...'; |
| } |
| |
| $arrayContent = implode( ', ', $results ); |
| } |
| else |
| { |
| $arrayContent = '...'; |
| } |
| |
| |
| return sprintf( |
| 'array (%s)', $arrayContent |
| ); |
| } |
| |
| /** |
| * Returns the string representation of an object. |
| * |
| * Returns the dump of the given object, respecting the $maxData, |
| * $maxChildren and $maxDepth paramaters. |
| * |
| * @param object $arg |
| * @param int $maxData |
| * @param int $maxChildren |
| * @param int $maxDepth |
| * @return string |
| */ |
| private static function dumpObject( $arg, $maxData, $maxChildren, $maxDepth ) |
| { |
| $refObj = new ReflectionObject( $arg ); |
| |
| $objectContent = ''; |
| if ( $maxDepth !== 0 ) |
| { |
| $refProps = $refObj->getProperties(); |
| |
| $max = ( |
| $maxChildren === false |
| ? min( count( $refProps ), $maxChildren ) |
| : count( $refProps ) |
| ); |
| $results = array(); |
| |
| reset( $refProps ); |
| for( $i = 0; $i < $max; $i++ ) |
| { |
| $refProp = current( $refProps ); |
| $results[] = sprintf( |
| '%s $%s = %s', |
| self::getPropertyVisibility( $refProp ), |
| $refProp->getName(), |
| self::getPropertyValue( |
| $refProp, |
| $arg, |
| $maxData, |
| $maxChildren, |
| ( $maxDepth === false ? $maxDepth : $maxDepth - 1 ) |
| ) |
| ); |
| next( $refProps ); |
| } |
| $objectContent = implode( '; ', $results ); |
| } |
| else |
| { |
| $objectContent = '...'; |
| } |
| |
| |
| return sprintf( |
| 'class %s { %s }', |
| $refObj->getName(), |
| $objectContent |
| ); |
| } |
| |
| /** |
| * Returns the string representation of a resource. |
| * |
| * Returns the dump of the given resource, respecting the $maxData |
| * paramater. |
| * |
| * @param resource $res |
| * @param int $maxData |
| * @return string |
| */ |
| private static function dumpResource( $res, $maxData ) |
| { |
| // @TODO: Ugly, but necessary. |
| // 'resource(5) of type (stream)' |
| preg_match( '(^Resource id #(?P<id>\d+)$)', (string) $res, $matches ); |
| return sprintf( |
| 'resource(%s) of type (%s)', |
| $matches['id'], |
| get_resource_type( $res ) |
| ); |
| } |
| |
| /** |
| * Returns the $value cut to $length and padded with '...'. |
| * |
| * @param string $value |
| * @param int $length |
| * @return string |
| */ |
| private static function cutString( $value, $length ) |
| { |
| if ( $length !== false && ( strlen( $value ) > ( $length - 3 ) ) ) |
| { |
| return substr( $value, 0, ( $length - 3 ) ) . '...'; |
| } |
| return $value; |
| } |
| |
| /** |
| * Returns private, protected or public. |
| * |
| * Returns the visibility of the given relfected property $refProp as a |
| * readable string. |
| * |
| * @param ReflectionProperty $refProp |
| * @return string |
| */ |
| private static function getPropertyVisibility( ReflectionProperty $refProp ) |
| { |
| $info = '%s %s = %s'; |
| if ( $refProp->isPrivate() ) |
| { |
| return 'private'; |
| } |
| if ( $refProp->isProtected() ) |
| { |
| return 'protected'; |
| } |
| return 'public'; |
| } |
| |
| /** |
| * Returns the dumped property value. |
| * |
| * Returns the dumped value for the given reflected property ($refProp) on |
| * the given $obj. Makes use of the ugly array casting hack to determine |
| * values of private and protected properties. |
| * |
| * @param ReflectionProperty $refProp |
| * @param object $obj |
| * @param int $maxData |
| * @param int $maxChildren |
| * @param int $maxDepth |
| * @return string |
| */ |
| private static function getPropertyValue( ReflectionProperty $refProp, $obj, $maxData, $maxChildren, $maxDepth ) |
| { |
| $value = null; |
| // @TODO: If we switch to PHP version 5.3, where Reflection can access |
| // protected/private property values, we should change this to the |
| // correct way. |
| if ( !$refProp->isPublic() ) |
| { |
| $objArr = (array) $obj; |
| $className = ( $refProp->isProtected() ? '*' : $refProp->getDeclaringClass()->getName() ); |
| $propName = $refProp->getName(); |
| $value = $objArr["\0{$className}\0{$propName}"]; |
| } |
| else |
| { |
| $value = $refProp->getValue( $obj ); |
| } |
| return self::dumpVariable( $value, $maxData, $maxChildren, $maxDepth ); |
| } |
| } |
| |
| ?> |