1<?php
2/*
3 * This file is part of PHPUnit.
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
11class PHPUnit_Runner_Filter_Test extends RecursiveFilterIterator
12{
13    /**
14     * @var string
15     */
16    protected $filter = null;
17
18    /**
19     * @var int
20     */
21    protected $filterMin;
22    /**
23     * @var int
24     */
25    protected $filterMax;
26
27    /**
28     * @param RecursiveIterator $iterator
29     * @param string            $filter
30     */
31    public function __construct(RecursiveIterator $iterator, $filter)
32    {
33        parent::__construct($iterator);
34        $this->setFilter($filter);
35    }
36
37    /**
38     * @param string $filter
39     */
40    protected function setFilter($filter)
41    {
42        if (PHPUnit_Util_Regex::pregMatchSafe($filter, '') === false) {
43            // Handles:
44            //  * testAssertEqualsSucceeds#4
45            //  * testAssertEqualsSucceeds#4-8
46            if (preg_match('/^(.*?)#(\d+)(?:-(\d+))?$/', $filter, $matches)) {
47                if (isset($matches[3]) && $matches[2] < $matches[3]) {
48                    $filter = sprintf(
49                        '%s.*with data set #(\d+)$',
50                        $matches[1]
51                    );
52
53                    $this->filterMin = $matches[2];
54                    $this->filterMax = $matches[3];
55                } else {
56                    $filter = sprintf(
57                        '%s.*with data set #%s$',
58                        $matches[1],
59                        $matches[2]
60                    );
61                }
62            } // Handles:
63            //  * testDetermineJsonError@JSON_ERROR_NONE
64            //  * testDetermineJsonError@JSON.*
65            elseif (preg_match('/^(.*?)@(.+)$/', $filter, $matches)) {
66                $filter = sprintf(
67                    '%s.*with data set "%s"$',
68                    $matches[1],
69                    $matches[2]
70                );
71            }
72
73            // Escape delimiters in regular expression. Do NOT use preg_quote,
74            // to keep magic characters.
75            $filter = sprintf('/%s/', str_replace(
76                '/',
77                '\\/',
78                $filter
79            ));
80        }
81
82        $this->filter = $filter;
83    }
84
85    /**
86     * @return bool
87     */
88    public function accept()
89    {
90        $test = $this->getInnerIterator()->current();
91
92        if ($test instanceof PHPUnit_Framework_TestSuite) {
93            return true;
94        }
95
96        if ($test instanceof PHPUnit_Framework_WarningTestCase) {
97            $name = $test->getMessage();
98        } else {
99            $tmp = PHPUnit_Util_Test::describe($test, false);
100
101            if ($tmp[0] != '') {
102                $name = implode('::', $tmp);
103            } else {
104                $name = $tmp[1];
105            }
106        }
107
108        $accepted = @preg_match($this->filter, $name, $matches);
109
110        if ($accepted && isset($this->filterMax)) {
111            $set      = end($matches);
112            $accepted = $set >= $this->filterMin && $set <= $this->filterMax;
113        }
114
115        return $accepted;
116    }
117}
118