1
<?php
2
/**
3
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
4
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
5
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
6
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
7
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
8
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
9
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
10
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
11
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
12
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
13
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
14
 *
15
 * This software consists of voluntary contributions made by many individuals
16
 * and is licensed under the LGPL. For more information please see
17
 * <http://phing.info>.
18
 */
19

20
/**
21
 * Reads the last <code>n</code> lines of a stream. (Default is last10 lines.)
22
 *
23
 * Example:
24
 *
25
 * <pre><tailfilter lines="3" /></pre>
26
 *
27
 * Or:
28
 *
29
 * <pre><filterreader classname="phing.filters.TailFilter">
30
 *   <param name="lines" value="3">
31
 * </filterreader></pre>
32
 *
33
 * @author    <a href="mailto:yl@seasonfive.com">Yannick Lecaillez</a>
34
 * @author    hans lellelid, hans@velum.net
35
 * @copyright 2003 seasonfive. All rights reserved
36
 *
37
 * @see BaseParamFilterReader
38
 *
39
 * @package phing.filters
40
 */
41
class TailFilter extends BaseParamFilterReader implements ChainableReader
42
{
43
    /**
44
     * Parameter name for the number of lines to be returned.
45
     *
46
     * @var string
47
     */
48
    public const LINES_KEY = "lines";
49

50
    /**
51
     * Parameter name for the number of lines to be skipped.
52
     */
53
    public const SKIP_KEY = "skip";
54

55
    /**
56
     * Number of lines to be returned in the filtered stream.
57
     *
58
     * @var integer
59
     */
60
    private $lines = 10;
61

62
    /**
63
     * Array to hold lines.
64
     *
65
     * @var array
66
     */
67
    private $lineBuffer = [];
68

69
    /**
70
     * Number of lines to be skipped.
71
     */
72
    private $skip = 0;
73

74
    /**
75
     * Returns the last n lines of a file.
76
     *
77
     * @param  int $len Num chars to read.
78
     * @return mixed The filtered buffer or -1 if EOF.
79
     */
80 1
    public function read($len = null)
81
    {
82 1
        if (!$this->getInitialized()) {
83 0
            $this->initialize();
84 0
            $this->setInitialized(true);
85
        }
86

87 1
        while (($buffer = $this->in->read($len)) !== -1) {
88
            // Remove the last "\n" from buffer for
89
            // prevent explode to add an empty cell at
90
            // the end of array
91 1
            $buffer = trim($buffer, "\n");
92

93 1
            $lines = explode("\n", $buffer);
94 1
            $skip = $this->skip > 0 ? $this->skip : 0;
95

96 1
            if (count($lines) >= $this->lines) {
97
                // Buffer have more (or same) number of lines than needed.
98
                // Fill lineBuffer with the last "$this->_lines" lasts ones.
99 1
                $off = count($lines) - $this->lines;
100 1
                if ($skip > 0) {
101 1
                    $this->lineBuffer = array_slice($lines, $off - $skip, -$skip);
102
                } else {
103 1
                    $this->lineBuffer = array_slice($lines, $off);
104
                }
105
            } else {
106
                // Some new lines ...
107
                // Prepare space for insert these new ones
108 1
                $this->lineBuffer = array_slice($this->lineBuffer, count($lines) - 1);
109 1
                $this->lineBuffer = array_merge($this->lineBuffer, $lines);
110
            }
111
        }
112

113 1
        if (empty($this->lineBuffer)) {
114 1
            $ret = -1;
115
        } else {
116 1
            $ret = implode("\n", $this->lineBuffer);
117 1
            $this->lineBuffer = [];
118
        }
119

120 1
        return $ret;
121
    }
122

123
    /**
124
     * Sets the number of lines to be returned in the filtered stream.
125
     *
126
     * @param integer $lines the number of lines to be returned in the filtered stream.
127
     */
128 1
    public function setLines($lines)
129
    {
130 1
        $this->lines = (int) $lines;
131
    }
132

133
    /**
134
     * Returns the number of lines to be returned in the filtered stream.
135
     *
136
     * @return integer The number of lines to be returned in the filtered stream.
137
     */
138 1
    public function getLines()
139
    {
140 1
        return $this->lines;
141
    }
142

143
    /**
144
     * Sets the number of lines to be skipped in the filtered stream.
145
     *
146
     * @param int $skip the number of lines to be skipped in the filtered stream
147
     */
148 1
    public function setSkip($skip)
149
    {
150 1
        $this->skip = (int) $skip;
151
    }
152

153
    /**
154
     * Returns the number of lines to be skipped in the filtered stream.
155
     *
156
     * @return int the number of lines to be skipped in the filtered stream
157
     */
158 1
    private function getSkip()
159
    {
160 1
        return $this->skip;
161
    }
162

163
    /**
164
     * Creates a new TailFilter using the passed in
165
     * Reader for instantiation.
166
     *
167
     * @param Reader $reader A Reader object providing the underlying stream.
168
     *                       Must not be <code>null</code>.
169
     *
170
     * @return TailFilter A new filter based on this configuration, but filtering
171
     *                    the specified reader.
172
     */
173 1
    public function chain(Reader $reader): Reader
174
    {
175 1
        $newFilter = new TailFilter($reader);
176 1
        $newFilter->setLines($this->getLines());
177 1
        $newFilter->setSkip($this->getSkip());
178 1
        $newFilter->setInitialized(true);
179 1
        $newFilter->setProject($this->getProject());
180

181 1
        return $newFilter;
182
    }
183

184
    /**
185
     * Scans the parameters list for the "lines" parameter and uses
186
     * it to set the number of lines to be returned in the filtered stream.
187
     */
188 0
    private function initialize()
189
    {
190 0
        $params = $this->getParameters();
191 0
        if ($params !== null) {
192 0
            for ($i = 0, $_i = count($params); $i < $_i; $i++) {
193 0
                if (self::LINES_KEY == $params[$i]->getName()) {
194 0
                    $this->lines = (int) $params[$i]->getValue();
195 0
                    continue;
196
                }
197 0
                if (self::SKIP_KEY == $params[$i]->getName()) {
198 0
                    $this->skip = (int) $params[$i]->getValue();
199 0
                    continue;
200
                }
201
            }
202
        }
203
    }
204
}

Read our documentation on viewing source code .

Loading