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\Asset;
13
14use Assetic\Asset\Iterator\AssetCollectionFilterIterator;
15use Assetic\Asset\Iterator\AssetCollectionIterator;
16use Assetic\Filter\FilterCollection;
17use Assetic\Filter\FilterInterface;
18
19/**
20 * A collection of assets.
21 *
22 * @author Kris Wallsmith <kris.wallsmith@gmail.com>
23 */
24class AssetCollection implements \IteratorAggregate, AssetCollectionInterface
25{
26    private $assets;
27    private $filters;
28    private $sourceRoot;
29    private $targetPath;
30    private $content;
31    private $clones;
32    private $vars;
33    private $values;
34
35    /**
36     * Constructor.
37     *
38     * @param array  $assets     Assets for the current collection
39     * @param array  $filters    Filters for the current collection
40     * @param string $sourceRoot The root directory
41     * @param array  $vars
42     */
43    public function __construct($assets = array(), $filters = array(), $sourceRoot = null, array $vars = array())
44    {
45        $this->assets = array();
46        foreach ($assets as $asset) {
47            $this->add($asset);
48        }
49
50        $this->filters = new FilterCollection($filters);
51        $this->sourceRoot = $sourceRoot;
52        $this->clones = new \SplObjectStorage();
53        $this->vars = $vars;
54        $this->values = array();
55    }
56
57    public function __clone()
58    {
59        $this->filters = clone $this->filters;
60        $this->clones = new \SplObjectStorage();
61    }
62
63    public function all()
64    {
65        return $this->assets;
66    }
67
68    public function add(AssetInterface $asset)
69    {
70        $this->assets[] = $asset;
71    }
72
73    public function removeLeaf(AssetInterface $needle, $graceful = false)
74    {
75        foreach ($this->assets as $i => $asset) {
76            $clone = isset($this->clones[$asset]) ? $this->clones[$asset] : null;
77            if (in_array($needle, array($asset, $clone), true)) {
78                unset($this->clones[$asset], $this->assets[$i]);
79
80                return true;
81            }
82
83            if ($asset instanceof AssetCollectionInterface && $asset->removeLeaf($needle, true)) {
84                return true;
85            }
86        }
87
88        if ($graceful) {
89            return false;
90        }
91
92        throw new \InvalidArgumentException('Leaf not found.');
93    }
94
95    public function replaceLeaf(AssetInterface $needle, AssetInterface $replacement, $graceful = false)
96    {
97        foreach ($this->assets as $i => $asset) {
98            $clone = isset($this->clones[$asset]) ? $this->clones[$asset] : null;
99            if (in_array($needle, array($asset, $clone), true)) {
100                unset($this->clones[$asset]);
101                $this->assets[$i] = $replacement;
102
103                return true;
104            }
105
106            if ($asset instanceof AssetCollectionInterface && $asset->replaceLeaf($needle, $replacement, true)) {
107                return true;
108            }
109        }
110
111        if ($graceful) {
112            return false;
113        }
114
115        throw new \InvalidArgumentException('Leaf not found.');
116    }
117
118    public function ensureFilter(FilterInterface $filter)
119    {
120        $this->filters->ensure($filter);
121    }
122
123    public function getFilters()
124    {
125        return $this->filters->all();
126    }
127
128    public function clearFilters()
129    {
130        $this->filters->clear();
131        $this->clones = new \SplObjectStorage();
132    }
133
134    public function load(FilterInterface $additionalFilter = null)
135    {
136        // loop through leaves and load each asset
137        $parts = array();
138        foreach ($this as $asset) {
139            $asset->load($additionalFilter);
140            $parts[] = $asset->getContent();
141        }
142
143        $this->content = implode("\n", $parts);
144    }
145
146    public function dump(FilterInterface $additionalFilter = null)
147    {
148        // loop through leaves and dump each asset
149        $parts = array();
150        foreach ($this as $asset) {
151            $parts[] = $asset->dump($additionalFilter);
152        }
153
154        return implode("\n", $parts);
155    }
156
157    public function getContent()
158    {
159        return $this->content;
160    }
161
162    public function setContent($content)
163    {
164        $this->content = $content;
165    }
166
167    public function getSourceRoot()
168    {
169        return $this->sourceRoot;
170    }
171
172    public function getSourcePath()
173    {
174    }
175
176    public function getSourceDirectory()
177    {
178    }
179
180    public function getTargetPath()
181    {
182        return $this->targetPath;
183    }
184
185    public function setTargetPath($targetPath)
186    {
187        $this->targetPath = $targetPath;
188    }
189
190    /**
191     * Returns the highest last-modified value of all assets in the current collection.
192     *
193     * @return integer|null A UNIX timestamp
194     */
195    public function getLastModified()
196    {
197        if (!count($this->assets)) {
198            return;
199        }
200
201        $mtime = 0;
202        foreach ($this as $asset) {
203            $assetMtime = $asset->getLastModified();
204            if ($assetMtime > $mtime) {
205                $mtime = $assetMtime;
206            }
207        }
208
209        return $mtime;
210    }
211
212    /**
213     * Returns an iterator for looping recursively over unique leaves.
214     */
215    public function getIterator()
216    {
217        return new \RecursiveIteratorIterator(new AssetCollectionFilterIterator(new AssetCollectionIterator($this, $this->clones)));
218    }
219
220    public function getVars()
221    {
222        return $this->vars;
223    }
224
225    public function setValues(array $values)
226    {
227        $this->values = $values;
228
229        foreach ($this as $asset) {
230            $asset->setValues(array_intersect_key($values, array_flip($asset->getVars())));
231        }
232    }
233
234    public function getValues()
235    {
236        return $this->values;
237    }
238}
239