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\Resource;
13
14/**
15 * A resource is something formulae can be loaded from.
16 *
17 * @author Kris Wallsmith <kris.wallsmith@gmail.com>
18 */
19class DirectoryResource implements IteratorResourceInterface
20{
21    private $path;
22    private $pattern;
23
24    /**
25     * Constructor.
26     *
27     * @param string $path    A directory path
28     * @param string $pattern A filename pattern
29     */
30    public function __construct($path, $pattern = null)
31    {
32        if (DIRECTORY_SEPARATOR != substr($path, -1)) {
33            $path .= DIRECTORY_SEPARATOR;
34        }
35
36        $this->path = $path;
37        $this->pattern = $pattern;
38    }
39
40    public function isFresh($timestamp)
41    {
42        if (!is_dir($this->path) || filemtime($this->path) > $timestamp) {
43            return false;
44        }
45
46        foreach ($this as $resource) {
47            if (!$resource->isFresh($timestamp)) {
48                return false;
49            }
50        }
51
52        return true;
53    }
54
55    /**
56     * Returns the combined content of all inner resources.
57     */
58    public function getContent()
59    {
60        $content = array();
61        foreach ($this as $resource) {
62            $content[] = $resource->getContent();
63        }
64
65        return implode("\n", $content);
66    }
67
68    public function __toString()
69    {
70        return $this->path;
71    }
72
73    public function getIterator()
74    {
75        return is_dir($this->path)
76            ? new DirectoryResourceIterator($this->getInnerIterator())
77            : new \EmptyIterator();
78    }
79
80    protected function getInnerIterator()
81    {
82        return new DirectoryResourceFilterIterator(new \RecursiveDirectoryIterator($this->path, \RecursiveDirectoryIterator::FOLLOW_SYMLINKS), $this->pattern);
83    }
84}
85
86/**
87 * An iterator that converts file objects into file resources.
88 *
89 * @author Kris Wallsmith <kris.wallsmith@gmail.com>
90 * @access private
91 */
92class DirectoryResourceIterator extends \RecursiveIteratorIterator
93{
94    public function current()
95    {
96        return new FileResource(parent::current()->getPathname());
97    }
98}
99
100/**
101 * Filters files by a basename pattern.
102 *
103 * @author Kris Wallsmith <kris.wallsmith@gmail.com>
104 * @access private
105 */
106class DirectoryResourceFilterIterator extends \RecursiveFilterIterator
107{
108    protected $pattern;
109
110    public function __construct(\RecursiveDirectoryIterator $iterator, $pattern = null)
111    {
112        parent::__construct($iterator);
113
114        $this->pattern = $pattern;
115    }
116
117    public function accept()
118    {
119        $file = $this->current();
120        $name = $file->getBasename();
121
122        if ($file->isDir()) {
123            return '.' != $name[0];
124        }
125
126        return null === $this->pattern || 0 < preg_match($this->pattern, $name);
127    }
128
129    public function getChildren()
130    {
131        return new self(new \RecursiveDirectoryIterator($this->current()->getPathname(), \RecursiveDirectoryIterator::FOLLOW_SYMLINKS), $this->pattern);
132    }
133}
134