annotate vendor/sebastian/global-state/src/Snapshot.php @ 0:4c8ae668cc8c

Initial import (non-working)
author Chris Cannam
date Wed, 29 Nov 2017 16:09:58 +0000
parents
children 1fec387a4317
rev   line source
Chris@0 1 <?php
Chris@0 2 /*
Chris@0 3 * This file is part of the GlobalState package.
Chris@0 4 *
Chris@0 5 * (c) Sebastian Bergmann <sebastian@phpunit.de>
Chris@0 6 *
Chris@0 7 * For the full copyright and license information, please view the LICENSE
Chris@0 8 * file that was distributed with this source code.
Chris@0 9 */
Chris@0 10
Chris@0 11 namespace SebastianBergmann\GlobalState;
Chris@0 12
Chris@0 13 use ReflectionClass;
Chris@0 14 use Serializable;
Chris@0 15
Chris@0 16 /**
Chris@0 17 * A snapshot of global state.
Chris@0 18 */
Chris@0 19 class Snapshot
Chris@0 20 {
Chris@0 21 /**
Chris@0 22 * @var Blacklist
Chris@0 23 */
Chris@0 24 private $blacklist;
Chris@0 25
Chris@0 26 /**
Chris@0 27 * @var array
Chris@0 28 */
Chris@0 29 private $globalVariables = array();
Chris@0 30
Chris@0 31 /**
Chris@0 32 * @var array
Chris@0 33 */
Chris@0 34 private $superGlobalArrays = array();
Chris@0 35
Chris@0 36 /**
Chris@0 37 * @var array
Chris@0 38 */
Chris@0 39 private $superGlobalVariables = array();
Chris@0 40
Chris@0 41 /**
Chris@0 42 * @var array
Chris@0 43 */
Chris@0 44 private $staticAttributes = array();
Chris@0 45
Chris@0 46 /**
Chris@0 47 * @var array
Chris@0 48 */
Chris@0 49 private $iniSettings = array();
Chris@0 50
Chris@0 51 /**
Chris@0 52 * @var array
Chris@0 53 */
Chris@0 54 private $includedFiles = array();
Chris@0 55
Chris@0 56 /**
Chris@0 57 * @var array
Chris@0 58 */
Chris@0 59 private $constants = array();
Chris@0 60
Chris@0 61 /**
Chris@0 62 * @var array
Chris@0 63 */
Chris@0 64 private $functions = array();
Chris@0 65
Chris@0 66 /**
Chris@0 67 * @var array
Chris@0 68 */
Chris@0 69 private $interfaces = array();
Chris@0 70
Chris@0 71 /**
Chris@0 72 * @var array
Chris@0 73 */
Chris@0 74 private $classes = array();
Chris@0 75
Chris@0 76 /**
Chris@0 77 * @var array
Chris@0 78 */
Chris@0 79 private $traits = array();
Chris@0 80
Chris@0 81 /**
Chris@0 82 * Creates a snapshot of the current global state.
Chris@0 83 *
Chris@0 84 * @param Blacklist $blacklist
Chris@0 85 * @param bool $includeGlobalVariables
Chris@0 86 * @param bool $includeStaticAttributes
Chris@0 87 * @param bool $includeConstants
Chris@0 88 * @param bool $includeFunctions
Chris@0 89 * @param bool $includeClasses
Chris@0 90 * @param bool $includeInterfaces
Chris@0 91 * @param bool $includeTraits
Chris@0 92 * @param bool $includeIniSettings
Chris@0 93 * @param bool $includeIncludedFiles
Chris@0 94 */
Chris@0 95 public function __construct(Blacklist $blacklist = null, $includeGlobalVariables = true, $includeStaticAttributes = true, $includeConstants = true, $includeFunctions = true, $includeClasses = true, $includeInterfaces = true, $includeTraits = true, $includeIniSettings = true, $includeIncludedFiles = true)
Chris@0 96 {
Chris@0 97 if ($blacklist === null) {
Chris@0 98 $blacklist = new Blacklist;
Chris@0 99 }
Chris@0 100
Chris@0 101 $this->blacklist = $blacklist;
Chris@0 102
Chris@0 103 if ($includeConstants) {
Chris@0 104 $this->snapshotConstants();
Chris@0 105 }
Chris@0 106
Chris@0 107 if ($includeFunctions) {
Chris@0 108 $this->snapshotFunctions();
Chris@0 109 }
Chris@0 110
Chris@0 111 if ($includeClasses || $includeStaticAttributes) {
Chris@0 112 $this->snapshotClasses();
Chris@0 113 }
Chris@0 114
Chris@0 115 if ($includeInterfaces) {
Chris@0 116 $this->snapshotInterfaces();
Chris@0 117 }
Chris@0 118
Chris@0 119 if ($includeGlobalVariables) {
Chris@0 120 $this->setupSuperGlobalArrays();
Chris@0 121 $this->snapshotGlobals();
Chris@0 122 }
Chris@0 123
Chris@0 124 if ($includeStaticAttributes) {
Chris@0 125 $this->snapshotStaticAttributes();
Chris@0 126 }
Chris@0 127
Chris@0 128 if ($includeIniSettings) {
Chris@0 129 $this->iniSettings = ini_get_all(null, false);
Chris@0 130 }
Chris@0 131
Chris@0 132 if ($includeIncludedFiles) {
Chris@0 133 $this->includedFiles = get_included_files();
Chris@0 134 }
Chris@0 135
Chris@0 136 if (function_exists('get_declared_traits')) {
Chris@0 137 $this->traits = get_declared_traits();
Chris@0 138 }
Chris@0 139 }
Chris@0 140
Chris@0 141 /**
Chris@0 142 * @return Blacklist
Chris@0 143 */
Chris@0 144 public function blacklist()
Chris@0 145 {
Chris@0 146 return $this->blacklist;
Chris@0 147 }
Chris@0 148
Chris@0 149 /**
Chris@0 150 * @return array
Chris@0 151 */
Chris@0 152 public function globalVariables()
Chris@0 153 {
Chris@0 154 return $this->globalVariables;
Chris@0 155 }
Chris@0 156
Chris@0 157 /**
Chris@0 158 * @return array
Chris@0 159 */
Chris@0 160 public function superGlobalVariables()
Chris@0 161 {
Chris@0 162 return $this->superGlobalVariables;
Chris@0 163 }
Chris@0 164
Chris@0 165 /**
Chris@0 166 * Returns a list of all super-global variable arrays.
Chris@0 167 *
Chris@0 168 * @return array
Chris@0 169 */
Chris@0 170 public function superGlobalArrays()
Chris@0 171 {
Chris@0 172 return $this->superGlobalArrays;
Chris@0 173 }
Chris@0 174
Chris@0 175 /**
Chris@0 176 * @return array
Chris@0 177 */
Chris@0 178 public function staticAttributes()
Chris@0 179 {
Chris@0 180 return $this->staticAttributes;
Chris@0 181 }
Chris@0 182
Chris@0 183 /**
Chris@0 184 * @return array
Chris@0 185 */
Chris@0 186 public function iniSettings()
Chris@0 187 {
Chris@0 188 return $this->iniSettings;
Chris@0 189 }
Chris@0 190
Chris@0 191 /**
Chris@0 192 * @return array
Chris@0 193 */
Chris@0 194 public function includedFiles()
Chris@0 195 {
Chris@0 196 return $this->includedFiles;
Chris@0 197 }
Chris@0 198
Chris@0 199 /**
Chris@0 200 * @return array
Chris@0 201 */
Chris@0 202 public function constants()
Chris@0 203 {
Chris@0 204 return $this->constants;
Chris@0 205 }
Chris@0 206
Chris@0 207 /**
Chris@0 208 * @return array
Chris@0 209 */
Chris@0 210 public function functions()
Chris@0 211 {
Chris@0 212 return $this->functions;
Chris@0 213 }
Chris@0 214
Chris@0 215 /**
Chris@0 216 * @return array
Chris@0 217 */
Chris@0 218 public function interfaces()
Chris@0 219 {
Chris@0 220 return $this->interfaces;
Chris@0 221 }
Chris@0 222
Chris@0 223 /**
Chris@0 224 * @return array
Chris@0 225 */
Chris@0 226 public function classes()
Chris@0 227 {
Chris@0 228 return $this->classes;
Chris@0 229 }
Chris@0 230
Chris@0 231 /**
Chris@0 232 * @return array
Chris@0 233 */
Chris@0 234 public function traits()
Chris@0 235 {
Chris@0 236 return $this->traits;
Chris@0 237 }
Chris@0 238
Chris@0 239 /**
Chris@0 240 * Creates a snapshot user-defined constants.
Chris@0 241 */
Chris@0 242 private function snapshotConstants()
Chris@0 243 {
Chris@0 244 $constants = get_defined_constants(true);
Chris@0 245
Chris@0 246 if (isset($constants['user'])) {
Chris@0 247 $this->constants = $constants['user'];
Chris@0 248 }
Chris@0 249 }
Chris@0 250
Chris@0 251 /**
Chris@0 252 * Creates a snapshot user-defined functions.
Chris@0 253 */
Chris@0 254 private function snapshotFunctions()
Chris@0 255 {
Chris@0 256 $functions = get_defined_functions();
Chris@0 257
Chris@0 258 $this->functions = $functions['user'];
Chris@0 259 }
Chris@0 260
Chris@0 261 /**
Chris@0 262 * Creates a snapshot user-defined classes.
Chris@0 263 */
Chris@0 264 private function snapshotClasses()
Chris@0 265 {
Chris@0 266 foreach (array_reverse(get_declared_classes()) as $className) {
Chris@0 267 $class = new ReflectionClass($className);
Chris@0 268
Chris@0 269 if (!$class->isUserDefined()) {
Chris@0 270 break;
Chris@0 271 }
Chris@0 272
Chris@0 273 $this->classes[] = $className;
Chris@0 274 }
Chris@0 275
Chris@0 276 $this->classes = array_reverse($this->classes);
Chris@0 277 }
Chris@0 278
Chris@0 279 /**
Chris@0 280 * Creates a snapshot user-defined interfaces.
Chris@0 281 */
Chris@0 282 private function snapshotInterfaces()
Chris@0 283 {
Chris@0 284 foreach (array_reverse(get_declared_interfaces()) as $interfaceName) {
Chris@0 285 $class = new ReflectionClass($interfaceName);
Chris@0 286
Chris@0 287 if (!$class->isUserDefined()) {
Chris@0 288 break;
Chris@0 289 }
Chris@0 290
Chris@0 291 $this->interfaces[] = $interfaceName;
Chris@0 292 }
Chris@0 293
Chris@0 294 $this->interfaces = array_reverse($this->interfaces);
Chris@0 295 }
Chris@0 296
Chris@0 297 /**
Chris@0 298 * Creates a snapshot of all global and super-global variables.
Chris@0 299 */
Chris@0 300 private function snapshotGlobals()
Chris@0 301 {
Chris@0 302 $superGlobalArrays = $this->superGlobalArrays();
Chris@0 303
Chris@0 304 foreach ($superGlobalArrays as $superGlobalArray) {
Chris@0 305 $this->snapshotSuperGlobalArray($superGlobalArray);
Chris@0 306 }
Chris@0 307
Chris@0 308 foreach (array_keys($GLOBALS) as $key) {
Chris@0 309 if ($key != 'GLOBALS' &&
Chris@0 310 !in_array($key, $superGlobalArrays) &&
Chris@0 311 $this->canBeSerialized($GLOBALS[$key]) &&
Chris@0 312 !$this->blacklist->isGlobalVariableBlacklisted($key)) {
Chris@0 313 $this->globalVariables[$key] = unserialize(serialize($GLOBALS[$key]));
Chris@0 314 }
Chris@0 315 }
Chris@0 316 }
Chris@0 317
Chris@0 318 /**
Chris@0 319 * Creates a snapshot a super-global variable array.
Chris@0 320 *
Chris@0 321 * @param $superGlobalArray
Chris@0 322 */
Chris@0 323 private function snapshotSuperGlobalArray($superGlobalArray)
Chris@0 324 {
Chris@0 325 $this->superGlobalVariables[$superGlobalArray] = array();
Chris@0 326
Chris@0 327 if (isset($GLOBALS[$superGlobalArray]) && is_array($GLOBALS[$superGlobalArray])) {
Chris@0 328 foreach ($GLOBALS[$superGlobalArray] as $key => $value) {
Chris@0 329 $this->superGlobalVariables[$superGlobalArray][$key] = unserialize(serialize($value));
Chris@0 330 }
Chris@0 331 }
Chris@0 332 }
Chris@0 333
Chris@0 334 /**
Chris@0 335 * Creates a snapshot of all static attributes in user-defined classes.
Chris@0 336 */
Chris@0 337 private function snapshotStaticAttributes()
Chris@0 338 {
Chris@0 339 foreach ($this->classes as $className) {
Chris@0 340 $class = new ReflectionClass($className);
Chris@0 341 $snapshot = array();
Chris@0 342
Chris@0 343 foreach ($class->getProperties() as $attribute) {
Chris@0 344 if ($attribute->isStatic()) {
Chris@0 345 $name = $attribute->getName();
Chris@0 346
Chris@0 347 if ($this->blacklist->isStaticAttributeBlacklisted($className, $name)) {
Chris@0 348 continue;
Chris@0 349 }
Chris@0 350
Chris@0 351 $attribute->setAccessible(true);
Chris@0 352 $value = $attribute->getValue();
Chris@0 353
Chris@0 354 if ($this->canBeSerialized($value)) {
Chris@0 355 $snapshot[$name] = unserialize(serialize($value));
Chris@0 356 }
Chris@0 357 }
Chris@0 358 }
Chris@0 359
Chris@0 360 if (!empty($snapshot)) {
Chris@0 361 $this->staticAttributes[$className] = $snapshot;
Chris@0 362 }
Chris@0 363 }
Chris@0 364 }
Chris@0 365
Chris@0 366 /**
Chris@0 367 * Returns a list of all super-global variable arrays.
Chris@0 368 *
Chris@0 369 * @return array
Chris@0 370 */
Chris@0 371 private function setupSuperGlobalArrays()
Chris@0 372 {
Chris@0 373 $this->superGlobalArrays = array(
Chris@0 374 '_ENV',
Chris@0 375 '_POST',
Chris@0 376 '_GET',
Chris@0 377 '_COOKIE',
Chris@0 378 '_SERVER',
Chris@0 379 '_FILES',
Chris@0 380 '_REQUEST'
Chris@0 381 );
Chris@0 382
Chris@0 383 if (ini_get('register_long_arrays') == '1') {
Chris@0 384 $this->superGlobalArrays = array_merge(
Chris@0 385 $this->superGlobalArrays,
Chris@0 386 array(
Chris@0 387 'HTTP_ENV_VARS',
Chris@0 388 'HTTP_POST_VARS',
Chris@0 389 'HTTP_GET_VARS',
Chris@0 390 'HTTP_COOKIE_VARS',
Chris@0 391 'HTTP_SERVER_VARS',
Chris@0 392 'HTTP_POST_FILES'
Chris@0 393 )
Chris@0 394 );
Chris@0 395 }
Chris@0 396 }
Chris@0 397
Chris@0 398 /**
Chris@0 399 * @param mixed $variable
Chris@0 400 * @return bool
Chris@0 401 * @todo Implement this properly
Chris@0 402 */
Chris@0 403 private function canBeSerialized($variable)
Chris@0 404 {
Chris@0 405 if (!is_object($variable)) {
Chris@0 406 return !is_resource($variable);
Chris@0 407 }
Chris@0 408
Chris@0 409 if ($variable instanceof \stdClass) {
Chris@0 410 return true;
Chris@0 411 }
Chris@0 412
Chris@0 413 $class = new ReflectionClass($variable);
Chris@0 414
Chris@0 415 do {
Chris@0 416 if ($class->isInternal()) {
Chris@0 417 return $variable instanceof Serializable;
Chris@0 418 }
Chris@0 419 } while ($class = $class->getParentClass());
Chris@0 420
Chris@0 421 return true;
Chris@0 422 }
Chris@0 423 }