Passed
Push — main ( f5700b...aaf4f3 )
by Michiel
32:12 queued 25:00
created

src/Phing/Filter/HeadFilter.php (1 issue)

Severity
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 Phing\Io\FilterReader;
24
use Phing\Io\Reader;
25
26
/**
27
 * Reads the first <code>n</code> lines of a stream.
28
 * (Default is first 10 lines.)
29
 * <p>
30
 * Example:
31
 * <pre><headfilter lines="3"/></pre>
32
 * Or:
33
 * <pre><filterreader classname="phing.filters.HeadFilter">
34
 *    <param name="lines" value="3"/>
35
 * </filterreader></pre>.
36
 *
37
 * @author <a href="mailto:[email protected]">Yannick Lecaillez</a>
38
 * @author hans lellelid, [email protected]
39
 *
40
 * @see FilterReader
41
 */
42
class HeadFilter extends BaseParamFilterReader implements ChainableReader
43
{
44
    /**
45
     * Parameter name for the number of lines to be returned.
46
     */
47
    public const LINES_KEY = 'lines';
48
49
    /**
50
     * Parameter name for the number of lines to be skipped.
51
     */
52
    public const SKIP_KEY = 'skip';
53
54
    /**
55
     * Number of lines currently read in.
56
     *
57
     * @var int
58
     */
59
    private $linesRead = 0;
60
61
    /**
62
     * Number of lines to be returned in the filtered stream.
63
     *
64
     * @var int
65
     */
66
    private $lines = 10;
67
68
    /**
69
     * Number of lines to be skipped.
70
     */
71
    private $skip = 0;
72
73
    /**
74
     * Returns first n lines of stream.
75
     *
76
     * @param int $len
77
     *
78
     * @return int|string the resulting stream, or -1
79
     *                    if the end of the resulting stream has been reached
80
     */
81 2
    public function read($len = null)
82
    {
83 2
        if (!$this->getInitialized()) {
84
            $this->initialize();
85
            $this->setInitialized(true);
86
        }
87
88
        // note, if buffer contains fewer lines than
89
        // $this->_lines this code will not work.
90
91 2
        if ($this->linesRead < $this->lines) {
92 2
            $buffer = $this->in->read($len);
93
94 2
            if (-1 === $buffer) {
95 2
                return -1;
96
            }
97
98
            // now grab first X lines from buffer
99
100 2
            $lines = explode("\n", $buffer);
101
102 2
            $linesCount = count($lines);
103
104
            // must account for possibility that the num lines requested could
105
            // involve more than one buffer read.
106 2
            $len = ($linesCount > $this->lines ? $this->lines - $this->linesRead : $linesCount);
107 2
            $filtered_buffer = implode("\n", array_slice($lines, $this->skip, $len));
108 2
            $this->linesRead += $len;
109
110 2
            return $filtered_buffer;
111
        }
112
113 2
        return -1; // EOF, since the file is "finished" as far as subsequent filters are concerned.
114
    }
115
116
    /**
117
     * Sets the number of lines to be returned in the filtered stream.
118
     *
119
     * @param int $lines the number of lines to be returned in the filtered stream
120
     */
121 2
    public function setLines($lines)
122
    {
123 2
        $this->lines = (int) $lines;
124
    }
125
126
    /**
127
     * Returns the number of lines to be returned in the filtered stream.
128
     *
129
     * @return int the number of lines to be returned in the filtered stream
130
     */
131 2
    public function getLines()
132
    {
133 2
        return $this->lines;
134
    }
135
136
    /**
137
     * Sets the number of lines to be skipped in the filtered stream.
138
     *
139
     * @param int $skip the number of lines to be skipped in the filtered stream
140
     */
141 2
    public function setSkip($skip)
142
    {
143 2
        $this->skip = (int) $skip;
144
    }
145
146
    /**
147
     * Creates a new HeadFilter using the passed in
148
     * Reader for instantiation.
149
     *
150
     * @param Reader $reader A Reader object providing the underlying stream.
151
     *                       Must not be <code>null</code>.
152
     *
153
     * @return HeadFilter a new filter based on this configuration, but filtering
154
     *                    the specified reader
155
     */
156 2
    public function chain(Reader $reader): Reader
157
    {
158 2
        $newFilter = new self($reader);
159 2
        $newFilter->setLines($this->getLines());
160 2
        $newFilter->setSkip($this->getSkip());
161 2
        $newFilter->setInitialized(true);
162 2
        $newFilter->setProject($this->getProject());
163
164 2
        return $newFilter;
165
    }
166
167
    /**
168
     * Returns the number of lines to be skipped in the filtered stream.
169
     *
170
     * @return int the number of lines to be skipped in the filtered stream
171
     */
172 2
    private function getSkip()
173
    {
174 2
        return $this->skip;
175
    }
176
177
    /**
178
     * Scans the parameters list for the "lines" parameter and uses
179
     * it to set the number of lines to be returned in the filtered stream.
180
     */
181
    private function initialize()
182
    {
183
        $params = $this->getParameters();
184
        if (null !== $params) {
0 ignored issues
show
The condition null !== $params is always true.
Loading history...
185
            foreach ($params as $param) {
186
                if (self::LINES_KEY === $param->getName()) {
187
                    $this->lines = (int) $param->getValue();
188
189
                    continue;
190
                }
191
                if (self::SKIP_KEY === $param->getName()) {
192
                    $this->lines = (int) $param->getValue();
193
194
                    continue;
195
                }
196
            }
197
        }
198
    }
199
}
200