annotate vendor/phpunit/phpunit-mock-objects/src/Invocation/StaticInvocation.php @ 19:fa3358dc1485 tip

Add ndrum files
author Chris Cannam
date Wed, 28 Aug 2019 13:14:47 +0100
parents 1fec387a4317
children
rev   line source
Chris@14 1 <?php
Chris@14 2 /*
Chris@14 3 * This file is part of the phpunit-mock-objects package.
Chris@14 4 *
Chris@14 5 * (c) Sebastian Bergmann <sebastian@phpunit.de>
Chris@14 6 *
Chris@14 7 * For the full copyright and license information, please view the LICENSE
Chris@14 8 * file that was distributed with this source code.
Chris@14 9 */
Chris@14 10 namespace PHPUnit\Framework\MockObject\Invocation;
Chris@14 11
Chris@14 12 use PHPUnit\Framework\MockObject\Generator;
Chris@14 13 use PHPUnit\Framework\MockObject\Invocation;
Chris@14 14 use PHPUnit\Framework\SelfDescribing;
Chris@14 15 use ReflectionObject;
Chris@14 16 use SebastianBergmann\Exporter\Exporter;
Chris@14 17
Chris@14 18 /**
Chris@14 19 * Represents a static invocation.
Chris@14 20 */
Chris@14 21 class StaticInvocation implements Invocation, SelfDescribing
Chris@14 22 {
Chris@14 23 /**
Chris@14 24 * @var array
Chris@14 25 */
Chris@14 26 private static $uncloneableExtensions = [
Chris@14 27 'mysqli' => true,
Chris@14 28 'SQLite' => true,
Chris@14 29 'sqlite3' => true,
Chris@14 30 'tidy' => true,
Chris@14 31 'xmlwriter' => true,
Chris@14 32 'xsl' => true
Chris@14 33 ];
Chris@14 34
Chris@14 35 /**
Chris@14 36 * @var array
Chris@14 37 */
Chris@14 38 private static $uncloneableClasses = [
Chris@14 39 'Closure',
Chris@14 40 'COMPersistHelper',
Chris@14 41 'IteratorIterator',
Chris@14 42 'RecursiveIteratorIterator',
Chris@14 43 'SplFileObject',
Chris@14 44 'PDORow',
Chris@14 45 'ZipArchive'
Chris@14 46 ];
Chris@14 47
Chris@14 48 /**
Chris@14 49 * @var string
Chris@14 50 */
Chris@14 51 private $className;
Chris@14 52
Chris@14 53 /**
Chris@14 54 * @var string
Chris@14 55 */
Chris@14 56 private $methodName;
Chris@14 57
Chris@14 58 /**
Chris@14 59 * @var array
Chris@14 60 */
Chris@14 61 private $parameters;
Chris@14 62
Chris@14 63 /**
Chris@14 64 * @var string
Chris@14 65 */
Chris@14 66 private $returnType;
Chris@14 67
Chris@14 68 /**
Chris@14 69 * @var bool
Chris@14 70 */
Chris@14 71 private $isReturnTypeNullable = false;
Chris@14 72
Chris@14 73 /**
Chris@14 74 * @param string $className
Chris@14 75 * @param string $methodName
Chris@14 76 * @param array $parameters
Chris@14 77 * @param string $returnType
Chris@14 78 * @param bool $cloneObjects
Chris@14 79 */
Chris@14 80 public function __construct($className, $methodName, array $parameters, $returnType, $cloneObjects = false)
Chris@14 81 {
Chris@14 82 $this->className = $className;
Chris@14 83 $this->methodName = $methodName;
Chris@14 84 $this->parameters = $parameters;
Chris@14 85
Chris@14 86 if (\strpos($returnType, '?') === 0) {
Chris@14 87 $returnType = \substr($returnType, 1);
Chris@14 88 $this->isReturnTypeNullable = true;
Chris@14 89 }
Chris@14 90
Chris@14 91 $this->returnType = $returnType;
Chris@14 92
Chris@14 93 if (!$cloneObjects) {
Chris@14 94 return;
Chris@14 95 }
Chris@14 96
Chris@14 97 foreach ($this->parameters as $key => $value) {
Chris@14 98 if (\is_object($value)) {
Chris@14 99 $this->parameters[$key] = $this->cloneObject($value);
Chris@14 100 }
Chris@14 101 }
Chris@14 102 }
Chris@14 103
Chris@14 104 public function getClassName(): string
Chris@14 105 {
Chris@14 106 return $this->className;
Chris@14 107 }
Chris@14 108
Chris@14 109 public function getMethodName(): string
Chris@14 110 {
Chris@14 111 return $this->methodName;
Chris@14 112 }
Chris@14 113
Chris@14 114 public function getParameters(): array
Chris@14 115 {
Chris@14 116 return $this->parameters;
Chris@14 117 }
Chris@14 118
Chris@14 119 public function getReturnType(): string
Chris@14 120 {
Chris@14 121 return $this->returnType;
Chris@14 122 }
Chris@14 123
Chris@14 124 public function isReturnTypeNullable(): bool
Chris@14 125 {
Chris@14 126 return $this->isReturnTypeNullable;
Chris@14 127 }
Chris@14 128
Chris@14 129 /**
Chris@14 130 * @return mixed Mocked return value
Chris@14 131 *
Chris@14 132 * @throws \ReflectionException
Chris@14 133 * @throws \PHPUnit\Framework\MockObject\RuntimeException
Chris@14 134 * @throws \PHPUnit\Framework\Exception
Chris@14 135 */
Chris@14 136 public function generateReturnValue()
Chris@14 137 {
Chris@14 138 if ($this->isReturnTypeNullable) {
Chris@14 139 return;
Chris@14 140 }
Chris@14 141
Chris@14 142 switch (\strtolower($this->returnType)) {
Chris@14 143 case '':
Chris@14 144 case 'void':
Chris@14 145 return;
Chris@14 146
Chris@14 147 case 'string':
Chris@14 148 return '';
Chris@14 149
Chris@14 150 case 'float':
Chris@14 151 return 0.0;
Chris@14 152
Chris@14 153 case 'int':
Chris@14 154 return 0;
Chris@14 155
Chris@14 156 case 'bool':
Chris@14 157 return false;
Chris@14 158
Chris@14 159 case 'array':
Chris@14 160 return [];
Chris@14 161
Chris@14 162 case 'object':
Chris@14 163 return new \stdClass;
Chris@14 164
Chris@14 165 case 'callable':
Chris@14 166 case 'closure':
Chris@14 167 return function () {
Chris@14 168 };
Chris@14 169
Chris@14 170 case 'traversable':
Chris@14 171 case 'generator':
Chris@14 172 case 'iterable':
Chris@14 173 $generator = function () {
Chris@14 174 yield;
Chris@14 175 };
Chris@14 176
Chris@14 177 return $generator();
Chris@14 178
Chris@14 179 default:
Chris@14 180 $generator = new Generator;
Chris@14 181
Chris@14 182 return $generator->getMock($this->returnType, [], [], '', false);
Chris@14 183 }
Chris@14 184 }
Chris@14 185
Chris@14 186 public function toString(): string
Chris@14 187 {
Chris@14 188 $exporter = new Exporter;
Chris@14 189
Chris@14 190 return \sprintf(
Chris@14 191 '%s::%s(%s)%s',
Chris@14 192 $this->className,
Chris@14 193 $this->methodName,
Chris@14 194 \implode(
Chris@14 195 ', ',
Chris@14 196 \array_map(
Chris@14 197 [$exporter, 'shortenedExport'],
Chris@14 198 $this->parameters
Chris@14 199 )
Chris@14 200 ),
Chris@14 201 $this->returnType ? \sprintf(': %s', $this->returnType) : ''
Chris@14 202 );
Chris@14 203 }
Chris@14 204
Chris@14 205 /**
Chris@14 206 * @param object $original
Chris@14 207 *
Chris@14 208 * @return object
Chris@14 209 */
Chris@14 210 private function cloneObject($original)
Chris@14 211 {
Chris@14 212 $cloneable = null;
Chris@14 213 $object = new ReflectionObject($original);
Chris@14 214
Chris@14 215 // Check the blacklist before asking PHP reflection to work around
Chris@14 216 // https://bugs.php.net/bug.php?id=53967
Chris@14 217 if ($object->isInternal() &&
Chris@14 218 isset(self::$uncloneableExtensions[$object->getExtensionName()])) {
Chris@14 219 $cloneable = false;
Chris@14 220 }
Chris@14 221
Chris@14 222 if ($cloneable === null) {
Chris@14 223 foreach (self::$uncloneableClasses as $class) {
Chris@14 224 if ($original instanceof $class) {
Chris@14 225 $cloneable = false;
Chris@14 226
Chris@14 227 break;
Chris@14 228 }
Chris@14 229 }
Chris@14 230 }
Chris@14 231
Chris@14 232 if ($cloneable === null) {
Chris@14 233 $cloneable = $object->isCloneable();
Chris@14 234 }
Chris@14 235
Chris@14 236 if ($cloneable === null && $object->hasMethod('__clone')) {
Chris@14 237 $method = $object->getMethod('__clone');
Chris@14 238 $cloneable = $method->isPublic();
Chris@14 239 }
Chris@14 240
Chris@14 241 if ($cloneable === null) {
Chris@14 242 $cloneable = true;
Chris@14 243 }
Chris@14 244
Chris@14 245 if ($cloneable) {
Chris@14 246 try {
Chris@14 247 return clone $original;
Chris@14 248 } catch (\Exception $e) {
Chris@14 249 return $original;
Chris@14 250 }
Chris@14 251 } else {
Chris@14 252 return $original;
Chris@14 253 }
Chris@14 254 }
Chris@14 255 }