Complex classes like Includes_processing 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 Includes_processing, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
18 | class Includes_processing { |
||
19 | /** |
||
20 | * Do not inline files bigger than 4 KiB |
||
21 | */ |
||
22 | const MAX_EMBEDDING_SIZE = 4096; |
||
23 | protected static $extension_to_mime = [ |
||
24 | 'jpeg' => 'image/jpg', |
||
25 | 'jpe' => 'image/jpg', |
||
26 | 'jpg' => 'image/jpg', |
||
27 | 'gif' => 'image/gif', |
||
28 | 'png' => 'image/png', |
||
29 | 'svg' => 'image/svg+xml', |
||
30 | 'svgz' => 'image/svg+xml', |
||
31 | 'woff' => 'application/font-woff', |
||
32 | //'woff2' => 'application/font-woff2', |
||
33 | 'css' => 'text/css' |
||
34 | ]; |
||
35 | /** |
||
36 | * Analyses file for images, fonts and css links and include they content into single resulting css file. |
||
37 | * |
||
38 | * Supports next file extensions for possible includes: |
||
39 | * jpeg, jpe, jpg, gif, png, ttf, ttc, svg, svgz, woff, eot, css |
||
40 | * |
||
41 | * @param string $data Content of processed file |
||
42 | * @param string $file Path to file, that includes specified in previous parameter content |
||
43 | * @param string[] $not_embedded_resources Some resources like images and fonts might not be embedded into resulting CSS because of their size |
||
44 | * |
||
45 | * @return string $data |
||
46 | */ |
||
47 | 4 | static function css ($data, $file, &$not_embedded_resources = []) { |
|
48 | 4 | $dir = dirname($file); |
|
49 | /** |
||
50 | * Remove comments, tabs and new lines |
||
51 | */ |
||
52 | 4 | $data = preg_replace('#(/\*.*?\*/)|\t|\n|\r#s', ' ', $data); |
|
53 | /** |
||
54 | * Remove unnecessary spaces |
||
55 | */ |
||
56 | 4 | $data = preg_replace('/\s*([,;>{}(])\s*/', '$1', $data); |
|
57 | 4 | $data = preg_replace('/\s+/', ' ', $data); |
|
58 | /** |
||
59 | * Return spaces required in media queries |
||
60 | */ |
||
61 | 4 | $data = preg_replace('/\s(and|or)\(/', ' $1 (', $data); |
|
62 | /** |
||
63 | * Duplicated semicolons |
||
64 | */ |
||
65 | 4 | $data = preg_replace('/;+/m', ';', $data); |
|
66 | /** |
||
67 | * Minify repeated colors declarations |
||
68 | */ |
||
69 | 4 | $data = preg_replace('/#([0-9a-f])\1([0-9a-f])\2([0-9a-f])\3/i', '#$1$2$3', $data); |
|
70 | /** |
||
71 | * Minify rgb colors declarations |
||
72 | */ |
||
73 | 4 | $data = preg_replace_callback( |
|
74 | 4 | '/rgb\(([0-9,.]+)\)/i', |
|
75 | function ($rgb) { |
||
76 | $rgb = explode(',', $rgb[1]); |
||
77 | return |
||
78 | '#'. |
||
79 | str_pad(dechex($rgb[0]), 2, 0, STR_PAD_LEFT). |
||
80 | str_pad(dechex($rgb[1]), 2, 0, STR_PAD_LEFT). |
||
81 | str_pad(dechex($rgb[2]), 2, 0, STR_PAD_LEFT); |
||
82 | 4 | }, |
|
83 | $data |
||
84 | ); |
||
85 | /** |
||
86 | * Remove unnecessary zeros |
||
87 | */ |
||
88 | 4 | $data = preg_replace('/(\D)0\.(\d+)/i', '$1.$2', $data); |
|
89 | /** |
||
90 | * Includes processing |
||
91 | */ |
||
92 | 4 | $data = preg_replace_callback( |
|
93 | 4 | '/url\((.*?)\)|@import[\s\t\n\r]*[\'"](.*?)[\'"]/', |
|
94 | function ($match) use ($dir, &$not_embedded_resources) { |
||
95 | 4 | $link = trim($match[1], '\'" '); |
|
96 | 4 | $link = explode('?', $link, 2)[0]; |
|
97 | 4 | if (!static::is_relative_path_and_exists($link, $dir)) { |
|
98 | 4 | return $match[0]; |
|
99 | } |
||
100 | 4 | $content = file_get_contents("$dir/$link"); |
|
101 | 4 | $extension = file_extension($link); |
|
102 | 4 | if (!isset(static::$extension_to_mime[$extension]) || filesize("$dir/$link") > static::MAX_EMBEDDING_SIZE) { |
|
103 | 4 | $path_relatively_to_the_root = str_replace(getcwd(), '', realpath("$dir/$link")); |
|
104 | 4 | $path_relatively_to_the_root .= '?'.substr(md5($content), 0, 5); |
|
105 | 4 | if (strpos($match[1], '?') === false) { |
|
106 | $not_embedded_resources[] = $path_relatively_to_the_root; |
||
107 | } |
||
108 | 4 | return str_replace($match[1], "'".str_replace("'", "\\'", $path_relatively_to_the_root)."'", $match[0]); |
|
109 | } |
||
110 | if ($extension == 'css') { |
||
111 | /** |
||
112 | * For recursive includes processing, if CSS file includes others CSS files |
||
113 | */ |
||
114 | $content = static::css($content, $link, $not_embedded_resources); |
||
115 | } |
||
116 | $mime_type = static::$extension_to_mime[$extension]; |
||
117 | $content = base64_encode($content); |
||
118 | return str_replace($match[1], "data:$mime_type;charset=utf-8;base64,$content", $match[0]); |
||
119 | 4 | }, |
|
120 | $data |
||
121 | ); |
||
122 | 4 | return trim($data); |
|
123 | } |
||
124 | /** |
||
125 | * Simple and fast JS minification |
||
126 | * |
||
127 | * @param string $data |
||
128 | * |
||
129 | * @return string |
||
130 | */ |
||
131 | 4 | static function js ($data) { |
|
132 | /** |
||
133 | * Split into array of lines |
||
134 | */ |
||
135 | 4 | $data = explode("\n", $data); |
|
136 | /** |
||
137 | * Flag that is `true` when inside comment |
||
138 | */ |
||
139 | 4 | $comment = false; |
|
140 | /** |
||
141 | * Set of symbols that are safe to be concatenated without new line with anything else |
||
142 | */ |
||
143 | $regexp = /** @lang PhpRegExp */ |
||
144 | 4 | '[:;,.+\-*/{}?><^\'"\[\]=&(]'; |
|
145 | 4 | foreach ($data as $index => &$d) { |
|
146 | 4 | $next_line = isset($data[$index + 1]) ? trim($data[$index + 1]) : ''; |
|
147 | /** |
||
148 | * Remove starting and trailing spaces |
||
149 | */ |
||
150 | 4 | $d = trim($d); |
|
151 | /** |
||
152 | * Remove single-line comments |
||
153 | */ |
||
154 | 4 | if (mb_strpos($d, '//') === 0) { |
|
155 | 4 | $d = ''; |
|
156 | 4 | continue; |
|
157 | } |
||
158 | /** |
||
159 | * Starts with multi-line comment |
||
160 | */ |
||
161 | 4 | if (mb_strpos($d, '/*') === 0) { |
|
162 | 4 | $comment = true; |
|
163 | } |
||
164 | /** |
||
165 | * Add new line at the end if only needed |
||
166 | */ |
||
167 | if ( |
||
168 | 4 | $d && |
|
169 | 4 | $next_line && |
|
170 | 4 | !$comment && |
|
171 | 4 | !preg_match("#$regexp\$#", $d) && |
|
172 | 4 | !preg_match("#^$regexp#", $next_line) |
|
173 | ) { |
||
174 | 4 | $d .= "\n"; |
|
175 | } |
||
176 | 4 | if ($comment) { |
|
177 | /** |
||
178 | * End of multi-line comment |
||
179 | */ |
||
180 | 4 | if (strpos($d, '*/') !== false) { |
|
181 | 4 | $d = explode('*/', $d)[1]; |
|
182 | 4 | $comment = false; |
|
183 | } else { |
||
184 | 4 | $d = ''; |
|
185 | } |
||
186 | } else { |
||
187 | /** |
||
188 | * Single-line comment |
||
189 | */ |
||
190 | 4 | $d = preg_replace('#^\s*//[^\'"]+$#', '', $d); |
|
191 | /** |
||
192 | * If we are not sure - just add new like afterwards |
||
193 | */ |
||
194 | 4 | $d = preg_replace('#//.*$#', "\\0\n", $d); |
|
195 | } |
||
196 | } |
||
197 | 4 | $data = implode('', $data); |
|
198 | 4 | $data = str_replace('</script>', '<\/script>', $data); |
|
199 | 4 | return trim($data, ';').';'; |
|
200 | } |
||
201 | /** |
||
202 | * Analyses file for scripts and styles, combines them into resulting files in order to optimize loading process |
||
203 | * (files with combined scripts and styles will be created) |
||
204 | * |
||
205 | * @param string $data Content of processed file |
||
206 | * @param string $file Path to file, that includes specified in previous parameter content |
||
207 | * @param string $base_target_file_path Base filename for resulting combined files |
||
208 | * @param bool $vulcanization Whether to put combined files separately or to make includes built-in (vulcanization) |
||
209 | * @param string[] $not_embedded_resources Resources like images/fonts might not be embedded into resulting CSS because of big size or CSS/JS because of CSP |
||
210 | * |
||
211 | * @return string |
||
212 | */ |
||
213 | 4 | static function html ($data, $file, $base_target_file_path, $vulcanization, &$not_embedded_resources = []) { |
|
226 | /** |
||
227 | * @param string $data Content of processed file |
||
228 | * @param string $file Path to file, that includes specified in previous parameter content |
||
229 | * @param string $base_target_file_path Base filename for resulting combined files |
||
230 | * @param bool $vulcanization Whether to put combined files separately or to make includes built-in (vulcanization) |
||
231 | * @param string[] $not_embedded_resources Resources like images/fonts might not be embedded into resulting CSS because of big size or CSS/JS because of CSP |
||
232 | * |
||
233 | * @return string |
||
|
|||
234 | */ |
||
235 | 4 | protected static function html_process_scripts (&$data, $file, $base_target_file_path, $vulcanization, &$not_embedded_resources) { |
|
280 | /** |
||
281 | * @param string $data Content of processed file |
||
282 | * @param string $file Path to file, that includes specified in previous parameter content |
||
283 | * @param string $base_target_file_path Base filename for resulting combined files |
||
284 | * @param bool $vulcanization Whether to put combined files separately or to make includes built-in (vulcanization) |
||
285 | * @param string[] $not_embedded_resources Resources like images/fonts might not be embedded into resulting CSS because of big size or CSS/JS because of CSP |
||
286 | * |
||
287 | * @return string |
||
288 | */ |
||
289 | 4 | protected static function html_process_links_and_styles (&$data, $file, $base_target_file_path, $vulcanization, &$not_embedded_resources) { |
|
359 | /** |
||
360 | * @param string $link |
||
361 | * @param string $url |
||
362 | * @param string $dir |
||
363 | * |
||
364 | * @return bool |
||
365 | */ |
||
366 | 4 | protected static function has_relative_href ($link, &$url, $dir) { |
|
376 | /** |
||
377 | * Simple check for http[s], ftp and absolute links |
||
378 | * |
||
379 | * @param string $path |
||
380 | * @param string $dir |
||
381 | * |
||
382 | * @return bool |
||
383 | */ |
||
384 | 4 | protected static function is_relative_path_and_exists ($path, $dir) { |
|
387 | } |
||
388 |
This check compares the return type specified in the
@return
annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.