@@ -24,6 +24,11 @@ class ConfigurableObject implements InterpreterInterface
2424 */
2525 private $ classWhitelist = [];
2626
27+ /**
28+ * @var array
29+ */
30+ private $ deniedClassList = [];
31+
2732 /**
2833 * @var ObjectManagerInterface
2934 */
@@ -52,17 +57,20 @@ class ConfigurableObject implements InterpreterInterface
5257 * @param array $classWhitelist
5358 * @param ClassReader|null $classReader
5459 * @param ConfigInterface|null $objectManagerConfig
60+ * @param array $deniedClassList
5561 */
5662 public function __construct (
5763 ObjectManagerInterface $ objectManager ,
5864 InterpreterInterface $ argumentInterpreter ,
5965 array $ classWhitelist = [],
6066 ClassReader $ classReader = null ,
61- ConfigInterface $ objectManagerConfig = null
67+ ConfigInterface $ objectManagerConfig = null ,
68+ array $ deniedClassList = []
6269 ) {
6370 $ this ->objectManager = $ objectManager ;
6471 $ this ->argumentInterpreter = $ argumentInterpreter ;
6572 $ this ->classWhitelist = $ classWhitelist ;
73+ $ this ->deniedClassList = $ deniedClassList ;
6674 $ this ->classReader = $ classReader ?? $ objectManager ->get (ClassReader::class);
6775 $ this ->objectManagerConfig = $ objectManagerConfig ?? $ objectManager ->get (ConfigInterface::class);
6876 }
@@ -85,25 +93,12 @@ public function evaluate(array $data)
8593 if (!isset ($ arguments ['class ' ])) {
8694 throw new \InvalidArgumentException ('Node "argument" with name "class" is required for this type. ' );
8795 }
88-
8996 $ className = $ arguments ['class ' ];
9097 unset($ arguments ['class ' ]);
91-
92- $ type = $ this ->objectManagerConfig ->getInstanceType (
93- $ this ->objectManagerConfig ->getPreference ($ className )
94- );
95-
96- $ classParents = $ this ->getParents ($ type );
97-
98- $ whitelistIntersection = array_intersect ($ classParents , $ this ->classWhitelist );
99-
100- if (empty ($ whitelistIntersection )) {
101- throw new \InvalidArgumentException (
102- sprintf ('Class argument is invalid: %s ' , $ className )
103- );
104- }
10598 }
10699
100+ $ this ->isValid ($ className );
101+
107102 return $ this ->objectManager ->create ($ className , $ arguments );
108103 }
109104
@@ -115,7 +110,7 @@ public function evaluate(array $data)
115110 */
116111 private function getParents (string $ type )
117112 {
118- $ classParents = $ this ->classReader ->getParents ($ type );
113+ $ classParents = $ this ->classReader ->getParents ($ type ) ?? [] ;
119114 foreach ($ classParents as $ parent ) {
120115 if (empty ($ parent )) {
121116 continue ;
@@ -125,4 +120,30 @@ private function getParents(string $type)
125120
126121 return $ classParents ;
127122 }
123+
124+ /**
125+ * Check that provided class could be evaluated like an argument.
126+ *
127+ * @param string $className
128+ * @throws \InvalidArgumentException
129+ */
130+ private function isValid (string $ className ): void
131+ {
132+ $ type = $ this ->objectManagerConfig ->getInstanceType (
133+ $ this ->objectManagerConfig ->getPreference ($ className )
134+ );
135+
136+ $ classParents = $ this ->getParents ($ type );
137+
138+ if (!empty ($ classParents )) {
139+ $ whitelistIntersection = array_intersect ($ classParents , $ this ->classWhitelist );
140+ $ deniedIntersection = array_intersect ($ classParents , $ this ->deniedClassList );
141+
142+ if (empty ($ whitelistIntersection ) || !empty ($ deniedIntersection )) {
143+ throw new \InvalidArgumentException (
144+ sprintf ('Class argument is invalid: %s ' , $ className )
145+ );
146+ }
147+ }
148+ }
128149}
0 commit comments