Complex classes like AssetController 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 AssetController, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
49 | class AssetController extends Controller |
||
50 | { |
||
51 | /** |
||
52 | * @var string controller default action ID. |
||
53 | */ |
||
54 | public $defaultAction = 'compress'; |
||
55 | /** |
||
56 | * @var array list of asset bundles to be compressed. |
||
57 | */ |
||
58 | public $bundles = []; |
||
59 | /** |
||
60 | * @var array list of asset bundles, which represents output compressed files. |
||
61 | * You can specify the name of the output compressed file using 'css' and 'js' keys: |
||
62 | * For example: |
||
63 | * |
||
64 | * ```php |
||
65 | * 'app\config\AllAsset' => [ |
||
66 | * 'js' => 'js/all-{hash}.js', |
||
67 | * 'css' => 'css/all-{hash}.css', |
||
68 | * 'depends' => [ ... ], |
||
69 | * ] |
||
70 | * ``` |
||
71 | * |
||
72 | * File names can contain placeholder "{hash}", which will be filled by the hash of the resulting file. |
||
73 | * |
||
74 | * You may specify several target bundles in order to compress different groups of assets. |
||
75 | * In this case you should use 'depends' key to specify, which bundles should be covered with particular |
||
76 | * target bundle. You may leave 'depends' to be empty for single bundle, which will compress all remaining |
||
77 | * bundles in this case. |
||
78 | * For example: |
||
79 | * |
||
80 | * ```php |
||
81 | * 'allShared' => [ |
||
82 | * 'js' => 'js/all-shared-{hash}.js', |
||
83 | * 'css' => 'css/all-shared-{hash}.css', |
||
84 | * 'depends' => [ |
||
85 | * // Include all assets shared between 'backend' and 'frontend' |
||
86 | * \yii\web\YiiAsset::class, |
||
87 | * \app\assets\SharedAsset::class, |
||
88 | * ], |
||
89 | * ], |
||
90 | * 'allBackEnd' => [ |
||
91 | * 'js' => 'js/all-{hash}.js', |
||
92 | * 'css' => 'css/all-{hash}.css', |
||
93 | * 'depends' => [ |
||
94 | * // Include only 'backend' assets: |
||
95 | * \app\assets\AdminAsset::class |
||
96 | * ], |
||
97 | * ], |
||
98 | * 'allFrontEnd' => [ |
||
99 | * 'js' => 'js/all-{hash}.js', |
||
100 | * 'css' => 'css/all-{hash}.css', |
||
101 | * 'depends' => [], // Include all remaining assets |
||
102 | * ], |
||
103 | * ``` |
||
104 | */ |
||
105 | public $targets = []; |
||
106 | /** |
||
107 | * @var string|callable JavaScript file compressor. |
||
108 | * If a string, it is treated as shell command template, which should contain |
||
109 | * placeholders {from} - source file name - and {to} - output file name. |
||
110 | * Otherwise, it is treated as PHP callback, which should perform the compression. |
||
111 | * |
||
112 | * Default value relies on usage of "Closure Compiler" |
||
113 | * @see https://developers.google.com/closure/compiler/ |
||
114 | */ |
||
115 | public $jsCompressor = 'java -jar compiler.jar --js {from} --js_output_file {to}'; |
||
116 | /** |
||
117 | * @var string|callable CSS file compressor. |
||
118 | * If a string, it is treated as shell command template, which should contain |
||
119 | * placeholders {from} - source file name - and {to} - output file name. |
||
120 | * Otherwise, it is treated as PHP callback, which should perform the compression. |
||
121 | * |
||
122 | * Default value relies on usage of "YUI Compressor" |
||
123 | * @see https://github.com/yui/yuicompressor/ |
||
124 | */ |
||
125 | public $cssCompressor = 'java -jar yuicompressor.jar --type css {from} -o {to}'; |
||
126 | /** |
||
127 | * @var bool whether to delete asset source files after compression. |
||
128 | * This option affects only those bundles, which have [[\yii\web\AssetBundle::sourcePath]] is set. |
||
129 | * @since 2.0.10 |
||
130 | */ |
||
131 | public $deleteSource = false; |
||
132 | |||
133 | /** |
||
134 | * @var array|AssetManager [[AssetManager]] instance or its array configuration, which will be used |
||
135 | * for assets processing. |
||
136 | */ |
||
137 | private $_assetManager = []; |
||
138 | |||
139 | |||
140 | /** |
||
141 | * Returns the asset manager instance. |
||
142 | * @throws \yii\console\Exception on invalid configuration. |
||
143 | * @return \yii\web\AssetManager asset manager instance. |
||
144 | */ |
||
145 | 5 | public function getAssetManager() |
|
168 | |||
169 | /** |
||
170 | * Sets asset manager instance or configuration. |
||
171 | * @param AssetManager|array $assetManager asset manager instance or its array configuration. |
||
172 | * @throws Exception on invalid argument type. |
||
173 | */ |
||
174 | 5 | public function setAssetManager($assetManager) |
|
181 | |||
182 | /** |
||
183 | * Combines and compresses the asset files according to the given configuration. |
||
184 | * During the process new asset bundle configuration file will be created. |
||
185 | * You should replace your original asset bundle configuration with this file in order to use compressed files. |
||
186 | * @param string $configFile configuration file name. |
||
187 | * @param string $bundleFile output asset bundles configuration file name. |
||
188 | */ |
||
189 | 5 | public function actionCompress($configFile, $bundleFile) |
|
212 | |||
213 | /** |
||
214 | * Applies configuration from the given file to self instance. |
||
215 | * @param string $configFile configuration file name. |
||
216 | * @throws \yii\console\Exception on failure. |
||
217 | */ |
||
218 | 5 | protected function loadConfiguration($configFile) |
|
232 | |||
233 | /** |
||
234 | * Creates full list of source asset bundles. |
||
235 | * @param string[] $bundles list of asset bundle names |
||
236 | * @return \yii\web\AssetBundle[] list of source asset bundles. |
||
237 | */ |
||
238 | 5 | protected function loadBundles($bundles) |
|
253 | |||
254 | /** |
||
255 | * Loads asset bundle dependencies recursively. |
||
256 | * @param \yii\web\AssetBundle $bundle bundle instance |
||
257 | * @param array $result already loaded bundles list. |
||
258 | * @throws Exception on failure. |
||
259 | */ |
||
260 | 5 | protected function loadDependency($bundle, &$result) |
|
274 | |||
275 | /** |
||
276 | * Creates full list of output asset bundles. |
||
277 | * @param array $targets output asset bundles configuration. |
||
278 | * @param \yii\web\AssetBundle[] $bundles list of source asset bundles. |
||
279 | * @return \yii\web\AssetBundle[] list of output asset bundles. |
||
280 | * @throws Exception on failure. |
||
281 | */ |
||
282 | 4 | protected function loadTargets($targets, $bundles) |
|
283 | { |
||
284 | // build the dependency order of bundles |
||
285 | 4 | $registered = []; |
|
286 | 4 | foreach ($bundles as $name => $bundle) { |
|
287 | 4 | $this->registerBundle($bundles, $name, $registered); |
|
288 | } |
||
289 | 4 | $bundleOrders = array_combine(array_keys($registered), range(0, count($bundles) - 1)); |
|
290 | |||
291 | // fill up the target which has empty 'depends'. |
||
292 | 4 | $referenced = []; |
|
293 | 4 | foreach ($targets as $name => $target) { |
|
294 | 4 | if (empty($target['depends'])) { |
|
295 | 4 | if (!isset($all)) { |
|
296 | 4 | $all = $name; |
|
297 | } else { |
||
298 | 4 | throw new Exception("Only one target can have empty 'depends' option. Found two now: $all, $name"); |
|
299 | } |
||
300 | } else { |
||
301 | foreach ($target['depends'] as $bundle) { |
||
302 | if (!isset($referenced[$bundle])) { |
||
303 | $referenced[$bundle] = $name; |
||
304 | } else { |
||
305 | 4 | throw new Exception("Target '{$referenced[$bundle]}' and '$name' cannot contain the bundle '$bundle' at the same time."); |
|
306 | } |
||
307 | } |
||
308 | } |
||
309 | } |
||
310 | 4 | if (isset($all)) { |
|
311 | 4 | $targets[$all]['depends'] = array_diff(array_keys($registered), array_keys($referenced)); |
|
312 | } |
||
313 | |||
314 | // adjust the 'depends' order for each target according to the dependency order of bundles |
||
315 | // create an AssetBundle object for each target |
||
316 | 4 | foreach ($targets as $name => $target) { |
|
317 | 4 | if (!isset($target['basePath'])) { |
|
318 | throw new Exception("Please specify 'basePath' for the '$name' target."); |
||
319 | } |
||
320 | 4 | if (!isset($target['baseUrl'])) { |
|
321 | throw new Exception("Please specify 'baseUrl' for the '$name' target."); |
||
322 | } |
||
323 | 4 | usort($target['depends'], function ($a, $b) use ($bundleOrders) { |
|
324 | 1 | if ($bundleOrders[$a] == $bundleOrders[$b]) { |
|
325 | return 0; |
||
326 | } |
||
327 | |||
328 | 1 | return $bundleOrders[$a] > $bundleOrders[$b] ? 1 : -1; |
|
329 | 4 | }); |
|
330 | 4 | if (!isset($target['class'])) { |
|
331 | 4 | $target['class'] = $name; |
|
332 | } |
||
333 | 4 | $targets[$name] = Yii::createObject($target); |
|
334 | } |
||
335 | |||
336 | 4 | return $targets; |
|
337 | } |
||
338 | |||
339 | /** |
||
340 | * Builds output asset bundle. |
||
341 | * @param \yii\web\AssetBundle $target output asset bundle |
||
342 | * @param string $type either 'js' or 'css'. |
||
343 | * @param \yii\web\AssetBundle[] $bundles source asset bundles. |
||
344 | * @throws Exception on failure. |
||
345 | */ |
||
346 | 4 | protected function buildTarget($target, $type, $bundles) |
|
383 | |||
384 | /** |
||
385 | * Adjust dependencies between asset bundles in the way source bundles begin to depend on output ones. |
||
386 | * @param \yii\web\AssetBundle[] $targets output asset bundles. |
||
387 | * @param \yii\web\AssetBundle[] $bundles source asset bundles. |
||
388 | * @return \yii\web\AssetBundle[] output asset bundles. |
||
389 | */ |
||
390 | 4 | protected function adjustDependency($targets, $bundles) |
|
431 | |||
432 | /** |
||
433 | * Registers asset bundles including their dependencies. |
||
434 | * @param \yii\web\AssetBundle[] $bundles asset bundles list. |
||
435 | * @param string $name bundle name. |
||
436 | * @param array $registered stores already registered names. |
||
437 | * @throws Exception if circular dependency is detected. |
||
438 | */ |
||
439 | 4 | protected function registerBundle($bundles, $name, &$registered) |
|
453 | |||
454 | /** |
||
455 | * Saves new asset bundles configuration. |
||
456 | * @param \yii\web\AssetBundle[] $targets list of asset bundles to be saved. |
||
457 | * @param string $bundleFile output file name. |
||
458 | * @throws \yii\console\Exception on failure. |
||
459 | */ |
||
460 | 4 | protected function saveTargets($targets, $bundleFile) |
|
503 | |||
504 | /** |
||
505 | * Compresses given JavaScript files and combines them into the single one. |
||
506 | * @param array $inputFiles list of source file names. |
||
507 | * @param string $outputFile output file name. |
||
508 | * @throws \yii\console\Exception on failure |
||
509 | */ |
||
510 | 3 | protected function compressJsFiles($inputFiles, $outputFile) |
|
532 | |||
533 | /** |
||
534 | * Compresses given CSS files and combines them into the single one. |
||
535 | * @param array $inputFiles list of source file names. |
||
536 | * @param string $outputFile output file name. |
||
537 | * @throws \yii\console\Exception on failure |
||
538 | */ |
||
539 | 3 | protected function compressCssFiles($inputFiles, $outputFile) |
|
561 | |||
562 | /** |
||
563 | * Combines JavaScript files into a single one. |
||
564 | * @param array $inputFiles source file names. |
||
565 | * @param string $outputFile output file name. |
||
566 | * @throws \yii\console\Exception on failure. |
||
567 | */ |
||
568 | 3 | public function combineJsFiles($inputFiles, $outputFile) |
|
580 | |||
581 | /** |
||
582 | * Combines CSS files into a single one. |
||
583 | * @param array $inputFiles source file names. |
||
584 | * @param string $outputFile output file name. |
||
585 | * @throws \yii\console\Exception on failure. |
||
586 | */ |
||
587 | 3 | public function combineCssFiles($inputFiles, $outputFile) |
|
600 | |||
601 | /** |
||
602 | * Adjusts CSS content allowing URL references pointing to the original resources. |
||
603 | * @param string $cssContent source CSS content. |
||
604 | * @param string $inputFilePath input CSS file name. |
||
605 | * @param string $outputFilePath output CSS file name. |
||
606 | * @return string adjusted CSS content. |
||
607 | */ |
||
608 | 16 | protected function adjustCssUrl($cssContent, $inputFilePath, $outputFilePath) |
|
679 | |||
680 | /** |
||
681 | * Creates template of configuration file for [[actionCompress]]. |
||
682 | * @param string $configFile output file name. |
||
683 | * @return int CLI exit code |
||
684 | * @throws \yii\console\Exception on failure. |
||
685 | */ |
||
686 | 1 | public function actionTemplate($configFile) |
|
743 | |||
744 | /** |
||
745 | * Returns canonicalized absolute pathname. |
||
746 | * Unlike regular `realpath()` this method does not expand symlinks and does not check path existence. |
||
747 | * @param string $path raw path |
||
748 | * @return string canonicalized absolute pathname |
||
749 | */ |
||
750 | 9 | private function findRealPath($path) |
|
765 | |||
766 | /** |
||
767 | * @param AssetBundle $bundle |
||
768 | * @return bool whether asset bundle external or not. |
||
769 | */ |
||
770 | 4 | private function isBundleExternal($bundle) |
|
774 | |||
775 | /** |
||
776 | * @param AssetBundle $bundle asset bundle instance. |
||
777 | * @return array bundle configuration. |
||
778 | */ |
||
779 | 2 | private function composeBundleConfig($bundle) |
|
785 | |||
786 | /** |
||
787 | * Composes trace info for bundle circular dependency. |
||
788 | * @param string $circularDependencyName name of the bundle, which have circular dependency |
||
789 | * @param array $registered list of bundles registered while detecting circular dependency. |
||
790 | * @return string bundle circular dependency trace string. |
||
791 | */ |
||
792 | 1 | private function composeCircularDependencyTrace($circularDependencyName, array $registered) |
|
807 | |||
808 | /** |
||
809 | * Deletes bundle asset files, which have been published from `sourcePath`. |
||
810 | * @param \yii\web\AssetBundle[] $bundles asset bundles to be processed. |
||
811 | * @since 2.0.10 |
||
812 | */ |
||
813 | 1 | private function deletePublishedAssets($bundles) |
|
835 | } |
||
836 |
If you suppress an error, we recommend checking for the error condition explicitly: