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