364 lines
11 KiB
PHP
364 lines
11 KiB
PHP
|
<?php
|
||
|
/**
|
||
|
* PHPUnit
|
||
|
*
|
||
|
* Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
|
||
|
* All rights reserved.
|
||
|
*
|
||
|
* Redistribution and use in source and binary forms, with or without
|
||
|
* modification, are permitted provided that the following conditions
|
||
|
* are met:
|
||
|
*
|
||
|
* * Redistributions of source code must retain the above copyright
|
||
|
* notice, this list of conditions and the following disclaimer.
|
||
|
*
|
||
|
* * Redistributions in binary form must reproduce the above copyright
|
||
|
* notice, this list of conditions and the following disclaimer in
|
||
|
* the documentation and/or other materials provided with the
|
||
|
* distribution.
|
||
|
*
|
||
|
* * Neither the name of Sebastian Bergmann nor the names of his
|
||
|
* contributors may be used to endorse or promote products derived
|
||
|
* from this software without specific prior written permission.
|
||
|
*
|
||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||
|
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||
|
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||
|
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||
|
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||
|
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||
|
*
|
||
|
* @package PHPUnit
|
||
|
* @subpackage Util
|
||
|
* @author Sebastian Bergmann <sebastian@phpunit.de>
|
||
|
* @copyright 2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
|
||
|
* @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License
|
||
|
* @link http://www.phpunit.de/
|
||
|
* @since File available since Release 3.1.0
|
||
|
*/
|
||
|
|
||
|
/**
|
||
|
* Class helpers.
|
||
|
*
|
||
|
* @package PHPUnit
|
||
|
* @subpackage Util
|
||
|
* @author Sebastian Bergmann <sebastian@phpunit.de>
|
||
|
* @copyright 2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
|
||
|
* @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License
|
||
|
* @link http://www.phpunit.de/
|
||
|
* @since Class available since Release 3.1.0
|
||
|
*/
|
||
|
class PHPUnit_Util_Class
|
||
|
{
|
||
|
protected static $buffer = array();
|
||
|
|
||
|
/**
|
||
|
* Starts the collection of loaded classes.
|
||
|
*
|
||
|
*/
|
||
|
public static function collectStart()
|
||
|
{
|
||
|
self::$buffer = get_declared_classes();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Stops the collection of loaded classes and
|
||
|
* returns the names of the loaded classes.
|
||
|
*
|
||
|
* @return array
|
||
|
*/
|
||
|
public static function collectEnd()
|
||
|
{
|
||
|
return array_values(
|
||
|
array_diff(get_declared_classes(), self::$buffer)
|
||
|
);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns the class hierarchy for a given class.
|
||
|
*
|
||
|
* @param string $className
|
||
|
* @param boolean $asReflectionObjects
|
||
|
* @return array
|
||
|
*/
|
||
|
public static function getHierarchy($className, $asReflectionObjects = FALSE)
|
||
|
{
|
||
|
if ($asReflectionObjects) {
|
||
|
$classes = array(new ReflectionClass($className));
|
||
|
} else {
|
||
|
$classes = array($className);
|
||
|
}
|
||
|
|
||
|
$done = FALSE;
|
||
|
|
||
|
while (!$done) {
|
||
|
if ($asReflectionObjects) {
|
||
|
$class = new ReflectionClass(
|
||
|
$classes[count($classes)-1]->getName()
|
||
|
);
|
||
|
} else {
|
||
|
$class = new ReflectionClass($classes[count($classes)-1]);
|
||
|
}
|
||
|
|
||
|
$parent = $class->getParentClass();
|
||
|
|
||
|
if ($parent !== FALSE) {
|
||
|
if ($asReflectionObjects) {
|
||
|
$classes[] = $parent;
|
||
|
} else {
|
||
|
$classes[] = $parent->getName();
|
||
|
}
|
||
|
} else {
|
||
|
$done = TRUE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return $classes;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns the parameters of a function or method.
|
||
|
*
|
||
|
* @param ReflectionFunction|ReflectionMethod $method
|
||
|
* @param boolean $forCall
|
||
|
* @return string
|
||
|
* @since Method available since Release 3.2.0
|
||
|
*/
|
||
|
public static function getMethodParameters($method, $forCall = FALSE)
|
||
|
{
|
||
|
$parameters = array();
|
||
|
|
||
|
foreach ($method->getParameters() as $i => $parameter) {
|
||
|
$name = '$' . $parameter->getName();
|
||
|
|
||
|
/* Note: PHP extensions may use empty names for reference arguments
|
||
|
* or "..." for methods taking a variable number of arguments.
|
||
|
*/
|
||
|
if ($name === '$' || $name === '$...') {
|
||
|
$name = '$arg' . $i;
|
||
|
}
|
||
|
|
||
|
$default = '';
|
||
|
$reference = '';
|
||
|
$typeHint = '';
|
||
|
|
||
|
if (!$forCall) {
|
||
|
if ($parameter->isArray()) {
|
||
|
$typeHint = 'array ';
|
||
|
}
|
||
|
|
||
|
else if (version_compare(PHP_VERSION, '5.4', '>') &&
|
||
|
$parameter->isCallable()) {
|
||
|
$typeHint = 'callable ';
|
||
|
}
|
||
|
|
||
|
else {
|
||
|
try {
|
||
|
$class = $parameter->getClass();
|
||
|
}
|
||
|
|
||
|
catch (ReflectionException $e) {
|
||
|
$class = FALSE;
|
||
|
}
|
||
|
|
||
|
if ($class) {
|
||
|
$typeHint = $class->getName() . ' ';
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ($parameter->isDefaultValueAvailable()) {
|
||
|
$value = $parameter->getDefaultValue();
|
||
|
$default = ' = ' . var_export($value, TRUE);
|
||
|
}
|
||
|
|
||
|
else if ($parameter->isOptional()) {
|
||
|
$default = ' = null';
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ($parameter->isPassedByReference()) {
|
||
|
$reference = '&';
|
||
|
}
|
||
|
|
||
|
$parameters[] = $typeHint . $reference . $name . $default;
|
||
|
}
|
||
|
|
||
|
return join(', ', $parameters);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns the package information of a user-defined class.
|
||
|
*
|
||
|
* @param string $className
|
||
|
* @param string $docComment
|
||
|
* @return array
|
||
|
*/
|
||
|
public static function getPackageInformation($className, $docComment)
|
||
|
{
|
||
|
$result = array(
|
||
|
'namespace' => '',
|
||
|
'fullPackage' => '',
|
||
|
'category' => '',
|
||
|
'package' => '',
|
||
|
'subpackage' => ''
|
||
|
);
|
||
|
|
||
|
if (strpos($className, '\\') !== FALSE) {
|
||
|
$result['namespace'] = self::arrayToName(
|
||
|
explode('\\', $className)
|
||
|
);
|
||
|
}
|
||
|
|
||
|
if (preg_match('/@category[\s]+([\.\w]+)/', $docComment, $matches)) {
|
||
|
$result['category'] = $matches[1];
|
||
|
}
|
||
|
|
||
|
if (preg_match('/@package[\s]+([\.\w]+)/', $docComment, $matches)) {
|
||
|
$result['package'] = $matches[1];
|
||
|
$result['fullPackage'] = $matches[1];
|
||
|
}
|
||
|
|
||
|
if (preg_match('/@subpackage[\s]+([\.\w]+)/', $docComment, $matches)) {
|
||
|
$result['subpackage'] = $matches[1];
|
||
|
$result['fullPackage'] .= '.' . $matches[1];
|
||
|
}
|
||
|
|
||
|
if (empty($result['fullPackage'])) {
|
||
|
$result['fullPackage'] = self::arrayToName(
|
||
|
explode('_', str_replace('\\', '_', $className)), '.'
|
||
|
);
|
||
|
}
|
||
|
|
||
|
return $result;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns the value of a static attribute.
|
||
|
* This also works for attributes that are declared protected or private.
|
||
|
*
|
||
|
* @param string $className
|
||
|
* @param string $attributeName
|
||
|
* @return mixed
|
||
|
* @throws PHPUnit_Framework_Exception
|
||
|
* @since Method available since Release 3.4.0
|
||
|
*/
|
||
|
public static function getStaticAttribute($className, $attributeName)
|
||
|
{
|
||
|
if (!is_string($className)) {
|
||
|
throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'string');
|
||
|
}
|
||
|
|
||
|
if (!class_exists($className)) {
|
||
|
throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'class name');
|
||
|
}
|
||
|
|
||
|
if (!is_string($attributeName)) {
|
||
|
throw PHPUnit_Util_InvalidArgumentHelper::factory(2, 'string');
|
||
|
}
|
||
|
|
||
|
$class = new ReflectionClass($className);
|
||
|
|
||
|
while ($class) {
|
||
|
$attributes = $class->getStaticProperties();
|
||
|
|
||
|
if (array_key_exists($attributeName, $attributes)) {
|
||
|
return $attributes[$attributeName];
|
||
|
}
|
||
|
|
||
|
$class = $class->getParentClass();
|
||
|
}
|
||
|
|
||
|
throw new PHPUnit_Framework_Exception(
|
||
|
sprintf(
|
||
|
'Attribute "%s" not found in class.',
|
||
|
|
||
|
$attributeName
|
||
|
)
|
||
|
);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns the value of an object's attribute.
|
||
|
* This also works for attributes that are declared protected or private.
|
||
|
*
|
||
|
* @param object $object
|
||
|
* @param string $attributeName
|
||
|
* @return mixed
|
||
|
* @throws PHPUnit_Framework_Exception
|
||
|
* @since Method available since Release 3.4.0
|
||
|
*/
|
||
|
public static function getObjectAttribute($object, $attributeName)
|
||
|
{
|
||
|
if (!is_object($object)) {
|
||
|
throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'object');
|
||
|
}
|
||
|
|
||
|
if (!is_string($attributeName)) {
|
||
|
throw PHPUnit_Util_InvalidArgumentHelper::factory(2, 'string');
|
||
|
}
|
||
|
|
||
|
try {
|
||
|
$attribute = new ReflectionProperty($object, $attributeName);
|
||
|
}
|
||
|
|
||
|
catch (ReflectionException $e) {
|
||
|
$reflector = new ReflectionObject($object);
|
||
|
|
||
|
while ($reflector = $reflector->getParentClass()) {
|
||
|
try {
|
||
|
$attribute = $reflector->getProperty($attributeName);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
catch(ReflectionException $e) {
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (isset($attribute)) {
|
||
|
if (!$attribute || $attribute->isPublic()) {
|
||
|
return $object->$attributeName;
|
||
|
}
|
||
|
$attribute->setAccessible(TRUE);
|
||
|
$value = $attribute->getValue($object);
|
||
|
$attribute->setAccessible(FALSE);
|
||
|
|
||
|
return $value;
|
||
|
}
|
||
|
|
||
|
throw new PHPUnit_Framework_Exception(
|
||
|
sprintf(
|
||
|
'Attribute "%s" not found in object.',
|
||
|
$attributeName
|
||
|
)
|
||
|
);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns the package information of a user-defined class.
|
||
|
*
|
||
|
* @param array $parts
|
||
|
* @param string $join
|
||
|
* @return string
|
||
|
* @since Method available since Release 3.2.12
|
||
|
*/
|
||
|
protected static function arrayToName(array $parts, $join = '\\')
|
||
|
{
|
||
|
$result = '';
|
||
|
|
||
|
if (count($parts) > 1) {
|
||
|
array_pop($parts);
|
||
|
|
||
|
$result = join($join, $parts);
|
||
|
}
|
||
|
|
||
|
return $result;
|
||
|
}
|
||
|
}
|