Test Setup Failed
Push — master ( 8d73bd...2022ae )
by Revin
01:56
created

CSS::process()   C

Complexity

Conditions 12
Paths 9

Size

Total Lines 74
Code Lines 43

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 48
CRAP Score 12.0092

Importance

Changes 0
Metric Value
dl 0
loc 74
ccs 48
cts 50
cp 0.96
rs 5.3992
c 0
b 0
f 0
cc 12
eloc 43
nc 9
nop 1
crap 12.0092

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * CSS.php
4
 * @author Revin Roman
5
 * @link https://rmrevin.com
6
 */
7
8
namespace rmrevin\yii\minify\components;
9
10
use tubalmartin\CssMin\Minifier as CSSmin;
11
use yii\helpers\Html;
12
13
/**
14
 * Class CSS
15
 * @package rmrevin\yii\minify\components
16
 */
17
class CSS extends MinifyComponent
18
{
19
20 8
    public function export()
21
    {
22 8
        $cssFiles = $this->view->cssFiles;
23
24 8
        $this->view->cssFiles = [];
25
26 8
        $toMinify = [];
27
28 8 View Code Duplication
        if (!empty($cssFiles)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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.

Loading history...
29 7
            foreach ($cssFiles as $file => $html) {
30 7
                if ($this->thisFileNeedMinify($file, $html)) {
31 7
                    if ($this->view->concatCss) {
32 7
                        $toMinify[$file] = $html;
33 7
                    } else {
34
                        $this->process([$file => $html]);
35
                    }
36 7
                } else {
37 2
                    if (!empty($toMinify)) {
38 2
                        $this->process($toMinify);
39
40 2
                        $toMinify = [];
41 2
                    }
42
43 2
                    $this->view->cssFiles[$file] = $html;
44
                }
45 7
            }
46 7
        }
47
48 8
        if (!empty($toMinify)) {
49 5
            $this->process($toMinify);
50 5
        }
51
52 8
        unset($toMinify);
53 8
    }
54
55
    /**
56
     * @param array $files
57
     */
58 7
    protected function process(array $files)
59
    {
60 7
        $resultFile = $this->view->minifyPath . DIRECTORY_SEPARATOR . $this->_getSummaryFilesHash($files) . '.css';
61
62 7
        if (!file_exists($resultFile)) {
63 7
            $css = '';
64
65 7
            foreach ($files as $file => $html) {
66 7
                $path = dirname($file);
67 7
                $file = $this->getAbsoluteFilePath($file);
68
69 7
                $content = '';
70
71 7
                if (!file_exists($file)) {
72
                    \Yii::warning(sprintf('Asset file not found `%s`', $file), __METHOD__);
73 7
                } elseif (!is_readable($file)) {
74
                    \Yii::warning(sprintf('Asset file not readable `%s`', $file), __METHOD__);
75 1
                } else {
76 7
                    $content = file_get_contents($file);
77
                }
78
79 7
                $result = [];
80
81 7
                preg_match_all('|url\(([^)]+)\)|is', $content, $m);
82 7
                if (!empty($m[0])) {
83 7
                    foreach ($m[0] as $k => $v) {
84 7
                        if (in_array(strpos($m[1][$k], 'data:'), [0, 1], true)) {
85 7
                            continue;
86
                        }
87
88 7
                        $url = str_replace(['\'', '"'], '', $m[1][$k]);
89
90 7
                        if ($this->isUrl($url)) {
91 7
                            $result[$m[1][$k]] = $url;
92 7
                        } else {
93 7
                            $result[$m[1][$k]] = $path . '/' . $url;
94
                        }
95 7
                    }
96
97 7
                    $content = strtr($content, $result);
98 7
                }
99
                
100 7
                $content = self::convertMediaTypeAttributeToMediaQuery($html, $content);
101
102 7
                $css .= $content;
103 7
            }
104
105 7
            $this->expandImports($css);
106
107 7
            $this->removeCssComments($css);
108
109 7
            if ($this->view->minifyCss) {
110 7
                $css = (new CSSmin())
111 7
                    ->run($css, $this->view->cssLinebreakPos);
112 7
            }
113
114 7
            $charsets = false !== $this->view->forceCharset
115 7
                ? ('@charset "' . (string)$this->view->forceCharset . '";' . "\n")
116 7
                : $this->collectCharsets($css);
117
118 7
            $imports = $this->collectImports($css);
119 7
            $fonts = $this->collectFonts($css);
120
121 7
            file_put_contents($resultFile, $charsets . $imports . $fonts . $css);
122
123 7
            if (false !== $this->view->fileMode) {
124 7
                @chmod($resultFile, $this->view->fileMode);
125 7
            }
126 7
        }
127
128 7
        $file = $this->prepareResultFile($resultFile);
129
130 7
        $this->view->cssFiles[$file] = Html::cssFile($file);
131 7
    }
132
133
    /**
134
     * @param string $code
135
     */
136 7
    protected function removeCssComments(&$code)
137
    {
138 7
        if (true === $this->view->removeComments) {
139 7
            $code = preg_replace('#/\*(?:[^*]*(?:\*(?!/))*)*\*/#', '', $code);
140 7
        }
141 7
    }
142
143
    /**
144
     * @param string $code
145
     */
146 7
    protected function expandImports(&$code)
147
    {
148 7
        if (true === $this->view->expandImports) {
149 7
            preg_match_all('|\@import\s([^;]+);|is', str_replace('&amp;', '&', $code), $m);
150
151 7
            if (!empty($m[0])) {
152 7
                foreach ($m[0] as $k => $v) {
153 7
                    $import_url = $m[1][$k];
154
155 7
                    if (!empty($import_url)) {
156 7
                        $import_content = $this->_getImportContent($import_url);
157
158 7
                        if (!empty($import_content)) {
159 7
                            $code = str_replace($m[0][$k], $import_content, $code);
160 7
                        }
161 7
                    }
162 7
                }
163 7
            }
164 7
        }
165 7
    }
166
167
    /**
168
     * @param string $code
169
     * @return string
170
     */
171
    protected function collectCharsets(&$code)
172
    {
173
        return $this->_collect($code, '|\@charset[^;]+|is', function ($string) {
174
            return $string . ';';
175
        });
176
    }
177
178
    /**
179
     * @param string $code
180
     * @return string
181
     */
182 7
    protected function collectImports(&$code)
183
    {
184
        return $this->_collect($code, '|\@import[^;]+|is', function ($string) {
185
            return $string . ';';
186 7
        });
187
    }
188
189
    /**
190
     * @param string $code
191
     * @return string
192
     */
193
    protected function collectFonts(&$code)
194
    {
195 7
        return $this->_collect($code, '|\@font-face\{[^}]+\}|is', function ($string) {
196 7
            return $string;
197 7
        });
198
    }
199
200
    /**
201
     * @param string $code
202
     * @param string $pattern
203
     * @param callable $handler
204
     * @return string
205
     */
206 7
    protected function _collect(&$code, $pattern, $handler)
207
    {
208 7
        $result = '';
209
210 7
        preg_match_all($pattern, $code, $m);
211
212 7
        foreach ($m[0] as $string) {
213 7
            $string = $handler($string);
214 7
            $code = str_replace($string, '', $code);
215
216 7
            $result .= $string . PHP_EOL;
217 7
        }
218
219 7
        return $result;
220
    }
221
222
    /**
223
     * @param string $url
224
     * @return null|string
225
     */
226 7
    protected function _getImportContent($url)
227
    {
228 7
        $result = null;
229
230 7
        if ('url(' === mb_substr($url, 0, 4)) {
231 7
            $url = str_replace(['url(\'', 'url("', 'url(', '\')', '")', ')'], '', $url);
232
233 7
            if (mb_substr($url, 0, 2) === '//') {
234 7
                $url = preg_replace('|^//|', 'http://', $url, 1);
235 7
            }
236
237 7
            if (!empty($url)) {
238 7
                if (!in_array(mb_substr($url, 0, 4), ['http', 'ftp:'], true)) {
239 7
                    $url = \Yii::getAlias($this->view->basePath . $url);
240 7
                }
241
242
                $context = [
243
                    'ssl' => [
244 7
                        'verify_peer'      => false,
245 7
                        'verify_peer_name' => false,
246 7
                    ],
247 7
                ];
248
249 7
                $result = file_get_contents($url, null, stream_context_create($context));
250 7
            }
251 7
        }
252
253 7
        return $result;
254
    }
255
    
256
    /**
257
     * If the <link> tag has a media="type" attribute, wrap the content in an equivalent media query
258
     * @param string $tag_html HTML of the link tag
0 ignored issues
show
Bug introduced by
There is no parameter named $tag_html. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
259
     * @param string $content CSS content
260
     * @return string $content CSS content wrapped with media query, if applicable
261
     */
262 8
    public static function convertMediaTypeAttributeToMediaQuery($html, $content)
263
    {
264 8
        if (preg_match('/\bmedia=(["\'])([^"\']+)\1/i', $html, $m)) {
265 1
            if ($m[2] !== 'all') {
266 1
                $content = '@media '.$m[2].'{' . $content . '}';
267 1
            }
268 1
        }        
269 8
        return $content;
270
    }
271
}
272