TYPO3 API  SVNRelease
DiskKeyCache.php
Go to the documentation of this file.
00001 <?php
00002 
00003 /*
00004  * This file is part of SwiftMailer.
00005  * (c) 2004-2009 Chris Corbyn
00006  *
00007  * For the full copyright and license information, please view the LICENSE
00008  * file that was distributed with this source code.
00009  */
00010 
00011 //@require 'Swift/KeyCache.php';
00012 //@require 'Swift/KeyCacheInputStream.php';
00013 //@require 'Swift/InputByteStream.php';
00014 //@require 'Swift/OutputByteStrean.php';
00015 //@require 'Swift/SwiftException.php';
00016 //@require 'Swift/IoException.php';
00017 
00018 /**
00019  * A KeyCache which streams to and from disk.
00020  * @package Swift
00021  * @subpackage KeyCache
00022  * @author Chris Corbyn
00023  */
00024 class Swift_KeyCache_DiskKeyCache implements Swift_KeyCache
00025 {
00026 
00027   /** Signal to place pointer at start of file */
00028   const POSITION_START = 0;
00029 
00030   /** Signal to place pointer at end of file */
00031   const POSITION_END = 1;
00032 
00033   /**
00034    * An InputStream for cloning.
00035    * @var Swift_KeyCache_KeyCacheInputStream
00036    * @access private
00037    */
00038   private $_stream;
00039 
00040   /**
00041    * A path to write to.
00042    * @var string
00043    * @access private
00044    */
00045   private $_path;
00046 
00047   /**
00048    * Stored keys.
00049    * @var array
00050    * @access private
00051    */
00052   private $_keys = array();
00053 
00054   /**
00055    * Will be true if magic_quotes_runtime is turned on.
00056    * @var boolean
00057    * @access private
00058    */
00059   private $_quotes = false;
00060 
00061   /**
00062    * Create a new DiskKeyCache with the given $stream for cloning to make
00063    * InputByteStreams, and the given $path to save to.
00064    * @param Swift_KeyCache_KeyCacheInputStream $stream
00065    * @param string $path to save to
00066    */
00067   public function __construct(Swift_KeyCache_KeyCacheInputStream $stream, $path)
00068   {
00069     $this->_stream = $stream;
00070     $this->_path = $path;
00071     $this->_quotes = get_magic_quotes_runtime();
00072   }
00073 
00074   /**
00075    * Set a string into the cache under $itemKey for the namespace $nsKey.
00076    * @param string $nsKey
00077    * @param string $itemKey
00078    * @param string $string
00079    * @param int $mode
00080    * @throws Swift_IoException
00081    * @see MODE_WRITE, MODE_APPEND
00082    */
00083   public function setString($nsKey, $itemKey, $string, $mode)
00084   {
00085     $this->_prepareCache($nsKey);
00086     switch ($mode)
00087     {
00088       case self::MODE_WRITE:
00089         $fp = $this->_getHandle($nsKey, $itemKey, self::POSITION_START);
00090         break;
00091       case self::MODE_APPEND:
00092         $fp = $this->_getHandle($nsKey, $itemKey, self::POSITION_END);
00093         break;
00094       default:
00095         throw new Swift_SwiftException(
00096           'Invalid mode [' . $mode . '] used to set nsKey='.
00097           $nsKey . ', itemKey=' . $itemKey
00098           );
00099         break;
00100     }
00101     fwrite($fp, $string);
00102   }
00103 
00104   /**
00105    * Set a ByteStream into the cache under $itemKey for the namespace $nsKey.
00106    * @param string $nsKey
00107    * @param string $itemKey
00108    * @param Swift_OutputByteStream $os
00109    * @param int $mode
00110    * @see MODE_WRITE, MODE_APPEND
00111    * @throws Swift_IoException
00112    */
00113   public function importFromByteStream($nsKey, $itemKey, Swift_OutputByteStream $os,
00114     $mode)
00115   {
00116     $this->_prepareCache($nsKey);
00117     switch ($mode)
00118     {
00119       case self::MODE_WRITE:
00120         $fp = $this->_getHandle($nsKey, $itemKey, self::POSITION_START);
00121         break;
00122       case self::MODE_APPEND:
00123         $fp = $this->_getHandle($nsKey, $itemKey, self::POSITION_END);
00124         break;
00125       default:
00126         throw new Swift_SwiftException(
00127           'Invalid mode [' . $mode . '] used to set nsKey='.
00128           $nsKey . ', itemKey=' . $itemKey
00129           );
00130         break;
00131     }
00132     while (false !== $bytes = $os->read(8192))
00133     {
00134       fwrite($fp, $bytes);
00135     }
00136   }
00137 
00138   /**
00139    * Provides a ByteStream which when written to, writes data to $itemKey.
00140    * NOTE: The stream will always write in append mode.
00141    * @param string $nsKey
00142    * @param string $itemKey
00143    * @return Swift_InputByteStream
00144    */
00145   public function getInputByteStream($nsKey, $itemKey,
00146     Swift_InputByteStream $writeThrough = null)
00147   {
00148     $is = clone $this->_stream;
00149     $is->setKeyCache($this);
00150     $is->setNsKey($nsKey);
00151     $is->setItemKey($itemKey);
00152     if (isset($writeThrough))
00153     {
00154       $is->setWriteThroughStream($writeThrough);
00155     }
00156     return $is;
00157   }
00158 
00159   /**
00160    * Get data back out of the cache as a string.
00161    * @param string $nsKey
00162    * @param string $itemKey
00163    * @return string
00164    * @throws Swift_IoException
00165    */
00166   public function getString($nsKey, $itemKey)
00167   {
00168     $this->_prepareCache($nsKey);
00169     if ($this->hasKey($nsKey, $itemKey))
00170     {
00171       $fp = $this->_getHandle($nsKey, $itemKey, self::POSITION_START);
00172       if ($this->_quotes)
00173       {
00174         set_magic_quotes_runtime(0);
00175       }
00176       $str = '';
00177       while (!feof($fp) && false !== $bytes = fread($fp, 8192))
00178       {
00179         $str .= $bytes;
00180       }
00181       if ($this->_quotes)
00182       {
00183         set_magic_quotes_runtime(1);
00184       }
00185       return $str;
00186     }
00187   }
00188 
00189   /**
00190    * Get data back out of the cache as a ByteStream.
00191    * @param string $nsKey
00192    * @param string $itemKey
00193    * @param Swift_InputByteStream $is to write the data to
00194    */
00195   public function exportToByteStream($nsKey, $itemKey, Swift_InputByteStream $is)
00196   {
00197     if ($this->hasKey($nsKey, $itemKey))
00198     {
00199       $fp = $this->_getHandle($nsKey, $itemKey, self::POSITION_START);
00200       if ($this->_quotes)
00201       {
00202         set_magic_quotes_runtime(0);
00203       }
00204       while (!feof($fp) && false !== $bytes = fread($fp, 8192))
00205       {
00206         $is->write($bytes);
00207       }
00208       if ($this->_quotes)
00209       {
00210         set_magic_quotes_runtime(1);
00211       }
00212     }
00213   }
00214 
00215   /**
00216    * Check if the given $itemKey exists in the namespace $nsKey.
00217    * @param string $nsKey
00218    * @param string $itemKey
00219    * @return boolean
00220    */
00221   public function hasKey($nsKey, $itemKey)
00222   {
00223     return is_file($this->_path . '/' . $nsKey . '/' . $itemKey);
00224   }
00225 
00226   /**
00227    * Clear data for $itemKey in the namespace $nsKey if it exists.
00228    * @param string $nsKey
00229    * @param string $itemKey
00230    */
00231   public function clearKey($nsKey, $itemKey)
00232   {
00233     if ($this->hasKey($nsKey, $itemKey))
00234     {
00235       $fp = $this->_getHandle($nsKey, $itemKey, self::POSITION_END);
00236       fclose($fp);
00237       unlink($this->_path . '/' . $nsKey . '/' . $itemKey);
00238     }
00239     unset($this->_keys[$nsKey][$itemKey]);
00240   }
00241 
00242   /**
00243    * Clear all data in the namespace $nsKey if it exists.
00244    * @param string $nsKey
00245    */
00246   public function clearAll($nsKey)
00247   {
00248     if (array_key_exists($nsKey, $this->_keys))
00249     {
00250       foreach ($this->_keys[$nsKey] as $itemKey=>$null)
00251       {
00252         $this->clearKey($nsKey, $itemKey);
00253       }
00254       rmdir($this->_path . '/' . $nsKey);
00255       unset($this->_keys[$nsKey]);
00256     }
00257   }
00258 
00259   // -- Private methods
00260 
00261   /**
00262    * Initialize the namespace of $nsKey if needed.
00263    * @param string $nsKey
00264    * @access private
00265    */
00266   private function _prepareCache($nsKey)
00267   {
00268     $cacheDir = $this->_path . '/' . $nsKey;
00269     if (!is_dir($cacheDir))
00270     {
00271       if (!mkdir($cacheDir))
00272       {
00273         throw new Swift_IoException('Failed to create cache directory ' . $cacheDir);
00274       }
00275       $this->_keys[$nsKey] = array();
00276     }
00277   }
00278 
00279   /**
00280    * Get a file handle on the cache item.
00281    * @param string $nsKey
00282    * @param string $itemKey
00283    * @param int $position
00284    * @return resource
00285    * @access private
00286    */
00287   private function _getHandle($nsKey, $itemKey, $position)
00288   {
00289     if (!isset($this->_keys[$nsKey]) || !array_key_exists($itemKey, $this->_keys[$nsKey]))
00290     {
00291       $fp = fopen($this->_path . '/' . $nsKey . '/' . $itemKey, 'w+b');
00292       $this->_keys[$nsKey][$itemKey] = $fp;
00293     }
00294     if (self::POSITION_START == $position)
00295     {
00296       fseek($this->_keys[$nsKey][$itemKey], 0, SEEK_SET);
00297     }
00298     else
00299     {
00300       fseek($this->_keys[$nsKey][$itemKey], 0, SEEK_END);
00301     }
00302     return $this->_keys[$nsKey][$itemKey];
00303   }
00304 
00305   /**
00306    * Destructor.
00307    */
00308   public function __destruct()
00309   {
00310     foreach ($this->_keys as $nsKey=>$null)
00311     {
00312       $this->clearAll($nsKey);
00313     }
00314   }
00315 
00316 }