1--TEST--
2Bug #77069 (stream filter loses final block of data)
3--FILE--
4<?php
5class MyFilter extends php_user_filter {
6    private $data = '';
7
8    public function filter($in, $out, &$consumed, $closing): int {
9        $return = PSFS_FEED_ME;
10
11        // While input data is available, continue to read it.
12        while ($bucket_in = stream_bucket_make_writeable($in)) {
13            $this->data .= $bucket_in->data;
14            $consumed   += $bucket_in->datalen;
15
16            // Process whole lines.
17            while (preg_match('/(.*?)[\r\n]+(.*)/s', $this->data, $match) === 1) {
18                list(, $data, $this->data) = $match;
19                // Send this record output.
20                $data       = strrev($data) . PHP_EOL;
21                $bucket_out = stream_bucket_new($this->stream, $data);
22                $return     = PSFS_PASS_ON;
23                stream_bucket_append($out, $bucket_out);
24            }
25        }
26
27        // Process the final line.
28        if ($closing && $this->data !== '') {
29            $data       = strrev($this->data) . PHP_EOL;
30            $bucket_out = stream_bucket_new($this->stream, $data);
31            $return     = PSFS_PASS_ON;
32            stream_bucket_append($out, $bucket_out);
33        }
34
35        return $return;
36    }
37}
38
39stream_filter_register('my-filter', 'MyFilter');
40
41$input = "Line one\nLine two\nLine three";
42
43$stream = fopen('data://text/plain,' . $input, 'r');
44stream_filter_append($stream, 'my-filter');
45
46$output = '';
47while (!feof($stream)) {
48    $output .= fread($stream, 16);
49}
50fclose($stream);
51
52echo $output;
53?>
54--EXPECT--
55eno eniL
56owt eniL
57eerht eniL
58