/** * Moving a css file should update all relative urls. * Relative references (e.g. ../images/image.gif) in a certain css file, * will have to be updated when a file is being saved at another location * (e.g. ../../images/image.gif, if the new CSS file is 1 folder deeper). * * @param Converter $converter Relative path converter * @param string $content The CSS content to update relative urls for. * * @return string */ protected function move(Converter $converter, $content) { /* * Relative path references will usually be enclosed by url(). @import * is an exception, where url() is not necessary around the path (but is * allowed). * This *could* be 1 regular expression, where both regular expressions * in this array are on different sides of a |. But we're using named * patterns in both regexes, the same name on both regexes. This is only * possible with a (?J) modifier, but that only works after a fairly * recent PCRE version. That's why I'm doing 2 separate regular * expressions & combining the matches after executing of both. */ $relativeRegexes = array('/ # open url() url\\( \\s* # open path enclosure (?P<quotes>["\'])? # fetch path (?P<path> # do not fetch data uris or external sources (?!( \\s? ["\']? (data|https?): )) .+? ) # close path enclosure (?(quotes)(?P=quotes)) \\s* # close url() \\) /ix', '/ # import statement @import # whitespace \\s+ # we don\'t have to check for @import url(), because the # condition above will already catch these # open path enclosure (?P<quotes>["\']) # fetch path (?P<path> # do not fetch data uris or external sources (?!( ["\']? (data|https?): )) .+? ) # close path enclosure (?P=quotes) /ix'); // find all relative urls in css $matches = array(); foreach ($relativeRegexes as $relativeRegex) { if (preg_match_all($relativeRegex, $content, $regexMatches, PREG_SET_ORDER)) { $matches = array_merge($matches, $regexMatches); } } $search = array(); $replace = array(); // loop all urls foreach ($matches as $match) { // determine if it's a url() or an @import match $type = strpos($match[0], '@import') === 0 ? 'import' : 'url'; // fix relative url $url = $converter->convert($match['path']); // build replacement $search[] = $match[0]; if ($type == 'url') { $replace[] = 'url(' . $url . ')'; } elseif ($type == 'import') { $replace[] = '@import "' . $url . '"'; } } // replace urls $content = str_replace($search, $replace, $content); return $content; }
/** * Test Converter, provided by dataProvider * * @test * @dataProvider dataProvider */ public function convert($relative, $from, $to, $expected) { $converter = new Converter($from, $to); $result = $converter->convert($relative); $this->assertEquals($expected, $result); }