1<?php 2 3/* 4 * This file is part of Component Installer. 5 * 6 * (c) Rob Loach (http://robloach.net) 7 * 8 * For the full copyright and license information, please view the LICENSE.md 9 * file that was distributed with this source code. 10 */ 11 12namespace ComponentInstaller\Process; 13 14use Composer\Config; 15use Assetic\Asset\AssetCollection; 16use Assetic\Filter\CssRewriteFilter; 17use Assetic\Asset\FileAsset; 18use Assetic\Filter\FilterCollection; 19 20/** 21 * Builds the require.css file from all Component stylesheets. 22 */ 23class RequireCssProcess extends Process 24{ 25 /** 26 * {@inheritdoc} 27 */ 28 public function process() 29 { 30 $filters = array(new CssRewriteFilter()); 31 if ($this->config->has('component-styleFilters')) { 32 $customFilters = $this->config->get('component-styleFilters'); 33 if (isset($customFilters) && is_array($customFilters)) { 34 foreach ($customFilters as $filter => $filterParams) { 35 $reflection = new \ReflectionClass($filter); 36 $filters[] = $reflection->newInstanceArgs($filterParams); 37 } 38 } 39 } 40 41 $filterCollection = new FilterCollection($filters); 42 43 $assets = new AssetCollection(); 44 $styles = $this->packageStyles($this->packages); 45 foreach ($styles as $package => $packageStyles) { 46 $packageAssets = new AssetCollection(); 47 $packagePath = $this->componentDir.'/'.$package; 48 49 foreach ($packageStyles as $style => $paths) { 50 foreach ($paths as $path) { 51 // The full path to the CSS file. 52 $assetPath = realpath($path); 53 // The root of the CSS file. 54 $sourceRoot = dirname($path); 55 // The style path to the CSS file when external. 56 $sourcePath = $package . '/' . $style; 57 //Replace glob patterns with filenames. 58 $filename = basename($style); 59 if(preg_match('~^\*(\.[^\.]+)$~', $filename, $matches)){ 60 $sourcePath = str_replace($filename, basename($assetPath), $sourcePath); 61 } 62 // Where the final CSS will be generated. 63 $targetPath = $this->componentDir; 64 // Build the asset and add it to the collection. 65 $asset = new FileAsset($assetPath, $filterCollection, $sourceRoot, $sourcePath); 66 $asset->setTargetPath($targetPath); 67 $assets->add($asset); 68 // Add asset to package collection. 69 $sourcePath = preg_replace('{^.*'.preg_quote($package).'/}', '', $sourcePath); 70 $asset = new FileAsset($assetPath, $filterCollection, $sourceRoot, $sourcePath); 71 $asset->setTargetPath($packagePath); 72 $packageAssets->add($asset); 73 } 74 } 75 76 if (file_put_contents($packagePath.'/'.$package.'-built.css', $packageAssets->dump()) === FALSE) { 77 $this->io->write("<error>Error writing $package-built.css to destination</error>"); 78 } 79 } 80 81 if (file_put_contents($this->componentDir . '/require.css', $assets->dump()) === FALSE) { 82 $this->io->write('<error>Error writing require.css to destination</error>'); 83 return false; 84 } 85 86 return null; 87 } 88 89 /** 90 * Retrieves an array of styles from a collection of packages. 91 * 92 * @param array $packages 93 * An array of packages from the composer.lock file. 94 * 95 * @return array 96 * A set of package styles. 97 */ 98 public function packageStyles(array $packages) 99 { 100 $output = array(); 101 102 // Construct the packages configuration. 103 foreach ($packages as $package) { 104 // Retrieve information from the extra options. 105 $extra = isset($package['extra']) ? $package['extra'] : array(); 106 $name = $this->getComponentName($package['name'], $extra); 107 $component = isset($extra['component']) ? $extra['component'] : array(); 108 $styles = isset($component['styles']) ? $component['styles'] : array(); 109 $vendorDir = $this->getVendorDir($package); 110 111 // Loop through each style. 112 foreach ($styles as $style) { 113 // Find the style path from the vendor directory. 114 $path = strtr($vendorDir.'/'.$style, '/', DIRECTORY_SEPARATOR); 115 116 // Search for the candidate with a glob recursive file search. 117 $files = $this->fs->recursiveGlobFiles($path); 118 foreach ($files as $file) { 119 // Provide the package name, style and full path. 120 $output[$name][$style][] = $file; 121 } 122 } 123 } 124 125 return $output; 126 } 127} 128