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\Cache\CacheInterface; 15use Assetic\Filter\FilterInterface; 16use Assetic\Filter\HashableInterface; 17 18/** 19 * Caches an asset to avoid the cost of loading and dumping. 20 * 21 * @author Kris Wallsmith <kris.wallsmith@gmail.com> 22 */ 23class AssetCache implements AssetInterface 24{ 25 private $asset; 26 private $cache; 27 28 public function __construct(AssetInterface $asset, CacheInterface $cache) 29 { 30 $this->asset = $asset; 31 $this->cache = $cache; 32 } 33 34 public function ensureFilter(FilterInterface $filter) 35 { 36 $this->asset->ensureFilter($filter); 37 } 38 39 public function getFilters() 40 { 41 return $this->asset->getFilters(); 42 } 43 44 public function clearFilters() 45 { 46 $this->asset->clearFilters(); 47 } 48 49 public function load(FilterInterface $additionalFilter = null) 50 { 51 $cacheKey = self::getCacheKey($this->asset, $additionalFilter, 'load'); 52 if ($this->cache->has($cacheKey)) { 53 $this->asset->setContent($this->cache->get($cacheKey)); 54 55 return; 56 } 57 58 $this->asset->load($additionalFilter); 59 $this->cache->set($cacheKey, $this->asset->getContent()); 60 } 61 62 public function dump(FilterInterface $additionalFilter = null) 63 { 64 $cacheKey = self::getCacheKey($this->asset, $additionalFilter, 'dump'); 65 if ($this->cache->has($cacheKey)) { 66 return $this->cache->get($cacheKey); 67 } 68 69 $content = $this->asset->dump($additionalFilter); 70 $this->cache->set($cacheKey, $content); 71 72 return $content; 73 } 74 75 public function getContent() 76 { 77 return $this->asset->getContent(); 78 } 79 80 public function setContent($content) 81 { 82 $this->asset->setContent($content); 83 } 84 85 public function getSourceRoot() 86 { 87 return $this->asset->getSourceRoot(); 88 } 89 90 public function getSourcePath() 91 { 92 return $this->asset->getSourcePath(); 93 } 94 95 public function getSourceDirectory() 96 { 97 return $this->asset->getSourceDirectory(); 98 } 99 100 public function getTargetPath() 101 { 102 return $this->asset->getTargetPath(); 103 } 104 105 public function setTargetPath($targetPath) 106 { 107 $this->asset->setTargetPath($targetPath); 108 } 109 110 public function getLastModified() 111 { 112 return $this->asset->getLastModified(); 113 } 114 115 public function getVars() 116 { 117 return $this->asset->getVars(); 118 } 119 120 public function setValues(array $values) 121 { 122 $this->asset->setValues($values); 123 } 124 125 public function getValues() 126 { 127 return $this->asset->getValues(); 128 } 129 130 /** 131 * Returns a cache key for the current asset. 132 * 133 * The key is composed of everything but an asset's content: 134 * 135 * * source root 136 * * source path 137 * * target url 138 * * last modified 139 * * filters 140 * 141 * @param AssetInterface $asset The asset 142 * @param FilterInterface $additionalFilter Any additional filter being applied 143 * @param string $salt Salt for the key 144 * 145 * @return string A key for identifying the current asset 146 */ 147 private static function getCacheKey(AssetInterface $asset, FilterInterface $additionalFilter = null, $salt = '') 148 { 149 if ($additionalFilter) { 150 $asset = clone $asset; 151 $asset->ensureFilter($additionalFilter); 152 } 153 154 $cacheKey = $asset->getSourceRoot(); 155 $cacheKey .= $asset->getSourcePath(); 156 $cacheKey .= $asset->getTargetPath(); 157 $cacheKey .= $asset->getLastModified(); 158 159 foreach ($asset->getFilters() as $filter) { 160 if ($filter instanceof HashableInterface) { 161 $cacheKey .= $filter->hash(); 162 } else { 163 $cacheKey .= serialize($filter); 164 } 165 } 166 167 if ($values = $asset->getValues()) { 168 asort($values); 169 $cacheKey .= serialize($values); 170 } 171 172 return md5($cacheKey.$salt); 173 } 174} 175