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; 15 16/** 17 * Fixes relative CSS urls. 18 * 19 * @author Kris Wallsmith <kris.wallsmith@gmail.com> 20 */ 21class CssRewriteFilter extends BaseCssFilter 22{ 23 public function filterLoad(AssetInterface $asset) 24 { 25 } 26 27 public function filterDump(AssetInterface $asset) 28 { 29 $sourceBase = $asset->getSourceRoot(); 30 $sourcePath = $asset->getSourcePath(); 31 $targetPath = $asset->getTargetPath(); 32 33 if (null === $sourcePath || null === $targetPath || $sourcePath == $targetPath) { 34 return; 35 } 36 37 // learn how to get from the target back to the source 38 if (false !== strpos($sourceBase, '://')) { 39 list($scheme, $url) = explode('://', $sourceBase.'/'.$sourcePath, 2); 40 list($host, $path) = explode('/', $url, 2); 41 42 $host = $scheme.'://'.$host.'/'; 43 $path = false === strpos($path, '/') ? '' : dirname($path); 44 $path .= '/'; 45 } else { 46 // assume source and target are on the same host 47 $host = ''; 48 49 // pop entries off the target until it fits in the source 50 if ('.' == dirname($sourcePath)) { 51 $path = str_repeat('../', substr_count($targetPath, '/')); 52 } elseif ('.' == $targetDir = dirname($targetPath)) { 53 $path = dirname($sourcePath).'/'; 54 } else { 55 $path = ''; 56 while (0 !== strpos($sourcePath, $targetDir)) { 57 if (false !== $pos = strrpos($targetDir, '/')) { 58 $targetDir = substr($targetDir, 0, $pos); 59 $path .= '../'; 60 } else { 61 $targetDir = ''; 62 $path .= '../'; 63 break; 64 } 65 } 66 $path .= ltrim(substr(dirname($sourcePath).'/', strlen($targetDir)), '/'); 67 } 68 } 69 70 $content = $this->filterReferences($asset->getContent(), function ($matches) use ($host, $path) { 71 if (false !== strpos($matches['url'], '://') || 0 === strpos($matches['url'], '//') || 0 === strpos($matches['url'], 'data:')) { 72 // absolute or protocol-relative or data uri 73 return $matches[0]; 74 } 75 76 if (isset($matches['url'][0]) && '/' == $matches['url'][0]) { 77 // root relative 78 return str_replace($matches['url'], $host.$matches['url'], $matches[0]); 79 } 80 81 // document relative 82 $url = $matches['url']; 83 while (0 === strpos($url, '../') && 2 <= substr_count($path, '/')) { 84 $path = substr($path, 0, strrpos(rtrim($path, '/'), '/') + 1); 85 $url = substr($url, 3); 86 } 87 88 $parts = array(); 89 foreach (explode('/', $host.$path.$url) as $part) { 90 if ('..' === $part && count($parts) && '..' !== end($parts)) { 91 array_pop($parts); 92 } else { 93 $parts[] = $part; 94 } 95 } 96 97 return str_replace($matches['url'], implode('/', $parts), $matches[0]); 98 }); 99 100 $asset->setContent($content); 101 } 102} 103