Total Complexity | 71 |
Total Lines | 465 |
Duplicated Lines | 0 % |
Changes | 1 | ||
Bugs | 0 | Features | 0 |
Complex classes like Apie often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use Apie, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
51 | final class Apie implements SerializerProviderInterface, |
||
52 | ResourceProviderInterface, |
||
53 | NormalizerProviderInterface, |
||
54 | EncoderProviderInterface, |
||
55 | SymfonyComponentProviderInterface, |
||
56 | CacheItemPoolProviderInterface, |
||
57 | AnnotationReaderProviderInterface, |
||
58 | ApiResourceFactoryProviderInterface, |
||
59 | OpenApiInfoProviderInterface, |
||
60 | ApieConfigInterface, |
||
61 | SchemaProviderInterface, |
||
62 | OpenApiEventProviderInterface, |
||
63 | PropertyInfoExtractorProviderInterface |
||
|
|||
64 | { |
||
65 | const VERSION = "3.0"; |
||
66 | |||
67 | /** |
||
68 | * @var bool |
||
69 | */ |
||
70 | private $debug; |
||
71 | |||
72 | /** |
||
73 | * @var string|null |
||
74 | */ |
||
75 | private $cacheFolder; |
||
76 | |||
77 | /** |
||
78 | * @var SerializerProviderInterface[] |
||
79 | */ |
||
80 | private $serializers = []; |
||
81 | |||
82 | /** |
||
83 | * @var ResourceProviderInterface[] |
||
84 | */ |
||
85 | private $resources = []; |
||
86 | |||
87 | /** |
||
88 | * @var NormalizerProviderInterface[] |
||
89 | */ |
||
90 | private $normalizers = []; |
||
91 | |||
92 | /** |
||
93 | * @var EncoderProviderInterface[] |
||
94 | */ |
||
95 | private $encoders = []; |
||
96 | |||
97 | /** |
||
98 | * @var SymfonyComponentProviderInterface[] |
||
99 | */ |
||
100 | private $symfonyComponents = []; |
||
101 | |||
102 | /** |
||
103 | * @var CacheItemPoolProviderInterface[] |
||
104 | */ |
||
105 | private $cacheItemPools = []; |
||
106 | |||
107 | /** |
||
108 | * @var object[] |
||
109 | */ |
||
110 | private $plugins = []; |
||
111 | |||
112 | /** |
||
113 | * @var AnnotationReaderProviderInterface[] |
||
114 | */ |
||
115 | private $annotationReaders = []; |
||
116 | |||
117 | /** |
||
118 | * @var ApiResourceFactoryProviderInterface[] |
||
119 | */ |
||
120 | private $apiResourceFactories = []; |
||
121 | |||
122 | /** |
||
123 | * @var OpenApiInfoProviderInterface[] |
||
124 | */ |
||
125 | private $openApiInfoProviders = []; |
||
126 | |||
127 | /** |
||
128 | * @var ApieConfigInterface[] |
||
129 | */ |
||
130 | private $configs = []; |
||
131 | |||
132 | /** |
||
133 | * @var SchemaProviderInterface[] |
||
134 | */ |
||
135 | private $schemaDefinitions = []; |
||
136 | |||
137 | /** |
||
138 | * @var ApieCore |
||
139 | */ |
||
140 | private $apieCore; |
||
141 | |||
142 | /** |
||
143 | * @var ChainableFactory|null |
||
144 | */ |
||
145 | private $chainableFactory; |
||
146 | |||
147 | /** |
||
148 | * @var ChainableFormatRetriever|null |
||
149 | */ |
||
150 | private $chainableFormatRetriever; |
||
151 | |||
152 | /** |
||
153 | * @var OpenApiEventProviderInterface[] |
||
154 | */ |
||
155 | private $openApiEventProviders = []; |
||
156 | |||
157 | /** |
||
158 | * @var ObjectAccessProviderInterface[] |
||
159 | */ |
||
160 | private $objectAccesses = []; |
||
161 | |||
162 | /** |
||
163 | * @var PropertyInfoExtractorProviderInterface[] |
||
164 | */ |
||
165 | private $propertyInfoExtractors = []; |
||
166 | |||
167 | /** |
||
168 | |||
169 | * @param object[] $plugins |
||
170 | * @param bool $debug |
||
171 | * @param string|null $cacheFolder |
||
172 | * @param bool $addCorePlugin |
||
173 | */ |
||
174 | public function __construct(array $plugins, bool $debug = false, ?string $cacheFolder = null, bool $addCorePlugin = true) |
||
175 | { |
||
176 | $this->debug = $debug; |
||
177 | $this->cacheFolder = $cacheFolder; |
||
178 | static $mapping = [ |
||
179 | SerializerProviderInterface::class => 'serializers', |
||
180 | ResourceProviderInterface::class => 'resources', |
||
181 | NormalizerProviderInterface::class => 'normalizers', |
||
182 | EncoderProviderInterface::class => 'encoders', |
||
183 | SymfonyComponentProviderInterface::class => 'symfonyComponents', |
||
184 | CacheItemPoolProviderInterface::class => 'cacheItemPools', |
||
185 | AnnotationReaderProviderInterface::class => 'annotationReaders', |
||
186 | ApiResourceFactoryProviderInterface::class => 'apiResourceFactories', |
||
187 | OpenApiInfoProviderInterface::class => 'openApiInfoProviders', |
||
188 | ApieConfigInterface::class => 'configs', |
||
189 | SchemaProviderInterface::class => 'schemaDefinitions', |
||
190 | OpenApiEventProviderInterface::class => 'openApiEventProviders', |
||
191 | ObjectAccessProviderInterface::class => 'objectAccesses', |
||
192 | PropertyInfoExtractorProviderInterface::class => 'propertyInfoExtractors', |
||
193 | ]; |
||
194 | if ($addCorePlugin) { |
||
195 | $plugins[] = new CorePlugin(); |
||
196 | } |
||
197 | $this->plugins = $plugins; |
||
198 | foreach ($plugins as $plugin) { |
||
199 | $isUsed = false; |
||
200 | foreach ($mapping as $className => $propertyName) { |
||
201 | if ($plugin instanceof $className) { |
||
202 | $this->$propertyName[] = $plugin; |
||
203 | if (!$isUsed && $plugin instanceof ApieAwareInterface) { |
||
204 | $plugin->setApie($this); |
||
205 | } |
||
206 | $isUsed = true; |
||
207 | } |
||
208 | } |
||
209 | if (!$isUsed) { |
||
210 | throw new NotAnApiePluginException($plugin); |
||
211 | } |
||
212 | } |
||
213 | $this->apieCore = new ApieCore($this); |
||
214 | } |
||
215 | |||
216 | /** |
||
217 | * Creates a new instance of Apie reusing the services/instances of the current Apie instance. |
||
218 | * |
||
219 | * @param array $plugins |
||
220 | * @return Apie |
||
221 | */ |
||
222 | public function createContext(array $plugins = []): self |
||
223 | { |
||
224 | $plugins[] = $this; |
||
225 | return new Apie($plugins, $this->debug, $this->cacheFolder, false); |
||
226 | } |
||
227 | |||
228 | /** |
||
229 | * @return bool |
||
230 | */ |
||
231 | public function isDebug(): bool |
||
232 | { |
||
233 | return $this->debug; |
||
234 | } |
||
235 | |||
236 | /** |
||
237 | * @return string|null |
||
238 | */ |
||
239 | public function getCacheFolder(): ?string |
||
240 | { |
||
241 | return $this->cacheFolder; |
||
242 | } |
||
243 | |||
244 | public function getPlugin(string $pluginClass): object |
||
245 | { |
||
246 | $last = null; |
||
247 | foreach ($this->plugins as $plugin) { |
||
248 | if ($plugin instanceof $pluginClass) { |
||
249 | return $plugin; |
||
250 | } |
||
251 | $last = $plugin; |
||
252 | } |
||
253 | if ($last instanceof self) { |
||
254 | return $last->getPlugin($pluginClass); |
||
255 | } |
||
256 | throw new BadConfigurationException('Plugin ' . $pluginClass . ' not found!'); |
||
257 | } |
||
258 | |||
259 | /** |
||
260 | * @return ResourceSerializerInterface |
||
261 | */ |
||
262 | public function getResourceSerializer(): ResourceSerializerInterface |
||
263 | { |
||
264 | if (empty($this->serializers)) { |
||
265 | throw new BadConfigurationException('I have no resource serializer set up'); |
||
266 | } |
||
267 | return reset($this->serializers)->getResourceSerializer(); |
||
268 | } |
||
269 | |||
270 | /** |
||
271 | * Returns a list of Api resources. |
||
272 | * |
||
273 | * @return string[] |
||
274 | */ |
||
275 | public function getResources(): array |
||
276 | { |
||
277 | $resources = []; |
||
278 | foreach ($this->resources as $resourceProvider) { |
||
279 | $resources = array_merge($resources, $resourceProvider->getResources()); |
||
280 | } |
||
281 | return array_values(array_unique($resources)); |
||
282 | } |
||
283 | |||
284 | /** |
||
285 | * @return NormalizerInterface[]|DenormalizerInterface[] |
||
286 | */ |
||
287 | public function getNormalizers(): array |
||
288 | { |
||
289 | $normalizers = []; |
||
290 | foreach ($this->normalizers as $normalizerProvider) { |
||
291 | $normalizers = array_merge($normalizers, $normalizerProvider->getNormalizers()); |
||
292 | } |
||
293 | return $normalizers; |
||
294 | } |
||
295 | |||
296 | /** |
||
297 | * @return EncoderInterface[]|DecoderInterface[] |
||
298 | */ |
||
299 | public function getEncoders(): array |
||
300 | { |
||
301 | $encoders = []; |
||
302 | foreach ($this->encoders as $encoderProvider) { |
||
303 | $encoders = array_merge($encoders, $encoderProvider->getEncoders()); |
||
304 | } |
||
305 | return $encoders; |
||
306 | } |
||
307 | |||
308 | public function getClassMetadataFactory(): ClassMetadataFactoryInterface |
||
309 | { |
||
310 | if (empty($this->symfonyComponents)) { |
||
311 | throw new BadConfigurationException('I have no symfony component provider set up'); |
||
312 | } |
||
313 | return reset($this->symfonyComponents)->getClassMetadataFactory(); |
||
314 | } |
||
315 | |||
316 | public function getPropertyConverter(): NameConverterInterface |
||
317 | { |
||
318 | if (empty($this->symfonyComponents)) { |
||
319 | throw new BadConfigurationException('I have no symfony component provider set up'); |
||
320 | } |
||
321 | return reset($this->symfonyComponents)->getPropertyConverter(); |
||
322 | } |
||
323 | |||
324 | public function getPropertyAccessor(): PropertyAccessor |
||
325 | { |
||
326 | if (empty($this->symfonyComponents)) { |
||
327 | throw new BadConfigurationException('I have no symfony component provider set up'); |
||
328 | } |
||
329 | return reset($this->symfonyComponents)->getPropertyAccessor(); |
||
330 | } |
||
331 | |||
332 | public function getPropertyTypeExtractor(): PropertyTypeExtractorInterface |
||
333 | { |
||
334 | if (empty($this->symfonyComponents)) { |
||
335 | throw new BadConfigurationException('I have no symfony component provider set up'); |
||
336 | } |
||
337 | return reset($this->symfonyComponents)->getPropertyTypeExtractor(); |
||
338 | } |
||
339 | |||
340 | public function getCacheItemPool(): CacheItemPoolInterface |
||
341 | { |
||
342 | if (empty($this->cacheItemPools)) { |
||
343 | throw new BadConfigurationException('I have no cache item pool provider set up'); |
||
344 | } |
||
345 | return reset($this->cacheItemPools)->getCacheItemPool(); |
||
346 | } |
||
347 | |||
348 | public function getAnnotationReader(): Reader |
||
349 | { |
||
350 | if (empty($this->annotationReaders)) { |
||
351 | throw new BadConfigurationException('I have no annotation reader set up'); |
||
352 | } |
||
353 | return reset($this->annotationReaders)->getAnnotationReader(); |
||
354 | } |
||
355 | |||
356 | public function getFormatRetriever(): FormatRetrieverInterface |
||
357 | { |
||
358 | if (!$this->chainableFormatRetriever) { |
||
359 | $this->chainableFormatRetriever = new ChainableFormatRetriever( |
||
360 | array_map( |
||
361 | function (EncoderProviderInterface $encoderProvider) { |
||
362 | return $encoderProvider->getFormatRetriever(); |
||
363 | }, |
||
364 | $this->encoders |
||
365 | ) |
||
366 | ); |
||
367 | } |
||
368 | return $this->chainableFormatRetriever; |
||
369 | } |
||
370 | |||
371 | public function getIdentifierExtractor(): IdentifierExtractor |
||
372 | { |
||
373 | return $this->apieCore->getIdentifierExtractor(); |
||
374 | } |
||
375 | |||
376 | public function getApiResourceFacade(): ApiResourceFacade |
||
377 | { |
||
378 | return $this->apieCore->getApiResourceFacade(); |
||
379 | } |
||
380 | |||
381 | public function getOpenApiSpecGenerator(): OpenApiSpecGenerator |
||
382 | { |
||
383 | return $this->apieCore->getOpenApiSpecGenerator(); |
||
384 | } |
||
385 | |||
386 | public function getSchemaGenerator(): SchemaGenerator |
||
387 | { |
||
388 | return $this->apieCore->getSchemaGenerator(); |
||
389 | } |
||
390 | |||
391 | public function getApiResourceFactory(): ApiResourceFactoryInterface |
||
404 | } |
||
405 | |||
406 | public function createInfo(): Info |
||
407 | { |
||
408 | if (empty($this->openApiInfoProviders)) { |
||
409 | return new Info('Apie', Apie::VERSION); |
||
410 | } |
||
411 | return reset($this->openApiInfoProviders)->createInfo(); |
||
412 | } |
||
413 | |||
414 | public function getBaseUrl(): string |
||
415 | { |
||
416 | if (empty($this->configs)) { |
||
417 | throw new BadConfigurationException('I have no config set up'); |
||
418 | } |
||
419 | return reset($this->configs)->getBaseUrl(); |
||
420 | } |
||
421 | |||
422 | public function getDefinedStaticData(): array |
||
423 | { |
||
424 | $result = []; |
||
425 | foreach (array_reverse($this->schemaDefinitions) as $schemaDefinition) { |
||
426 | foreach ($schemaDefinition->getDefinedStaticData() as $className => $schema) { |
||
427 | $result[$className] = $schema; |
||
428 | } |
||
429 | } |
||
430 | return $result; |
||
431 | } |
||
432 | |||
433 | public function getDynamicSchemaLogic(): array |
||
442 | } |
||
443 | |||
444 | public function getClassResourceConverter(): ClassResourceConverter |
||
445 | { |
||
446 | return $this->apieCore->getClassResourceConverter(); |
||
447 | } |
||
448 | |||
449 | public function onOpenApiDocGenerated(Document $document): Document |
||
450 | { |
||
451 | foreach ($this->openApiEventProviders as $openApiEventProvider) { |
||
452 | $document = $openApiEventProvider->onOpenApiDocGenerated($document); |
||
453 | } |
||
454 | return $document; |
||
455 | } |
||
456 | |||
457 | public function getListExtractors(): array |
||
458 | { |
||
459 | $result = []; |
||
460 | foreach ($this->propertyInfoExtractors as $extractor) { |
||
461 | $result = $result + $extractor->getListExtractors(); |
||
462 | } |
||
463 | return $result; |
||
464 | } |
||
465 | |||
466 | public function getTypeExtractors(): array |
||
467 | { |
||
468 | $result = []; |
||
469 | foreach ($this->propertyInfoExtractors as $extractor) { |
||
470 | $result = $result + $extractor->getTypeExtractors(); |
||
471 | } |
||
472 | return $result; |
||
473 | } |
||
474 | |||
475 | public function getDescriptionExtractors(): array |
||
476 | { |
||
477 | $result = []; |
||
478 | foreach ($this->propertyInfoExtractors as $extractor) { |
||
479 | $result = $result + $extractor->getDescriptionExtractors(); |
||
480 | } |
||
481 | return $result; |
||
482 | } |
||
483 | |||
484 | public function getAccessExtractors(): array |
||
491 | } |
||
492 | |||
493 | public function getInitializableExtractors(): array |
||
494 | { |
||
495 | $result = []; |
||
496 | foreach ($this->propertyInfoExtractors as $extractor) { |
||
497 | $result = $result + $extractor->getInitializableExtractors(); |
||
498 | } |
||
499 | return $result; |
||
500 | } |
||
501 | |||
502 | public function getObjectAccess(): ObjectAccessInterface |
||
516 | } |
||
517 | } |
||
518 |
This interface has been deprecated. The supplier of the interface has supplied an explanatory message.
The explanatory message should give you some clue as to whether and when the interface will be removed and what other interface to use instead.