1<?php 2 3/* 4 * This file is part of the Assetic package, an OpenSky project. 5 * 6 * (c) 2010-2014 OpenSky Project Inc 7 * 8 * For the full copyright and license information, please view the LICENSE 9 * file that was distributed with this source code. 10 */ 11 12namespace Assetic\Filter; 13 14use Assetic\Asset\AssetInterface; 15use Assetic\Asset\FileAsset; 16use Assetic\Asset\HttpAsset; 17use Assetic\Factory\AssetFactory; 18 19/** 20 * Inlines imported stylesheets. 21 * 22 * @author Kris Wallsmith <kris.wallsmith@gmail.com> 23 */ 24class CssImportFilter extends BaseCssFilter implements DependencyExtractorInterface 25{ 26 private $importFilter; 27 28 /** 29 * Constructor. 30 * 31 * @param FilterInterface $importFilter Filter for each imported asset 32 */ 33 public function __construct(FilterInterface $importFilter = null) 34 { 35 $this->importFilter = $importFilter ?: new CssRewriteFilter(); 36 } 37 38 public function filterLoad(AssetInterface $asset) 39 { 40 $importFilter = $this->importFilter; 41 $sourceRoot = $asset->getSourceRoot(); 42 $sourcePath = $asset->getSourcePath(); 43 44 $callback = function ($matches) use ($importFilter, $sourceRoot, $sourcePath) { 45 if (!$matches['url'] || null === $sourceRoot) { 46 return $matches[0]; 47 } 48 49 $importRoot = $sourceRoot; 50 51 if (false !== strpos($matches['url'], '://')) { 52 // absolute 53 list($importScheme, $tmp) = explode('://', $matches['url'], 2); 54 list($importHost, $importPath) = explode('/', $tmp, 2); 55 $importRoot = $importScheme.'://'.$importHost; 56 } elseif (0 === strpos($matches['url'], '//')) { 57 // protocol-relative 58 list($importHost, $importPath) = explode('/', substr($matches['url'], 2), 2); 59 $importRoot = '//'.$importHost; 60 } elseif ('/' == $matches['url'][0]) { 61 // root-relative 62 $importPath = substr($matches['url'], 1); 63 } elseif (null !== $sourcePath) { 64 // document-relative 65 $importPath = $matches['url']; 66 if ('.' != $sourceDir = dirname($sourcePath)) { 67 $importPath = $sourceDir.'/'.$importPath; 68 } 69 } else { 70 return $matches[0]; 71 } 72 73 $importSource = $importRoot.'/'.$importPath; 74 if (false !== strpos($importSource, '://') || 0 === strpos($importSource, '//')) { 75 $import = new HttpAsset($importSource, array($importFilter), true); 76 } elseif ('css' != pathinfo($importPath, PATHINFO_EXTENSION) || !file_exists($importSource)) { 77 // ignore non-css and non-existant imports 78 return $matches[0]; 79 } else { 80 $import = new FileAsset($importSource, array($importFilter), $importRoot, $importPath); 81 } 82 83 $import->setTargetPath($sourcePath); 84 85 return $import->dump(); 86 }; 87 88 $content = $asset->getContent(); 89 $lastHash = md5($content); 90 91 do { 92 $content = $this->filterImports($content, $callback); 93 $hash = md5($content); 94 } while ($lastHash != $hash && $lastHash = $hash); 95 96 $asset->setContent($content); 97 } 98 99 public function filterDump(AssetInterface $asset) 100 { 101 } 102 103 public function getChildren(AssetFactory $factory, $content, $loadPath = null) 104 { 105 // todo 106 return array(); 107 } 108} 109