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