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 |
||
31 | class GlW3CValidator |
||
32 | { |
||
33 | const MAX_RETRY = 3; |
||
34 | |||
35 | private $types = [ |
||
36 | 'html' => [ |
||
37 | 'validator' => '/', |
||
38 | 'selector' => '.success', |
||
39 | 'resulttag' => '#results', |
||
40 | 'field' => 'file', |
||
41 | 'css' => [ |
||
42 | '/style.css' |
||
43 | ] |
||
44 | ], |
||
45 | 'css' => [ |
||
46 | 'validator' => '/validator', |
||
47 | 'selector' => '#congrats', |
||
48 | 'resulttag' => '#results_container', |
||
49 | 'field' => 'file', |
||
50 | 'css' => [ |
||
51 | '/style/base.css', |
||
52 | '/style/results.css' |
||
53 | ] |
||
54 | ] |
||
55 | ]; |
||
56 | |||
57 | /** |
||
58 | * @var \Symfony\Component\Filesystem\Filesystem |
||
59 | */ |
||
60 | private $fs; |
||
61 | |||
62 | /** |
||
63 | * @var string |
||
64 | */ |
||
65 | private $resultrootdir; |
||
66 | |||
67 | /** |
||
68 | * @param string $resultrootdir |
||
69 | * @param string $urlHtmlValidator |
||
70 | * @param string $urlCssValidator |
||
71 | */ |
||
72 | public function __construct( |
||
73 | $resultrootdir, |
||
74 | $urlHtmlValidator = "https://validator.w3.org/nu", |
||
75 | $urlCssValidator = "http://jigsaw.w3.org/css-validator" |
||
76 | ) { |
||
77 | $this->fs = new Filesystem(); |
||
78 | $this->resultrootdir = $resultrootdir; |
||
79 | |||
80 | $this->types['html']['w3curl'] = $urlHtmlValidator; |
||
81 | $this->types['css']['w3curl'] = $urlCssValidator; |
||
82 | |||
83 | if (!($this->fs->exists($resultrootdir))) { |
||
84 | $this->fs->mkdir($resultrootdir); |
||
85 | } |
||
86 | } |
||
87 | |||
88 | /** |
||
89 | * @param string $w3curl |
||
90 | * @param string $validator |
||
91 | * @param string $selector |
||
92 | * @param string $field |
||
93 | * @param string $htmltag |
||
94 | * @param string $file |
||
95 | * @param string $title |
||
96 | * @param array $csslist |
||
97 | * |
||
98 | * @return string |
||
99 | */ |
||
100 | private function sendToW3C($w3curl, $validator, $selector, $field, $htmltag, $file, $title, $csslist) |
||
101 | { |
||
102 | $client = new Client(); |
||
103 | |||
104 | $retry = self::MAX_RETRY; |
||
105 | $response = null; |
||
106 | while ($retry--) { |
||
107 | $response = $client->post($w3curl . $validator, |
||
108 | [ |
||
109 | 'exceptions' => false, |
||
110 | 'verify' => false, |
||
111 | 'multipart' => [['name' => $field, 'contents' => fopen($file, 'r')]] |
||
112 | ] |
||
113 | ); |
||
114 | if ($response->getStatusCode() == 200) { |
||
115 | break; |
||
116 | } |
||
117 | } |
||
118 | |||
119 | $html = $response->getBody()->getContents(); |
||
120 | |||
121 | $html = new GlHtml($html); |
||
122 | |||
123 | if ($html->get($selector)) { |
||
124 | return null; |
||
125 | } |
||
126 | |||
127 | $html->delete('#w3c-include'); |
||
128 | $html->delete('head style'); |
||
129 | $style = '<style type="text/css" media="all">'; |
||
130 | foreach ($csslist as $css) { |
||
131 | $style .= '@import url("' . $w3curl . $css . '");'; |
||
132 | } |
||
133 | $style .= '</style>'; |
||
134 | $html->get("head")[0]->add($style); |
||
135 | |||
136 | |||
137 | $stats = $html->get("p.stats"); |
||
138 | if (isset($stats) && count($stats) > 0) { |
||
139 | $stats[0]->delete(); |
||
140 | } |
||
141 | |||
142 | $head = $html->get("head")[0]->getHtml(); |
||
143 | |||
144 | $resulttag = $html->get($htmltag); |
||
145 | if (count($resulttag) <= 0) { |
||
146 | $result = '<p class="failure">There were errors.</p>'; |
||
147 | } else { |
||
148 | $result = $resulttag[0]->getHtml(); |
||
149 | } |
||
150 | |||
151 | $view = '<!DOCTYPE html><html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8">' . |
||
152 | $head . "</head><body><h2>$title</h2>" . |
||
153 | $result . "</body></html>"; |
||
154 | |||
155 | return $view; |
||
156 | } |
||
157 | |||
158 | /** |
||
159 | * @param SplFileInfo $fileinfo |
||
160 | * |
||
161 | * @throws \Exception |
||
162 | * @return string |
||
163 | */ |
||
164 | private function validateFile(SplFileInfo $fileinfo) |
||
192 | |||
193 | /** |
||
194 | * @param array $files |
||
195 | * @param array $types |
||
196 | * @param callable $callback |
||
197 | * |
||
198 | * @throws \Exception |
||
199 | * @return array |
||
200 | */ |
||
201 | public function validate(array $files, array $types, callable $callback) |
||
220 | |||
221 | |||
222 | /** |
||
223 | * @param Finder $files |
||
224 | * @param string $filter |
||
225 | * @param callable $callback |
||
226 | * @param array $result |
||
227 | */ |
||
228 | private function validateFinder(Finder $files, $filter, callable $callback, array &$result) |
||
241 | |||
242 | /** |
||
243 | * @param string $file |
||
244 | * @param string $filter |
||
245 | * @param callable $callback |
||
246 | * @param array $result |
||
247 | */ |
||
248 | private function validateDirect($file, $filter, callable $callback, array &$result) |
||
274 | } |
||
275 |
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.