Complex classes like AbstractManagerBuilder 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. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.
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 AbstractManagerBuilder, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 28 | abstract class AbstractManagerBuilder implements ManagerBuilder |
||
| 29 | { |
||
| 30 | use OptionsTrait; |
||
| 31 | |||
| 32 | /** |
||
| 33 | * Manager builder's common default options. |
||
| 34 | * |
||
| 35 | * @var array |
||
| 36 | */ |
||
| 37 | private $defaultOptions = [ |
||
| 38 | 'proxies_auto_generation' => AbstractProxyFactory::AUTOGENERATE_NEVER, |
||
| 39 | ]; |
||
| 40 | |||
| 41 | /** |
||
| 42 | * Builder name. |
||
| 43 | * |
||
| 44 | * @var |
||
| 45 | */ |
||
| 46 | protected $name; |
||
| 47 | |||
| 48 | /** |
||
| 49 | * Object Manager. |
||
| 50 | * |
||
| 51 | * @var ObjectManager |
||
| 52 | */ |
||
| 53 | protected $manager; |
||
| 54 | |||
| 55 | /** |
||
| 56 | * Metadata mapping driver. |
||
| 57 | * |
||
| 58 | * @var MappingDriverChain |
||
| 59 | */ |
||
| 60 | protected $mappingDriver; |
||
| 61 | |||
| 62 | /** |
||
| 63 | * Metadata cache driver. |
||
| 64 | * |
||
| 65 | * @var CacheProvider |
||
| 66 | */ |
||
| 67 | protected $metadataCacheDriver; |
||
| 68 | |||
| 69 | /** |
||
| 70 | * Event manager. |
||
| 71 | * |
||
| 72 | * @var EventManager |
||
| 73 | */ |
||
| 74 | protected $eventManager; |
||
| 75 | |||
| 76 | /** |
||
| 77 | * ManagerBuilder constructor. |
||
| 78 | * |
||
| 79 | * @param array $options |
||
| 80 | * @param string|null $name |
||
| 81 | */ |
||
| 82 | public function __construct(array $options = [], $name = null) |
||
| 83 | { |
||
| 84 | $this->setOptions(array_merge($this->defaultOptions, $this->getDefaultOptions(), $options)); |
||
| 85 | $this->setName($name); |
||
| 86 | } |
||
| 87 | |||
| 88 | /** |
||
| 89 | * Get manager builder's default options. |
||
| 90 | * |
||
| 91 | * @return array |
||
| 92 | */ |
||
| 93 | abstract protected function getDefaultOptions(); |
||
| 94 | |||
| 95 | /** |
||
| 96 | * {@inheritdoc} |
||
| 97 | * |
||
| 98 | * @return ObjectManager |
||
| 99 | */ |
||
| 100 | public function getManager($force = false) |
||
| 101 | { |
||
| 102 | if ($force === true) { |
||
| 103 | $this->wipe(); |
||
| 104 | } |
||
| 105 | |||
| 106 | if (!$this->manager instanceof ObjectManager) { |
||
| 107 | $this->manager = $this->buildManager(); |
||
| 108 | } |
||
| 109 | |||
| 110 | return $this->manager; |
||
| 111 | } |
||
| 112 | |||
| 113 | /** |
||
| 114 | * Unset created objects for rebuild. |
||
| 115 | */ |
||
| 116 | abstract protected function wipe(); |
||
| 117 | |||
| 118 | /** |
||
| 119 | * Build new Doctrine object manager. |
||
| 120 | * |
||
| 121 | * @return ObjectManager |
||
| 122 | */ |
||
| 123 | abstract protected function buildManager(); |
||
| 124 | |||
| 125 | /** |
||
| 126 | * {@inheritdoc} |
||
| 127 | * |
||
| 128 | * @return string|null |
||
| 129 | */ |
||
| 130 | public function getName() |
||
| 131 | { |
||
| 132 | return $this->name; |
||
| 133 | } |
||
| 134 | |||
| 135 | /** |
||
| 136 | * {@inheritdoc} |
||
| 137 | * |
||
| 138 | * @return $this |
||
| 139 | */ |
||
| 140 | public function setName($name = null) |
||
| 141 | { |
||
| 142 | $this->name = $name; |
||
| 143 | |||
| 144 | return $this; |
||
| 145 | } |
||
| 146 | |||
| 147 | /** |
||
| 148 | * Set up annotation metadata. |
||
| 149 | * |
||
| 150 | * @throws \InvalidArgumentException |
||
| 151 | * @throws \RuntimeException |
||
| 152 | */ |
||
| 153 | protected function setupAnnotationMetadata() |
||
| 154 | { |
||
| 155 | $annotationFiles = (array) $this->getOption('annotation_files'); |
||
| 156 | array_walk( |
||
| 157 | $annotationFiles, |
||
| 158 | function ($file) { |
||
| 159 | if (!file_exists($file)) { |
||
| 160 | throw new \RuntimeException(sprintf('"%s" file does not exist', $file)); |
||
| 161 | } |
||
| 162 | |||
| 163 | AnnotationRegistry::registerFile($file); |
||
| 164 | } |
||
| 165 | ); |
||
| 166 | |||
| 167 | AnnotationRegistry::registerAutoloadNamespaces($this->getAnnotationNamespaces()); |
||
| 168 | |||
| 169 | $annotationLoaders = (array) $this->getOption('annotation_autoloaders'); |
||
| 170 | array_walk( |
||
| 171 | $annotationLoaders, |
||
| 172 | function ($autoLoader) { |
||
| 173 | AnnotationRegistry::registerLoader($autoLoader); |
||
| 174 | } |
||
| 175 | ); |
||
| 176 | } |
||
| 177 | |||
| 178 | /** |
||
| 179 | * Retrieve annotation namespaces. |
||
| 180 | * |
||
| 181 | * @return array |
||
| 182 | */ |
||
| 183 | protected function getAnnotationNamespaces() |
||
| 184 | { |
||
| 185 | $namespaces = (array) $this->getOption('annotation_namespaces'); |
||
| 186 | |||
| 187 | return array_filter( |
||
| 188 | $namespaces, |
||
| 189 | function ($namespace) { |
||
| 190 | return is_string($namespace); |
||
| 191 | }, |
||
| 192 | ARRAY_FILTER_USE_KEY |
||
| 193 | ); |
||
| 194 | } |
||
| 195 | |||
| 196 | /** |
||
| 197 | * {@inheritdoc} |
||
| 198 | * |
||
| 199 | * @throws \RuntimeException |
||
| 200 | * @throws \UnexpectedValueException |
||
| 201 | */ |
||
| 202 | public function getMetadataMappingDriver() |
||
| 203 | { |
||
| 204 | if (!$this->mappingDriver instanceof MappingDriverChain) { |
||
| 205 | $metadataDriverChain = new MappingDriverChain; |
||
| 206 | |||
| 207 | $this->parseMetadataMapping($metadataDriverChain); |
||
| 208 | |||
| 209 | if ($metadataDriverChain->getDefaultDriver() === null && count($metadataDriverChain->getDrivers()) === 0) { |
||
| 210 | throw new \RuntimeException('No metadata mapping defined'); |
||
| 211 | } |
||
| 212 | |||
| 213 | $this->mappingDriver = $metadataDriverChain; |
||
| 214 | } |
||
| 215 | |||
| 216 | return $this->mappingDriver; |
||
| 217 | } |
||
| 218 | |||
| 219 | /** |
||
| 220 | * Parse metadata mapping configuration. |
||
| 221 | * |
||
| 222 | * @param MappingDriverChain $metadataDriverChain |
||
| 223 | * |
||
| 224 | * @throws \RuntimeException |
||
| 225 | */ |
||
| 226 | protected function parseMetadataMapping(MappingDriverChain $metadataDriverChain) |
||
| 227 | { |
||
| 228 | foreach ((array) $this->getOption('metadata_mapping') as $metadataMapping) { |
||
| 229 | if (!is_array($metadataMapping)) { |
||
| 230 | $metadataMapping = ['driver' => $metadataMapping]; |
||
| 231 | } |
||
| 232 | |||
| 233 | if (!array_key_exists('namespace', $metadataMapping) && $metadataDriverChain->getDefaultDriver() !== null) { |
||
| 234 | throw new \RuntimeException( |
||
| 235 | 'Only one default metadata mapping driver allowed, a namespace must be defined' |
||
| 236 | ); |
||
| 237 | } |
||
| 238 | |||
| 239 | $mappingDriver = $this->getMappingDriver($metadataMapping); |
||
| 240 | |||
| 241 | if (array_key_exists('namespace', $metadataMapping)) { |
||
| 242 | $metadataDriverChain->addDriver($mappingDriver, $metadataMapping['namespace']); |
||
| 243 | } else { |
||
| 244 | $metadataDriverChain->setDefaultDriver($mappingDriver); |
||
| 245 | } |
||
| 246 | } |
||
| 247 | } |
||
| 248 | |||
| 249 | /** |
||
| 250 | * Retrieve mapping driver. |
||
| 251 | * |
||
| 252 | * @param array $metadataMapping |
||
| 253 | * |
||
| 254 | * @throws \UnexpectedValueException |
||
| 255 | * |
||
| 256 | * @return MappingDriver |
||
| 257 | */ |
||
| 258 | protected function getMappingDriver(array $metadataMapping) |
||
| 259 | { |
||
| 260 | if (array_key_exists('driver', $metadataMapping)) { |
||
| 261 | $mappingDriver = $metadataMapping['driver']; |
||
| 262 | |||
| 263 | if (!$mappingDriver instanceof MappingDriver) { |
||
| 264 | throw new \UnexpectedValueException( |
||
| 265 | sprintf('Provided driver should be of the type MappingDriver, "%s" given', gettype($mappingDriver)) |
||
| 266 | ); |
||
| 267 | } |
||
| 268 | |||
| 269 | return $mappingDriver; |
||
| 270 | } |
||
| 271 | |||
| 272 | if (count(array_intersect(['type', 'path'], array_keys($metadataMapping))) === 2) { |
||
| 273 | $metadataMapping = array_merge(['extension' => null], $metadataMapping); |
||
| 274 | |||
| 275 | return $this->getMappingDriverImplementation( |
||
| 276 | $metadataMapping['type'], |
||
| 277 | (array) $metadataMapping['path'], |
||
| 278 | $metadataMapping['extension'] |
||
| 279 | ); |
||
| 280 | } |
||
| 281 | |||
| 282 | throw new \UnexpectedValueException( |
||
| 283 | 'metadata_mapping must be array with "driver" key or "type" and "path" keys' |
||
| 284 | ); |
||
| 285 | } |
||
| 286 | |||
| 287 | /** |
||
| 288 | * Get metadata mapping driver implementation. |
||
| 289 | * |
||
| 290 | * @param string $type |
||
| 291 | * @param array $paths |
||
| 292 | * @param string $extension |
||
| 293 | * |
||
| 294 | * @throws \UnexpectedValueException |
||
| 295 | * |
||
| 296 | * @return MappingDriver|PHPDriver |
||
| 297 | */ |
||
| 298 | protected function getMappingDriverImplementation($type, $paths, $extension) |
||
| 299 | { |
||
| 300 | switch ($type) { |
||
| 301 | case ManagerBuilder::METADATA_MAPPING_ANNOTATION: |
||
| 302 | return $this->getAnnotationMappingDriver($paths); |
||
| 303 | |||
| 304 | case ManagerBuilder::METADATA_MAPPING_XML: |
||
| 305 | return $this->getXmlMappingDriver($paths, $extension); |
||
| 306 | |||
| 307 | case ManagerBuilder::METADATA_MAPPING_YAML: |
||
| 308 | return $this->getYamlMappingDriver($paths, $extension); |
||
| 309 | |||
| 310 | case ManagerBuilder::METADATA_MAPPING_PHP: |
||
| 311 | return $this->getPhpMappingDriver($paths); |
||
| 312 | } |
||
| 313 | |||
| 314 | throw new \UnexpectedValueException( |
||
| 315 | sprintf('"%s" is not a valid metadata mapping type', $type) |
||
| 316 | ); |
||
| 317 | } |
||
| 318 | |||
| 319 | /** |
||
| 320 | * Get annotation metadata driver. |
||
| 321 | * |
||
| 322 | * @param array $paths |
||
| 323 | * |
||
| 324 | * @return MappingDriver |
||
| 325 | */ |
||
| 326 | abstract protected function getAnnotationMappingDriver(array $paths); |
||
| 327 | |||
| 328 | /** |
||
| 329 | * Get XML metadata driver. |
||
| 330 | * |
||
| 331 | * @param array $paths |
||
| 332 | * @param string|null $extension |
||
| 333 | * |
||
| 334 | * @return MappingDriver |
||
| 335 | */ |
||
| 336 | abstract protected function getXmlMappingDriver(array $paths, $extension = null); |
||
| 337 | |||
| 338 | /** |
||
| 339 | * Get YAML metadata driver. |
||
| 340 | * |
||
| 341 | * @param array $paths |
||
| 342 | * @param string|null $extension |
||
| 343 | * |
||
| 344 | * @return MappingDriver |
||
| 345 | */ |
||
| 346 | abstract protected function getYamlMappingDriver(array $paths, $extension = null); |
||
| 347 | |||
| 348 | /** |
||
| 349 | * Get PHP metadata driver. |
||
| 350 | * |
||
| 351 | * @param array $paths |
||
| 352 | * |
||
| 353 | * @return PHPDriver |
||
| 354 | */ |
||
| 355 | protected function getPhpMappingDriver(array $paths) |
||
| 356 | { |
||
| 357 | return new PHPDriver($paths); |
||
| 358 | } |
||
| 359 | |||
| 360 | /** |
||
| 361 | * {@inheritdoc} |
||
| 362 | * |
||
| 363 | * @return $this |
||
| 364 | */ |
||
| 365 | public function setMetadataMappingDriver(MappingDriverChain $mappingDriver) |
||
| 366 | { |
||
| 367 | $this->mappingDriver = $mappingDriver; |
||
| 368 | |||
| 369 | return $this; |
||
| 370 | } |
||
| 371 | |||
| 372 | /** |
||
| 373 | * Get custom repository factory. |
||
| 374 | */ |
||
| 375 | abstract protected function getRepositoryFactory(); |
||
| 376 | |||
| 377 | /** |
||
| 378 | * Get default repository class name. |
||
| 379 | * |
||
| 380 | * @return string|null |
||
| 381 | */ |
||
| 382 | protected function getDefaultRepositoryClass() |
||
| 383 | { |
||
| 384 | return array_key_exists('default_repository_class', $this->options) |
||
| 385 | ? (string) $this->options['default_repository_class'] |
||
| 386 | : null; |
||
| 387 | } |
||
| 388 | |||
| 389 | /** |
||
| 390 | * Retrieve proxies path. |
||
| 391 | * |
||
| 392 | * @return string |
||
| 393 | */ |
||
| 394 | protected function getProxiesPath() |
||
| 395 | { |
||
| 396 | return (string) $this->getOption('proxies_path', sys_get_temp_dir()); |
||
| 397 | } |
||
| 398 | |||
| 399 | /** |
||
| 400 | * Retrieve proxies namespace. |
||
| 401 | * |
||
| 402 | * @return null|string |
||
| 403 | */ |
||
| 404 | protected function getProxiesNamespace() |
||
| 405 | { |
||
| 406 | $proxyNamespace = $this->getOption('proxies_namespace'); |
||
| 407 | |||
| 408 | return is_string($proxyNamespace) ? $proxyNamespace : null; |
||
| 409 | } |
||
| 410 | |||
| 411 | /** |
||
| 412 | * Retrieve proxy generation strategy. |
||
| 413 | * |
||
| 414 | * @return int |
||
| 415 | */ |
||
| 416 | protected function getProxiesAutoGeneration() |
||
| 417 | { |
||
| 418 | return (int) $this->getOption('proxies_auto_generation'); |
||
| 419 | } |
||
| 420 | |||
| 421 | /** |
||
| 422 | * {@inheritdoc} |
||
| 423 | * |
||
| 424 | * @throws \InvalidArgumentException |
||
| 425 | */ |
||
| 426 | public function getMetadataCacheDriver() |
||
| 444 | |||
| 445 | /** |
||
| 446 | * {@inheritdoc} |
||
| 447 | * |
||
| 448 | * @return $this |
||
| 449 | */ |
||
| 450 | public function setMetadataCacheDriver(CacheProvider $metadataCacheDriver) |
||
| 451 | { |
||
| 452 | $this->metadataCacheDriver = $metadataCacheDriver; |
||
| 453 | |||
| 454 | return $this; |
||
| 455 | } |
||
| 456 | |||
| 457 | /** |
||
| 458 | * {@inheritdoc} |
||
| 459 | */ |
||
| 460 | public function getEventManager() |
||
| 461 | { |
||
| 462 | if (!$this->eventManager instanceof EventManager) { |
||
| 463 | $eventManager = $this->getOption('event_manager'); |
||
| 464 | |||
| 465 | if (!$eventManager instanceof EventManager) { |
||
| 466 | $eventManager = new EventManager; |
||
| 467 | } |
||
| 468 | |||
| 474 | |||
| 475 | /** |
||
| 476 | * {@inheritdoc} |
||
| 477 | * |
||
| 478 | * @return $this |
||
| 479 | */ |
||
| 480 | public function setEventManager(EventManager $eventManager) |
||
| 486 | |||
| 487 | /** |
||
| 488 | * Get event subscribers. |
||
| 489 | * |
||
| 490 | * @return array|null |
||
| 491 | */ |
||
| 492 | protected function getEventSubscribers() |
||
| 508 | } |
||
| 509 |