File: stream-filter-register.xml

package info (click to toggle)
php-doc 20081024-1
  • links: PTS
  • area: main
  • in suites: lenny
  • size: 57,752 kB
  • ctags: 3,858
  • sloc: xml: 686,554; php: 19,446; perl: 610; cpp: 500; makefile: 336; sh: 114; awk: 28
file content (307 lines) | stat: -rw-r--r-- 9,551 bytes parent folder | download
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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- $Revision: 1.14 $ -->
<refentry xml:id="function.stream-filter-register" xmlns="http://docbook.org/ns/docbook">
 <refnamediv>
  <refname>stream_filter_register</refname>
  <refpurpose>Register a stream filter implemented as a PHP class derived from <literal>php_user_filter</literal></refpurpose>
 </refnamediv>
 <refsect1>
  <title>Description</title>
  <methodsynopsis>
   <type>bool</type><methodname>stream_filter_register</methodname>
   <methodparam><type>string</type><parameter>filtername</parameter></methodparam>
   <methodparam><type>string</type><parameter>classname</parameter></methodparam>
  </methodsynopsis>
  <para>
   <function>stream_filter_register</function> allows you to implement
   your own filter on any registered stream used with all the other
   filesystem functions (such as <function>fopen</function>,
   <function>fread</function> etc.).
  </para>
  <para>
   To implement a filter, you need to define a class as an extension of
   <literal>php_user_filter</literal> with a number of member functions
   as defined below. When performing read/write operations on the stream
   to which your filter is attached, PHP will pass the data through your
   filter (and any other filters attached to that stream) so that the
   data may be modified as desired. You must implement the methods
   exactly as described below - doing otherwise will lead to undefined
   behaviour.
  </para>
  <para>
   <function>stream_filter_register</function> will return &false; if the
   <parameter>filtername</parameter> is already defined.
  </para>

  <methodsynopsis>
   <type>int</type><methodname>filter</methodname>
   <methodparam><type>resource</type><parameter>in</parameter></methodparam>
   <methodparam><type>resource</type><parameter>out</parameter></methodparam>
   <methodparam><type>int</type><parameter role="reference">consumed</parameter></methodparam>
   <methodparam><type>bool</type><parameter>closing</parameter></methodparam>
  </methodsynopsis>
  <para>
   This method is called whenever data is read from or written to
   the attached stream (such as with <function>fread</function> or <function>fwrite</function>).
   <parameter>in</parameter> is a resource pointing to a <literal>bucket brigade</literal>
   which contains one or more <literal>bucket</literal> objects containing data to be filtered.
   <parameter>out</parameter> is a resource pointing to a second <literal>bucket brigade</literal>
   into which your modified buckets should be placed.
   <parameter>consumed</parameter>, which must <emphasis>always</emphasis>
   be declared by reference, should be incremented by the length of the data
   which your filter reads in and alters.  In most cases this means you will
   increment <parameter>consumed</parameter> by $bucket->datalen for each $bucket.
   If the stream is in the process of closing (and therefore this is the last pass
   through the filterchain), the <parameter>closing</parameter> parameter will be
   set to &true;  The <methodname>filter</methodname> method must return one of
   three values upon completion.

   <informaltable>
    <tgroup cols="2">
     <thead>
      <row>
       <entry>Return Value</entry>
       <entry>Meaning</entry>
      </row>
     </thead>
     <tbody>
      <row>
       <entry><constant>PSFS_PASS_ON</constant></entry>
       <entry>
        Filter processed successfully with data available in the
        <parameter>out</parameter> <literal>bucket brigade</literal>.
       </entry>
      </row>
      <row>
       <entry><constant>PSFS_FEED_ME</constant></entry>
       <entry>
        Filter processed successfully, however no data was available to
        return.  More data is required from the stream or prior filter.
       </entry>
      </row>
      <row>
       <entry><constant>PSFS_ERR_FATAL</constant> (default)</entry>
       <entry>
        The filter experienced an unrecoverable error and cannot continue.
       </entry>
      </row>
     </tbody>
    </tgroup>
   </informaltable>
  </para>

  <methodsynopsis>
   <type>bool</type><methodname>onCreate</methodname>
   <void/>
  </methodsynopsis>
  <simpara>
   This method is called during instantiation of the filter class
   object.  If your filter allocates or initializes any other resources
   (such as a buffer), this is the place to do it.  Your implementation of
   this method should return &false; on failure, or &true; on success.
  </simpara>
  <simpara>
   When your filter is first instantiated, and
   <literal>yourfilter-&gt;onCreate()</literal> is called, a number of properties
   will be available as shown in the table below.
  </simpara>
  <para>
   <informaltable>
    <tgroup cols="2">
     <thead>
      <row>
       <entry>Property</entry>
       <entry>Contents</entry>
      </row>
     </thead>
     <tbody>
      <row>
       <entry><literal>FilterClass-&gt;filtername</literal></entry>
       <entry>A string containing the name the filter was instantiated with.
              Filters may be registered under multiple names or under wildcards.
              Use this property to determine which name was used.</entry>
      </row>
      <row>
       <entry><literal>FilterClass-&gt;params</literal></entry>
       <entry>The contents of the <parameter>params</parameter> parameter passed
              to <function>stream_filter_append</function>
              or <function>stream_filter_prepend</function>.</entry>
      </row>
     </tbody>
    </tgroup>
   </informaltable>
  </para>

  <methodsynopsis>
   <type>void</type><methodname>onClose</methodname>
   <void/>
  </methodsynopsis>
  <para>
   This method is called upon filter shutdown (typically, this is also
   during stream shutdown), and is executed <emphasis>after</emphasis>
   the <literal>flush</literal> method is called.  If any resources
   were allocated or initialzed during <literal>onCreate</literal>
   this would be the time to destroy or dispose of them.
  </para>

  <para>
   The example below implements a filter named <literal>strtoupper</literal>
   on the <literal>foo-bar.txt</literal> stream which will capitalize
   all letter characters written to/read from that stream.

   <example>
    <title>Filter for capitalizing characters on foo-bar.txt stream</title>
    <programlisting role="php">
<![CDATA[
<?php

/* Define our filter class */
class strtoupper_filter extends php_user_filter {
  function filter($in, $out, &$consumed, $closing)
  {
    while ($bucket = stream_bucket_make_writeable($in)) {
      $bucket->data = strtoupper($bucket->data);
      $consumed += $bucket->datalen;
      stream_bucket_append($out, $bucket);
    }
    return PSFS_PASS_ON;
  }
}

/* Register our filter with PHP */
stream_filter_register("strtoupper", "strtoupper_filter")
    or die("Failed to register filter");

$fp = fopen("foo-bar.txt", "w");

/* Attach the registered filter to the stream just opened */
stream_filter_append($fp, "strtoupper");

fwrite($fp, "Line1\n");
fwrite($fp, "Word - 2\n");
fwrite($fp, "Easy As 123\n");

fclose($fp);

/* Read the contents back out
 */
readfile("foo-bar.txt");

?>
]]>
    </programlisting>
    &example.outputs;
    <screen>
<![CDATA[
LINE1
WORD - 2
EASY AS 123
]]>
    </screen>
   </example>
  </para>
  <para>
   <example>
    <title>Registering a generic filter class to match multiple filter names.</title>
    <programlisting role="php">
<![CDATA[
<?php

/* Define our filter class */
class string_filter extends php_user_filter {
  var $mode;

  function filter($in, $out, &$consumed, $closing)
  {
    while ($bucket = stream_bucket_make_writeable($in)) {
      if ($this->mode == 1) {
        $bucket->data = strtoupper($bucket->data);
      } elseif ($this->mode == 0) {
        $bucket->data = strtolower($bucket->data);
      }

      $consumed += $bucket->datalen;
      stream_bucket_append($out, $bucket);
    }
    return PSFS_PASS_ON;
  }

  function onCreate()
  {
    if ($this->filtername == 'str.toupper') {
      $this->mode = 1;
    } elseif ($this->filtername == 'str.tolower') {
      $this->mode = 0;
    } else {
      /* Some other str.* filter was asked for,
         report failure so that PHP will keep looking */
      return false;
    }

    return true;
  }
}

/* Register our filter with PHP */
stream_filter_register("str.*", "string_filter")
    or die("Failed to register filter");

$fp = fopen("foo-bar.txt", "w");

/* Attach the registered filter to the stream just opened
   We could alternately bind to str.tolower here */
stream_filter_append($fp, "str.toupper");

fwrite($fp, "Line1\n");
fwrite($fp, "Word - 2\n");
fwrite($fp, "Easy As 123\n");

fclose($fp);

/* Read the contents back out
 */
readfile("foo-bar.txt");
?>
]]>
    </programlisting>
    &example.outputs;
    <screen>
<![CDATA[
LINE1
WORD - 2
EASY AS 123
]]>
    </screen>
   </example>
  </para>

  <simpara>
   See also
   <function>stream_wrapper_register</function>,
   <function>stream_filter_prepend</function>, and
   <function>stream_filter_append</function>.
  </simpara>
 </refsect1>
</refentry>


<!-- Keep this comment at the end of the file
Local variables:
mode: sgml
sgml-omittag:t
sgml-shorttag:t
sgml-minimize-attributes:nil
sgml-always-quote-attributes:t
sgml-indent-step:1
sgml-indent-data:t
indent-tabs-mode:nil
sgml-parent-document:nil
sgml-default-dtd-file:"../../../../manual.ced"
sgml-exposed-tags:nil
sgml-local-catalogs:nil
sgml-local-ecat-files:nil
End:
vim600: syn=xml fen fdm=syntax fdl=2 si
vim: et tw=78 syn=sgml
vi: ts=1 sw=1
-->