Completed
Push — master ( d01bcd...578ad1 )
by Revin
04:37
created

CSS   B

Complexity

Total Complexity 37

Size/Duplication

Total Lines 237
Duplicated Lines 8.02 %

Coupling/Cohesion

Components 1
Dependencies 4

Test Coverage

Coverage 94.66%

Importance

Changes 0
Metric Value
wmc 37
lcom 1
cbo 4
dl 19
loc 237
ccs 124
cts 131
cp 0.9466
rs 8.6
c 0
b 0
f 0

9 Methods

Rating   Name   Duplication   Size   Complexity  
C export() 19 34 7
A removeCssComments() 0 6 2
B expandImports() 0 20 6
A collectCharsets() 0 6 1
A collectImports() 0 6 1
A collectFonts() 0 6 1
A _collect() 0 15 2
B _getImportContent() 0 29 5
C process() 0 72 12

How to fix   Duplicated Code   

Duplicated Code

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
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
                $css .= $content;
101 7
            }
102
103 7
            $this->expandImports($css);
104
105 7
            $this->removeCssComments($css);
106
107 7
            if ($this->view->minifyCss) {
108 7
                $css = (new CSSmin())
109 7
                    ->run($css, $this->view->cssLinebreakPos);
110 7
            }
111
112 7
            $charsets = false !== $this->view->forceCharset
113 7
                ? ('@charset "' . (string)$this->view->forceCharset . '";' . "\n")
114 7
                : $this->collectCharsets($css);
115
116 7
            $imports = $this->collectImports($css);
117 7
            $fonts = $this->collectFonts($css);
118
119 7
            file_put_contents($resultFile, $charsets . $imports . $fonts . $css);
120
121 7
            if (false !== $this->view->fileMode) {
122 7
                @chmod($resultFile, $this->view->fileMode);
123 7
            }
124 7
        }
125
126 7
        $file = $this->prepareResultFile($resultFile);
127
128 7
        $this->view->cssFiles[$file] = Html::cssFile($file);
129 7
    }
130
131
    /**
132
     * @param string $code
133
     */
134 7
    protected function removeCssComments(&$code)
135
    {
136 7
        if (true === $this->view->removeComments) {
137 7
            $code = preg_replace('#/\*(?:[^*]*(?:\*(?!/))*)*\*/#', '', $code);
138 7
        }
139 7
    }
140
141
    /**
142
     * @param string $code
143
     */
144 7
    protected function expandImports(&$code)
145
    {
146 7
        if (true === $this->view->expandImports) {
147 7
            preg_match_all('|\@import\s([^;]+);|is', str_replace('&amp;', '&', $code), $m);
148
149 7
            if (!empty($m[0])) {
150 7
                foreach ($m[0] as $k => $v) {
151 7
                    $import_url = $m[1][$k];
152
153 7
                    if (!empty($import_url)) {
154 7
                        $import_content = $this->_getImportContent($import_url);
155
156 7
                        if (!empty($import_content)) {
157 7
                            $code = str_replace($m[0][$k], $import_content, $code);
158 7
                        }
159 7
                    }
160 7
                }
161 7
            }
162 7
        }
163 7
    }
164
165
    /**
166
     * @param string $code
167
     * @return string
168
     */
169
    protected function collectCharsets(&$code)
170
    {
171
        return $this->_collect($code, '|\@charset[^;]+|is', function ($string) {
172
            return $string . ';';
173
        });
174
    }
175
176
    /**
177
     * @param string $code
178
     * @return string
179
     */
180 7
    protected function collectImports(&$code)
181
    {
182
        return $this->_collect($code, '|\@import[^;]+|is', function ($string) {
183
            return $string . ';';
184 7
        });
185
    }
186
187
    /**
188
     * @param string $code
189
     * @return string
190
     */
191
    protected function collectFonts(&$code)
192
    {
193 7
        return $this->_collect($code, '|\@font-face\{[^}]+\}|is', function ($string) {
194 7
            return $string;
195 7
        });
196
    }
197
198
    /**
199
     * @param string $code
200
     * @param string $pattern
201
     * @param callable $handler
202
     * @return string
203
     */
204 7
    protected function _collect(&$code, $pattern, $handler)
205
    {
206 7
        $result = '';
207
208 7
        preg_match_all($pattern, $code, $m);
209
210 7
        foreach ($m[0] as $string) {
211 7
            $string = $handler($string);
212 7
            $code = str_replace($string, '', $code);
213
214 7
            $result .= $string . PHP_EOL;
215 7
        }
216
217 7
        return $result;
218
    }
219
220
    /**
221
     * @param string $url
222
     * @return null|string
223
     */
224 7
    protected function _getImportContent($url)
225
    {
226 7
        $result = null;
227
228 7
        if ('url(' === mb_substr($url, 0, 4)) {
229 7
            $url = str_replace(['url(\'', 'url("', 'url(', '\')', '")', ')'], '', $url);
230
231 7
            if (mb_substr($url, 0, 2) === '//') {
232 7
                $url = preg_replace('|^//|', 'http://', $url, 1);
233 7
            }
234
235 7
            if (!empty($url)) {
236 7
                if (!in_array(mb_substr($url, 0, 4), ['http', 'ftp:'], true)) {
237 7
                    $url = \Yii::getAlias($this->view->basePath . $url);
238 7
                }
239
240
                $context = [
241
                    'ssl' => [
242 7
                        'verify_peer'      => false,
243 7
                        'verify_peer_name' => false,
244 7
                    ],
245 7
                ];
246
247 7
                $result = file_get_contents($url, null, stream_context_create($context));
248 7
            }
249 7
        }
250
251 7
        return $result;
252
    }
253
}
254