functions.php 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. <?php
  2. namespace Clue\StreamFilter;
  3. use RuntimeException;
  4. /**
  5. * append a callback filter to the given stream
  6. *
  7. * @param resource $stream
  8. * @param callable $callback
  9. * @param int $read_write
  10. * @return resource filter resource which can be used for `remove()`
  11. * @throws Exception on error
  12. * @uses stream_filter_append()
  13. */
  14. function append($stream, $callback, $read_write = STREAM_FILTER_ALL)
  15. {
  16. $ret = @stream_filter_append($stream, register(), $read_write, $callback);
  17. if ($ret === false) {
  18. $error = error_get_last() + array('message' => '');
  19. throw new RuntimeException('Unable to append filter: ' . $error['message']);
  20. }
  21. return $ret;
  22. }
  23. /**
  24. * prepend a callback filter to the given stream
  25. *
  26. * @param resource $stream
  27. * @param callable $callback
  28. * @param int $read_write
  29. * @return resource filter resource which can be used for `remove()`
  30. * @throws Exception on error
  31. * @uses stream_filter_prepend()
  32. */
  33. function prepend($stream, $callback, $read_write = STREAM_FILTER_ALL)
  34. {
  35. $ret = @stream_filter_prepend($stream, register(), $read_write, $callback);
  36. if ($ret === false) {
  37. $error = error_get_last() + array('message' => '');
  38. throw new RuntimeException('Unable to prepend filter: ' . $error['message']);
  39. }
  40. return $ret;
  41. }
  42. /**
  43. * Creates filter fun (function) which uses the given built-in $filter
  44. *
  45. * Some filters may accept or require additional filter parameters – most
  46. * filters do not require filter parameters.
  47. * If given, the optional `$parameters` argument will be passed to the
  48. * underlying filter handler as-is.
  49. * In particular, note how *not passing* this parameter at all differs from
  50. * explicitly passing a `null` value (which many filters do not accept).
  51. * Please refer to the individual filter definition for more details.
  52. *
  53. * @param string $filter built-in filter name. See stream_get_filters() or http://php.net/manual/en/filters.php
  54. * @param mixed $parameters (optional) parameters to pass to the built-in filter as-is
  55. * @return callable a filter callback which can be append()'ed or prepend()'ed
  56. * @throws RuntimeException on error
  57. * @link http://php.net/manual/en/filters.php
  58. * @see stream_get_filters()
  59. * @see append()
  60. */
  61. function fun($filter, $parameters = null)
  62. {
  63. $fp = fopen('php://memory', 'w');
  64. if (func_num_args() === 1) {
  65. $filter = @stream_filter_append($fp, $filter, STREAM_FILTER_WRITE);
  66. } else {
  67. $filter = @stream_filter_append($fp, $filter, STREAM_FILTER_WRITE, $parameters);
  68. }
  69. if ($filter === false) {
  70. fclose($fp);
  71. $error = error_get_last() + array('message' => '');
  72. throw new RuntimeException('Unable to access built-in filter: ' . $error['message']);
  73. }
  74. // append filter function which buffers internally
  75. $buffer = '';
  76. append($fp, function ($chunk) use (&$buffer) {
  77. $buffer .= $chunk;
  78. // always return empty string in order to skip actually writing to stream resource
  79. return '';
  80. }, STREAM_FILTER_WRITE);
  81. $closed = false;
  82. return function ($chunk = null) use ($fp, $filter, &$buffer, &$closed) {
  83. if ($closed) {
  84. throw new \RuntimeException('Unable to perform operation on closed stream');
  85. }
  86. if ($chunk === null) {
  87. $closed = true;
  88. $buffer = '';
  89. fclose($fp);
  90. return $buffer;
  91. }
  92. // initialize buffer and invoke filters by attempting to write to stream
  93. $buffer = '';
  94. fwrite($fp, $chunk);
  95. // buffer now contains everything the filter function returned
  96. return $buffer;
  97. };
  98. }
  99. /**
  100. * remove a callback filter from the given stream
  101. *
  102. * @param resource $filter
  103. * @return boolean true on success or false on error
  104. * @throws Exception on error
  105. * @uses stream_filter_remove()
  106. */
  107. function remove($filter)
  108. {
  109. if (@stream_filter_remove($filter) === false) {
  110. throw new RuntimeException('Unable to remove given filter');
  111. }
  112. }
  113. /**
  114. * registers the callback filter and returns the resulting filter name
  115. *
  116. * There should be little reason to call this function manually.
  117. *
  118. * @return string filter name
  119. * @uses CallbackFilter
  120. */
  121. function register()
  122. {
  123. static $registered = null;
  124. if ($registered === null) {
  125. $registered = 'stream-callback';
  126. stream_filter_register($registered, __NAMESPACE__ . '\CallbackFilter');
  127. }
  128. return $registered;
  129. }