1<?php
2/*
3 * This file is part of the File_Iterator package.
4 *
5 * (c) Sebastian Bergmann <sebastian@phpunit.de>
6 *
7 * For the full copyright and license information, please view the LICENSE
8 * file that was distributed with this source code.
9 */
10
11/**
12 * FilterIterator implementation that filters files based on prefix(es) and/or
13 * suffix(es). Hidden files and files from hidden directories are also filtered.
14 *
15 * @since     Class available since Release 1.0.0
16 */
17class File_Iterator extends FilterIterator
18{
19    const PREFIX = 0;
20    const SUFFIX = 1;
21
22    /**
23     * @var array
24     */
25    protected $suffixes = array();
26
27    /**
28     * @var array
29     */
30    protected $prefixes = array();
31
32    /**
33     * @var array
34     */
35    protected $exclude = array();
36
37    /**
38     * @var string
39     */
40    protected $basepath;
41
42    /**
43     * @param Iterator $iterator
44     * @param array    $suffixes
45     * @param array    $prefixes
46     * @param array    $exclude
47     * @param string   $basepath
48     */
49    public function __construct(Iterator $iterator, array $suffixes = array(), array $prefixes = array(), array $exclude = array(), $basepath = NULL)
50    {
51        $exclude = array_filter(array_map('realpath', $exclude));
52
53        if ($basepath !== NULL) {
54            $basepath = realpath($basepath);
55        }
56
57        if ($basepath === FALSE) {
58            $basepath = NULL;
59        } else {
60            foreach ($exclude as &$_exclude) {
61                $_exclude = str_replace($basepath, '', $_exclude);
62            }
63        }
64
65        $this->prefixes = $prefixes;
66        $this->suffixes = $suffixes;
67        $this->exclude  = $exclude;
68        $this->basepath = $basepath;
69
70        parent::__construct($iterator);
71    }
72
73    /**
74     * @return bool
75     */
76    public function accept()
77    {
78        $current  = $this->getInnerIterator()->current();
79        $filename = $current->getFilename();
80        $realpath = $current->getRealPath();
81
82        if ($this->basepath !== NULL) {
83            $realpath = str_replace($this->basepath, '', $realpath);
84        }
85
86        // Filter files in hidden directories.
87        if (preg_match('=/\.[^/]*/=', $realpath)) {
88            return FALSE;
89        }
90
91        return $this->acceptPath($realpath) &&
92               $this->acceptPrefix($filename) &&
93               $this->acceptSuffix($filename);
94    }
95
96    /**
97     * @param  string $path
98     * @return bool
99     * @since  Method available since Release 1.1.0
100     */
101    protected function acceptPath($path)
102    {
103        foreach ($this->exclude as $exclude) {
104            if (strpos($path, $exclude) === 0) {
105                return FALSE;
106            }
107        }
108
109        return TRUE;
110    }
111
112    /**
113     * @param  string $filename
114     * @return bool
115     * @since  Method available since Release 1.1.0
116     */
117    protected function acceptPrefix($filename)
118    {
119        return $this->acceptSubString($filename, $this->prefixes, self::PREFIX);
120    }
121
122    /**
123     * @param  string $filename
124     * @return bool
125     * @since  Method available since Release 1.1.0
126     */
127    protected function acceptSuffix($filename)
128    {
129        return $this->acceptSubString($filename, $this->suffixes, self::SUFFIX);
130    }
131
132    /**
133     * @param  string $filename
134     * @param  array  $subStrings
135     * @param  int    $type
136     * @return bool
137     * @since  Method available since Release 1.1.0
138     */
139    protected function acceptSubString($filename, array $subStrings, $type)
140    {
141        if (empty($subStrings)) {
142            return TRUE;
143        }
144
145        $matched = FALSE;
146
147        foreach ($subStrings as $string) {
148            if (($type == self::PREFIX && strpos($filename, $string) === 0) ||
149                ($type == self::SUFFIX &&
150                 substr($filename, -1 * strlen($string)) == $string)) {
151                $matched = TRUE;
152                break;
153            }
154        }
155
156        return $matched;
157    }
158}
159