1<?php
2/*
3 * This file is part of the GlobalState package.
4 *
5 * (c) Sebastian Bergmann <sebastian@phpunit.de>
6 *
7 * For the full copyright and license information, please view the LICENSE
8 * file that was distributed with this source code.
9 */
10
11namespace SebastianBergmann\GlobalState;
12
13use ReflectionClass;
14
15/**
16 * A blacklist for global state elements that should not be snapshotted.
17 */
18class Blacklist
19{
20    /**
21     * @var array
22     */
23    private $globalVariables = array();
24
25    /**
26     * @var array
27     */
28    private $classes = array();
29
30    /**
31     * @var array
32     */
33    private $classNamePrefixes = array();
34
35    /**
36     * @var array
37     */
38    private $parentClasses = array();
39
40    /**
41     * @var array
42     */
43    private $interfaces = array();
44
45    /**
46     * @var array
47     */
48    private $staticAttributes = array();
49
50    /**
51     * @param string $variableName
52     */
53    public function addGlobalVariable($variableName)
54    {
55        $this->globalVariables[$variableName] = true;
56    }
57
58    /**
59     * @param string $className
60     */
61    public function addClass($className)
62    {
63        $this->classes[] = $className;
64    }
65
66    /**
67     * @param string $className
68     */
69    public function addSubclassesOf($className)
70    {
71        $this->parentClasses[] = $className;
72    }
73
74    /**
75     * @param string $interfaceName
76     */
77    public function addImplementorsOf($interfaceName)
78    {
79        $this->interfaces[] = $interfaceName;
80    }
81
82    /**
83     * @param string $classNamePrefix
84     */
85    public function addClassNamePrefix($classNamePrefix)
86    {
87        $this->classNamePrefixes[] = $classNamePrefix;
88    }
89
90    /**
91     * @param string $className
92     * @param string $attributeName
93     */
94    public function addStaticAttribute($className, $attributeName)
95    {
96        if (!isset($this->staticAttributes[$className])) {
97            $this->staticAttributes[$className] = array();
98        }
99
100        $this->staticAttributes[$className][$attributeName] = true;
101    }
102
103    /**
104     * @param  string $variableName
105     * @return bool
106     */
107    public function isGlobalVariableBlacklisted($variableName)
108    {
109        return isset($this->globalVariables[$variableName]);
110    }
111
112    /**
113     * @param  string $className
114     * @param  string $attributeName
115     * @return bool
116     */
117    public function isStaticAttributeBlacklisted($className, $attributeName)
118    {
119        if (in_array($className, $this->classes)) {
120            return true;
121        }
122
123        foreach ($this->classNamePrefixes as $prefix) {
124            if (strpos($className, $prefix) === 0) {
125                return true;
126            }
127        }
128
129        $class = new ReflectionClass($className);
130
131        foreach ($this->parentClasses as $type) {
132            if ($class->isSubclassOf($type)) {
133                return true;
134            }
135        }
136
137        foreach ($this->interfaces as $type) {
138            if ($class->implementsInterface($type)) {
139                return true;
140            }
141        }
142
143        if (isset($this->staticAttributes[$className][$attributeName])) {
144            return true;
145        }
146
147        return false;
148    }
149}
150