3 * This file is part of the GlobalState package.
5 * (c) Sebastian Bergmann <sebastian@phpunit.de>
7 * For the full copyright and license information, please view the LICENSE
8 * file that was distributed with this source code.
11 namespace SebastianBergmann\GlobalState;
17 * A snapshot of global state.
29 private $globalVariables = array();
34 private $superGlobalArrays = array();
39 private $superGlobalVariables = array();
44 private $staticAttributes = array();
49 private $iniSettings = array();
54 private $includedFiles = array();
59 private $constants = array();
64 private $functions = array();
69 private $interfaces = array();
74 private $classes = array();
79 private $traits = array();
82 * Creates a snapshot of the current global state.
84 * @param Blacklist $blacklist
85 * @param bool $includeGlobalVariables
86 * @param bool $includeStaticAttributes
87 * @param bool $includeConstants
88 * @param bool $includeFunctions
89 * @param bool $includeClasses
90 * @param bool $includeInterfaces
91 * @param bool $includeTraits
92 * @param bool $includeIniSettings
93 * @param bool $includeIncludedFiles
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)
97 if ($blacklist === null) {
98 $blacklist = new Blacklist;
101 $this->blacklist = $blacklist;
103 if ($includeConstants) {
104 $this->snapshotConstants();
107 if ($includeFunctions) {
108 $this->snapshotFunctions();
111 if ($includeClasses || $includeStaticAttributes) {
112 $this->snapshotClasses();
115 if ($includeInterfaces) {
116 $this->snapshotInterfaces();
119 if ($includeGlobalVariables) {
120 $this->setupSuperGlobalArrays();
121 $this->snapshotGlobals();
124 if ($includeStaticAttributes) {
125 $this->snapshotStaticAttributes();
128 if ($includeIniSettings) {
129 $this->iniSettings = ini_get_all(null, false);
132 if ($includeIncludedFiles) {
133 $this->includedFiles = get_included_files();
136 if (function_exists('get_declared_traits')) {
137 $this->traits = get_declared_traits();
144 public function blacklist()
146 return $this->blacklist;
152 public function globalVariables()
154 return $this->globalVariables;
160 public function superGlobalVariables()
162 return $this->superGlobalVariables;
166 * Returns a list of all super-global variable arrays.
170 public function superGlobalArrays()
172 return $this->superGlobalArrays;
178 public function staticAttributes()
180 return $this->staticAttributes;
186 public function iniSettings()
188 return $this->iniSettings;
194 public function includedFiles()
196 return $this->includedFiles;
202 public function constants()
204 return $this->constants;
210 public function functions()
212 return $this->functions;
218 public function interfaces()
220 return $this->interfaces;
226 public function classes()
228 return $this->classes;
234 public function traits()
236 return $this->traits;
240 * Creates a snapshot user-defined constants.
242 private function snapshotConstants()
244 $constants = get_defined_constants(true);
246 if (isset($constants['user'])) {
247 $this->constants = $constants['user'];
252 * Creates a snapshot user-defined functions.
254 private function snapshotFunctions()
256 $functions = get_defined_functions();
258 $this->functions = $functions['user'];
262 * Creates a snapshot user-defined classes.
264 private function snapshotClasses()
266 foreach (array_reverse(get_declared_classes()) as $className) {
267 $class = new ReflectionClass($className);
269 if (!$class->isUserDefined()) {
273 $this->classes[] = $className;
276 $this->classes = array_reverse($this->classes);
280 * Creates a snapshot user-defined interfaces.
282 private function snapshotInterfaces()
284 foreach (array_reverse(get_declared_interfaces()) as $interfaceName) {
285 $class = new ReflectionClass($interfaceName);
287 if (!$class->isUserDefined()) {
291 $this->interfaces[] = $interfaceName;
294 $this->interfaces = array_reverse($this->interfaces);
298 * Creates a snapshot of all global and super-global variables.
300 private function snapshotGlobals()
302 $superGlobalArrays = $this->superGlobalArrays();
304 foreach ($superGlobalArrays as $superGlobalArray) {
305 $this->snapshotSuperGlobalArray($superGlobalArray);
308 foreach (array_keys($GLOBALS) as $key) {
309 if ($key != 'GLOBALS' &&
310 !in_array($key, $superGlobalArrays) &&
311 $this->canBeSerialized($GLOBALS[$key]) &&
312 !$this->blacklist->isGlobalVariableBlacklisted($key)) {
313 $this->globalVariables[$key] = unserialize(serialize($GLOBALS[$key]));
319 * Creates a snapshot a super-global variable array.
321 * @param $superGlobalArray
323 private function snapshotSuperGlobalArray($superGlobalArray)
325 $this->superGlobalVariables[$superGlobalArray] = array();
327 if (isset($GLOBALS[$superGlobalArray]) && is_array($GLOBALS[$superGlobalArray])) {
328 foreach ($GLOBALS[$superGlobalArray] as $key => $value) {
329 $this->superGlobalVariables[$superGlobalArray][$key] = unserialize(serialize($value));
335 * Creates a snapshot of all static attributes in user-defined classes.
337 private function snapshotStaticAttributes()
339 foreach ($this->classes as $className) {
340 $class = new ReflectionClass($className);
343 foreach ($class->getProperties() as $attribute) {
344 if ($attribute->isStatic()) {
345 $name = $attribute->getName();
347 if ($this->blacklist->isStaticAttributeBlacklisted($className, $name)) {
351 $attribute->setAccessible(true);
352 $value = $attribute->getValue();
354 if ($this->canBeSerialized($value)) {
355 $snapshot[$name] = unserialize(serialize($value));
360 if (!empty($snapshot)) {
361 $this->staticAttributes[$className] = $snapshot;
367 * Returns a list of all super-global variable arrays.
371 private function setupSuperGlobalArrays()
373 $this->superGlobalArrays = array(
383 if (ini_get('register_long_arrays') == '1') {
384 $this->superGlobalArrays = array_merge(
385 $this->superGlobalArrays,
399 * @param mixed $variable
401 * @todo Implement this properly
403 private function canBeSerialized($variable)
405 if (!is_object($variable)) {
406 return !is_resource($variable);
409 if ($variable instanceof \stdClass) {
413 $class = new ReflectionClass($variable);
416 if ($class->isInternal()) {
417 return $variable instanceof Serializable;
419 } while ($class = $class->getParentClass());