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:
1 | <?php |
||
25 | class RestXmlCollectionLoader extends XmlFileLoader |
||
26 | { |
||
27 | protected $collectionParents = []; |
||
28 | private $processor; |
||
29 | private $includeFormat; |
||
30 | private $formats; |
||
31 | private $defaultFormat; |
||
32 | |||
33 | /** |
||
34 | * Initializes xml loader. |
||
35 | * |
||
36 | * @param FileLocatorInterface $locator |
||
37 | * @param RestRouteProcessor $processor |
||
38 | * @param bool $includeFormat |
||
39 | * @param string[] $formats |
||
40 | * @param string $defaultFormat |
||
41 | */ |
||
42 | 22 | View Code Duplication | public function __construct( |
56 | |||
57 | /** |
||
58 | * {@inheritdoc} |
||
59 | */ |
||
60 | 9 | protected function parseNode(RouteCollection $collection, \DOMElement $node, $path, $file) |
|
61 | { |
||
62 | 9 | switch ($node->tagName) { |
|
63 | 9 | case 'route': |
|
64 | 6 | $this->parseRoute($collection, $node, $path); |
|
65 | 6 | break; |
|
66 | 3 | case 'import': |
|
67 | 3 | $name = (string) $node->getAttribute('id'); |
|
68 | 3 | $resource = (string) $node->getAttribute('resource'); |
|
69 | 3 | $prefix = (string) $node->getAttribute('prefix'); |
|
70 | 3 | $namePrefix = (string) $node->getAttribute('name-prefix'); |
|
71 | 3 | $parent = (string) $node->getAttribute('parent'); |
|
72 | 3 | $type = (string) $node->getAttribute('type'); |
|
73 | 3 | $host = isset($config['host']) ? $config['host'] : null; |
|
74 | 3 | $currentDir = dirname($path); |
|
75 | |||
76 | 3 | $parents = []; |
|
77 | 3 | View Code Duplication | if (!empty($parent)) { |
78 | 3 | if (!isset($this->collectionParents[$parent])) { |
|
79 | 1 | throw new \InvalidArgumentException(sprintf('Cannot find parent resource with name %s', $parent)); |
|
80 | } |
||
81 | |||
82 | 2 | $parents = $this->collectionParents[$parent]; |
|
83 | 2 | } |
|
84 | |||
85 | 2 | $imported = $this->processor->importResource($this, $resource, $parents, $prefix, $namePrefix, $type, $currentDir); |
|
86 | |||
87 | 2 | if (!empty($name) && $imported instanceof RestRouteCollection) { |
|
88 | 2 | $parents[] = (!empty($prefix) ? $prefix.'/' : '').$imported->getSingularName(); |
|
89 | 2 | $prefix = null; |
|
90 | |||
91 | 2 | $this->collectionParents[$name] = $parents; |
|
92 | 2 | } |
|
93 | |||
94 | 2 | if (!empty($host)) { |
|
95 | $imported->setHost($host); |
||
96 | } |
||
97 | |||
98 | 2 | $imported->addPrefix($prefix); |
|
99 | 2 | $collection->addCollection($imported); |
|
100 | 2 | break; |
|
101 | default: |
||
102 | throw new \InvalidArgumentException(sprintf('Unable to parse tag "%s"', $node->tagName)); |
||
103 | 8 | } |
|
104 | 8 | } |
|
105 | |||
106 | /** |
||
107 | * {@inheritdoc} |
||
108 | */ |
||
109 | 6 | protected function parseRoute(RouteCollection $collection, \DOMElement $node, $path) |
|
179 | |||
180 | 6 | private function getOptions(\DOMElement $node) |
|
197 | |||
198 | /** |
||
199 | * {@inheritdoc} |
||
200 | */ |
||
201 | 2 | public function supports($resource, $type = null) |
|
207 | |||
208 | /** |
||
209 | * @param \DOMDocument $dom |
||
210 | * |
||
211 | * @throws \InvalidArgumentException When xml doesn't validate its xsd schema |
||
212 | */ |
||
213 | 10 | protected function validate(\DOMDocument $dom) |
|
214 | { |
||
215 | 10 | $restRoutinglocation = realpath(__DIR__.'/../../Resources/config/schema/routing/rest_routing-1.0.xsd'); |
|
216 | 10 | $restRoutinglocation = rawurlencode(str_replace('\\', '/', $restRoutinglocation)); |
|
217 | 10 | $routinglocation = realpath(__DIR__.'/../../Resources/config/schema/routing-1.0.xsd'); |
|
218 | 10 | $routinglocation = rawurlencode(str_replace('\\', '/', $routinglocation)); |
|
219 | $source = <<<EOF |
||
220 | <?xml version="1.0" encoding="utf-8" ?> |
||
221 | <xsd:schema xmlns="http://symfony.com/schema" |
||
222 | xmlns:xsd="http://www.w3.org/2001/XMLSchema" |
||
223 | targetNamespace="http://symfony.com/schema" |
||
224 | elementFormDefault="qualified"> |
||
225 | |||
226 | <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> |
||
227 | <xsd:import namespace="http://friendsofsymfony.github.com/schema/rest" schemaLocation="$restRoutinglocation" /> |
||
228 | 10 | <xsd:import namespace="http://symfony.com/schema/routing" schemaLocation="$routinglocation" /> |
|
229 | 10 | </xsd:schema> |
|
230 | 10 | EOF; |
|
231 | |||
232 | 10 | $current = libxml_use_internal_errors(true); |
|
233 | 10 | libxml_clear_errors(); |
|
234 | |||
235 | 10 | if (!$dom->schemaValidateSource($source)) { |
|
236 | 1 | throw new \InvalidArgumentException(implode("\n", $this->getXmlErrors_($current))); |
|
237 | } |
||
238 | 9 | libxml_use_internal_errors($current); |
|
239 | 9 | } |
|
240 | |||
241 | /** |
||
242 | * {@inheritdoc} |
||
243 | * |
||
244 | * @internal |
||
245 | */ |
||
246 | 10 | protected function loadFile($file) |
|
257 | |||
258 | /** |
||
259 | * Retrieves libxml errors and clears them. |
||
260 | * |
||
261 | * Note: The underscore postfix on the method name is to ensure compatibility with versions |
||
262 | * before 2.0.16 while working around a bug in PHP https://bugs.php.net/bug.php?id=62956 |
||
263 | * |
||
264 | * @param bool $internalErrors The previous state of internal errors to reset it |
||
265 | * |
||
266 | * @return array An array of libxml error strings |
||
267 | */ |
||
268 | 1 | private function getXmlErrors_($internalErrors) |
|
287 | } |
||
288 |
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.