Passed
Push — main ( 221f6d...f8c128 )
by Siad
05:28
created

src/Phing/Filter/LineContainsRegexp.php (2 issues)

1
<?php
2
3
/**
4
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
5
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
6
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
7
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
8
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
9
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
10
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
11
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
12
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
13
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
14
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
15
 *
16
 * This software consists of voluntary contributions made by many individuals
17
 * and is licensed under the LGPL. For more information please see
18
 * <http://phing.info>.
19
 */
20
21
namespace Phing\Filter;
22
23
use Exception;
24
use Phing\Io\FilterReader;
25
use Phing\Io\IOException;
26
use Phing\Io\Reader;
27
use Phing\Project;
28
use Phing\Type\RegularExpression;
29
use Phing\Util\RegexpException;
30
31
/**
32
 * Filter which includes only those lines that contain the user-specified
33
 * regular expression matching strings.
34
 *
35
 * Example:
36
 * <pre><linecontainsregexp>
37
 *   <regexp pattern="foo*">
38
 * </linecontainsregexp></pre>
39
 *
40
 * Or:
41
 *
42
 * <pre><filterreader classname="phing.filters.LineContainsRegExp">
43
 *    <param type="regexp" value="foo*"/>
44
 * </filterreader></pre>
45
 *
46
 * This will fetch all those lines that contain the pattern <code>foo</code>
47
 *
48
 * @author  Yannick Lecaillez <[email protected]>
49
 * @author  Hans Lellelid <[email protected]>
50
 *
51
 * @see     FilterReader
52
 */
53
class LineContainsRegexp extends BaseParamFilterReader implements ChainableReader
54
{
55
    /**
56
     * Parameter name for regular expression.
57
     *
58
     * @var string
59
     */
60
    public const REGEXP_KEY = 'regexp';
61
    public const NEGATE_KEY = 'negate';
62
    public const CS_KEY = 'casesensitive';
63
64
    /**
65
     * Regular expressions that are applied against lines.
66
     *
67
     * @var RegularExpression[]
68
     */
69
    private $regexps = [];
70
71
    /**
72
     * @var bool
73
     */
74
    private $negate = false;
75
76
    /**
77
     * @var bool
78
     */
79
    private $casesensitive = true;
80
81
    /**
82
     * Returns all lines in a buffer that contain specified strings.
83
     *
84
     * @param int $len
85
     *
86
     * @throws IOException
87
     * @throws RegexpException
88
     *
89
     * @return mixed buffer, -1 on EOF
90
     */
91 3
    public function read($len = null)
92
    {
93 3
        if (!$this->getInitialized()) {
94 3
            $this->initialize();
95 3
            $this->setInitialized(true);
96
        }
97
98 3
        $buffer = $this->in->read($len);
99
100 3
        if (-1 === $buffer) {
101 3
            return -1;
102
        }
103
104 3
        $lines = explode("\n", $buffer);
105 3
        $matched = [];
106
107 3
        $regexpsSize = count($this->regexps);
108 3
        foreach ($lines as $line) {
109 3
            for ($i = 0; $i < $regexpsSize; ++$i) {
110 3
                $regexp = $this->regexps[$i];
111 3
                $re = $regexp->getRegexp($this->getProject());
112 3
                $re->setIgnoreCase(!$this->casesensitive);
113 3
                $matches = $re->matches($line);
114 3
                if (!$matches) {
115 3
                    $line = null;
116
117 3
                    break;
118
                }
119
            }
120 3
            if (null !== $line) {
121 3
                $matched[] = $line;
122
            }
123
        }
124 3
        $filtered_buffer = implode("\n", $matched);
125
126 3
        if ($this->isNegated()) {
127 1
            $filtered_buffer = implode("\n", array_diff($lines, $matched));
128
        }
129
130 3
        return $filtered_buffer;
131
    }
132
133
    /**
134
     * Whether to match casesensitevly.
135
     */
136 1
    public function setCaseSensitive(bool $b)
137
    {
138 1
        $this->casesensitive = $b;
139 1
    }
140
141
    /**
142
     * Find out whether we match casesensitevly.
143
     *
144
     * @return bool negation flag
145
     */
146
    public function isCaseSensitive()
147
    {
148
        return $this->casesensitive;
149
    }
150
151
    /**
152
     * Set the negation mode.  Default false (no negation).
153
     *
154
     * @param bool $b the bool negation mode to set
155
     */
156 1
    public function setNegate(bool $b)
157
    {
158 1
        $this->negate = $b;
159 1
    }
160
161
    /**
162
     * Find out whether we have been negated.
163
     *
164
     * @return bool negation flag
165
     */
166 3
    public function isNegated()
167
    {
168 3
        return $this->negate;
169
    }
170
171
    /**
172
     * Adds a <code>regexp</code> element.
173
     *
174
     * @return object regExp The <code>regexp</code> element added
175
     */
176
    public function createRegexp()
177
    {
178
        $num = array_push($this->regexps, new RegularExpression());
179
180
        return $this->regexps[$num - 1];
181
    }
182
183
    /**
184
     * Sets the vector of regular expressions which must be contained within
185
     * a line read from the original stream in order for it to match this
186
     * filter.
187
     *
188
     * @param array $regexps
189
     *
190
     * @throws Exception
191
     *
192
     * @internal param An $regexps array of regular expressions which must be contained
193
     *                within a line in order for it to match in this filter. Must not be
194
     *                <code>null</code>.
195
     */
196
    public function setRegexps($regexps)
197
    {
198
        // type check, error must never occur, bad code of it does
199
        if (!is_array($regexps)) {
0 ignored issues
show
The condition is_array($regexps) is always true.
Loading history...
200
            throw new Exception("Expected an 'array', got something else");
201
        }
202
        $this->regexps = $regexps;
203
    }
204
205
    /**
206
     * Returns the array of regular expressions which must be contained within
207
     * a line read from the original stream in order for it to match this
208
     * filter.
209
     *
210
     * @return array The array of regular expressions which must be contained within
211
     *               a line read from the original stream in order for it to match this
212
     *               filter. The returned object is "live" - in other words, changes made to
213
     *               the returned object are mirrored in the filter.
214
     */
215
    public function getRegexps()
216
    {
217
        return $this->regexps;
218
    }
219
220
    /**
221
     * Set the regular expression as an attribute.
222
     *
223
     * @param mixed $pattern
224
     */
225
    public function setRegexp($pattern)
226
    {
227
        $regexp = new RegularExpression();
228
        $regexp->setPattern($pattern);
229
        $this->regexps[] = $regexp;
230
    }
231
232
    /**
233
     * Creates a new LineContainsRegExp using the passed in
234
     * Reader for instantiation.
235
     *
236
     * @throws Exception
237
     *
238
     * @return LineContainsRegexp A new filter based on this configuration, but filtering
239
     *                            the specified reader
240
     *
241
     * @internal param A $object Reader object providing the underlying stream.
242
     *               Must not be <code>null</code>.
243
     */
244
    public function chain(Reader $reader): Reader
245
    {
246
        $newFilter = new LineContainsRegexp($reader);
247
        $newFilter->setRegexps($this->getRegexps());
248
        $newFilter->setNegate($this->isNegated());
249
        $newFilter->setCaseSensitive($this->isCaseSensitive());
250
        $newFilter->setInitialized(true);
251
        $newFilter->setProject($this->getProject());
252
253
        return $newFilter;
254
    }
255
256
    /**
257
     * Parses parameters to add user defined regular expressions.
258
     */
259 3
    private function initialize()
260
    {
261 3
        $params = $this->getParameters();
262 3
        if (null !== $params) {
0 ignored issues
show
The condition null !== $params is always true.
Loading history...
263 3
            for ($i = 0, $paramsCount = count($params); $i < $paramsCount; ++$i) {
264 3
                if (self::REGEXP_KEY === $params[$i]->getType()) {
265 3
                    $pattern = $params[$i]->getValue();
266 3
                    $regexp = new RegularExpression();
267 3
                    $regexp->setPattern($pattern);
268 3
                    $this->regexps[] = $regexp;
269 2
                } elseif (self::NEGATE_KEY === $params[$i]->getType()) {
270 1
                    $this->setNegate(Project::toBoolean($params[$i]->getValue()));
271 1
                } elseif (self::CS_KEY === $params[$i]->getType()) {
272 1
                    $this->setCaseSensitive(Project::toBoolean($params[$i]->getValue()));
273
                }
274
            }
275
        }
276 3
    }
277
}
278