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 HtmlMin 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 HtmlMin, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
21 | class HtmlMin implements HtmlMinInterface |
||
22 | { |
||
23 | /** |
||
24 | * @var string |
||
25 | */ |
||
26 | private static $regExSpace = "/[[:space:]]{2,}|[\r\n]/u"; |
||
27 | |||
28 | /** |
||
29 | * @var string[] |
||
30 | * |
||
31 | * @psalm-var list<string> |
||
32 | */ |
||
33 | private static $optional_end_tags = [ |
||
34 | 'html', |
||
35 | 'head', |
||
36 | 'body', |
||
37 | ]; |
||
38 | |||
39 | /** |
||
40 | * @var string[] |
||
41 | * |
||
42 | * @psalm-var list<string> |
||
43 | */ |
||
44 | private static $selfClosingTags = [ |
||
45 | 'area', |
||
46 | 'base', |
||
47 | 'basefont', |
||
48 | 'br', |
||
49 | 'col', |
||
50 | 'command', |
||
51 | 'embed', |
||
52 | 'frame', |
||
53 | 'hr', |
||
54 | 'img', |
||
55 | 'input', |
||
56 | 'isindex', |
||
57 | 'keygen', |
||
58 | 'link', |
||
59 | 'meta', |
||
60 | 'param', |
||
61 | 'source', |
||
62 | 'track', |
||
63 | 'wbr', |
||
64 | ]; |
||
65 | |||
66 | /** |
||
67 | * @var string[] |
||
68 | * |
||
69 | * @psalm-var array<string, string> |
||
70 | */ |
||
71 | private static $trimWhitespaceFromTags = [ |
||
72 | 'article' => '', |
||
73 | 'br' => '', |
||
74 | 'div' => '', |
||
75 | 'footer' => '', |
||
76 | 'hr' => '', |
||
77 | 'nav' => '', |
||
78 | 'p' => '', |
||
79 | 'script' => '', |
||
80 | ]; |
||
81 | |||
82 | /** |
||
83 | * @var array |
||
84 | */ |
||
85 | private static $booleanAttributes = [ |
||
86 | 'allowfullscreen' => '', |
||
87 | 'async' => '', |
||
88 | 'autofocus' => '', |
||
89 | 'autoplay' => '', |
||
90 | 'checked' => '', |
||
91 | 'compact' => '', |
||
92 | 'controls' => '', |
||
93 | 'declare' => '', |
||
94 | 'default' => '', |
||
95 | 'defaultchecked' => '', |
||
96 | 'defaultmuted' => '', |
||
97 | 'defaultselected' => '', |
||
98 | 'defer' => '', |
||
99 | 'disabled' => '', |
||
100 | 'enabled' => '', |
||
101 | 'formnovalidate' => '', |
||
102 | 'hidden' => '', |
||
103 | 'indeterminate' => '', |
||
104 | 'inert' => '', |
||
105 | 'ismap' => '', |
||
106 | 'itemscope' => '', |
||
107 | 'loop' => '', |
||
108 | 'multiple' => '', |
||
109 | 'muted' => '', |
||
110 | 'nohref' => '', |
||
111 | 'noresize' => '', |
||
112 | 'noshade' => '', |
||
113 | 'novalidate' => '', |
||
114 | 'nowrap' => '', |
||
115 | 'open' => '', |
||
116 | 'pauseonexit' => '', |
||
117 | 'readonly' => '', |
||
118 | 'required' => '', |
||
119 | 'reversed' => '', |
||
120 | 'scoped' => '', |
||
121 | 'seamless' => '', |
||
122 | 'selected' => '', |
||
123 | 'sortable' => '', |
||
124 | 'truespeed' => '', |
||
125 | 'typemustmatch' => '', |
||
126 | 'visible' => '', |
||
127 | ]; |
||
128 | |||
129 | /** |
||
130 | * @var array |
||
131 | */ |
||
132 | private static $skipTagsForRemoveWhitespace = [ |
||
133 | 'code', |
||
134 | 'pre', |
||
135 | 'script', |
||
136 | 'style', |
||
137 | 'textarea', |
||
138 | ]; |
||
139 | |||
140 | /** |
||
141 | * @var array |
||
142 | */ |
||
143 | private $protectedChildNodes = []; |
||
144 | |||
145 | /** |
||
146 | * @var string |
||
147 | */ |
||
148 | private $protectedChildNodesHelper = 'html-min--voku--saved-content'; |
||
149 | |||
150 | /** |
||
151 | * @var bool |
||
152 | */ |
||
153 | private $doOptimizeViaHtmlDomParser = true; |
||
154 | |||
155 | /** |
||
156 | * @var bool |
||
157 | */ |
||
158 | private $doOptimizeAttributes = true; |
||
159 | |||
160 | /** |
||
161 | * @var bool |
||
162 | */ |
||
163 | private $doRemoveComments = true; |
||
164 | |||
165 | /** |
||
166 | * @var bool |
||
167 | */ |
||
168 | private $doRemoveWhitespaceAroundTags = false; |
||
169 | |||
170 | /** |
||
171 | * @var bool |
||
172 | */ |
||
173 | private $doRemoveOmittedQuotes = true; |
||
174 | |||
175 | /** |
||
176 | * @var bool |
||
177 | */ |
||
178 | private $doRemoveOmittedHtmlTags = true; |
||
179 | |||
180 | /** |
||
181 | * @var bool |
||
182 | */ |
||
183 | private $doRemoveHttpPrefixFromAttributes = false; |
||
184 | |||
185 | /** |
||
186 | * @var bool |
||
187 | */ |
||
188 | private $doRemoveHttpsPrefixFromAttributes = false; |
||
189 | |||
190 | /** |
||
191 | * @var bool |
||
192 | */ |
||
193 | private $keepPrefixOnExternalAttributes = false; |
||
194 | |||
195 | /** |
||
196 | * @var bool |
||
197 | */ |
||
198 | private $doMakeSameDomainLinksRelative = false; |
||
199 | |||
200 | /** |
||
201 | * @var string |
||
202 | */ |
||
203 | private $localDomain = ''; |
||
204 | |||
205 | /** |
||
206 | * @var array |
||
207 | */ |
||
208 | private $domainsToRemoveHttpPrefixFromAttributes = [ |
||
209 | 'google.com', |
||
210 | 'google.de', |
||
211 | ]; |
||
212 | |||
213 | /** |
||
214 | * @var bool |
||
215 | */ |
||
216 | private $doSortCssClassNames = true; |
||
217 | |||
218 | /** |
||
219 | * @var bool |
||
220 | */ |
||
221 | private $doSortHtmlAttributes = true; |
||
222 | |||
223 | /** |
||
224 | * @var bool |
||
225 | */ |
||
226 | private $doRemoveDeprecatedScriptCharsetAttribute = true; |
||
227 | |||
228 | /** |
||
229 | * @var bool |
||
230 | */ |
||
231 | private $doRemoveDefaultAttributes = false; |
||
232 | |||
233 | /** |
||
234 | * @var bool |
||
235 | */ |
||
236 | private $doRemoveDeprecatedAnchorName = true; |
||
237 | |||
238 | /** |
||
239 | * @var bool |
||
240 | */ |
||
241 | private $doRemoveDeprecatedTypeFromStylesheetLink = true; |
||
242 | |||
243 | /** |
||
244 | * @var bool |
||
245 | */ |
||
246 | private $doRemoveDeprecatedTypeFromScriptTag = true; |
||
247 | |||
248 | /** |
||
249 | * @var bool |
||
250 | */ |
||
251 | private $doRemoveValueFromEmptyInput = true; |
||
252 | |||
253 | /** |
||
254 | * @var bool |
||
255 | */ |
||
256 | private $doRemoveEmptyAttributes = true; |
||
257 | |||
258 | /** |
||
259 | * @var bool |
||
260 | */ |
||
261 | private $doSumUpWhitespace = true; |
||
262 | |||
263 | /** |
||
264 | * @var bool |
||
265 | */ |
||
266 | private $doRemoveSpacesBetweenTags = false; |
||
267 | |||
268 | /** |
||
269 | * @var bool |
||
270 | */ |
||
271 | private $keepBrokenHtml = false; |
||
272 | |||
273 | /** |
||
274 | * @var bool |
||
275 | */ |
||
276 | private $withDocType = false; |
||
277 | |||
278 | /** |
||
279 | * @var HtmlMinDomObserverInterface[]|\SplObjectStorage |
||
280 | */ |
||
281 | private $domLoopObservers; |
||
282 | |||
283 | /** |
||
284 | * @var int |
||
285 | */ |
||
286 | private $protected_tags_counter = 0; |
||
287 | |||
288 | /** |
||
289 | * HtmlMin constructor. |
||
290 | */ |
||
291 | 55 | public function __construct() |
|
297 | |||
298 | /** |
||
299 | * @param HtmlMinDomObserverInterface $observer |
||
300 | * |
||
301 | * @return void |
||
302 | */ |
||
303 | 55 | public function attachObserverToTheDomLoop(HtmlMinDomObserverInterface $observer) |
|
307 | |||
308 | /** |
||
309 | * @param bool $doOptimizeAttributes |
||
310 | * |
||
311 | * @return $this |
||
312 | */ |
||
313 | 2 | public function doOptimizeAttributes(bool $doOptimizeAttributes = true): self |
|
319 | |||
320 | /** |
||
321 | * @param bool $doOptimizeViaHtmlDomParser |
||
322 | * |
||
323 | * @return $this |
||
324 | */ |
||
325 | 1 | public function doOptimizeViaHtmlDomParser(bool $doOptimizeViaHtmlDomParser = true): self |
|
331 | |||
332 | /** |
||
333 | * @param bool $doRemoveComments |
||
334 | * |
||
335 | * @return $this |
||
336 | */ |
||
337 | 3 | public function doRemoveComments(bool $doRemoveComments = true): self |
|
343 | |||
344 | /** |
||
345 | * @param bool $doRemoveDefaultAttributes |
||
346 | * |
||
347 | * @return $this |
||
348 | */ |
||
349 | 2 | public function doRemoveDefaultAttributes(bool $doRemoveDefaultAttributes = true): self |
|
355 | |||
356 | /** |
||
357 | * @param bool $doRemoveDeprecatedAnchorName |
||
358 | * |
||
359 | * @return $this |
||
360 | */ |
||
361 | 2 | public function doRemoveDeprecatedAnchorName(bool $doRemoveDeprecatedAnchorName = true): self |
|
367 | |||
368 | /** |
||
369 | * @param bool $doRemoveDeprecatedScriptCharsetAttribute |
||
370 | * |
||
371 | * @return $this |
||
372 | */ |
||
373 | 2 | public function doRemoveDeprecatedScriptCharsetAttribute(bool $doRemoveDeprecatedScriptCharsetAttribute = true): self |
|
379 | |||
380 | /** |
||
381 | * @param bool $doRemoveDeprecatedTypeFromScriptTag |
||
382 | * |
||
383 | * @return $this |
||
384 | */ |
||
385 | 2 | public function doRemoveDeprecatedTypeFromScriptTag(bool $doRemoveDeprecatedTypeFromScriptTag = true): self |
|
391 | |||
392 | /** |
||
393 | * @param bool $doRemoveDeprecatedTypeFromStylesheetLink |
||
394 | * |
||
395 | * @return $this |
||
396 | */ |
||
397 | 2 | public function doRemoveDeprecatedTypeFromStylesheetLink(bool $doRemoveDeprecatedTypeFromStylesheetLink = true): self |
|
403 | |||
404 | /** |
||
405 | * @param bool $doRemoveEmptyAttributes |
||
406 | * |
||
407 | * @return $this |
||
408 | */ |
||
409 | 2 | public function doRemoveEmptyAttributes(bool $doRemoveEmptyAttributes = true): self |
|
415 | |||
416 | /** |
||
417 | * @param bool $doRemoveHttpPrefixFromAttributes |
||
418 | * |
||
419 | * @return $this |
||
420 | */ |
||
421 | 6 | public function doRemoveHttpPrefixFromAttributes(bool $doRemoveHttpPrefixFromAttributes = true): self |
|
427 | |||
428 | /** |
||
429 | * @param bool $doRemoveHttpsPrefixFromAttributes |
||
430 | * |
||
431 | * @return $this |
||
432 | */ |
||
433 | 1 | public function doRemoveHttpsPrefixFromAttributes(bool $doRemoveHttpsPrefixFromAttributes = true): self |
|
439 | |||
440 | /** |
||
441 | * @param bool $keepPrefixOnExternalAttributes |
||
442 | * |
||
443 | * @return $this |
||
444 | */ |
||
445 | 1 | public function keepPrefixOnExternalAttributes(bool $keepPrefixOnExternalAttributes = true): self |
|
446 | { |
||
447 | 1 | $this->keepPrefixOnExternalAttributes = $keepPrefixOnExternalAttributes; |
|
448 | |||
449 | 1 | return $this; |
|
450 | } |
||
451 | |||
452 | /** |
||
453 | * @param bool $doMakeSameDomainLinksRelative |
||
454 | * |
||
455 | * @return $this |
||
456 | */ |
||
457 | 2 | public function doMakeSameDomainLinksRelative(bool $doMakeSameDomainLinksRelative = true): self |
|
458 | { |
||
459 | 2 | $this->doMakeSameDomainLinksRelative = $doMakeSameDomainLinksRelative; |
|
460 | |||
461 | 2 | return $this; |
|
462 | } |
||
463 | |||
464 | /** |
||
465 | * @param bool $setLocalDomain |
||
|
|||
466 | * |
||
467 | * @return $this |
||
468 | */ |
||
469 | 2 | public function setLocalDomain(string $localDomain = ''): self |
|
470 | { |
||
471 | 2 | if ($localDomain === ''){ |
|
472 | $this->localDomain = $_SERVER['SERVER_NAME']; |
||
473 | }else{ |
||
474 | 2 | $this->localDomain = rtrim(preg_replace('/(https?:)?\/\//', '', $localDomain), '/'); |
|
475 | } |
||
476 | |||
477 | 2 | return $this; |
|
478 | } |
||
479 | |||
480 | /** |
||
481 | * @param void |
||
482 | * |
||
483 | * @return $this->localDomain |
||
484 | */ |
||
485 | 2 | public function getLocalDomain(): string |
|
486 | { |
||
487 | 2 | return $this->localDomain; |
|
488 | } |
||
489 | |||
490 | /** |
||
491 | * @param bool $doRemoveOmittedHtmlTags |
||
492 | * |
||
493 | * @return $this |
||
494 | */ |
||
495 | 1 | public function doRemoveOmittedHtmlTags(bool $doRemoveOmittedHtmlTags = true): self |
|
501 | |||
502 | /** |
||
503 | * @param bool $doRemoveOmittedQuotes |
||
504 | * |
||
505 | * @return $this |
||
506 | */ |
||
507 | 1 | public function doRemoveOmittedQuotes(bool $doRemoveOmittedQuotes = true): self |
|
513 | |||
514 | /** |
||
515 | * @param bool $doRemoveSpacesBetweenTags |
||
516 | * |
||
517 | * @return $this |
||
518 | */ |
||
519 | 1 | public function doRemoveSpacesBetweenTags(bool $doRemoveSpacesBetweenTags = true): self |
|
525 | |||
526 | /** |
||
527 | * @param bool $doRemoveValueFromEmptyInput |
||
528 | * |
||
529 | * @return $this |
||
530 | */ |
||
531 | 2 | public function doRemoveValueFromEmptyInput(bool $doRemoveValueFromEmptyInput = true): self |
|
537 | |||
538 | /** |
||
539 | * @param bool $doRemoveWhitespaceAroundTags |
||
540 | * |
||
541 | * @return $this |
||
542 | */ |
||
543 | 5 | public function doRemoveWhitespaceAroundTags(bool $doRemoveWhitespaceAroundTags = true): self |
|
549 | |||
550 | /** |
||
551 | * @param bool $doSortCssClassNames |
||
552 | * |
||
553 | * @return $this |
||
554 | */ |
||
555 | 2 | public function doSortCssClassNames(bool $doSortCssClassNames = true): self |
|
561 | |||
562 | /** |
||
563 | * @param bool $doSortHtmlAttributes |
||
564 | * |
||
565 | * @return $this |
||
566 | */ |
||
567 | 2 | public function doSortHtmlAttributes(bool $doSortHtmlAttributes = true): self |
|
573 | |||
574 | /** |
||
575 | * @param bool $doSumUpWhitespace |
||
576 | * |
||
577 | * @return $this |
||
578 | */ |
||
579 | 2 | public function doSumUpWhitespace(bool $doSumUpWhitespace = true): self |
|
585 | |||
586 | 51 | private function domNodeAttributesToString(\DOMNode $node): string |
|
647 | |||
648 | /** |
||
649 | * @param \DOMNode $node |
||
650 | * |
||
651 | * @return bool |
||
652 | */ |
||
653 | 50 | private function domNodeClosingTagOptional(\DOMNode $node): bool |
|
908 | |||
909 | 51 | protected function domNodeToString(\DOMNode $node): string |
|
1021 | |||
1022 | /** |
||
1023 | * @return array |
||
1024 | */ |
||
1025 | public function getDomainsToRemoveHttpPrefixFromAttributes(): array |
||
1029 | |||
1030 | /** |
||
1031 | * @return bool |
||
1032 | */ |
||
1033 | public function isDoOptimizeAttributes(): bool |
||
1037 | |||
1038 | /** |
||
1039 | * @return bool |
||
1040 | */ |
||
1041 | public function isDoOptimizeViaHtmlDomParser(): bool |
||
1045 | |||
1046 | /** |
||
1047 | * @return bool |
||
1048 | */ |
||
1049 | public function isDoRemoveComments(): bool |
||
1053 | |||
1054 | /** |
||
1055 | * @return bool |
||
1056 | */ |
||
1057 | 34 | public function isDoRemoveDefaultAttributes(): bool |
|
1061 | |||
1062 | /** |
||
1063 | * @return bool |
||
1064 | */ |
||
1065 | 34 | public function isDoRemoveDeprecatedAnchorName(): bool |
|
1069 | |||
1070 | /** |
||
1071 | * @return bool |
||
1072 | */ |
||
1073 | 34 | public function isDoRemoveDeprecatedScriptCharsetAttribute(): bool |
|
1077 | |||
1078 | /** |
||
1079 | * @return bool |
||
1080 | */ |
||
1081 | 34 | public function isDoRemoveDeprecatedTypeFromScriptTag(): bool |
|
1085 | |||
1086 | /** |
||
1087 | * @return bool |
||
1088 | */ |
||
1089 | 34 | public function isDoRemoveDeprecatedTypeFromStylesheetLink(): bool |
|
1093 | |||
1094 | /** |
||
1095 | * @return bool |
||
1096 | */ |
||
1097 | 34 | public function isDoRemoveEmptyAttributes(): bool |
|
1101 | |||
1102 | /** |
||
1103 | * @return bool |
||
1104 | */ |
||
1105 | 34 | public function isDoRemoveHttpPrefixFromAttributes(): bool |
|
1109 | |||
1110 | /** |
||
1111 | * @return bool |
||
1112 | */ |
||
1113 | 34 | public function isDoRemoveHttpsPrefixFromAttributes(): bool |
|
1117 | |||
1118 | /** |
||
1119 | * @return bool |
||
1120 | */ |
||
1121 | 4 | public function isKeepPrefixOnExternalAttributes(): bool |
|
1125 | |||
1126 | /** |
||
1127 | * @return bool |
||
1128 | */ |
||
1129 | 34 | public function isDoMakeSameDomainLinksRelative(): bool |
|
1133 | |||
1134 | /** |
||
1135 | * @param bool |
||
1136 | */ |
||
1137 | 2 | public function isLocalDomainSet(): bool |
|
1138 | { |
||
1139 | 2 | return (!empty($this->localDomain)); |
|
1140 | } |
||
1141 | |||
1142 | /** |
||
1143 | * @return bool |
||
1144 | */ |
||
1145 | public function isDoRemoveOmittedHtmlTags(): bool |
||
1149 | |||
1150 | /** |
||
1151 | * @return bool |
||
1152 | */ |
||
1153 | public function isDoRemoveOmittedQuotes(): bool |
||
1157 | |||
1158 | /** |
||
1159 | * @return bool |
||
1160 | */ |
||
1161 | public function isDoRemoveSpacesBetweenTags(): bool |
||
1165 | |||
1166 | /** |
||
1167 | * @return bool |
||
1168 | */ |
||
1169 | 34 | public function isDoRemoveValueFromEmptyInput(): bool |
|
1173 | |||
1174 | /** |
||
1175 | * @return bool |
||
1176 | */ |
||
1177 | public function isDoRemoveWhitespaceAroundTags(): bool |
||
1181 | |||
1182 | /** |
||
1183 | * @return bool |
||
1184 | */ |
||
1185 | 34 | public function isDoSortCssClassNames(): bool |
|
1189 | |||
1190 | /** |
||
1191 | * @return bool |
||
1192 | */ |
||
1193 | 34 | public function isDoSortHtmlAttributes(): bool |
|
1197 | |||
1198 | /** |
||
1199 | * @return bool |
||
1200 | */ |
||
1201 | public function isDoSumUpWhitespace(): bool |
||
1205 | |||
1206 | /** |
||
1207 | * @param string $html |
||
1208 | * @param bool $multiDecodeNewHtmlEntity |
||
1209 | * |
||
1210 | * @return string |
||
1211 | */ |
||
1212 | 55 | public function minify($html, $multiDecodeNewHtmlEntity = false): string |
|
1337 | |||
1338 | /** |
||
1339 | * @param \DOMNode $node |
||
1340 | * |
||
1341 | * @return \DOMNode|null |
||
1342 | */ |
||
1343 | 50 | protected function getNextSiblingOfTypeDOMElement(\DOMNode $node) |
|
1352 | |||
1353 | /** |
||
1354 | * Check if the current string is an conditional comment. |
||
1355 | * |
||
1356 | * INFO: since IE >= 10 conditional comment are not working anymore |
||
1357 | * |
||
1358 | * <!--[if expression]> HTML <![endif]--> |
||
1359 | * <![if expression]> HTML <![endif]> |
||
1360 | * |
||
1361 | * @param string $comment |
||
1362 | * |
||
1363 | * @return bool |
||
1364 | */ |
||
1365 | 4 | private function isConditionalComment($comment): bool |
|
1383 | |||
1384 | /** |
||
1385 | * @param string $html |
||
1386 | * @param bool $multiDecodeNewHtmlEntity |
||
1387 | * |
||
1388 | * @return string |
||
1389 | */ |
||
1390 | 51 | private function minifyHtmlDom($html, $multiDecodeNewHtmlEntity): string |
|
1391 | { |
||
1392 | // init dom |
||
1393 | 51 | $dom = new HtmlDomParser(); |
|
1394 | /** @noinspection UnusedFunctionResultInspection */ |
||
1395 | 51 | $dom->useKeepBrokenHtml($this->keepBrokenHtml); |
|
1396 | |||
1397 | 51 | $dom->getDocument()->preserveWhiteSpace = false; // remove redundant white space |
|
1398 | 51 | $dom->getDocument()->formatOutput = false; // do not formats output with indentation |
|
1399 | |||
1400 | // load dom |
||
1401 | /** @noinspection UnusedFunctionResultInspection */ |
||
1402 | 51 | $dom->loadHtml($html); |
|
1403 | |||
1404 | 51 | $this->withDocType = (\stripos(\ltrim($html), '<!DOCTYPE') === 0); |
|
1405 | |||
1406 | // ------------------------------------------------------------------------- |
||
1407 | // Protect <nocompress> HTML tags first. |
||
1408 | // ------------------------------------------------------------------------- |
||
1409 | |||
1410 | 51 | $dom = $this->protectTagHelper($dom, 'nocompress'); |
|
1411 | |||
1412 | // ------------------------------------------------------------------------- |
||
1413 | // Notify the Observer before the minification. |
||
1414 | // ------------------------------------------------------------------------- |
||
1415 | |||
1416 | 51 | foreach ($dom->find('*') as $element) { |
|
1417 | 51 | $this->notifyObserversAboutDomElementBeforeMinification($element); |
|
1418 | } |
||
1419 | |||
1420 | // ------------------------------------------------------------------------- |
||
1421 | // Protect HTML tags and conditional comments. |
||
1422 | // ------------------------------------------------------------------------- |
||
1423 | |||
1424 | 51 | $dom = $this->protectTags($dom); |
|
1425 | |||
1426 | // ------------------------------------------------------------------------- |
||
1427 | // Remove default HTML comments. [protected html is still protected] |
||
1428 | // ------------------------------------------------------------------------- |
||
1429 | |||
1430 | 51 | if ($this->doRemoveComments) { |
|
1431 | 49 | $dom = $this->removeComments($dom); |
|
1432 | } |
||
1433 | |||
1434 | // ------------------------------------------------------------------------- |
||
1435 | // Sum-Up extra whitespace from the Dom. [protected html is still protected] |
||
1436 | // ------------------------------------------------------------------------- |
||
1437 | |||
1438 | 51 | if ($this->doSumUpWhitespace) { |
|
1439 | 50 | $dom = $this->sumUpWhitespace($dom); |
|
1440 | } |
||
1441 | |||
1442 | 51 | foreach ($dom->find('*') as $element) { |
|
1443 | |||
1444 | // ------------------------------------------------------------------------- |
||
1445 | // Remove whitespace around tags. [protected html is still protected] |
||
1446 | // ------------------------------------------------------------------------- |
||
1447 | |||
1448 | 51 | if ($this->doRemoveWhitespaceAroundTags) { |
|
1449 | 3 | $this->removeWhitespaceAroundTags($element); |
|
1450 | } |
||
1451 | |||
1452 | // ------------------------------------------------------------------------- |
||
1453 | // Notify the Observer after the minification. |
||
1454 | // ------------------------------------------------------------------------- |
||
1455 | |||
1456 | 51 | $this->notifyObserversAboutDomElementAfterMinification($element); |
|
1457 | } |
||
1458 | |||
1459 | // ------------------------------------------------------------------------- |
||
1460 | // Convert the Dom into a string. |
||
1461 | // ------------------------------------------------------------------------- |
||
1462 | |||
1463 | 51 | return $dom->fixHtmlOutput( |
|
1464 | 51 | $this->domNodeToString($dom->getDocument()), |
|
1465 | $multiDecodeNewHtmlEntity |
||
1466 | ); |
||
1467 | } |
||
1468 | |||
1469 | /** |
||
1470 | * @param SimpleHtmlDomInterface $domElement |
||
1471 | * |
||
1472 | * @return void |
||
1473 | */ |
||
1474 | 51 | private function notifyObserversAboutDomElementAfterMinification(SimpleHtmlDomInterface $domElement) |
|
1480 | |||
1481 | /** |
||
1482 | * @param SimpleHtmlDomInterface $domElement |
||
1483 | * |
||
1484 | * @return void |
||
1485 | */ |
||
1486 | 51 | private function notifyObserversAboutDomElementBeforeMinification(SimpleHtmlDomInterface $domElement) |
|
1492 | |||
1493 | /** |
||
1494 | * @param HtmlDomParser $dom |
||
1495 | * @param string $selector |
||
1496 | * |
||
1497 | * @return HtmlDomParser |
||
1498 | */ |
||
1499 | 51 | private function protectTagHelper(HtmlDomParser $dom, string $selector): HtmlDomParser |
|
1517 | |||
1518 | /** |
||
1519 | * Prevent changes of inline "styles" and "scripts". |
||
1520 | * |
||
1521 | * @param HtmlDomParser $dom |
||
1522 | * |
||
1523 | * @return HtmlDomParser |
||
1524 | */ |
||
1525 | 51 | private function protectTags(HtmlDomParser $dom): HtmlDomParser |
|
1575 | |||
1576 | /** |
||
1577 | * Remove comments in the dom. |
||
1578 | * |
||
1579 | * @param HtmlDomParser $dom |
||
1580 | * |
||
1581 | * @return HtmlDomParser |
||
1582 | */ |
||
1583 | 49 | private function removeComments(HtmlDomParser $dom): HtmlDomParser |
|
1600 | |||
1601 | /** |
||
1602 | * Trim tags in the dom. |
||
1603 | * |
||
1604 | * @param SimpleHtmlDomInterface $element |
||
1605 | * |
||
1606 | * @return void |
||
1607 | */ |
||
1608 | 3 | private function removeWhitespaceAroundTags(SimpleHtmlDomInterface $element) |
|
1637 | |||
1638 | /** |
||
1639 | * Callback function for preg_replace_callback use. |
||
1640 | * |
||
1641 | * @param array $matches PREG matches |
||
1642 | * |
||
1643 | * @return string |
||
1644 | */ |
||
1645 | 9 | private function restoreProtectedHtml($matches): string |
|
1651 | |||
1652 | /** |
||
1653 | * @param array $domainsToRemoveHttpPrefixFromAttributes |
||
1654 | * |
||
1655 | * @return $this |
||
1656 | */ |
||
1657 | 2 | public function setDomainsToRemoveHttpPrefixFromAttributes($domainsToRemoveHttpPrefixFromAttributes): self |
|
1663 | |||
1664 | /** |
||
1665 | * Sum-up extra whitespace from dom-nodes. |
||
1666 | * |
||
1667 | * @param HtmlDomParser $dom |
||
1668 | * |
||
1669 | * @return HtmlDomParser |
||
1670 | */ |
||
1671 | 50 | private function sumUpWhitespace(HtmlDomParser $dom): HtmlDomParser |
|
1704 | |||
1705 | /** |
||
1706 | * WARNING: maybe bad for performance ... |
||
1707 | * |
||
1708 | * @param bool $keepBrokenHtml |
||
1709 | * |
||
1710 | * @return HtmlMin |
||
1711 | */ |
||
1712 | 2 | public function useKeepBrokenHtml(bool $keepBrokenHtml): self |
|
1718 | } |
||
1719 |
This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function. It has, however, found a similar but not annotated parameter which might be a good fit.
Consider the following example. The parameter
$ireland
is not defined by the methodfinale(...)
.The most likely cause is that the parameter was changed, but the annotation was not.