summaryrefslogtreecommitdiff
path: root/inc/mailgun/clue/stream-filter/src/functions.php
blob: 6c8125b370ac3033516e9d98db7af7f47dd6675d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
<?php

namespace Clue\StreamFilter;

use RuntimeException;

/**
 * append a callback filter to the given stream
 *
 * @param resource $stream
 * @param callable $callback
 * @param int $read_write
 * @return resource filter resource which can be used for `remove()`
 * @throws Exception on error
 * @uses stream_filter_append()
 */
function append($stream, $callback, $read_write = STREAM_FILTER_ALL)
{
    $ret = @stream_filter_append($stream, register(), $read_write, $callback);

    if ($ret === false) {
        $error = error_get_last() + array('message' => '');
        throw new RuntimeException('Unable to append filter: ' . $error['message']);
    }

    return $ret;
}

/**
 * prepend a callback filter to the given stream
 *
 * @param resource $stream
 * @param callable $callback
 * @param int $read_write
 * @return resource filter resource which can be used for `remove()`
 * @throws Exception on error
 * @uses stream_filter_prepend()
 */
function prepend($stream, $callback, $read_write = STREAM_FILTER_ALL)
{
    $ret = @stream_filter_prepend($stream, register(), $read_write, $callback);

    if ($ret === false) {
        $error = error_get_last() + array('message' => '');
        throw new RuntimeException('Unable to prepend filter: ' . $error['message']);
    }

    return $ret;
}

/**
 * Creates filter fun (function) which uses the given built-in $filter
 *
 * @param string $filter built-in filter name, see stream_get_filters()
 * @param mixed  $params additional parameters to pass to the built-in filter
 * @return callable a filter callback which can be append()'ed or prepend()'ed
 * @throws RuntimeException on error
 * @see stream_get_filters()
 * @see append()
 */
function fun($filter, $params = null)
{
    $fp = fopen('php://memory', 'w');
    $filter = @stream_filter_append($fp, $filter, STREAM_FILTER_WRITE, $params);

    if ($filter === false) {
        fclose($fp);
        $error = error_get_last() + array('message' => '');
        throw new RuntimeException('Unable to access built-in filter: ' . $error['message']);
    }

    // append filter function which buffers internally
    $buffer = '';
    append($fp, function ($chunk) use (&$buffer) {
        $buffer .= $chunk;

        // always return empty string in order to skip actually writing to stream resource
        return '';
    }, STREAM_FILTER_WRITE);

    $closed = false;

    return function ($chunk = null) use ($fp, $filter, &$buffer, &$closed) {
        if ($closed) {
            throw new \RuntimeException('Unable to perform operation on closed stream');
        }
        if ($chunk === null) {
            $closed = true;
            $buffer = '';
            fclose($fp);
            return $buffer;
        }
        // initialize buffer and invoke filters by attempting to write to stream
        $buffer = '';
        fwrite($fp, $chunk);

        // buffer now contains everything the filter function returned
        return $buffer;
    };
}

/**
 * remove a callback filter from the given stream
 *
 * @param resource $filter
 * @return boolean true on success or false on error
 * @throws Exception on error
 * @uses stream_filter_remove()
 */
function remove($filter)
{
    if (@stream_filter_remove($filter) === false) {
        throw new RuntimeException('Unable to remove given filter');
    }
}

/**
 * registers the callback filter and returns the resulting filter name
 *
 * There should be little reason to call this function manually.
 *
 * @return string filter name
 * @uses CallbackFilter
 */
function register()
{
    static $registered = null;
    if ($registered === null) {
        $registered = 'stream-callback';
        stream_filter_register($registered, __NAMESPACE__ . '\CallbackFilter');
    }
    return $registered;
}