1 | <?php |
||
2 | |||
3 | |||
4 | namespace carono\yii2bower; |
||
5 | |||
6 | use yii\helpers\ArrayHelper; |
||
7 | use yii\helpers\Inflector; |
||
8 | use yii\helpers\StringHelper; |
||
9 | use yii\helpers\VarDumper; |
||
10 | use yii\web\AssetBundle; |
||
11 | use yii\web\View; |
||
12 | |||
13 | class Asset extends AssetBundle |
||
14 | { |
||
15 | public $packageNamespace = 'app\runtime\bower'; |
||
16 | public $packages = []; |
||
17 | public $alias = '@bower'; |
||
18 | public $config = 'bower.json'; |
||
19 | protected static $_installedPackages = []; |
||
20 | |||
21 | public function init() |
||
22 | { |
||
23 | $timestamp = $this->getFileTimestamp(static::getClassFile(get_class($this))); |
||
24 | static::loadPackages($this->alias, $this->config); |
||
25 | foreach ($this->packages as $idx => $value) { |
||
26 | $package = is_numeric($idx) ? $value : $idx; |
||
27 | $files = is_numeric($idx) ? [] : $value; |
||
28 | if (!static::packageInstalled($package, $this->alias) && !static::packageAsFolder($package, $this->alias)) { |
||
29 | continue; |
||
30 | } |
||
31 | if (!$this->assetExists($package) || $this->needRewrite($package)) { |
||
32 | if ($classFile = static::createAssetClass($package, $this->packageNamespace, $this->alias, $files)) { |
||
33 | touch($classFile, (int)$timestamp); |
||
34 | } |
||
35 | }; |
||
36 | $this->depends[] = static::getPackageClass($package, $this->packageNamespace); |
||
37 | } |
||
38 | parent::init(); |
||
39 | } |
||
40 | |||
41 | /** |
||
42 | * @param $package |
||
43 | * @param $namespace |
||
44 | * @return string |
||
45 | */ |
||
46 | public static function getPackageClass($package, $namespace) |
||
47 | { |
||
48 | return $namespace . '\\' . static::formClassNameFromPackage($package); |
||
49 | } |
||
50 | |||
51 | /** |
||
52 | * @param $package |
||
53 | * @return string |
||
54 | */ |
||
55 | public static function formClassNameFromPackage($package) |
||
56 | { |
||
57 | return Inflector::camelize($package); |
||
58 | } |
||
59 | |||
60 | /** |
||
61 | * @param $package |
||
62 | * @param $namespace |
||
63 | * @return string |
||
64 | */ |
||
65 | protected static function getPackageFile($package, $namespace) |
||
66 | { |
||
67 | return static::getClassFile(static::getPackageClass($package, $namespace)); |
||
68 | } |
||
69 | |||
70 | public static function packageAsFolder($package, $alias) |
||
71 | { |
||
72 | return is_dir(\Yii::getAlias("$alias/$package")); |
||
73 | } |
||
74 | |||
75 | public static function packageInstalled($package, $alias, $config = 'bower.json') |
||
76 | { |
||
77 | if (!static::$_installedPackages) { |
||
0 ignored issues
–
show
|
|||
78 | static::loadPackages($alias, $config); |
||
79 | } |
||
80 | return isset(static::$_installedPackages[$package]); |
||
81 | } |
||
82 | |||
83 | public static function loadPackages($alias, $config) |
||
84 | { |
||
85 | static::$_installedPackages = []; |
||
86 | foreach (glob(\Yii::getAlias("$alias/**/$config"), GLOB_BRACE) as $file) { |
||
87 | $json = json_decode(file_get_contents($file), true); |
||
88 | if (($name = ArrayHelper::getValue($json, 'name'))) { |
||
89 | static::$_installedPackages[$name] = $file; |
||
90 | } |
||
91 | } |
||
92 | } |
||
93 | |||
94 | public static function getPackageJson($package, $alias) |
||
95 | { |
||
96 | if (isset(static::$_installedPackages[$package])) { |
||
97 | $file = static::$_installedPackages[$package]; |
||
98 | return json_decode(file_get_contents($file), true); |
||
99 | } |
||
100 | |||
101 | if (static::packageAsFolder($package, $alias)) { |
||
102 | return []; |
||
103 | } |
||
104 | |||
105 | return null; |
||
106 | } |
||
107 | |||
108 | public static function getPackageDir($package, $alias) |
||
109 | { |
||
110 | if (isset(static::$_installedPackages[$package])) { |
||
111 | $file = static::$_installedPackages[$package]; |
||
112 | return basename(dirname($file)); |
||
113 | } |
||
114 | |||
115 | if (static::packageAsFolder($package, $alias)) { |
||
116 | return $package; |
||
117 | } |
||
118 | |||
119 | return null; |
||
120 | } |
||
121 | |||
122 | protected static function filesToConfig($files) |
||
123 | { |
||
124 | $config = []; |
||
125 | foreach ($files as $key => $file) { |
||
126 | if (!is_numeric($key)) { |
||
127 | $config[$key] = $file; |
||
128 | continue; |
||
129 | } |
||
130 | if (StringHelper::endsWith($file, '.css')) { |
||
131 | $config['css'][] = ltrim($file, "./\\"); |
||
132 | } |
||
133 | if (StringHelper::endsWith($file, '.js')) { |
||
134 | $config['js'][] = ltrim($file, "./\\"); |
||
135 | } |
||
136 | } |
||
137 | return $config; |
||
138 | } |
||
139 | |||
140 | /** |
||
141 | * @param $package |
||
142 | * @param $namespace |
||
143 | * @param $alias |
||
144 | * @param array $files |
||
145 | * @return mixed|string |
||
146 | */ |
||
147 | public static function createAssetClass($package, $namespace, $alias, $files = []) |
||
148 | { |
||
149 | $configJson = static::getPackageJson($package, $alias); |
||
150 | |||
151 | if ($configJson === null) { |
||
152 | \Yii::warning("Bower $package package not found"); |
||
153 | return false; |
||
154 | } |
||
155 | |||
156 | $main = ArrayHelper::getValue($configJson, 'main'); |
||
157 | |||
158 | $dir = static::getPackageDir($package, $alias); |
||
159 | |||
160 | $defaultConfig = [ |
||
161 | 'baseUrl' => '@web', |
||
162 | 'jsOptions' => ['position' => View::POS_END] |
||
163 | ]; |
||
164 | $packageConfig = self::filesToConfig($files ?: (array)$main); |
||
165 | $sourcePath = implode('/', array_filter([ |
||
166 | $alias, |
||
167 | $dir, |
||
168 | trim((string)ArrayHelper::remove($packageConfig, 'sourcePath', ''), '/') |
||
169 | ])); |
||
170 | $config = ArrayHelper::merge($defaultConfig, $packageConfig, ['sourcePath' => $sourcePath]); |
||
171 | $str = ''; |
||
172 | foreach ($config as $key => $value) { |
||
173 | $str .= ' public $' . $key . ' = ' . VarDumper::export($value) . ";\n"; |
||
174 | } |
||
175 | $class = static::formClassNameFromPackage($package); |
||
176 | $template = <<<PHP |
||
177 | <?php |
||
178 | |||
179 | namespace $namespace; |
||
180 | |||
181 | |||
182 | use yii\web\AssetBundle; |
||
183 | use yii\web\View; |
||
184 | |||
185 | class $class extends AssetBundle |
||
186 | { |
||
187 | $str |
||
188 | } |
||
189 | PHP; |
||
190 | $dir = \Yii::getAlias('@' . str_replace('\\', '/', ltrim($namespace, '\\'))); |
||
191 | if (!is_dir($dir)) { |
||
192 | if (!mkdir($dir, 0777, true) && !is_dir($dir)) { |
||
193 | throw new \RuntimeException(sprintf('Directory "%s" was not created', $dir)); |
||
194 | } |
||
195 | } |
||
196 | $file = $dir . DIRECTORY_SEPARATOR . $class . '.php'; |
||
197 | file_put_contents($file, $template); |
||
198 | return $file; |
||
199 | } |
||
200 | |||
201 | /** |
||
202 | * @param $package |
||
203 | * @return bool |
||
204 | */ |
||
205 | protected function assetExists($package) |
||
206 | { |
||
207 | return class_exists(static::getPackageClass($package, $this->packageNamespace)); |
||
208 | } |
||
209 | |||
210 | /** |
||
211 | * @param $package |
||
212 | * @return bool |
||
213 | */ |
||
214 | protected function needRewrite($package) |
||
215 | { |
||
216 | $timestamp = $this->getFileTimestamp(static::getPackageFile($package, $this->packageNamespace)); |
||
217 | if ($timestamp) { |
||
0 ignored issues
–
show
The expression
$timestamp of type false|integer is loosely compared to true ; this is ambiguous if the integer can be 0. You might want to explicitly use !== false instead.
In PHP, under loose comparison (like For 0 == false // true
0 == null // true
123 == false // false
123 == null // false
// It is often better to use strict comparison
0 === false // false
0 === null // false
![]() |
|||
218 | $assetTimestamp = $this->getFileTimestamp(static::getClassFile(get_class($this))); |
||
219 | return $timestamp != $assetTimestamp; |
||
220 | } |
||
221 | return false; |
||
222 | } |
||
223 | |||
224 | /** |
||
225 | * @param $class |
||
226 | * @return string |
||
227 | */ |
||
228 | protected static function getClassFile($class) |
||
229 | { |
||
230 | return \Yii::getAlias('@' . ltrim(str_replace('\\', '/', $class), '/')) . '.php'; |
||
231 | } |
||
232 | |||
233 | /** |
||
234 | * @param $file |
||
235 | * @return bool|int |
||
236 | */ |
||
237 | protected function getFileTimestamp($file) |
||
238 | { |
||
239 | if ($timestamp = @filemtime($file)) { |
||
240 | $timestamp = (int)$timestamp / 100 * 100; |
||
241 | } |
||
242 | return $timestamp; |
||
243 | } |
||
244 | } |
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.
Consider making the comparison explicit by using
empty(..)
or! empty(...)
instead.