Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
Complex classes like UpdateCommand 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 UpdateCommand, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
18 | class UpdateCommand extends AbstractMagentoCommand |
||
19 | { |
||
20 | /** |
||
21 | * @var string |
||
22 | */ |
||
23 | protected $baseFolder; |
||
24 | |||
25 | /** |
||
26 | * @var string |
||
27 | */ |
||
28 | protected $moduleDirectory; |
||
29 | |||
30 | /** |
||
31 | * @var string |
||
32 | */ |
||
33 | protected $vendorNamespace; |
||
34 | |||
35 | /** |
||
36 | * @var string |
||
37 | */ |
||
38 | protected $moduleName; |
||
39 | |||
40 | /** |
||
41 | * @var string |
||
42 | */ |
||
43 | protected $codePool; |
||
44 | |||
45 | /** |
||
46 | * @var array |
||
47 | */ |
||
48 | protected $configNodes = array(); |
||
49 | |||
50 | /** |
||
51 | * @var bool |
||
52 | */ |
||
53 | protected $testMode = false; |
||
54 | |||
55 | /** |
||
56 | * @param boolean $testMode |
||
57 | */ |
||
58 | public function setTestMode($testMode) |
||
59 | { |
||
60 | $this->testMode = $testMode; |
||
61 | } |
||
62 | |||
63 | /** |
||
64 | * @return boolean |
||
65 | */ |
||
66 | public function getTestMode() |
||
67 | { |
||
68 | return $this->testMode; |
||
69 | } |
||
70 | |||
71 | protected function configure() |
||
125 | |||
126 | /** |
||
127 | * @param InputInterface $input |
||
128 | * @param OutputInterface $output |
||
129 | * |
||
130 | * @return int|void |
||
131 | * @throws InvalidArgumentException |
||
132 | */ |
||
133 | protected function execute(InputInterface $input, OutputInterface $output) |
||
134 | { |
||
135 | $this->initMagento(); |
||
136 | $this->initArguments($input); |
||
137 | |||
138 | if ($this->hasAddResourceModelOption($input)) { |
||
139 | $this->askResourceModelOptions($output); |
||
140 | } |
||
141 | |||
142 | if ($this->hasAddRoutersOption($input)) { |
||
143 | $this->askRoutersOptions($output); |
||
144 | } |
||
145 | |||
146 | if ($this->hasAddEventsOption($input)) { |
||
147 | $this->askEventsOptions($output); |
||
148 | } |
||
149 | |||
150 | if ($this->hasAddLayoutUpdatesOptions($input)) { |
||
151 | $this->askLayoutUpdatesOptions($output); |
||
152 | } |
||
153 | |||
154 | if ($this->hasAddTranslateOption($input)) { |
||
155 | $this->askTranslateOptions($output); |
||
156 | } |
||
157 | |||
158 | if ($this->hasAddDefaultOption($input)) { |
||
159 | $this->askDefaultOptions($output); |
||
160 | } |
||
161 | |||
162 | $this->setModuleDirectory($this->getModuleDir()); |
||
163 | $this->writeModuleConfig($input, $output); |
||
164 | } |
||
165 | |||
166 | /** |
||
167 | * @param InputInterface $input |
||
168 | */ |
||
169 | protected function initArguments(InputInterface $input) |
||
170 | { |
||
171 | $this->vendorNamespace = ucfirst($input->getArgument('vendorNamespace')); |
||
172 | $this->moduleName = ucfirst($input->getArgument('moduleName')); |
||
173 | $this->determineModuleCodePool(); |
||
174 | } |
||
175 | |||
176 | /** |
||
177 | * Find module codepool from module directory |
||
178 | * |
||
179 | * @return string |
||
180 | */ |
||
181 | protected function determineModuleCodePool() |
||
182 | { |
||
183 | if ($this->testMode === true) { |
||
184 | $this->codePool = 'local'; |
||
185 | $this->_magentoRootFolder = './' . $this->getModuleNamespace() . '/src'; |
||
186 | $this->moduleDirectory = $this->_magentoRootFolder |
||
187 | . '/app/code/' |
||
188 | . $this->codePool |
||
189 | . '/' . $this->vendorNamespace |
||
190 | . '/' . $this->moduleName; |
||
191 | } else { |
||
192 | $this->moduleDirectory = $this->getModuleDir(); |
||
193 | } |
||
194 | |||
195 | if (preg_match('/community/', $this->moduleDirectory)) { |
||
196 | $this->codePool = 'community'; |
||
197 | } |
||
198 | |||
199 | if (preg_match('/local/', $this->moduleDirectory)) { |
||
200 | $this->codePool = 'local'; |
||
201 | } |
||
202 | |||
203 | return $this->codePool; |
||
204 | } |
||
205 | |||
206 | /** |
||
207 | * @param string $moduleDir |
||
208 | * @throws RuntimeException |
||
209 | */ |
||
210 | protected function setModuleDirectory($moduleDir) |
||
220 | |||
221 | /** |
||
222 | * @return DialogHelper |
||
223 | */ |
||
224 | protected function getDialog() |
||
225 | { |
||
226 | return $this->getHelper('dialog'); |
||
227 | } |
||
228 | |||
229 | /** |
||
230 | * Writes module config file for given options |
||
231 | * |
||
232 | * @param InputInterface $input |
||
233 | * @param OutputInterface $output |
||
234 | */ |
||
235 | protected function writeModuleConfig(InputInterface $input, OutputInterface $output) |
||
236 | { |
||
237 | $configXml = $this->getConfigXml(); |
||
238 | |||
239 | $this->setVersion($input, $output, $configXml); |
||
240 | $this->setGlobalNode($input, $output, $configXml); |
||
241 | $this->setResourceModelNode($input, $configXml); |
||
242 | $this->setRoutersNode($input, $configXml); |
||
243 | $this->setEventsNode($input, $configXml); |
||
244 | $this->setLayoutUpdatesNode($input, $configXml); |
||
245 | $this->setTranslateNode($input, $configXml); |
||
246 | $this->setDefaultNode($input, $configXml); |
||
247 | $this->putConfigXml($configXml); |
||
248 | |||
249 | $output->writeln('<info>Edited file: <comment>' . $this->getOutFile() . '<comment></info>'); |
||
250 | } |
||
251 | |||
252 | /** |
||
253 | * @param InputInterface $input |
||
254 | * @param OutputInterface $output |
||
255 | * @param SimpleXMLElement $configXml |
||
256 | */ |
||
257 | protected function setVersion(InputInterface $input, OutputInterface $output, \SimpleXMLElement $configXml) |
||
258 | { |
||
259 | if ($this->shouldSetVersion($input)) { |
||
260 | $modulesNode = $configXml->modules->{$this->getModuleNamespace()}; |
||
261 | $dialog = $this->getDialog(); |
||
262 | $version = trim($dialog->ask($output, '<question>Enter version number:</question>')); |
||
263 | $modulesNode->version = $version; |
||
264 | } |
||
265 | } |
||
266 | |||
267 | /** |
||
268 | * Sets global xml config node |
||
269 | * |
||
270 | * @param InputInterface $input |
||
271 | * @param OutputInterface $output |
||
272 | * @param SimpleXMLElement $configXml |
||
273 | */ |
||
274 | protected function setGlobalNode(InputInterface $input, OutputInterface $output, SimpleXMLElement $configXml) |
||
275 | { |
||
276 | if ($this->shouldAddAll($input)) { |
||
277 | $this->addGlobalNode($configXml, 'blocks', '_Block'); |
||
278 | $this->addGlobalNode($configXml, 'helpers', '_Helper'); |
||
279 | $this->addGlobalNode($configXml, 'models', '_Model'); |
||
280 | $this->addResourceModelNodeIfConfirmed($output, $configXml); |
||
281 | } else { |
||
282 | if ($this->shouldAddBlocks($input)) { |
||
283 | $this->addGlobalNode($configXml, 'blocks', '_Block'); |
||
284 | } |
||
285 | |||
286 | if ($this->shouldAddHelpers($input)) { |
||
287 | $this->addGlobalNode($configXml, 'helpers', '_Helper'); |
||
288 | } |
||
289 | |||
290 | if ($this->shouldAddModels($input)) { |
||
291 | $this->addGlobalNode($configXml, 'models', '_Model'); |
||
292 | $this->addResourceModelNodeIfConfirmed($output, $configXml); |
||
293 | } |
||
294 | } |
||
295 | } |
||
296 | |||
297 | /** |
||
298 | * @param OutputInterface $output |
||
299 | * @param SimpleXMLElement $configXml |
||
300 | */ |
||
301 | protected function addResourceModelNodeIfConfirmed(OutputInterface $output, \SimpleXMLElement $configXml) |
||
315 | |||
316 | /** |
||
317 | * @param InputInterface $input |
||
318 | * @param SimpleXMLElement $configXml |
||
319 | */ |
||
320 | protected function setResourceModelNode(InputInterface $input, \SimpleXMLElement $configXml) |
||
321 | { |
||
322 | if ($this->hasAddResourceModelOption($input)) { |
||
323 | $this->addResourceModel($configXml); |
||
324 | } |
||
325 | } |
||
326 | |||
327 | /** |
||
328 | * @param InputInterface $input |
||
329 | * @param SimpleXMLElement $configXml |
||
330 | */ |
||
331 | protected function setRoutersNode(InputInterface $input, \SimpleXMLElement $configXml) |
||
332 | { |
||
333 | if ($this->hasAddRoutersOption($input)) { |
||
334 | $this->addRouter($configXml, $this->configNodes['router_area']); |
||
335 | } |
||
336 | } |
||
337 | |||
338 | /** |
||
339 | * @param InputInterface $input |
||
340 | * @param SimpleXMLElement $configXml |
||
341 | */ |
||
342 | protected function setEventsNode(InputInterface $input, \SimpleXMLElement $configXml) |
||
343 | { |
||
344 | if ($this->hasAddEventsOption($input)) { |
||
345 | $this->addEvent($configXml, $this->configNodes['events_area'], $this->configNodes['event_name']); |
||
346 | } |
||
347 | } |
||
348 | |||
349 | /** |
||
350 | * @param InputInterface $input |
||
351 | * @param SimpleXMLElement $configXml |
||
352 | */ |
||
353 | protected function setLayoutUpdatesNode(InputInterface $input, \SimpleXMLElement $configXml) |
||
363 | |||
364 | /** |
||
365 | * @param InputInterface $input |
||
366 | * @param SimpleXMLElement $configXml |
||
367 | */ |
||
368 | protected function setTranslateNode(InputInterface $input, \SimpleXMLElement $configXml) |
||
378 | |||
379 | /** |
||
380 | * @param InputInterface $input |
||
381 | * @param SimpleXMLElement $configXml |
||
382 | */ |
||
383 | protected function setDefaultNode(InputInterface $input, \SimpleXMLElement $configXml) |
||
389 | |||
390 | /** |
||
391 | * Gets config XML |
||
392 | * |
||
393 | * @return SimpleXMLElement |
||
394 | */ |
||
395 | protected function getConfigXml() |
||
396 | { |
||
397 | $currentConfigXml = $this->getCurrentConfigContent(); |
||
398 | $simpleXml = new \SimpleXMLElement($currentConfigXml); |
||
399 | |||
400 | return $simpleXml; |
||
401 | } |
||
402 | |||
403 | /** |
||
404 | * Returns current content of /etc/config.xml |
||
405 | * |
||
406 | * @return string |
||
407 | */ |
||
408 | protected function getCurrentConfigContent() |
||
409 | { |
||
410 | $configFile = $this->getModuleDir() . '/etc/config.xml'; |
||
411 | |||
412 | return file_get_contents($configFile); |
||
413 | } |
||
414 | |||
415 | /** |
||
416 | * @return string |
||
417 | */ |
||
418 | protected function getModuleDir() |
||
424 | |||
425 | /** |
||
426 | * Initiates resource nodes specific values |
||
427 | */ |
||
428 | protected function initResourceModelConfigNodes() |
||
435 | |||
436 | /** |
||
437 | * Initiates routers config nodes specific values |
||
438 | */ |
||
439 | protected function initRoutersConfigNodes() |
||
445 | |||
446 | /** |
||
447 | * Initiates events config nodes specific values |
||
448 | */ |
||
449 | protected function initEventsConfigNodes() |
||
457 | |||
458 | /** |
||
459 | * Initiates layout updates nodes specific values |
||
460 | */ |
||
461 | protected function initLayoutUpdatesConfigNodes() |
||
467 | |||
468 | /** |
||
469 | * Initiates layout updates nodes specific values |
||
470 | */ |
||
471 | protected function initTranslateConfigNodes() |
||
477 | |||
478 | /** |
||
479 | * Initiates resource nodes specific values |
||
480 | */ |
||
481 | protected function initDefaultConfigNodes() |
||
488 | |||
489 | /** |
||
490 | * Asks for routers node options |
||
491 | * |
||
492 | * @param OutputInterface $output |
||
493 | * @throws RuntimeException |
||
494 | */ |
||
495 | protected function askResourceModelOptions(OutputInterface $output) |
||
496 | { |
||
497 | $this->initResourceModelConfigNodes(); |
||
498 | $dialog = $this->getDialog(); |
||
499 | |||
500 | if ($dialog->askConfirmation($output, |
||
501 | '<question>Would you like to set mysql4 deprecated node(y/n)?</question>', |
||
502 | false |
||
503 | ) |
||
504 | ) { |
||
505 | $this->configNodes['resource_deprecated_mysql4_node'] = true; |
||
506 | } |
||
507 | |||
508 | $entityName = true; |
||
509 | |||
510 | while ($entityName) { |
||
511 | $entityName = trim($dialog->ask($output, '<question>Entity Name (leave blank to exit):</question>')); |
||
512 | if (!$entityName) { |
||
513 | break; |
||
514 | } |
||
515 | $entityTable = trim($dialog->ask($output, '<question>Entity Table:</question>')); |
||
516 | $this->configNodes['resource_entities'][$entityName] = $entityTable; |
||
517 | } |
||
518 | } |
||
519 | |||
520 | /** |
||
521 | * Asks for routers node options |
||
522 | * |
||
523 | * @param OutputInterface $output |
||
524 | * @throws RuntimeException |
||
525 | */ |
||
526 | View Code Duplication | protected function askRoutersOptions(OutputInterface $output) |
|
|
|||
527 | { |
||
528 | $this->initRoutersConfigNodes(); |
||
529 | $dialog = $this->getDialog(); |
||
530 | $area = trim($dialog->ask($output, '<question>Area (frontend|admin):</question>')); |
||
531 | $use = trim($dialog->ask($output, '<question>Use:</question>')); |
||
532 | $frontName = trim($dialog->ask($output, '<question>Frontname:</question>')); |
||
533 | |||
534 | if ($area != 'frontend' && $area != 'admin') { |
||
535 | throw new RuntimeException('Router area must be either "frontend" or "admin"'); |
||
536 | } |
||
537 | |||
538 | $this->configNodes['router_area'] = $area; |
||
539 | $this->configNodes['use'] = $use; |
||
540 | $this->configNodes['frontname'] = $frontName; |
||
541 | } |
||
542 | |||
543 | /** |
||
544 | * Asks for events node options |
||
545 | * |
||
546 | * @param OutputInterface $output |
||
547 | * @throws RuntimeException |
||
548 | */ |
||
549 | protected function askEventsOptions(OutputInterface $output) |
||
569 | |||
570 | /** |
||
571 | * Asks for layout updates node options |
||
572 | * |
||
573 | * @param OutputInterface $output |
||
574 | * @throws RuntimeException |
||
575 | */ |
||
576 | View Code Duplication | protected function askLayoutUpdatesOptions(OutputInterface $output) |
|
592 | |||
593 | /** |
||
594 | * Asks for translate node options |
||
595 | * |
||
596 | * @param OutputInterface $output |
||
597 | * @throws RuntimeException |
||
598 | */ |
||
599 | protected function askTranslateOptions(OutputInterface $output) |
||
613 | |||
614 | /** |
||
615 | * Asks for default node options |
||
616 | * |
||
617 | * @param OutputInterface $output |
||
618 | * @throws RuntimeException |
||
619 | */ |
||
620 | protected function askDefaultOptions(OutputInterface $output) |
||
634 | |||
635 | /** |
||
636 | * @param SimpleXMLElement $configXml |
||
637 | * @param string $type e.g. "blocks" |
||
638 | * @param string $classSuffix e.g. "_Block" |
||
639 | */ |
||
640 | protected function addGlobalNode(\SimpleXMLElement $configXml, $type, $classSuffix) |
||
641 | { |
||
642 | $this->removeChildNodeIfNotNull($configXml->global, $type); |
||
643 | $global = $configXml->global ? $configXml->global : $configXml->addChild('global'); |
||
644 | $globalNode = $global->addChild($type); |
||
645 | $moduleNamespaceNode = $globalNode->addChild($this->getLowercaseModuleNamespace()); |
||
646 | $moduleNamespaceNode->addChild('class', $this->getModuleNamespace() . $classSuffix); |
||
647 | } |
||
648 | |||
649 | /** |
||
650 | * @param SimpleXMLElement $simpleXml |
||
651 | */ |
||
652 | protected function addResourceModel(\SimpleXMLElement $simpleXml) |
||
685 | |||
686 | /** |
||
687 | * @param SimpleXMLElement $simpleXml |
||
688 | * @param $area |
||
689 | */ |
||
690 | protected function addRouter(\SimpleXMLElement $simpleXml, $area) |
||
701 | |||
702 | /** |
||
703 | * @param SimpleXMLElement $simpleXml |
||
704 | * @param $area |
||
705 | * @param $event |
||
706 | */ |
||
707 | View Code Duplication | protected function addEvent(\SimpleXMLElement $simpleXml, $area, $event) |
|
708 | { |
||
709 | $areaNode = $simpleXml->{$area} ? $simpleXml->{$area} : $simpleXml->addChild($area); |
||
710 | $eventsNode = $areaNode->events ? $areaNode->events : $areaNode->addChild('events'); |
||
711 | $this->removeChildNodeIfNotNull($eventsNode, $event); |
||
712 | $eventNode = $eventsNode->addChild($event); |
||
713 | $observersNode = $eventNode->addChild('observers'); |
||
714 | $eventObserverNode = $observersNode->addChild($this->configNodes['event_observer']); |
||
715 | $eventObserverNode->addChild('class', $this->configNodes['event_observer_class']); |
||
716 | $eventObserverNode->addChild('method', $this->configNodes['event_observer_method']); |
||
717 | } |
||
718 | |||
719 | /** |
||
720 | * @param SimpleXMLElement $simpleXml |
||
721 | * @param $area |
||
722 | * @param $module |
||
723 | */ |
||
724 | protected function addLayoutUpdate(\SimpleXMLElement $simpleXml, $area, $module) |
||
733 | |||
734 | /** |
||
735 | * @param SimpleXMLElement $simpleXml |
||
736 | * @param $area |
||
737 | * @param $module |
||
738 | */ |
||
739 | View Code Duplication | protected function addTranslate(\SimpleXMLElement $simpleXml, $area, $module) |
|
749 | |||
750 | /** |
||
751 | * @param SimpleXMLElement $simpleXml |
||
752 | */ |
||
753 | protected function addDefault(\SimpleXMLElement $simpleXml) |
||
765 | |||
766 | /** |
||
767 | * @return string |
||
768 | */ |
||
769 | protected function getOutFile() |
||
770 | { |
||
771 | return $this->moduleDirectory . '/etc/config.xml'; |
||
772 | } |
||
773 | |||
774 | /** |
||
775 | * @param SimpleXMLElement $configXml |
||
776 | */ |
||
777 | protected function putConfigXml(SimpleXMLElement $configXml) |
||
778 | { |
||
779 | $outFile = $this->getOutFile(); |
||
780 | |||
781 | $xml = $configXml->asXML(); |
||
782 | if (false === $xml) { |
||
783 | throw new RuntimeException(sprintf('Failed to get XML from config SimpleXMLElement')); |
||
784 | } |
||
785 | |||
786 | file_put_contents($outFile, $this->asPrettyXml($xml)); |
||
787 | } |
||
788 | |||
789 | /** |
||
790 | * @param InputInterface $input |
||
791 | * @return mixed |
||
792 | */ |
||
793 | protected function hasAddResourceModelOption(InputInterface $input) |
||
794 | { |
||
795 | return $input->getOption('add-resource-model'); |
||
796 | } |
||
797 | |||
798 | /** |
||
799 | * @param InputInterface $input |
||
800 | * @return mixed |
||
801 | */ |
||
802 | protected function hasAddRoutersOption(InputInterface $input) |
||
803 | { |
||
804 | return $input->getOption('add-routers'); |
||
805 | } |
||
806 | |||
807 | /** |
||
808 | * @param InputInterface $input |
||
809 | * @return mixed |
||
810 | */ |
||
811 | protected function hasAddEventsOption(InputInterface $input) |
||
812 | { |
||
813 | return $input->getOption('add-events'); |
||
814 | } |
||
815 | |||
816 | /** |
||
817 | * @param InputInterface $input |
||
818 | * @return mixed |
||
819 | */ |
||
820 | protected function hasAddLayoutUpdatesOptions(InputInterface $input) |
||
821 | { |
||
822 | return $input->getOption('add-layout-updates'); |
||
823 | } |
||
824 | |||
825 | /** |
||
826 | * @param InputInterface $input |
||
827 | * @return mixed |
||
828 | */ |
||
829 | protected function hasAddTranslateOption(InputInterface $input) |
||
830 | { |
||
831 | return $input->getOption('add-translate'); |
||
832 | } |
||
833 | |||
834 | /** |
||
835 | * @param InputInterface $input |
||
836 | * @return mixed |
||
837 | */ |
||
838 | protected function hasAddDefaultOption(InputInterface $input) |
||
839 | { |
||
840 | return $input->getOption('add-default'); |
||
841 | } |
||
842 | |||
843 | /** |
||
844 | * @param InputInterface $input |
||
845 | * @return mixed |
||
846 | */ |
||
847 | protected function shouldSetVersion(InputInterface $input) |
||
848 | { |
||
849 | return $input->getOption('set-version'); |
||
850 | } |
||
851 | |||
852 | /** |
||
853 | * @param InputInterface $input |
||
854 | * @return mixed |
||
855 | */ |
||
856 | protected function shouldAddBlocks(InputInterface $input) |
||
857 | { |
||
858 | return $input->getOption('add-blocks'); |
||
859 | } |
||
860 | |||
861 | /** |
||
862 | * @param InputInterface $input |
||
863 | * @return mixed |
||
864 | */ |
||
865 | protected function shouldAddHelpers(InputInterface $input) |
||
866 | { |
||
867 | return $input->getOption('add-helpers'); |
||
868 | } |
||
869 | |||
870 | /** |
||
871 | * @param InputInterface $input |
||
872 | * @return mixed |
||
873 | */ |
||
874 | protected function shouldAddModels(InputInterface $input) |
||
875 | { |
||
876 | return $input->getOption('add-models'); |
||
877 | } |
||
878 | |||
879 | /** |
||
880 | * @param InputInterface $input |
||
881 | * @return mixed |
||
882 | */ |
||
883 | protected function shouldAddAll(InputInterface $input) |
||
884 | { |
||
885 | return $input->getOption('add-all'); |
||
886 | } |
||
887 | |||
888 | /** |
||
889 | * Gets module namespace e.g. Company_Modulename |
||
890 | * |
||
891 | * @return string |
||
892 | */ |
||
893 | protected function getModuleNamespace() |
||
894 | { |
||
895 | return $this->vendorNamespace . '_' . $this->moduleName; |
||
896 | } |
||
897 | |||
898 | /** |
||
899 | * @return string |
||
900 | */ |
||
901 | protected function getLowercaseModuleNamespace() |
||
902 | { |
||
903 | return strtolower($this->vendorNamespace . '_' . $this->moduleName); |
||
904 | } |
||
905 | |||
906 | /** |
||
907 | * @return string |
||
908 | */ |
||
909 | protected function getLowercaseModuleName() |
||
910 | { |
||
911 | return strtolower($this->moduleName); |
||
912 | } |
||
913 | |||
914 | /** |
||
915 | * Removes a child node if not null. |
||
916 | * Deals with duplications of nodes when already in config |
||
917 | * |
||
918 | * @param $node |
||
919 | * @param $child |
||
920 | */ |
||
921 | protected function removeChildNodeIfNotNull($node, $child) |
||
922 | { |
||
923 | if (!is_null($node->{$child})) { |
||
924 | unset($node->{$child}); |
||
925 | } |
||
926 | } |
||
927 | |||
928 | /** |
||
929 | * Formats given string as pretty xml |
||
930 | * |
||
931 | * @param string $string |
||
932 | * |
||
933 | * @return string |
||
934 | */ |
||
935 | protected function asPrettyXml($string) |
||
956 | } |
||
957 |
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.