Complex classes like ResourceGenerator 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 ResourceGenerator, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
30 | class ResourceGenerator extends AbstractGenerator |
||
31 | { |
||
32 | /** |
||
33 | * @private Filesystem |
||
34 | */ |
||
35 | private $filesystem; |
||
36 | |||
37 | /** |
||
38 | * @private DoctrineRegistry |
||
39 | */ |
||
40 | private $doctrine; |
||
41 | |||
42 | /** |
||
43 | * @private HttpKernelInterface |
||
44 | */ |
||
45 | private $kernel; |
||
46 | |||
47 | /** |
||
48 | * our json file definition |
||
49 | * |
||
50 | * @var JsonDefinition|null |
||
51 | */ |
||
52 | private $json = null; |
||
53 | |||
54 | /** |
||
55 | * @var ArrayCollection |
||
56 | */ |
||
57 | protected $xmlParameters; |
||
58 | |||
59 | /** |
||
60 | * @var \DomDocument |
||
61 | */ |
||
62 | private $serviceDOM; |
||
63 | |||
64 | /** |
||
65 | * @var FieldMapper |
||
66 | */ |
||
67 | private $mapper; |
||
68 | |||
69 | /** |
||
70 | * @var boolean |
||
71 | */ |
||
72 | private $generateController = false; |
||
73 | |||
74 | /** |
||
75 | * @var ParameterBuilder |
||
76 | */ |
||
77 | private $parameterBuilder; |
||
78 | |||
79 | /** |
||
80 | * Instantiates generator object |
||
81 | * |
||
82 | * @param Filesystem $filesystem fs abstraction layer |
||
83 | * @param DoctrineRegistry $doctrine odm registry |
||
84 | * @param HttpKernelInterface $kernel app kernel |
||
85 | * @param FieldMapper $mapper field type mapper |
||
86 | * @param ParameterBuilder $parameterBuilder param builder |
||
87 | */ |
||
88 | 2 | public function __construct( |
|
89 | Filesystem $filesystem, |
||
90 | DoctrineRegistry $doctrine, |
||
91 | HttpKernelInterface $kernel, |
||
92 | FieldMapper $mapper, |
||
93 | ParameterBuilder $parameterBuilder |
||
94 | ) { |
||
95 | 2 | $this->filesystem = $filesystem; |
|
96 | 2 | $this->doctrine = $doctrine; |
|
97 | 2 | $this->kernel = $kernel; |
|
98 | 2 | $this->mapper = $mapper; |
|
99 | 2 | $this->parameterBuilder = $parameterBuilder; |
|
100 | 2 | $this->xmlParameters = new ArrayCollection(); |
|
101 | 2 | } |
|
102 | |||
103 | /** |
||
104 | * @param JsonDefinition $json optional JsonDefinition object |
||
105 | * |
||
106 | * @return void |
||
107 | */ |
||
108 | public function setJson(JsonDefinition $json) |
||
109 | { |
||
110 | $this->json = $json; |
||
111 | } |
||
112 | |||
113 | /** |
||
114 | * @param boolean $generateController should the controller be generated or not |
||
115 | * |
||
116 | * @return void |
||
117 | */ |
||
118 | public function setGenerateController($generateController) |
||
119 | { |
||
120 | $this->generateController = $generateController; |
||
121 | } |
||
122 | |||
123 | /** |
||
124 | * generate the resource with all its bits and parts |
||
125 | * |
||
126 | * @param BundleInterface $bundle bundle |
||
127 | * @param string $document document name |
||
128 | * @param string $format format of config files (please use xml) |
||
129 | * @param array $fields fields to add |
||
130 | * @param boolean $withRepository generate repository class |
||
131 | * |
||
132 | * @return void |
||
133 | */ |
||
134 | public function generate( |
||
185 | |||
186 | /** |
||
187 | * Writes the current services definition to a file. |
||
188 | * |
||
189 | * @param string $dir base bundle dir |
||
190 | * |
||
191 | * @return void |
||
192 | */ |
||
193 | 8 | protected function persistServicesXML($dir) |
|
194 | { |
||
195 | 8 | $services = $this->loadServices($dir); |
|
196 | |||
197 | 8 | file_put_contents($dir . '/Resources/config/services.xml', $services->saveXML()); |
|
198 | 8 | } |
|
199 | |||
200 | /** |
||
201 | * generate document part of a resource |
||
202 | * |
||
203 | * @param array $parameters twig parameters |
||
204 | * @param string $dir base bundle dir |
||
205 | * @param string $document document name |
||
206 | * @param boolean $withRepository generate repository class |
||
207 | * |
||
208 | * @return void |
||
209 | */ |
||
210 | 6 | protected function generateDocument($parameters, $dir, $document, $withRepository) |
|
211 | { |
||
212 | // doctrine mapping normal class |
||
213 | 6 | $this->renderFile( |
|
214 | 6 | 'document/Document.mongodb.xml.twig', |
|
215 | 6 | $dir . '/Resources/config/doctrine/' . $document . '.mongodb.xml', |
|
216 | $parameters |
||
217 | 3 | ); |
|
218 | |||
219 | // doctrine mapping embedded |
||
220 | 6 | $this->renderFile( |
|
221 | 6 | 'document/Document.mongodb.xml.twig', |
|
222 | 6 | $dir . '/Resources/config/doctrine/' . $document . 'Embedded.mongodb.xml', |
|
223 | 3 | array_merge( |
|
224 | 3 | $parameters, |
|
225 | [ |
||
226 | 6 | 'document' => $document.'Embedded', |
|
227 | 3 | 'docType' => 'embedded-document' |
|
228 | 3 | ] |
|
229 | 3 | ) |
|
230 | 3 | ); |
|
231 | |||
232 | 6 | $this->renderFile( |
|
233 | 6 | 'document/Document.php.twig', |
|
234 | 6 | $dir . '/Document/' . $document . '.php', |
|
235 | $parameters |
||
236 | 3 | ); |
|
237 | 6 | $this->renderFile( |
|
238 | 6 | 'document/DocumentEmbedded.php.twig', |
|
239 | 6 | $dir . '/Document/' . $document . 'Embedded.php', |
|
240 | $parameters |
||
241 | 3 | ); |
|
242 | 6 | $this->renderFile( |
|
243 | 6 | 'document/DocumentBase.php.twig', |
|
244 | 6 | $dir . '/Document/' . $document . 'Base.php', |
|
245 | $parameters |
||
246 | 3 | ); |
|
247 | |||
248 | 6 | $this->generateServices($parameters, $dir, $document, $withRepository); |
|
249 | 6 | } |
|
250 | |||
251 | /** |
||
252 | * update xml services |
||
253 | * |
||
254 | * @param array $parameters twig parameters |
||
255 | * @param string $dir base bundle dir |
||
256 | * @param string $document document name |
||
257 | * @param boolean $withRepository generate repository class |
||
258 | * |
||
259 | * @return void |
||
260 | */ |
||
261 | 6 | protected function generateServices($parameters, $dir, $document, $withRepository) |
|
262 | { |
||
263 | 6 | $services = $this->loadServices($dir); |
|
264 | |||
265 | 6 | $bundleParts = explode('\\', $parameters['base']); |
|
266 | 6 | $shortName = $bundleParts[0]; |
|
267 | 6 | $shortBundle = $this->getBundleBaseName($bundleParts[1]); |
|
268 | |||
269 | 6 | $docName = implode( |
|
270 | 6 | '.', |
|
271 | array( |
||
272 | 6 | strtolower($shortName), |
|
273 | 6 | strtolower($shortBundle), |
|
274 | 6 | 'document', |
|
275 | 6 | strtolower($parameters['document']) |
|
276 | 3 | ) |
|
277 | 3 | ); |
|
278 | |||
279 | 6 | $this->addXMLParameter( |
|
280 | 6 | $parameters['base'] . 'Document\\' . $parameters['document'], |
|
281 | 3 | $docName . '.class' |
|
282 | 3 | ); |
|
283 | |||
284 | 6 | $this->addXMLParameter( |
|
285 | 6 | $parameters['json']->getRoles(), |
|
286 | 6 | $docName . '.roles', |
|
287 | 3 | 'collection' |
|
288 | 3 | ); |
|
289 | |||
290 | 6 | $services = $this->addService( |
|
291 | 3 | $services, |
|
292 | $docName |
||
293 | 3 | ); |
|
294 | |||
295 | 6 | if ($withRepository) { |
|
296 | $repoName = implode( |
||
297 | '.', |
||
298 | array( |
||
299 | strtolower($shortName), |
||
300 | strtolower($shortBundle), |
||
301 | 'repository', |
||
302 | strtolower($parameters['document']) |
||
303 | ) |
||
304 | ); |
||
305 | |||
306 | // normal repo service |
||
307 | $services = $this->addParam( |
||
308 | $services, |
||
309 | $repoName . '.class', |
||
310 | $parameters['base'] . 'Repository\\' . $parameters['document'] |
||
311 | ); |
||
312 | |||
313 | $this->addService( |
||
314 | $services, |
||
315 | $repoName, |
||
316 | null, |
||
317 | null, |
||
318 | array(), |
||
319 | null, |
||
320 | array( |
||
321 | array( |
||
322 | 'type' => 'string', |
||
323 | 'value' => $parameters['bundle'] . ':' . $document |
||
324 | ) |
||
325 | ), |
||
326 | 'doctrine_mongodb.odm.default_document_manager', |
||
327 | 'getRepository' |
||
328 | ); |
||
329 | |||
330 | // embedded repo service |
||
331 | $services = $this->addParam( |
||
332 | $services, |
||
333 | $repoName . 'embedded.class', |
||
334 | $parameters['base'] . 'Repository\\' . $parameters['document'] . 'Embedded' |
||
335 | ); |
||
336 | |||
337 | $this->addService( |
||
338 | $services, |
||
339 | $repoName . 'embedded', |
||
340 | null, |
||
341 | null, |
||
342 | array(), |
||
343 | null, |
||
344 | array( |
||
345 | array( |
||
346 | 'type' => 'string', |
||
347 | 'value' => $parameters['bundle'] . ':' . $document . 'Embedded' |
||
348 | ) |
||
349 | ), |
||
350 | 'doctrine_mongodb.odm.default_document_manager', |
||
351 | 'getRepository' |
||
352 | ); |
||
353 | |||
354 | $this->renderFile( |
||
355 | 'document/DocumentRepository.php.twig', |
||
356 | $dir . '/Repository/' . $document . 'Repository.php', |
||
357 | $parameters |
||
358 | ); |
||
359 | $this->renderFile( |
||
360 | 'document/DocumentRepository.php.twig', |
||
361 | $dir . '/Repository/' . $document . 'EmbeddedRepository.php', |
||
362 | array_merge( |
||
363 | $parameters, |
||
364 | [ |
||
365 | 'document' => $document.'Embedded', |
||
366 | ] |
||
367 | ) |
||
368 | ); |
||
369 | } |
||
370 | |||
371 | 6 | $this->persistServicesXML($dir); |
|
372 | 6 | } |
|
373 | |||
374 | /** |
||
375 | * Generates the parameters section of the services.xml file. |
||
376 | * |
||
377 | * @param string $dir base bundle dir |
||
378 | * |
||
379 | * @return void |
||
380 | */ |
||
381 | 2 | protected function generateParameters($dir) |
|
382 | { |
||
383 | 2 | if ($this->xmlParameters->count() > 0) { |
|
384 | 2 | $services = $this->loadServices($dir); |
|
385 | |||
386 | 2 | foreach ($this->xmlParameters as $parameter) { |
|
387 | 2 | switch ($parameter['type']) { |
|
388 | 2 | case 'collection': |
|
389 | 2 | $this->addCollectionParam($services, $parameter['key'], $parameter['content']); |
|
390 | 2 | break; |
|
391 | 2 | case 'string': |
|
392 | 1 | default: |
|
393 | 2 | $this->addParam($services, $parameter['key'], $parameter['content']); |
|
394 | 1 | } |
|
395 | 1 | } |
|
396 | 1 | } |
|
397 | |||
398 | 2 | $this->persistServicesXML($dir); |
|
399 | 2 | } |
|
400 | |||
401 | /** |
||
402 | * Registers information to be generated to a parameter tag. |
||
403 | * |
||
404 | * @param mixed $value Content of the tag |
||
405 | * @param string $key Content of the key attribute |
||
406 | * @param string $type Type of the tag |
||
407 | * |
||
408 | * @return void |
||
409 | */ |
||
410 | 2 | protected function addXmlParameter($value, $key, $type = 'string') |
|
411 | { |
||
412 | $element = array( |
||
413 | 2 | 'content' => $value, |
|
414 | 2 | 'key' => $key, |
|
415 | 2 | 'type' => strtolower($type), |
|
416 | 1 | ); |
|
417 | |||
418 | 2 | if (!isset($this->xmlParameters)) { |
|
419 | $this->xmlParameters = new ArrayCollection(); |
||
420 | } |
||
421 | |||
422 | 2 | if (!$this->xmlParameters->contains($element)) { |
|
423 | 2 | $this->xmlParameters->add($element); |
|
424 | 1 | } |
|
425 | 2 | } |
|
426 | |||
427 | /** |
||
428 | * load services.xml |
||
429 | * |
||
430 | * @param string $dir base dir |
||
431 | * |
||
432 | * @return \DOMDocument |
||
433 | */ |
||
434 | 4 | protected function loadServices($dir) |
|
435 | { |
||
436 | 4 | if (empty($this->serviceDOM)) { |
|
437 | 4 | $this->serviceDOM = new \DOMDocument; |
|
438 | 4 | $this->serviceDOM->formatOutput = true; |
|
439 | 4 | $this->serviceDOM->preserveWhiteSpace = false; |
|
440 | 4 | $this->serviceDOM->load($dir . '/Resources/config/services.xml'); |
|
441 | 2 | } |
|
442 | |||
443 | 4 | return $this->serviceDOM; |
|
444 | } |
||
445 | |||
446 | /** |
||
447 | * add param to services.xml |
||
448 | * |
||
449 | * @param \DOMDocument $dom services.xml document |
||
450 | * @param string $key parameter key |
||
451 | * @param string $value parameter value |
||
452 | * |
||
453 | * @return \DOMDocument |
||
454 | */ |
||
455 | 6 | protected function addParam(\DOMDocument $dom, $key, $value) |
|
456 | { |
||
457 | 6 | $paramNode = $this->addNodeIfMissing($dom, 'parameters', '//services'); |
|
458 | |||
459 | 6 | if (!$this->parameterNodeExists($dom, $key)) { |
|
460 | 6 | $attrNode = $dom->createElement('parameter', $value); |
|
461 | |||
462 | 6 | $this->addAttributeToNode('key', $key, $dom, $attrNode); |
|
463 | |||
464 | 6 | $paramNode->appendChild($attrNode); |
|
465 | 3 | } |
|
466 | |||
467 | 6 | return $dom; |
|
468 | } |
||
469 | |||
470 | /** |
||
471 | * Adds a new parameter tag to parameters section reflecting the defined roles. |
||
472 | * |
||
473 | * @param \DOMDocument $dom services.xml document |
||
474 | * @param string $key parameter key |
||
475 | * @param array $values parameter value |
||
476 | * |
||
477 | * @return void |
||
478 | * |
||
479 | * @link http://symfony.com/doc/current/book/service_container.html#array-parameters |
||
480 | */ |
||
481 | 4 | protected function addCollectionParam(\DomDocument $dom, $key, array $values) |
|
482 | { |
||
483 | 4 | $paramNode = $this->addNodeIfMissing($dom, 'parameters', '//services'); |
|
484 | |||
485 | 4 | if (!$this->parameterNodeExists($dom, $key)) { |
|
486 | 4 | if (!empty($values)) { |
|
487 | 4 | $rolesNode = $dom->createElement('parameter'); |
|
488 | 4 | $this->addAttributeToNode('key', $key, $dom, $rolesNode); |
|
489 | 4 | $this->addAttributeToNode('type', 'collection', $dom, $rolesNode); |
|
490 | |||
491 | 4 | foreach ($values as $item) { |
|
492 | 4 | $roleNode = $dom->createElement('parameter', $item); |
|
493 | 4 | $rolesNode->appendChild($roleNode); |
|
494 | 2 | } |
|
495 | |||
496 | 4 | $paramNode->appendChild($rolesNode); |
|
497 | 2 | } |
|
498 | 2 | } |
|
499 | |||
500 | 4 | } |
|
501 | |||
502 | /** |
||
503 | * Determines, if the provided key attribute was already claimed by a parameter node. |
||
504 | * |
||
505 | * @param \DomDocument $dom Current document |
||
506 | * @param string $key Key to be found in document |
||
507 | * |
||
508 | * @return bool |
||
509 | */ |
||
510 | 8 | private function parameterNodeExists(\DomDocument $dom, $key) |
|
|
|||
511 | { |
||
512 | 8 | $xpath = new \DomXpath($dom); |
|
513 | 8 | $nodes = $xpath->query('//parameters/parameter[@key="' . $key . '"]'); |
|
514 | |||
515 | 8 | return $nodes->length > 0; |
|
516 | } |
||
517 | |||
518 | /** |
||
519 | * add node if missing |
||
520 | * |
||
521 | * @param \DOMDocument $dom document |
||
522 | * @param string $element name for new node element |
||
523 | * @param string $insertBefore xPath query of the new node shall be added before |
||
524 | * @param string $container name of container tag |
||
525 | * |
||
526 | * @return \DOMNode new element node |
||
527 | */ |
||
528 | 8 | private function addNodeIfMissing(&$dom, $element, $insertBefore = '', $container = 'container') |
|
529 | { |
||
530 | 8 | $container = $dom->getElementsByTagName($container) |
|
531 | 8 | ->item(0); |
|
532 | 8 | $nodes = $dom->getElementsByTagName($element); |
|
533 | 8 | if ($nodes->length < 1) { |
|
534 | 8 | $newNode = $dom->createElement($element); |
|
535 | |||
536 | 8 | if (!empty($insertBefore)) { |
|
537 | 8 | $xpath = new \DomXpath($dom); |
|
538 | 8 | $found = $xpath->query($insertBefore); |
|
539 | |||
540 | 8 | if ($found->length > 0) { |
|
541 | $container->insertBefore($newNode, $found->item(0)); |
||
542 | } else { |
||
543 | 8 | $container->appendChild($newNode); |
|
544 | } |
||
545 | 4 | } else { |
|
546 | 4 | $container->appendChild($newNode); |
|
547 | } |
||
548 | 4 | } else { |
|
549 | 4 | $newNode = $nodes->item(0); |
|
550 | } |
||
551 | |||
552 | 8 | return $newNode; |
|
553 | } |
||
554 | |||
555 | /** |
||
556 | * add attribute to node if needed |
||
557 | * |
||
558 | * @param string $name attribute name |
||
559 | * @param string $value attribute value |
||
560 | * @param \DOMDocument $dom document |
||
561 | * @param \DOMElement $node parent node |
||
562 | * |
||
563 | * @return void |
||
564 | */ |
||
565 | 8 | private function addAttributeToNode($name, $value, $dom, $node) |
|
566 | { |
||
567 | 8 | if ($value) { |
|
568 | 8 | $attr = $dom->createAttribute($name); |
|
569 | 8 | $attr->value = $value; |
|
570 | 8 | $node->appendChild($attr); |
|
571 | 4 | } |
|
572 | 8 | } |
|
573 | |||
574 | /** |
||
575 | * add service to services.xml |
||
576 | * |
||
577 | * @param \DOMDocument $dom services.xml dom |
||
578 | * @param string $id id of new service |
||
579 | * @param string $parent parent for service |
||
580 | * @param string $scope scope of service |
||
581 | * @param array $calls methodCalls to add |
||
582 | * @param string $tag tag name or empty if no tag needed |
||
583 | * @param array $arguments service arguments |
||
584 | * @param string $factoryService factory service id |
||
585 | * @param string $factoryMethod factory method name |
||
586 | * |
||
587 | * @return \DOMDocument |
||
588 | */ |
||
589 | protected function addService( |
||
653 | |||
654 | /** |
||
655 | * add calls to service |
||
656 | * |
||
657 | * @param array $calls info on calls to create |
||
658 | * @param \DOMDocument $dom current domdocument |
||
659 | * @param \DOMElement $node node to add call to |
||
660 | * |
||
661 | * @return void |
||
662 | */ |
||
663 | private function addCallsToService($calls, $dom, $node) |
||
664 | { |
||
665 | foreach ($calls as $call) { |
||
666 | $this->addCallToService($call, $dom, $node); |
||
667 | } |
||
669 | |||
670 | /** |
||
671 | * add call to service |
||
672 | * |
||
673 | * @param array $call info on call node to create |
||
674 | * @param \DOMDocument $dom current domdocument |
||
675 | * @param \DOMElement $node node to add call to |
||
676 | * |
||
677 | * @return void |
||
678 | */ |
||
679 | private function addCallToService($call, $dom, $node) |
||
701 | |||
702 | /** |
||
703 | * add arguments to servie |
||
704 | * |
||
705 | * @param array $arguments arguments to create |
||
706 | * @param \DOMDocument $dom dom document to add to |
||
707 | * @param \DOMElement $node node to use as parent |
||
708 | * |
||
709 | * @return void |
||
710 | */ |
||
711 | private function addArgumentsToService($arguments, $dom, $node) |
||
717 | |||
718 | /** |
||
719 | * add argument to service |
||
720 | * |
||
721 | * @param array $argument info on argument to create |
||
722 | * @param \DOMDocument $dom dom document to add to |
||
723 | * @param \DOMElement $node node to use as parent |
||
724 | * |
||
725 | * @return void |
||
726 | */ |
||
727 | private function addArgumentToService($argument, $dom, $node) |
||
747 | |||
748 | /** |
||
749 | * generate serializer part of a resource |
||
750 | * |
||
751 | * @param array $parameters twig parameters |
||
752 | * @param string $dir base bundle dir |
||
753 | * @param string $document document name |
||
754 | * |
||
755 | * @return void |
||
756 | */ |
||
757 | protected function generateSerializer(array $parameters, $dir, $document) |
||
806 | |||
807 | /** |
||
808 | * generate model part of a resource |
||
809 | * |
||
810 | * @param array $parameters twig parameters |
||
811 | * @param string $dir base bundle dir |
||
812 | * @param string $document document name |
||
813 | * |
||
814 | * @return void |
||
815 | */ |
||
816 | protected function generateModel(array $parameters, $dir, $document) |
||
894 | |||
895 | /** |
||
896 | * generate RESTful controllers ans service configs |
||
897 | * |
||
898 | * @param array $parameters twig parameters |
||
899 | * @param string $dir base bundle dir |
||
900 | * @param string $document document name |
||
901 | * |
||
902 | * @return void |
||
903 | */ |
||
904 | protected function generateController(array $parameters, $dir, $document) |
||
943 | |||
944 | /** |
||
945 | * generates fixtures |
||
946 | * |
||
947 | * @param array $parameters twig parameters |
||
948 | * @param string $dir base bundle dir |
||
949 | * @param string $document document name |
||
950 | * |
||
951 | * @return void |
||
952 | */ |
||
953 | protected function generateFixtures(array $parameters, $dir, $document) |
||
964 | } |
||
965 |
This check examines a number of code elements and verifies that they conform to the given naming conventions.
You can set conventions for local variables, abstract classes, utility classes, constant, properties, methods, parameters, interfaces, classes, exceptions and special methods.