2424use Neos \Flow \ObjectManagement \Exception \InvalidObjectConfigurationException ;
2525use Neos \Flow \ObjectManagement \Exception \UnknownObjectException ;
2626use Neos \Flow \ObjectManagement \Exception \WrongScopeException ;
27+ use Neos \Flow \Package ;
2728use Neos \Flow \Package \FlowPackageInterface ;
2829use Neos \Flow \Package \PackageInterface ;
30+ use Neos \Flow \Package \PackageKeyAwareInterface ;
2931use Neos \Flow \Reflection \ReflectionService ;
3032use Psr \Log \LoggerInterface ;
3133
3436 * singleton scoped objects. This Object Manager is used during compile time when the proxy
3537 * class based DI mechanism is not yet available.
3638 *
39+ * @template ObjectRecordInstance of object
40+ * @extends ObjectManager<ObjectRecordInstance>
41+ * @phpstan-type CompileTimeObjectRecordShape array{
42+ * l: string,
43+ * s: int,
44+ * p: string,
45+ * c?: class-string,
46+ * ca?: array<int, null|array{t:int, v:mixed, wm:int}>,
47+ * f?: array{string, string},
48+ * fa?: array<int, null|array{t:int, v:mixed}>
49+ * }
3750 * @Flow\Scope("singleton")
3851 * @Flow\Proxy(false)
3952 */
@@ -60,24 +73,24 @@ class CompileTimeObjectManager extends ObjectManager
6073 protected ?LoggerInterface $ logger ;
6174
6275 /**
63- * @var array
76+ * @var array<class-string,Configuration>
6477 */
6578 protected array $ objectConfigurations = [];
6679
6780 /**
6881 * A list of all class names known to the Object Manager
6982 *
70- * @var array
83+ * @var array<string,array<int,class-string>>
7184 */
7285 protected array $ registeredClassNames = [];
7386
7487 /**
75- * @var array
88+ * @var array<string>
7689 */
7790 protected array $ objectNameBuildStack = [];
7891
7992 /**
80- * @var array
93+ * @var array<int,array<int,class-string>>
8194 */
8295 protected array $ cachedClassNamesByScope = [];
8396
@@ -124,18 +137,47 @@ public function injectLogger(LoggerInterface $logger): void
124137 /**
125138 * Initializes the object configurations and some other parts of this Object Manager.
126139 *
127- * @param PackageInterface[] $packages An array of active packages to consider
140+ * @param array<string, PackageInterface&PackageKeyAwareInterface> $packages An array of active packages to consider
128141 * @return void
129142 * @throws InvalidConfigurationTypeException
130143 * @throws InvalidObjectConfigurationException
131144 * @throws CacheException
132145 */
133146 public function initialize (array $ packages ): void
134147 {
148+ if ($ this ->reflectionService === null || $ this ->configurationManager === null || $ this ->logger === null ) {
149+ $ missingDependencies = [];
150+ if ($ this ->reflectionService === null ) {
151+ $ missingDependencies [] = 'reflectionService ' ;
152+ }
153+ if ($ this ->configurationManager === null ) {
154+ $ missingDependencies [] = 'configurationManager ' ;
155+ }
156+ if ($ this ->logger === null ) {
157+ $ missingDependencies [] = 'logger ' ;
158+ }
159+ throw new \Exception (sprintf ('%s is missing dependencies: %s ' , self ::class, implode (', ' , $ missingDependencies )), 1784221618 );
160+ }
135161 $ this ->registeredClassNames = $ this ->registerClassFiles ($ packages );
136162 $ this ->reflectionService ->buildReflectionData ($ this ->registeredClassNames );
137163
138- $ rawCustomObjectConfigurations = $ this ->configurationManager ->getConfiguration (ConfigurationManager::CONFIGURATION_TYPE_OBJECTS );
164+ /**
165+ * @var array<string,array<string,array{
166+ * className?: class-string,
167+ * scope?: string,
168+ * factoryObjectName?: class-string,
169+ * factoryMethodName?: string,
170+ * arguments?: array<mixed>,
171+ * properties?: array<string,array{
172+ * object?: class-string|array{
173+ * factoryObjectName: class-string,
174+ * factoryMethodName?: string,
175+ * arguments?: array<mixed>
176+ * }
177+ * }>,
178+ * }>> $rawCustomObjectConfigurations
179+ */
180+ $ rawCustomObjectConfigurations = $ this ->configurationManager ->getConfiguration (ConfigurationManager::CONFIGURATION_TYPE_OBJECTS ) ?: [];
139181
140182 $ configurationBuilder = new ConfigurationBuilder (
141183 $ this ->reflectionService ,
@@ -174,7 +216,7 @@ public function setInstance($objectName, $instance): void
174216 /**
175217 * Returns a list of all class names, grouped by package key, which were registered by registerClassFiles()
176218 *
177- * @return array
219+ * @return array<string,array<int,class-string>>
178220 */
179221 public function getRegisteredClassNames (): array
180222 {
@@ -185,7 +227,7 @@ public function getRegisteredClassNames(): array
185227 * Returns a list of class names, which are configured with the given scope
186228 *
187229 * @param integer $scope One of the ObjectConfiguration::SCOPE_ constants
188- * @return array An array of class names configured with the given scope
230+ * @return array<int,class-string> An array of class names configured with the given scope
189231 */
190232 public function getClassNamesByScope (int $ scope ): array
191233 {
@@ -194,7 +236,7 @@ public function getClassNamesByScope(int $scope): array
194236 if ($ information [self ::KEY_SCOPE ] === $ scope ) {
195237 if (isset ($ information [self ::KEY_CLASS_NAME ])) {
196238 $ this ->cachedClassNamesByScope [$ scope ][] = $ information [self ::KEY_CLASS_NAME ];
197- } else {
239+ } elseif ( is_string ( $ objectName ) && class_exists ( $ objectName )) {
198240 $ this ->cachedClassNamesByScope [$ scope ][] = $ objectName ;
199241 }
200242 }
@@ -210,14 +252,14 @@ public function getClassNamesByScope(int $scope): array
210252 *
211253 * For performance reasons this function ignores classes whose name ends with "Exception".
212254 *
213- * @param array $packages A list of packages to consider
214- * @return array A list of class names which were discovered in the given packages
255+ * @param array<string, PackageInterface&PackageKeyAwareInterface> $packages A list of packages to consider
256+ * @return array<string, array<class-string>> A list of class names which were discovered in the given packages
215257 *
216258 * @throws InvalidConfigurationTypeException
217259 */
218260 protected function registerClassFiles (array $ packages ): array
219261 {
220- $ allSettings = $ this ->configurationManager ->getConfiguration (ConfigurationManager::CONFIGURATION_TYPE_SETTINGS );
262+ $ allSettings = $ this ->configurationManager ? ->getConfiguration(ConfigurationManager::CONFIGURATION_TYPE_SETTINGS ) ?? [] ;
221263 $ includeClassesConfiguration = [];
222264 if (isset ($ allSettings ['Neos ' ]['Flow ' ]['object ' ]['includeClasses ' ])) {
223265 if (!is_array ($ allSettings ['Neos ' ]['Flow ' ]['object ' ]['includeClasses ' ])) {
@@ -246,7 +288,7 @@ protected function registerClassFiles(array $packages): array
246288 }
247289 }
248290 }
249- if (isset ($ availableClassNames [$ packageKey ]) && is_array ( $ availableClassNames [ $ packageKey ]) ) {
291+ if (isset ($ availableClassNames [$ packageKey ])) {
250292 $ availableClassNames [$ packageKey ] = array_unique ($ availableClassNames [$ packageKey ]);
251293 }
252294 }
@@ -258,9 +300,9 @@ protected function registerClassFiles(array $packages): array
258300 * Given an array of class names by package key this filters out classes that
259301 * have been configured to be included by object management.
260302 *
261- * @param array $classNames 2-level array - key of first level is package key, value of second level is classname (FQN)
262- * @param array $includeClassesConfiguration array of includeClasses configurations
263- * @return array The input array with all configured to be included in object management added in
303+ * @param array<string, array<class-string>> $classNames 2-level array - key of first level is package key, value of second level is classname (FQN)
304+ * @param array<string, array<string>> $includeClassesConfiguration array of includeClasses configurations
305+ * @return array<string, array<class-string>> The input array with all configured to be included in object management added in
264306 * @throws InvalidConfigurationTypeException
265307 */
266308 protected function filterClassNamesFromConfiguration (array $ classNames , array $ includeClassesConfiguration ): array
@@ -271,16 +313,16 @@ protected function filterClassNamesFromConfiguration(array $classNames, array $i
271313 /**
272314 * Filters the classnames available for object management by filter expressions that includes classes.
273315 *
274- * @param array $classNames All classnames per package
275- * @param array $filterConfiguration The filter configuration to apply
276- * @return array the remaining class
316+ * @param array<string, array<class-string>> $classNames All classnames per package
317+ * @param array<string, array<string>> $filterConfiguration The filter configuration to apply
318+ * @return array<string, array<class-string>> the remaining class
277319 * @throws InvalidConfigurationTypeException
278320 */
279321 protected function applyClassFilterConfiguration (array $ classNames , array $ filterConfiguration ): array
280322 {
281323 foreach ($ filterConfiguration as $ packageKey => $ filterExpressions ) {
282324 if (!array_key_exists ($ packageKey , $ classNames )) {
283- $ this ->logger ->debug ('The package " ' . $ packageKey . '" specified in the setting "Neos.Flow.object.includeClasses" was either excluded or is not loaded. ' );
325+ $ this ->logger ? ->debug('The package " ' . $ packageKey . '" specified in the setting "Neos.Flow.object.includeClasses" was either excluded or is not loaded. ' );
284326 continue ;
285327 }
286328 if (!is_array ($ filterExpressions )) {
@@ -314,7 +356,7 @@ static function ($className) use ($filterExpression) {
314356 * Builds the objects array which contains information about the registered objects,
315357 * their scope, class, built method etc.
316358 *
317- * @return array
359+ * @return array<string, CompileTimeObjectRecordShape>
318360 * @throws CacheException
319361 */
320362 protected function buildObjectsArray (): array
@@ -341,10 +383,15 @@ protected function buildObjectsArray(): array
341383 $ factoryMethodArguments = $ objectConfiguration ->getFactoryArguments ();
342384 if (count ($ factoryMethodArguments ) > 0 ) {
343385 foreach ($ factoryMethodArguments as $ index => $ argument ) {
344- $ objects [$ objectName ][self ::KEY_FACTORY_ARGUMENTS ][$ index ] = [
345- self ::KEY_ARGUMENT_TYPE => $ argument ->getType (),
346- self ::KEY_ARGUMENT_VALUE => $ argument ->getValue ()
347- ];
386+ if ($ argument === null ) {
387+ $ objects [$ objectName ][self ::KEY_FACTORY_ARGUMENTS ][$ index ] = null ;
388+ continue ;
389+ } else {
390+ $ objects [$ objectName ][self ::KEY_FACTORY_ARGUMENTS ][$ index ] = [
391+ self ::KEY_ARGUMENT_TYPE => $ argument ->getType (),
392+ self ::KEY_ARGUMENT_VALUE => $ argument ->getValue ()
393+ ];
394+ }
348395 }
349396 }
350397 }
@@ -363,14 +410,14 @@ protected function buildObjectsArray(): array
363410 }
364411 }
365412 }
366- $ this ->configurationCache ->set ('objects ' , $ objects );
413+ $ this ->configurationCache ? ->set('objects ' , $ objects );
367414 return $ objects ;
368415 }
369416
370417 /**
371418 * Returns object configurations which were previously built by the ConfigurationBuilder.
372419 *
373- * @return array
420+ * @return array<class-string, Configuration>
374421 */
375422 public function getObjectConfigurations (): array
376423 {
@@ -422,7 +469,7 @@ public function get($objectName, ...$constructorArguments): object
422469 break ;
423470 case Property::PROPERTY_TYPES_CONFIGURATION :
424471 $ propertyValue = $ property ->getValue ();
425- $ value = $ this ->configurationManager ->getConfiguration ($ propertyValue ['type ' ], $ propertyValue ['path ' ]);
472+ $ value = $ this ->configurationManager ? ->getConfiguration($ propertyValue ['type ' ], $ propertyValue ['path ' ]);
426473 break ;
427474 case Property::PROPERTY_TYPES_OBJECT :
428475 $ propertyObjectName = $ property ->getValue ();
0 commit comments