Chris@0: Chris@0: * Chris@0: * For the full copyright and license information, please view the LICENSE Chris@0: * file that was distributed with this source code. Chris@0: */ Chris@0: Chris@0: use SebastianBergmann\Exporter\Exporter; Chris@0: Chris@0: /** Chris@0: * Represents a static invocation. Chris@0: * Chris@0: * @since Class available since Release 1.0.0 Chris@0: */ Chris@0: class PHPUnit_Framework_MockObject_Invocation_Static implements PHPUnit_Framework_MockObject_Invocation, PHPUnit_Framework_SelfDescribing Chris@0: { Chris@0: /** Chris@0: * @var array Chris@0: */ Chris@0: protected static $uncloneableExtensions = array( Chris@0: 'mysqli' => true, Chris@0: 'SQLite' => true, Chris@0: 'sqlite3' => true, Chris@0: 'tidy' => true, Chris@0: 'xmlwriter' => true, Chris@0: 'xsl' => true Chris@0: ); Chris@0: Chris@0: /** Chris@0: * @var array Chris@0: */ Chris@0: protected static $uncloneableClasses = array( Chris@0: 'Closure', Chris@0: 'COMPersistHelper', Chris@0: 'IteratorIterator', Chris@0: 'RecursiveIteratorIterator', Chris@0: 'SplFileObject', Chris@0: 'PDORow', Chris@0: 'ZipArchive' Chris@0: ); Chris@0: Chris@0: /** Chris@0: * @var string Chris@0: */ Chris@0: public $className; Chris@0: Chris@0: /** Chris@0: * @var string Chris@0: */ Chris@0: public $methodName; Chris@0: Chris@0: /** Chris@0: * @var array Chris@0: */ Chris@0: public $parameters; Chris@0: Chris@0: /** Chris@0: * @param string $className Chris@0: * @param string $methodname Chris@0: * @param array $parameters Chris@0: * @param bool $cloneObjects Chris@0: */ Chris@0: public function __construct($className, $methodName, array $parameters, $cloneObjects = false) Chris@0: { Chris@0: $this->className = $className; Chris@0: $this->methodName = $methodName; Chris@0: $this->parameters = $parameters; Chris@0: Chris@0: if (!$cloneObjects) { Chris@0: return; Chris@0: } Chris@0: Chris@0: foreach ($this->parameters as $key => $value) { Chris@0: if (is_object($value)) { Chris@0: $this->parameters[$key] = $this->cloneObject($value); Chris@0: } Chris@0: } Chris@0: } Chris@0: Chris@0: /** Chris@0: * @return string Chris@0: */ Chris@0: public function toString() Chris@0: { Chris@0: $exporter = new Exporter; Chris@0: Chris@0: return sprintf( Chris@0: '%s::%s(%s)', Chris@0: $this->className, Chris@0: $this->methodName, Chris@0: implode( Chris@0: ', ', Chris@0: array_map( Chris@0: array($exporter, 'shortenedExport'), Chris@0: $this->parameters Chris@0: ) Chris@0: ) Chris@0: ); Chris@0: } Chris@0: Chris@0: /** Chris@0: * @param object $original Chris@0: * @return object Chris@0: */ Chris@0: protected function cloneObject($original) Chris@0: { Chris@0: $cloneable = null; Chris@0: $object = new ReflectionObject($original); Chris@0: Chris@0: // Check the blacklist before asking PHP reflection to work around Chris@0: // https://bugs.php.net/bug.php?id=53967 Chris@0: if ($object->isInternal() && Chris@0: isset(self::$uncloneableExtensions[$object->getExtensionName()])) { Chris@0: $cloneable = false; Chris@0: } Chris@0: Chris@0: if ($cloneable === null) { Chris@0: foreach (self::$uncloneableClasses as $class) { Chris@0: if ($original instanceof $class) { Chris@0: $cloneable = false; Chris@0: break; Chris@0: } Chris@0: } Chris@0: } Chris@0: Chris@0: if ($cloneable === null && method_exists($object, 'isCloneable')) { Chris@0: $cloneable = $object->isCloneable(); Chris@0: } Chris@0: Chris@0: if ($cloneable === null && $object->hasMethod('__clone')) { Chris@0: $method = $object->getMethod('__clone'); Chris@0: $cloneable = $method->isPublic(); Chris@0: } Chris@0: Chris@0: if ($cloneable === null) { Chris@0: $cloneable = true; Chris@0: } Chris@0: Chris@0: if ($cloneable) { Chris@0: try { Chris@0: return clone $original; Chris@0: } catch (Exception $e) { Chris@0: return $original; Chris@0: } Chris@0: } else { Chris@0: return $original; Chris@0: } Chris@0: } Chris@0: }