[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/lib/horde/framework/Horde/Stream/Wrapper/ -> Combine.php (source)

   1  <?php
   2  /**
   3   * Copyright 2009-2014 Horde LLC (http://www.horde.org/)
   4   *
   5   * See the enclosed file COPYING for license information (BSD). If you
   6   * did not receive this file, see http://www.horde.org/licenses/bsd.
   7   *
   8   * @category  Horde
   9   * @copyright 2009-2014 Horde LLC
  10   * @license   http://www.horde.org/licenses/bsd BSD
  11   * @package   Stream_Wrapper
  12   */
  13  
  14  /**
  15   * A stream wrapper that will combine multiple strings/streams into a single
  16   * stream.
  17   *
  18   * @author    Michael Slusarz <slusarz@horde.org>
  19   * @category  Horde
  20   * @copyright 2009-2014 Horde LLC
  21   * @license   http://www.horde.org/licenses/bsd BSD
  22   * @package   Stream_Wrapper
  23   */
  24  class Horde_Stream_Wrapper_Combine
  25  {
  26      /**/
  27      const WRAPPER_NAME = 'horde-stream-wrapper-combine';
  28  
  29      /**
  30       * Context.
  31       *
  32       * @var resource
  33       */
  34      public $context;
  35  
  36      /**
  37       * Array that holds the various streams.
  38       *
  39       * @var array
  40       */
  41      protected $_data = array();
  42  
  43      /**
  44       * The combined length of the stream.
  45       *
  46       * @var integer
  47       */
  48      protected $_length = 0;
  49  
  50      /**
  51       * The current position in the string.
  52       *
  53       * @var integer
  54       */
  55      protected $_position = 0;
  56  
  57      /**
  58       * The current position in the data array.
  59       *
  60       * @var integer
  61       */
  62      protected $_datapos = 0;
  63  
  64      /**
  65       * Have we reached EOF?
  66       *
  67       * @var boolean
  68       */
  69      protected $_ateof = false;
  70  
  71      /**
  72       * Unique ID tracker for the streams.
  73       *
  74       * @var integer
  75       */
  76      static private $_id = 0;
  77  
  78      /**
  79       * Create a stream from multiple data sources.
  80       *
  81       * @since 2.1.0
  82       *
  83       * @param array $data  An array of strings and/or streams to combine into
  84       *                     a single stream.
  85       *
  86       * @return resource  A PHP stream.
  87       */
  88      static public function getStream($data)
  89      {
  90          if (!self::$_id) {
  91              stream_wrapper_register(self::WRAPPER_NAME, __CLASS__);
  92          }
  93  
  94          return fopen(
  95              self::WRAPPER_NAME . '://' . ++self::$_id,
  96              'wb',
  97              false,
  98              stream_context_create(array(
  99                  self::WRAPPER_NAME => array(
 100                      'data' => $data
 101                  )
 102              ))
 103          );
 104      }
 105      /**
 106       * @see streamWrapper::stream_open()
 107       *
 108       * @param string $path
 109       * @param string $mode
 110       * @param integer $options
 111       * @param string &$opened_path
 112       *
 113       * @throws Exception
 114       */
 115      public function stream_open($path, $mode, $options, &$opened_path)
 116      {
 117          $opts = stream_context_get_options($this->context);
 118  
 119          if (isset($opts[self::WRAPPER_NAME]['data'])) {
 120              $data = $opts[self::WRAPPER_NAME]['data'];
 121          } elseif (isset($opts['horde-combine']['data'])) {
 122              // @deprecated
 123              $data = $opts['horde-combine']['data']->getData();
 124          } else {
 125              throw new Exception('Use ' . __CLASS__ . '::getStream() to initialize the stream.');
 126          }
 127  
 128          reset($data);
 129          while (list(,$val) = each($data)) {
 130              if (is_string($val)) {
 131                  $fp = fopen('php://temp', 'r+');
 132                  fwrite($fp, $val);
 133              } else {
 134                  $fp = $val;
 135              }
 136  
 137              fseek($fp, 0, SEEK_END);
 138              $length = ftell($fp);
 139              rewind($fp);
 140  
 141              $this->_data[] = array(
 142                  'fp' => $fp,
 143                  'l' => $length,
 144                  'p' => 0
 145              );
 146  
 147              $this->_length += $length;
 148          }
 149  
 150          return true;
 151      }
 152  
 153      /**
 154       * @see streamWrapper::stream_read()
 155       *
 156       * @param integer $count
 157       *
 158       * @return mixed
 159       */
 160      public function stream_read($count)
 161      {
 162          if ($this->stream_eof()) {
 163              return false;
 164          }
 165  
 166          $out = '';
 167  
 168          while ($count) {
 169              $tmp = &$this->_data[$this->_datapos];
 170              $curr_read = min($count, $tmp['l'] - $tmp['p']);
 171              $out .= fread($tmp['fp'], $curr_read);
 172              $count -= $curr_read;
 173              $this->_position += $curr_read;
 174  
 175              if ($this->_position == $this->_length) {
 176                  if ($count) {
 177                      $this->_ateof = true;
 178                      break;
 179                  } else {
 180                      $tmp['p'] += $curr_read;
 181                  }
 182              } elseif ($count) {
 183                  $tmp = &$this->_data[++$this->_datapos];
 184                  rewind($tmp['fp']);
 185                  $tmp['p'] = 0;
 186              } else {
 187                  $tmp['p'] += $curr_read;
 188              }
 189          }
 190  
 191          return $out;
 192      }
 193  
 194      /**
 195       * @see streamWrapper::stream_write()
 196       *
 197       * @param string $data
 198       *
 199       * @return integer
 200       */
 201      public function stream_write($data)
 202      {
 203          $tmp = &$this->_data[$this->_datapos];
 204  
 205          $oldlen = $tmp['l'];
 206          $res = fwrite($tmp['fp'], $data);
 207          if ($res === false) {
 208              return false;
 209          }
 210  
 211          $tmp['p'] = ftell($tmp['fp']);
 212          if ($tmp['p'] > $oldlen) {
 213              $tmp['l'] = $tmp['p'];
 214              $this->_length += ($tmp['l'] - $oldlen);
 215          }
 216  
 217          return $res;
 218      }
 219  
 220      /**
 221       * @see streamWrapper::stream_tell()
 222       *
 223       * @return integer
 224       */
 225      public function stream_tell()
 226      {
 227          return $this->_position;
 228      }
 229  
 230      /**
 231       * @see streamWrapper::stream_eof()
 232       *
 233       * @return boolean
 234       */
 235      public function stream_eof()
 236      {
 237          return $this->_ateof;
 238      }
 239  
 240      /**
 241       * @see streamWrapper::stream_stat()
 242       *
 243       * @return array
 244       */
 245      public function stream_stat()
 246      {
 247          return array(
 248              'dev' => 0,
 249              'ino' => 0,
 250              'mode' => 0,
 251              'nlink' => 0,
 252              'uid' => 0,
 253              'gid' => 0,
 254              'rdev' => 0,
 255              'size' => $this->_length,
 256              'atime' => 0,
 257              'mtime' => 0,
 258              'ctime' => 0,
 259              'blksize' => 0,
 260              'blocks' => 0
 261          );
 262      }
 263  
 264      /**
 265       * @see streamWrapper::stream_seek()
 266       *
 267       * @param integer $offset
 268       * @param integer $whence  SEEK_SET, SEEK_CUR, or SEEK_END
 269       *
 270       * @return boolean
 271       */
 272      public function stream_seek($offset, $whence)
 273      {
 274          $oldpos = $this->_position;
 275          $this->_ateof = false;
 276  
 277          switch ($whence) {
 278          case SEEK_SET:
 279              $offset = $offset;
 280              break;
 281  
 282          case SEEK_CUR:
 283              $offset = $this->_position + $offset;
 284              break;
 285  
 286          case SEEK_END:
 287              $offset = $this->_length + $offset;
 288              break;
 289  
 290          default:
 291              return false;
 292          }
 293  
 294          $count = $this->_position = min($this->_length, $offset);
 295  
 296          foreach ($this->_data as $key => $val) {
 297              if ($count < $val['l']) {
 298                  $this->_datapos = $key;
 299                  $val['p'] = $count;
 300                  fseek($val['fp'], $count, SEEK_SET);
 301                  break;
 302              }
 303              $count -= $val['l'];
 304          }
 305  
 306          return ($oldpos != $this->_position);
 307      }
 308  
 309  }


Generated: Thu Aug 11 10:00:09 2016 Cross-referenced by PHPXref 0.7.1