Chris@0
|
1 <?php
|
Chris@0
|
2 /*
|
Chris@14
|
3 * This file is part of sebastian/global-state.
|
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@14
|
11 declare(strict_types=1);
|
Chris@14
|
12
|
Chris@0
|
13 namespace SebastianBergmann\GlobalState;
|
Chris@0
|
14
|
Chris@0
|
15 use ReflectionProperty;
|
Chris@0
|
16
|
Chris@0
|
17 /**
|
Chris@0
|
18 * Restorer of snapshots of global state.
|
Chris@0
|
19 */
|
Chris@0
|
20 class Restorer
|
Chris@0
|
21 {
|
Chris@0
|
22 /**
|
Chris@0
|
23 * Deletes function definitions that are not defined in a snapshot.
|
Chris@0
|
24 *
|
Chris@0
|
25 * @throws RuntimeException when the uopz_delete() function is not available
|
Chris@14
|
26 *
|
Chris@0
|
27 * @see https://github.com/krakjoe/uopz
|
Chris@0
|
28 */
|
Chris@0
|
29 public function restoreFunctions(Snapshot $snapshot)
|
Chris@0
|
30 {
|
Chris@14
|
31 if (!\function_exists('uopz_delete')) {
|
Chris@0
|
32 throw new RuntimeException('The uopz_delete() function is required for this operation');
|
Chris@0
|
33 }
|
Chris@0
|
34
|
Chris@14
|
35 $functions = \get_defined_functions();
|
Chris@0
|
36
|
Chris@14
|
37 foreach (\array_diff($functions['user'], $snapshot->functions()) as $function) {
|
Chris@0
|
38 uopz_delete($function);
|
Chris@0
|
39 }
|
Chris@0
|
40 }
|
Chris@0
|
41
|
Chris@0
|
42 /**
|
Chris@0
|
43 * Restores all global and super-global variables from a snapshot.
|
Chris@0
|
44 */
|
Chris@0
|
45 public function restoreGlobalVariables(Snapshot $snapshot)
|
Chris@0
|
46 {
|
Chris@0
|
47 $superGlobalArrays = $snapshot->superGlobalArrays();
|
Chris@0
|
48
|
Chris@0
|
49 foreach ($superGlobalArrays as $superGlobalArray) {
|
Chris@0
|
50 $this->restoreSuperGlobalArray($snapshot, $superGlobalArray);
|
Chris@0
|
51 }
|
Chris@0
|
52
|
Chris@0
|
53 $globalVariables = $snapshot->globalVariables();
|
Chris@0
|
54
|
Chris@14
|
55 foreach (\array_keys($GLOBALS) as $key) {
|
Chris@0
|
56 if ($key != 'GLOBALS' &&
|
Chris@14
|
57 !\in_array($key, $superGlobalArrays) &&
|
Chris@0
|
58 !$snapshot->blacklist()->isGlobalVariableBlacklisted($key)) {
|
Chris@14
|
59 if (\array_key_exists($key, $globalVariables)) {
|
Chris@0
|
60 $GLOBALS[$key] = $globalVariables[$key];
|
Chris@0
|
61 } else {
|
Chris@0
|
62 unset($GLOBALS[$key]);
|
Chris@0
|
63 }
|
Chris@0
|
64 }
|
Chris@0
|
65 }
|
Chris@0
|
66 }
|
Chris@0
|
67
|
Chris@0
|
68 /**
|
Chris@0
|
69 * Restores all static attributes in user-defined classes from this snapshot.
|
Chris@0
|
70 */
|
Chris@0
|
71 public function restoreStaticAttributes(Snapshot $snapshot)
|
Chris@0
|
72 {
|
Chris@0
|
73 $current = new Snapshot($snapshot->blacklist(), false, false, false, false, true, false, false, false, false);
|
Chris@14
|
74 $newClasses = \array_diff($current->classes(), $snapshot->classes());
|
Chris@14
|
75
|
Chris@0
|
76 unset($current);
|
Chris@0
|
77
|
Chris@0
|
78 foreach ($snapshot->staticAttributes() as $className => $staticAttributes) {
|
Chris@0
|
79 foreach ($staticAttributes as $name => $value) {
|
Chris@0
|
80 $reflector = new ReflectionProperty($className, $name);
|
Chris@0
|
81 $reflector->setAccessible(true);
|
Chris@0
|
82 $reflector->setValue($value);
|
Chris@0
|
83 }
|
Chris@0
|
84 }
|
Chris@0
|
85
|
Chris@0
|
86 foreach ($newClasses as $className) {
|
Chris@0
|
87 $class = new \ReflectionClass($className);
|
Chris@0
|
88 $defaults = $class->getDefaultProperties();
|
Chris@0
|
89
|
Chris@0
|
90 foreach ($class->getProperties() as $attribute) {
|
Chris@0
|
91 if (!$attribute->isStatic()) {
|
Chris@0
|
92 continue;
|
Chris@0
|
93 }
|
Chris@0
|
94
|
Chris@0
|
95 $name = $attribute->getName();
|
Chris@0
|
96
|
Chris@0
|
97 if ($snapshot->blacklist()->isStaticAttributeBlacklisted($className, $name)) {
|
Chris@0
|
98 continue;
|
Chris@0
|
99 }
|
Chris@0
|
100
|
Chris@0
|
101 if (!isset($defaults[$name])) {
|
Chris@0
|
102 continue;
|
Chris@0
|
103 }
|
Chris@0
|
104
|
Chris@0
|
105 $attribute->setAccessible(true);
|
Chris@0
|
106 $attribute->setValue($defaults[$name]);
|
Chris@0
|
107 }
|
Chris@0
|
108 }
|
Chris@0
|
109 }
|
Chris@0
|
110
|
Chris@0
|
111 /**
|
Chris@0
|
112 * Restores a super-global variable array from this snapshot.
|
Chris@0
|
113 */
|
Chris@14
|
114 private function restoreSuperGlobalArray(Snapshot $snapshot, string $superGlobalArray)
|
Chris@0
|
115 {
|
Chris@0
|
116 $superGlobalVariables = $snapshot->superGlobalVariables();
|
Chris@0
|
117
|
Chris@0
|
118 if (isset($GLOBALS[$superGlobalArray]) &&
|
Chris@14
|
119 \is_array($GLOBALS[$superGlobalArray]) &&
|
Chris@0
|
120 isset($superGlobalVariables[$superGlobalArray])) {
|
Chris@14
|
121 $keys = \array_keys(
|
Chris@14
|
122 \array_merge(
|
Chris@0
|
123 $GLOBALS[$superGlobalArray],
|
Chris@0
|
124 $superGlobalVariables[$superGlobalArray]
|
Chris@0
|
125 )
|
Chris@0
|
126 );
|
Chris@0
|
127
|
Chris@0
|
128 foreach ($keys as $key) {
|
Chris@0
|
129 if (isset($superGlobalVariables[$superGlobalArray][$key])) {
|
Chris@0
|
130 $GLOBALS[$superGlobalArray][$key] = $superGlobalVariables[$superGlobalArray][$key];
|
Chris@0
|
131 } else {
|
Chris@0
|
132 unset($GLOBALS[$superGlobalArray][$key]);
|
Chris@0
|
133 }
|
Chris@0
|
134 }
|
Chris@0
|
135 }
|
Chris@0
|
136 }
|
Chris@0
|
137 }
|