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\Iterator;
13
14use Assetic\Asset\AssetCollectionInterface;
15
16/**
17 * Iterates over an asset collection.
18 *
19 * The iterator is responsible for cascading filters and target URL patterns
20 * from parent to child assets.
21 *
22 * @author Kris Wallsmith <kris.wallsmith@gmail.com>
23 */
24class AssetCollectionIterator implements \RecursiveIterator
25{
26    private $assets;
27    private $filters;
28    private $vars;
29    private $output;
30    private $clones;
31
32    public function __construct(AssetCollectionInterface $coll, \SplObjectStorage $clones)
33    {
34        $this->assets  = $coll->all();
35        $this->filters = $coll->getFilters();
36        $this->vars    = $coll->getVars();
37        $this->output  = $coll->getTargetPath();
38        $this->clones  = $clones;
39
40        if (false === $pos = strrpos($this->output, '.')) {
41            $this->output .= '_*';
42        } else {
43            $this->output = substr($this->output, 0, $pos).'_*'.substr($this->output, $pos);
44        }
45    }
46
47    /**
48     * Returns a copy of the current asset with filters and a target URL applied.
49     *
50     * @param Boolean $raw Returns the unmodified asset if true
51     *
52     * @return \Assetic\Asset\AssetInterface
53     */
54    public function current($raw = false)
55    {
56        $asset = current($this->assets);
57
58        if ($raw) {
59            return $asset;
60        }
61
62        // clone once
63        if (!isset($this->clones[$asset])) {
64            $clone = $this->clones[$asset] = clone $asset;
65
66            // generate a target path based on asset name
67            $name = sprintf('%s_%d', pathinfo($asset->getSourcePath(), PATHINFO_FILENAME) ?: 'part', $this->key() + 1);
68
69            $name = $this->removeDuplicateVar($name);
70
71            $clone->setTargetPath(str_replace('*', $name, $this->output));
72        } else {
73            $clone = $this->clones[$asset];
74        }
75
76        // cascade filters
77        foreach ($this->filters as $filter) {
78            $clone->ensureFilter($filter);
79        }
80
81        return $clone;
82    }
83
84    public function key()
85    {
86        return key($this->assets);
87    }
88
89    public function next()
90    {
91        return next($this->assets);
92    }
93
94    public function rewind()
95    {
96        return reset($this->assets);
97    }
98
99    public function valid()
100    {
101        return false !== current($this->assets);
102    }
103
104    public function hasChildren()
105    {
106        return current($this->assets) instanceof AssetCollectionInterface;
107    }
108
109    /**
110     * @uses current()
111     */
112    public function getChildren()
113    {
114        return new self($this->current(), $this->clones);
115    }
116
117    private function removeDuplicateVar($name)
118    {
119        foreach ($this->vars as $var) {
120            $var = '{'.$var.'}';
121            if (false !== strpos($name, $var) && false !== strpos($this->output, $var)) {
122                $name = str_replace($var, '', $name);
123            }
124        }
125
126        return $name;
127    }
128}
129