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\Factory\Worker;
13
14use Assetic\Asset\AssetCollectionInterface;
15use Assetic\Asset\AssetInterface;
16use Assetic\Factory\AssetFactory;
17
18/**
19 * Adds cache busting code
20 *
21 * @author Kris Wallsmith <kris.wallsmith@gmail.com>
22 */
23class CacheBustingWorker implements WorkerInterface
24{
25    private $separator;
26
27    public function __construct($separator = '-')
28    {
29        $this->separator = $separator;
30    }
31
32    public function process(AssetInterface $asset, AssetFactory $factory)
33    {
34        if (!$path = $asset->getTargetPath()) {
35            // no path to work with
36            return;
37        }
38
39        if (!$search = pathinfo($path, PATHINFO_EXTENSION)) {
40            // nothing to replace
41            return;
42        }
43
44        $replace = $this->separator.$this->getHash($asset, $factory).'.'.$search;
45        if (preg_match('/'.preg_quote($replace, '/').'$/', $path)) {
46            // already replaced
47            return;
48        }
49
50        $asset->setTargetPath(
51            preg_replace('/\.'.preg_quote($search, '/').'$/', $replace, $path)
52        );
53    }
54
55    protected function getHash(AssetInterface $asset, AssetFactory $factory)
56    {
57        $hash = hash_init('sha1');
58
59        hash_update($hash, $factory->getLastModified($asset));
60
61        if ($asset instanceof AssetCollectionInterface) {
62            foreach ($asset as $i => $leaf) {
63                $sourcePath = $leaf->getSourcePath();
64                hash_update($hash, $sourcePath ?: $i);
65            }
66        }
67
68        return substr(hash_final($hash), 0, 7);
69    }
70}
71