Complex classes like CssToInlineStyles 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 CssToInlineStyles, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 14 | class CssToInlineStyles |
||
| 15 | { |
||
| 16 | |||
| 17 | /** |
||
| 18 | * @var CssSelectorConverter |
||
| 19 | */ |
||
| 20 | private $cssConverter; |
||
| 21 | |||
| 22 | /** |
||
| 23 | * regular expression: css media queries |
||
| 24 | * |
||
| 25 | * @var string |
||
| 26 | */ |
||
| 27 | private static $cssMediaQueriesRegEx = '#@media\\s+(?:only\\s)?(?:[\\s{\\(]|screen|all)\\s?[^{]+{.*}\\s*}\\s*#misU'; |
||
| 28 | |||
| 29 | /** |
||
| 30 | * regular expression: css charset |
||
| 31 | * |
||
| 32 | * @var string |
||
| 33 | */ |
||
| 34 | private static $cssCharsetRegEx = '/@charset [\'"][^\'"]+[\'"];/i'; |
||
| 35 | |||
| 36 | /** |
||
| 37 | * regular expression: conditional inline style tags |
||
| 38 | * |
||
| 39 | * @var string |
||
| 40 | */ |
||
| 41 | private static $excludeConditionalInlineStylesBlockRegEx = '/<!--\[if.*<style.*-->/isU'; |
||
| 42 | |||
| 43 | /** |
||
| 44 | * regular expression: inline style tags |
||
| 45 | * |
||
| 46 | * @var string |
||
| 47 | */ |
||
| 48 | private static $styleTagRegEx = '|<style(?:\s.*)?>(.*)</style>|isU'; |
||
| 49 | |||
| 50 | /** |
||
| 51 | * regular expression: html-comments without conditional comments |
||
| 52 | * |
||
| 53 | * @var string |
||
| 54 | */ |
||
| 55 | private static $htmlCommentWithoutConditionalCommentRegEx = '|<!--(?!\[if).*?-->|isU'; |
||
| 56 | |||
| 57 | /** |
||
| 58 | * regular expression: style-tag with 'cleanup'-css-class |
||
| 59 | * |
||
| 60 | * @var string |
||
| 61 | */ |
||
| 62 | private static $styleTagWithCleanupClassRegEx = '|<style[^>]+class="cleanup"[^>]*>.*</style>|isU'; |
||
| 63 | |||
| 64 | /** |
||
| 65 | * regular expression: css-comments |
||
| 66 | * |
||
| 67 | * @var string |
||
| 68 | */ |
||
| 69 | private static $styleCommentRegEx = '/\\/\\*.*\\*\\//sU'; |
||
| 70 | |||
| 71 | /** |
||
| 72 | * The CSS to use. |
||
| 73 | * |
||
| 74 | * @var string |
||
| 75 | */ |
||
| 76 | private $css; |
||
| 77 | |||
| 78 | /** |
||
| 79 | * The CSS-Media-Queries to use. |
||
| 80 | * |
||
| 81 | * @var string |
||
| 82 | */ |
||
| 83 | private $css_media_queries; |
||
| 84 | |||
| 85 | /** |
||
| 86 | * Should the generated HTML be cleaned. |
||
| 87 | * |
||
| 88 | * @var bool |
||
| 89 | */ |
||
| 90 | private $cleanup = false; |
||
| 91 | |||
| 92 | /** |
||
| 93 | * The encoding to use. |
||
| 94 | * |
||
| 95 | * @var string |
||
| 96 | */ |
||
| 97 | private $encoding = 'UTF-8'; |
||
| 98 | |||
| 99 | /** |
||
| 100 | * The HTML to process. |
||
| 101 | * |
||
| 102 | * @var string |
||
| 103 | */ |
||
| 104 | private $html; |
||
| 105 | |||
| 106 | /** |
||
| 107 | * Use inline-styles block as CSS. |
||
| 108 | * |
||
| 109 | * @var bool |
||
| 110 | */ |
||
| 111 | private $useInlineStylesBlock = false; |
||
| 112 | |||
| 113 | /** |
||
| 114 | * Use link block reference as CSS. |
||
| 115 | * |
||
| 116 | * @var bool |
||
| 117 | */ |
||
| 118 | private $loadCSSFromHTML = false; |
||
| 119 | |||
| 120 | /** |
||
| 121 | * Strip original style tags. |
||
| 122 | * |
||
| 123 | * @var bool |
||
| 124 | */ |
||
| 125 | private $stripOriginalStyleTags = false; |
||
| 126 | |||
| 127 | /** |
||
| 128 | * Exclude conditional inline-style blocks. |
||
| 129 | * |
||
| 130 | * @var bool |
||
| 131 | */ |
||
| 132 | private $excludeConditionalInlineStylesBlock = true; |
||
| 133 | |||
| 134 | /** |
||
| 135 | * Exclude media queries from "$this->css" and keep media queries for inline-styles blocks. |
||
| 136 | * |
||
| 137 | * @var bool |
||
| 138 | */ |
||
| 139 | private $excludeMediaQueries = true; |
||
| 140 | |||
| 141 | /** |
||
| 142 | * Exclude media queries from "$this->css" and keep media queries for inline-styles blocks. |
||
| 143 | * |
||
| 144 | * @var bool |
||
| 145 | */ |
||
| 146 | private $excludeCssCharset = true; |
||
| 147 | |||
| 148 | /** |
||
| 149 | * Creates an instance, you could set the HTML and CSS here, or load it later. |
||
| 150 | * |
||
| 151 | * @param null|string $html The HTML to process. |
||
| 152 | * @param null|string $css The CSS to use. |
||
| 153 | */ |
||
| 154 | 56 | public function __construct($html = null, $css = null) |
|
| 168 | |||
| 169 | /** |
||
| 170 | * Set HTML to process. |
||
| 171 | * |
||
| 172 | * @param string $html The HTML to process. |
||
| 173 | * |
||
| 174 | * @return $this |
||
| 175 | */ |
||
| 176 | 54 | public function setHTML($html) |
|
| 183 | |||
| 184 | /** |
||
| 185 | * Set CSS to use. |
||
| 186 | * |
||
| 187 | * @param string $css The CSS to use. |
||
| 188 | * |
||
| 189 | * @return $this |
||
| 190 | */ |
||
| 191 | 49 | public function setCSS($css) |
|
| 199 | |||
| 200 | /** |
||
| 201 | * Sort an array on the specificity element in an ascending way. |
||
| 202 | * |
||
| 203 | * INFO: Lower specificity will be sorted to the beginning of the array. |
||
| 204 | * |
||
| 205 | * @param Specificity[] $e1 The first element. |
||
| 206 | * @param Specificity[] $e2 The second element. |
||
| 207 | * |
||
| 208 | * @return int |
||
| 209 | */ |
||
| 210 | 23 | private static function sortOnSpecificity($e1, $e2) |
|
| 222 | |||
| 223 | /** |
||
| 224 | * Converts the loaded HTML into an HTML-string with inline styles based on the loaded CSS. |
||
| 225 | * |
||
| 226 | * @param bool $outputXHTML [optional] Should we output valid XHTML? |
||
| 227 | * @param int|null $libXMLExtraOptions [optional] $libXMLExtraOptions Since PHP 5.4.0 and Libxml 2.6.0, |
||
| 228 | * you may also use the options parameter to specify additional |
||
| 229 | * Libxml parameters. |
||
| 230 | * @param bool $path [optional] Set the path to your external css-files. |
||
| 231 | * |
||
| 232 | * @return string |
||
| 233 | * |
||
| 234 | * @throws Exception |
||
| 235 | */ |
||
| 236 | 54 | public function convert($outputXHTML = false, $libXMLExtraOptions = null, $path = false) |
|
| 312 | |||
| 313 | /** |
||
| 314 | * get css from inline-html style-block |
||
| 315 | * |
||
| 316 | * @param string $html |
||
| 317 | * |
||
| 318 | * @return string |
||
| 319 | */ |
||
| 320 | 32 | public function getCssFromInlineHtmlStyleBlock($html) |
|
| 341 | |||
| 342 | /** |
||
| 343 | * Process the loaded CSS |
||
| 344 | * |
||
| 345 | * @param string $css |
||
| 346 | * |
||
| 347 | * @return array |
||
| 348 | */ |
||
| 349 | 53 | private function processCSS($css) |
|
| 419 | |||
| 420 | /** |
||
| 421 | * @param string $css |
||
| 422 | * |
||
| 423 | * @return string |
||
| 424 | */ |
||
| 425 | 53 | private function doCleanup($css) |
|
| 452 | |||
| 453 | /** |
||
| 454 | * remove css media queries from the string |
||
| 455 | * |
||
| 456 | * @param string $css |
||
| 457 | * |
||
| 458 | * @return string |
||
| 459 | */ |
||
| 460 | 51 | private function stripeMediaQueries($css) |
|
| 467 | |||
| 468 | /** |
||
| 469 | * get css media queries from the string |
||
| 470 | * |
||
| 471 | * @param string $css |
||
| 472 | * |
||
| 473 | * @return string |
||
| 474 | */ |
||
| 475 | 49 | private function getMediaQueries($css) |
|
| 484 | |||
| 485 | /** |
||
| 486 | * remove charset from the string |
||
| 487 | * |
||
| 488 | * @param string $css |
||
| 489 | * |
||
| 490 | * @return string |
||
| 491 | */ |
||
| 492 | 53 | private function stripeCharsetInCss($css) |
|
| 496 | |||
| 497 | /** |
||
| 498 | * Process the CSS-properties |
||
| 499 | * |
||
| 500 | * @return array |
||
| 501 | * |
||
| 502 | * @param string $propertyString The CSS-properties. |
||
| 503 | */ |
||
| 504 | 40 | private function processCSSProperties($propertyString) |
|
| 542 | |||
| 543 | /** |
||
| 544 | * Split a style string into an array of properties. |
||
| 545 | * The returned array can contain empty strings. |
||
| 546 | * |
||
| 547 | * @param string $styles ex: 'color:blue;font-size:12px;' |
||
| 548 | * |
||
| 549 | * @return array an array of strings containing css property ex: array('color:blue','font-size:12px') |
||
| 550 | */ |
||
| 551 | 40 | private function splitIntoProperties($styles) |
|
| 573 | |||
| 574 | /** |
||
| 575 | * create XPath |
||
| 576 | * |
||
| 577 | * @param \DOMDocument $document |
||
| 578 | * @param array $cssRules |
||
| 579 | * |
||
| 580 | * @return \DOMXPath |
||
| 581 | */ |
||
| 582 | 53 | private function createXPath(\DOMDocument $document, array $cssRules) |
|
| 685 | |||
| 686 | /** |
||
| 687 | * @param \DOMElement $element |
||
| 688 | * @param array $ruleProperties |
||
| 689 | * |
||
| 690 | * @return string |
||
| 691 | */ |
||
| 692 | 38 | private function createPropertyChunks(\DOMElement $element, array $ruleProperties) |
|
| 739 | |||
| 740 | /** |
||
| 741 | * @param array $definedProperties |
||
| 742 | * |
||
| 743 | * @return array |
||
| 744 | */ |
||
| 745 | 38 | private function splitStyleIntoChunks(array $definedProperties) |
|
| 775 | |||
| 776 | /** |
||
| 777 | * Strip style tags into the generated HTML. |
||
| 778 | * |
||
| 779 | * @param \DOMXPath $xPath The DOMXPath for the entire document. |
||
| 780 | */ |
||
| 781 | 13 | private function stripOriginalStyleTags(\DOMXPath $xPath) |
|
| 803 | |||
| 804 | /** |
||
| 805 | * Remove id and class attributes. |
||
| 806 | * |
||
| 807 | * @param \DOMXPath $xPath The DOMXPath for the entire document. |
||
| 808 | */ |
||
| 809 | 3 | private function cleanupHTML(\DOMXPath $xPath) |
|
| 816 | |||
| 817 | /** |
||
| 818 | * Should the IDs and classes be removed? |
||
| 819 | * |
||
| 820 | * @param bool $on Should we enable cleanup? |
||
| 821 | * |
||
| 822 | * @return $this |
||
| 823 | */ |
||
| 824 | 3 | public function setCleanup($on = true) |
|
| 830 | |||
| 831 | /** |
||
| 832 | * Set the encoding to use with the DOMDocument. |
||
| 833 | * |
||
| 834 | * @param string $encoding The encoding to use. |
||
| 835 | * |
||
| 836 | * @return $this |
||
| 837 | * |
||
| 838 | * @deprecated Doesn't have any effect |
||
| 839 | */ |
||
| 840 | public function setEncoding($encoding) |
||
| 846 | |||
| 847 | /** |
||
| 848 | * Set use of inline styles block. |
||
| 849 | * |
||
| 850 | * Info: If this is enabled the class will use the style-block in the HTML. |
||
| 851 | * |
||
| 852 | * @param bool $on Should we process inline styles? |
||
| 853 | * |
||
| 854 | * @return $this |
||
| 855 | */ |
||
| 856 | 30 | public function setUseInlineStylesBlock($on = true) |
|
| 862 | |||
| 863 | /** |
||
| 864 | * Set use of inline link block. |
||
| 865 | * |
||
| 866 | * Info: If this is enabled the class will use the links reference in the HTML. |
||
| 867 | * |
||
| 868 | * @param bool [optional] $on Should we process link styles? |
||
| 869 | * |
||
| 870 | * @return $this |
||
| 871 | */ |
||
| 872 | 2 | public function setLoadCSSFromHTML($on = true) |
|
| 878 | |||
| 879 | /** |
||
| 880 | * Set strip original style tags. |
||
| 881 | * |
||
| 882 | * Info: If this is enabled the class will remove all style tags in the HTML. |
||
| 883 | * |
||
| 884 | * @param bool $on Should we process inline styles? |
||
| 885 | * |
||
| 886 | * @return $this |
||
| 887 | */ |
||
| 888 | 17 | public function setStripOriginalStyleTags($on = true) |
|
| 894 | |||
| 895 | /** |
||
| 896 | * Set exclude media queries. |
||
| 897 | * |
||
| 898 | * Info: If this is enabled the media queries will be removed before inlining the rules. |
||
| 899 | * |
||
| 900 | * WARNING: If you use inline styles block "<style>" the this option will keep the media queries. |
||
| 901 | * |
||
| 902 | * @param bool $on |
||
| 903 | * |
||
| 904 | * @return $this |
||
| 905 | */ |
||
| 906 | 15 | public function setExcludeMediaQueries($on = true) |
|
| 912 | |||
| 913 | /** |
||
| 914 | * Set exclude charset. |
||
| 915 | * |
||
| 916 | * @param bool $on |
||
| 917 | * |
||
| 918 | * @return $this |
||
| 919 | */ |
||
| 920 | 1 | public function setExcludeCssCharset($on = true) |
|
| 926 | |||
| 927 | /** |
||
| 928 | * Set exclude conditional inline-style blocks. |
||
| 929 | * |
||
| 930 | * e.g.: <!--[if gte mso 9]><style>.foo { bar } </style><![endif]--> |
||
| 931 | * |
||
| 932 | * @param bool $on |
||
| 933 | * |
||
| 934 | * @return $this |
||
| 935 | */ |
||
| 936 | 6 | public function setExcludeConditionalInlineStylesBlock($on = true) |
|
| 942 | } |
||
| 943 |
This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.
If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.
In this case you can add the
@ignorePhpDoc annotation to the duplicate definition and it will be ignored.