Cache_Lite
[ class tree: Cache_Lite ] [ index: Cache_Lite ] [ all elements ]

Source for file Lite.php

Documentation is available at Lite.php

  1. <?php
  2.  
  3. /**
  4. * Fast, light and safe Cache Class
  5. *
  6. * Cache_Lite is a fast, light and safe cache system. It's optimized
  7. * for file containers. It is fast and safe (because it uses file
  8. * locking and/or anti-corruption tests).
  9. *
  10. * There are some examples in the 'docs/examples' file
  11. * Technical choices are described in the 'docs/technical' file
  12. *
  13. * Memory Caching is from an original idea of
  14. * Mike BENOIT <ipso@snappymail.ca>
  15. *
  16. * Nota : A chinese documentation (thanks to RainX <china_1982@163.com>) is
  17. * available at :
  18. * http://rainx.phpmore.com/manual/cache_lite.html
  19. *
  20. @package Cache_Lite
  21. @category Caching
  22. @author Fabien MARTY <fab@php.net>
  23. @author Markus Tacker <tacker@php.net>
  24. */
  25.  
  26. define('CACHE_LITE_ERROR_RETURN'1);
  27. define('CACHE_LITE_ERROR_DIE'8);
  28.  
  29. class Cache_Lite
  30. {
  31.  
  32.     // --- Private properties ---
  33.  
  34.     /**
  35.     * Directory where to put the cache files
  36.     * (make sure to add a trailing slash)
  37.     *
  38.     * @var string $_cacheDir 
  39.     */
  40.     var $_cacheDir '/tmp/';
  41.  
  42.     /**
  43.     * Enable / disable caching
  44.     *
  45.     * (can be very usefull for the debug of cached scripts)
  46.     *
  47.     * @var boolean $_caching 
  48.     */
  49.     var $_caching = true;
  50.  
  51.     /**
  52.     * Cache lifetime (in seconds)
  53.     *
  54.     * If null, the cache is valid forever.
  55.     *
  56.     * @var int $_lifeTime 
  57.     */
  58.     var $_lifeTime = 3600;
  59.  
  60.     /**
  61.     * Enable / disable fileLocking
  62.     *
  63.     * (can avoid cache corruption under bad circumstances)
  64.     *
  65.     * @var boolean $_fileLocking 
  66.     */
  67.     var $_fileLocking = true;
  68.  
  69.     /**
  70.     * Timestamp of the last valid cache
  71.     *
  72.     * @var int $_refreshTime 
  73.     */
  74.     var $_refreshTime;
  75.  
  76.     /**
  77.     * File name (with path)
  78.     *
  79.     * @var string $_file 
  80.     */
  81.     var $_file;
  82.     
  83.     /**
  84.     * File name (without path)
  85.     *
  86.     * @var string $_fileName 
  87.     */
  88.     var $_fileName;
  89.  
  90.     /**
  91.     * Enable / disable write control (the cache is read just after writing to detect corrupt entries)
  92.     *
  93.     * Enable write control will lightly slow the cache writing but not the cache reading
  94.     * Write control can detect some corrupt cache files but maybe it's not a perfect control
  95.     *
  96.     * @var boolean $_writeControl 
  97.     */
  98.     var $_writeControl = true;
  99.  
  100.     /**
  101.     * Enable / disable read control
  102.     *
  103.     * If enabled, a control key is embeded in cache file and this key is compared with the one
  104.     * calculated after the reading.
  105.     *
  106.     * @var boolean $_writeControl 
  107.     */
  108.     var $_readControl = true;
  109.  
  110.     /**
  111.     * Type of read control (only if read control is enabled)
  112.     *
  113.     * Available values are :
  114.     * 'md5' for a md5 hash control (best but slowest)
  115.     * 'crc32' for a crc32 hash control (lightly less safe but faster, better choice)
  116.     * 'strlen' for a length only test (fastest)
  117.     *
  118.     * @var boolean $_readControlType 
  119.     */
  120.     var $_readControlType 'crc32';
  121.  
  122.     /**
  123.     * Pear error mode (when raiseError is called)
  124.     *
  125.     * (see PEAR doc)
  126.     *
  127.     * @see setToDebug()
  128.     * @var int $_pearErrorMode 
  129.     */
  130.     var $_pearErrorMode = CACHE_LITE_ERROR_RETURN;
  131.     
  132.     /**
  133.     * Current cache id
  134.     *
  135.     * @var string $_id 
  136.     */
  137.     var $_id;
  138.  
  139.     /**
  140.     * Current cache group
  141.     *
  142.     * @var string $_group 
  143.     */
  144.     var $_group;
  145.  
  146.     /**
  147.     * Enable / Disable "Memory Caching"
  148.     *
  149.     * NB : There is no lifetime for memory caching !
  150.     *
  151.     * @var boolean $_memoryCaching 
  152.     */
  153.     var $_memoryCaching = false;
  154.  
  155.     /**
  156.     * Enable / Disable "Only Memory Caching"
  157.     * (be carefull, memory caching is "beta quality")
  158.     *
  159.     * @var boolean $_onlyMemoryCaching 
  160.     */
  161.     var $_onlyMemoryCaching = false;
  162.  
  163.     /**
  164.     * Memory caching array
  165.     *
  166.     * @var array $_memoryCachingArray 
  167.     */
  168.     var $_memoryCachingArray = array();
  169.  
  170.     /**
  171.     * Memory caching counter
  172.     *
  173.     * @var int $memoryCachingCounter 
  174.     */
  175.     var $_memoryCachingCounter = 0;
  176.  
  177.     /**
  178.     * Memory caching limit
  179.     *
  180.     * @var int $memoryCachingLimit 
  181.     */
  182.     var $_memoryCachingLimit = 1000;
  183.     
  184.     /**
  185.     * File Name protection
  186.     *
  187.     * if set to true, you can use any cache id or group name
  188.     * if set to false, it can be faster but cache ids and group names
  189.     * will be used directly in cache file names so be carefull with
  190.     * special characters...
  191.     *
  192.     * @var boolean $fileNameProtection 
  193.     */
  194.     var $_fileNameProtection = true;
  195.     
  196.     /**
  197.     * Enable / disable automatic serialization
  198.     *
  199.     * it can be used to save directly datas which aren't strings
  200.     * (but it's slower)
  201.     *
  202.     * @var boolean $_serialize 
  203.     */
  204.     var $_automaticSerialization = false;
  205.     
  206.     /**
  207.     * Disable / Tune the automatic cleaning process
  208.     *
  209.     * The automatic cleaning process destroy too old (for the given life time)
  210.     * cache files when a new cache file is written.
  211.     * 0               => no automatic cache cleaning
  212.     * 1               => systematic cache cleaning
  213.     * x (integer) > 1 => automatic cleaning randomly 1 times on x cache write
  214.     *
  215.     * @var int $_automaticCleaning 
  216.     */
  217.     var $_automaticCleaningFactor = 0;
  218.     
  219.     /**
  220.     * Nested directory level
  221.     *
  222.     * Set the hashed directory structure level. 0 means "no hashed directory
  223.     * structure", 1 means "one level of directory", 2 means "two levels"...
  224.     * This option can speed up Cache_Lite only when you have many thousands of
  225.     * cache file. Only specific benchs can help you to choose the perfect value
  226.     * for you. Maybe, 1 or 2 is a good start.
  227.     *
  228.     * @var int $_hashedDirectoryLevel 
  229.     */
  230.     var $_hashedDirectoryLevel = 0;
  231.     
  232.     /**
  233.     * Umask for hashed directory structure
  234.     *
  235.     * @var int $_hashedDirectoryUmask 
  236.     */
  237.     var $_hashedDirectoryUmask = 0700;
  238.     
  239.     /**
  240.      * API break for error handling in CACHE_LITE_ERROR_RETURN mode
  241.      * 
  242.      * In CACHE_LITE_ERROR_RETURN mode, error handling was not good because
  243.      * for example save() method always returned a boolean (a PEAR_Error object
  244.      * would be better in CACHE_LITE_ERROR_RETURN mode). To correct this without
  245.      * breaking the API, this option (false by default) can change this handling.
  246.      * 
  247.      * @var boolean 
  248.      */
  249.     var $_errorHandlingAPIBreak = false;
  250.     
  251.     // --- Public methods ---
  252.  
  253.     /**
  254.     * Constructor
  255.     *
  256.     * $options is an assoc. Available options are :
  257.     * $options = array(
  258.     *     'cacheDir' => directory where to put the cache files (string),
  259.     *     'caching' => enable / disable caching (boolean),
  260.     *     'lifeTime' => cache lifetime in seconds (int),
  261.     *     'fileLocking' => enable / disable fileLocking (boolean),
  262.     *     'writeControl' => enable / disable write control (boolean),
  263.     *     'readControl' => enable / disable read control (boolean),
  264.     *     'readControlType' => type of read control 'crc32', 'md5', 'strlen' (string),
  265.     *     'pearErrorMode' => pear error mode (when raiseError is called) (cf PEAR doc) (int),
  266.     *     'memoryCaching' => enable / disable memory caching (boolean),
  267.     *     'onlyMemoryCaching' => enable / disable only memory caching (boolean),
  268.     *     'memoryCachingLimit' => max nbr of records to store into memory caching (int),
  269.     *     'fileNameProtection' => enable / disable automatic file name protection (boolean),
  270.     *     'automaticSerialization' => enable / disable automatic serialization (boolean),
  271.     *     'automaticCleaningFactor' => distable / tune automatic cleaning process (int),
  272.     *     'hashedDirectoryLevel' => level of the hashed directory system (int),
  273.     *     'hashedDirectoryUmask' => umask for hashed directory structure (int),
  274.     *     'errorHandlingAPIBreak' => API break for better error handling ? (boolean)
  275.     * );
  276.     * 
  277.     * If sys_get_temp_dir() is available and the
  278.     * 'cacheDir' option is not provided in the
  279.     * constructor options array its output is used
  280.     * to determine the suitable temporary directory.
  281.     * 
  282.     * @see http://de.php.net/sys_get_temp_dir
  283.     * @see http://pear.php.net/bugs/bug.php?id=18328
  284.     *
  285.     * @param array $options options
  286.     * @access public
  287.     */
  288.     function Cache_Lite($options = array(NULL))
  289.     {
  290.         foreach($options as $key => $value{
  291.             $this->setOption($key$value);
  292.         }
  293.         if (!isset($options['cacheDir']&& function_exists('sys_get_temp_dir')) {
  294.             $this->setOption('cacheDir'sys_get_temp_dir(. DIRECTORY_SEPARATOR);
  295.         }
  296.     }
  297.     
  298.     /**
  299.     * Generic way to set a Cache_Lite option
  300.     *
  301.     * see Cache_Lite constructor for available options
  302.     *
  303.     * @var string $name name of the option
  304.     * @var mixed $value value of the option
  305.     * @access public
  306.     */
  307.     function setOption($name$value
  308.     {
  309.         $availableOptions = array('errorHandlingAPIBreak''hashedDirectoryUmask''hashedDirectoryLevel''automaticCleaningFactor''automaticSerialization''fileNameProtection''memoryCaching''onlyMemoryCaching''memoryCachingLimit''cacheDir''caching''lifeTime''fileLocking''writeControl''readControl''readControlType''pearErrorMode');
  310.         if (in_array($name$availableOptions)) {
  311.             $property '_'.$name;
  312.             $this->$property $value;
  313.         }
  314.     }
  315.     
  316.     /**
  317.     * Test if a cache is available and (if yes) return it
  318.     *
  319.     * @param string $id cache id
  320.     * @param string $group name of the cache group
  321.     * @param boolean $doNotTestCacheValidity if set to true, the cache validity won't be tested
  322.     * @return string data of the cache (else : false)
  323.     * @access public
  324.     */
  325.     function get($id$group 'default'$doNotTestCacheValidity = false)
  326.     {
  327.         $this->_id $id;
  328.         $this->_group $group;
  329.         $data = false;
  330.         if ($this->_caching{
  331.             $this->_setRefreshTime();
  332.             $this->_setFileName($id$group);
  333.             clearstatcache();
  334.             if ($this->_memoryCaching{
  335.                 if (isset($this->_memoryCachingArray[$this->_file])) {
  336.                     if ($this->_automaticSerialization{
  337.                         return unserialize($this->_memoryCachingArray[$this->_file]);
  338.                     }
  339.                     return $this->_memoryCachingArray[$this->_file];
  340.                 }
  341.                 if ($this->_onlyMemoryCaching{
  342.                     return false;
  343.                 }                
  344.             }
  345.             if (($doNotTestCacheValidity|| (is_null($this->_refreshTime))) {
  346.                 if (file_exists($this->_file)) {
  347.                     $data $this->_read();
  348.                 }
  349.             else {
  350.                 if ((file_exists($this->_file)) && (@filemtime($this->_file$this->_refreshTime)) {
  351.                     $data $this->_read();
  352.                 }
  353.             }
  354.             if (($dataand ($this->_memoryCaching)) {
  355.                 $this->_memoryCacheAdd($data);
  356.             }
  357.             if (($this->_automaticSerializationand (is_string($data))) {
  358.                 $data unserialize($data);
  359.             }
  360.             return $data;
  361.         }
  362.         return false;
  363.     }
  364.     
  365.     /**
  366.     * Save some data in a cache file
  367.     *
  368.     * @param string $data data to put in cache (can be another type than strings if automaticSerialization is on)
  369.     * @param string $id cache id
  370.     * @param string $group name of the cache group
  371.     * @return boolean true if no problem (else : false or a PEAR_Error object)
  372.     * @access public
  373.     */
  374.     function save($data$id = NULL$group 'default')
  375.     {
  376.         if ($this->_caching{
  377.             if ($this->_automaticSerialization{
  378.                 $data serialize($data);
  379.             }
  380.             if (isset($id)) {
  381.                 $this->_setFileName($id$group);
  382.             }
  383.             if ($this->_memoryCaching{
  384.                 $this->_memoryCacheAdd($data);
  385.                 if ($this->_onlyMemoryCaching{
  386.                     return true;
  387.                 }
  388.             }
  389.             if ($this->_automaticCleaningFactor>0 && ($this->_automaticCleaningFactor==1 || mt_rand(1$this->_automaticCleaningFactor)==1)) {
  390.                 $this->clean(false'old');            
  391.             }
  392.             if ($this->_writeControl{
  393.                 $res $this->_writeAndControl($data);
  394.                 if (is_bool($res)) {
  395.                     if ($res{
  396.                         return true;  
  397.                     }
  398.                     // if $res if false, we need to invalidate the cache
  399.                     @touch($this->_filetime(- 2*abs($this->_lifeTime));
  400.                     return false;
  401.                 }            
  402.             else {
  403.                 $res $this->_write($data);
  404.             }
  405.             if (is_object($res)) {
  406.                 // $res is a PEAR_Error object 
  407.                 if (!($this->_errorHandlingAPIBreak)) {   
  408.                     return false; // we return false (old API)
  409.                 }
  410.             }
  411.             return $res;
  412.         }
  413.         return false;
  414.     }
  415.  
  416.     /**
  417.     * Remove a cache file
  418.     *
  419.     * @param string $id cache id
  420.     * @param string $group name of the cache group
  421.     * @param boolean $checkbeforeunlink check if file exists before removing it
  422.     * @return boolean true if no problem
  423.     * @access public
  424.     */
  425.     function remove($id$group 'default'$checkbeforeunlink = false)
  426.     {
  427.         $this->_setFileName($id$group);
  428.         if ($this->_memoryCaching{
  429.             if (isset($this->_memoryCachingArray[$this->_file])) {
  430.                 unset($this->_memoryCachingArray[$this->_file]);
  431.                 $this->_memoryCachingCounter $this->_memoryCachingCounter - 1;
  432.             }
  433.             if ($this->_onlyMemoryCaching{
  434.                 return true;
  435.             }
  436.         }
  437.         if $checkbeforeunlink {
  438.             if (!file_exists($this->_file)) return true;
  439.         }
  440.         return $this->_unlink($this->_file);
  441.     }
  442.  
  443.     /**
  444.     * Clean the cache
  445.     *
  446.     * if no group is specified all cache files will be destroyed
  447.     * else only cache files of the specified group will be destroyed
  448.     *
  449.     * @param string $group name of the cache group
  450.     * @param string $mode flush cache mode : 'old', 'ingroup', 'notingroup',
  451.     *                                         'callback_myFunction'
  452.     * @return boolean true if no problem
  453.     * @access public
  454.     */
  455.     function clean($group = false$mode 'ingroup')
  456.     {
  457.         return $this->_cleanDir($this->_cacheDir$group$mode);
  458.     }
  459.        
  460.     /**
  461.     * Set to debug mode
  462.     *
  463.     * When an error is found, the script will stop and the message will be displayed
  464.     * (in debug mode only).
  465.     *
  466.     * @access public
  467.     */
  468.     function setToDebug()
  469.     {
  470.         $this->setOption('pearErrorMode'CACHE_LITE_ERROR_DIE);
  471.     }
  472.  
  473.     /**
  474.     * Set a new life time
  475.     *
  476.     * @param int $newLifeTime new life time (in seconds)
  477.     * @access public
  478.     */
  479.     function setLifeTime($newLifeTime)
  480.     {
  481.         $this->_lifeTime $newLifeTime;
  482.         $this->_setRefreshTime();
  483.     }
  484.  
  485.     /**
  486.     * Save the state of the caching memory array into a cache file cache
  487.     *
  488.     * @param string $id cache id
  489.     * @param string $group name of the cache group
  490.     * @access public
  491.     */
  492.     function saveMemoryCachingState($id$group 'default')
  493.     {
  494.         if ($this->_caching{
  495.             $array = array(
  496.                 'counter' => $this->_memoryCachingCounter,
  497.                 'array' => $this->_memoryCachingArray
  498.             );
  499.             $data serialize($array);
  500.             $this->save($data$id$group);
  501.         }
  502.     }
  503.  
  504.     /**
  505.     * Load the state of the caching memory array from a given cache file cache
  506.     *
  507.     * @param string $id cache id
  508.     * @param string $group name of the cache group
  509.     * @param boolean $doNotTestCacheValidity if set to true, the cache validity won't be tested
  510.     * @access public
  511.     */
  512.     function getMemoryCachingState($id$group 'default'$doNotTestCacheValidity = false)
  513.     {
  514.         if ($this->_caching{
  515.             if ($data $this->get($id$group$doNotTestCacheValidity)) {
  516.                 $array unserialize($data);
  517.                 $this->_memoryCachingCounter $array['counter'];
  518.                 $this->_memoryCachingArray $array['array'];
  519.             }
  520.         }
  521.     }
  522.     
  523.     /**
  524.     * Return the cache last modification time
  525.     *
  526.     * BE CAREFUL : THIS METHOD IS FOR HACKING ONLY !
  527.     *
  528.     * @return int last modification time
  529.     */
  530.     function lastModified(
  531.     {
  532.         return @filemtime($this->_file);
  533.     }
  534.     
  535.     /**
  536.     * Trigger a PEAR error
  537.     *
  538.     * To improve performances, the PEAR.php file is included dynamically.
  539.     * The file is so included only when an error is triggered. So, in most
  540.     * cases, the file isn't included and perfs are much better.
  541.     *
  542.     * @param string $msg error message
  543.     * @param int $code error code
  544.     * @access public
  545.     */
  546.     function raiseError($msg$code)
  547.     {
  548.         include_once('PEAR.php');
  549.         return PEAR::raiseError($msg$code$this->_pearErrorMode);
  550.     }
  551.     
  552.     /**
  553.      * Extend the life of a valid cache file
  554.      * 
  555.      * see http://pear.php.net/bugs/bug.php?id=6681
  556.      * 
  557.      * @access public
  558.      */
  559.     function extendLife()
  560.     {
  561.         @touch($this->_file);
  562.     }
  563.     
  564.     // --- Private methods ---
  565.     
  566.     /**
  567.     * Compute & set the refresh time
  568.     *
  569.     * @access private
  570.     */
  571.     function _setRefreshTime(
  572.     {
  573.         if (is_null($this->_lifeTime)) {
  574.             $this->_refreshTime = null;
  575.         else {
  576.             $this->_refreshTime time($this->_lifeTime;
  577.         }
  578.     }
  579.     
  580.     /**
  581.     * Remove a file
  582.     * 
  583.     * @param string $file complete file path and name
  584.     * @return boolean true if no problem
  585.     * @access private
  586.     */
  587.     function _unlink($file)
  588.     {
  589.         if (!@unlink($file)) {
  590.             return $this->raiseError('Cache_Lite : Unable to remove cache !'-3);
  591.         }
  592.         return true;        
  593.     }
  594.  
  595.     /**
  596.     * Recursive function for cleaning cache file in the given directory
  597.     *
  598.     * @param string $dir directory complete path (with a trailing slash)
  599.     * @param string $group name of the cache group
  600.     * @param string $mode flush cache mode : 'old', 'ingroup', 'notingroup',
  601.                                              'callback_myFunction'
  602.     * @return boolean true if no problem
  603.     * @access private
  604.     */
  605.     function _cleanDir($dir$group = false$mode 'ingroup')     
  606.     {
  607.         if ($this->_fileNameProtection{
  608.             $motif ($group'cache_'.md5($group).'_' 'cache_';
  609.         else {
  610.             $motif ($group'cache_'.$group.'_' 'cache_';
  611.         }
  612.         if ($this->_memoryCaching{
  613.         foreach($this->_memoryCachingArray as $key => $v{
  614.                 if (strpos($key$motif!== false{
  615.                     unset($this->_memoryCachingArray[$key]);
  616.                     $this->_memoryCachingCounter $this->_memoryCachingCounter - 1;
  617.                 }
  618.             }
  619.             if ($this->_onlyMemoryCaching{
  620.                 return true;
  621.             }
  622.         }
  623.         if (!($dh opendir($dir))) {
  624.             return $this->raiseError('Cache_Lite : Unable to open cache directory !'-4);
  625.         }
  626.         $result = true;
  627.         while (($file readdir($dh)) !== false{
  628.             if (($file != '.'&& ($file != '..')) {
  629.                 if (substr($file06)=='cache_'{
  630.                     $file2 $dir $file;
  631.                     if (is_file($file2)) {
  632.                         switch (substr($mode09)) {
  633.                             case 'old':
  634.                                 // files older than lifeTime get deleted from cache
  635.                                 if (!is_null($this->_lifeTime)) {
  636.                                     if ((time(@filemtime($file2)) $this->_lifeTime{
  637.                                         $result ($result and ($this->_unlink($file2)));
  638.                                     }
  639.                                 }
  640.                                 break;
  641.                             case 'notingrou':
  642.                                 if (strpos($file2$motif=== false{
  643.                                     $result ($result and ($this->_unlink($file2)));
  644.                                 }
  645.                                 break;
  646.                             case 'callback_':
  647.                                 $func substr($mode9strlen($mode- 9);
  648.                                 if ($func($file2$group)) {
  649.                                     $result ($result and ($this->_unlink($file2)));
  650.                                 }
  651.                                 break;
  652.                             case 'ingroup':
  653.                             default:
  654.                                 if (strpos($file2$motif!== false{
  655.                                     $result ($result and ($this->_unlink($file2)));
  656.                                 }
  657.                                 break;
  658.                         }
  659.                     }
  660.                     if ((is_dir($file2)) and ($this->_hashedDirectoryLevel>0)) {
  661.                         $result ($result and ($this->_cleanDir($file2 '/'$group$mode)));
  662.                     }
  663.                 }
  664.             }
  665.         }
  666.         return $result;
  667.     }
  668.       
  669.     /**
  670.     * Add some date in the memory caching array
  671.     *
  672.     * @param string $data data to cache
  673.     * @access private
  674.     */
  675.     function _memoryCacheAdd($data)
  676.     {
  677.         $this->_memoryCachingArray[$this->_file$data;
  678.         if ($this->_memoryCachingCounter >= $this->_memoryCachingLimit{
  679.             list($keyeach($this->_memoryCachingArray);
  680.             unset($this->_memoryCachingArray[$key]);
  681.         else {
  682.             $this->_memoryCachingCounter $this->_memoryCachingCounter + 1;
  683.         }
  684.     }
  685.  
  686.     /**
  687.     * Make a file name (with path)
  688.     *
  689.     * @param string $id cache id
  690.     * @param string $group name of the group
  691.     * @access private
  692.     */
  693.     function _setFileName($id$group)
  694.     {
  695.         
  696.         if ($this->_fileNameProtection{
  697.             $suffix 'cache_'.md5($group).'_'.md5($id);
  698.         else {
  699.             $suffix 'cache_'.$group.'_'.$id;
  700.         }
  701.         $root $this->_cacheDir;
  702.         if ($this->_hashedDirectoryLevel>0{
  703.             $hash md5($suffix);
  704.             for ($i=0 ; $i<$this->_hashedDirectoryLevel $i++{
  705.                 $root $root 'cache_' substr($hash0$i + 1'/';
  706.             }   
  707.         }
  708.         $this->_fileName $suffix;
  709.         $this->_file $root.$suffix;
  710.     }
  711.     
  712.     /**
  713.     * Read the cache file and return the content
  714.     *
  715.     * @return string content of the cache file (else : false or a PEAR_Error object)
  716.     * @access private
  717.     */
  718.     function _read()
  719.     {
  720.         $fp @fopen($this->_file"rb");
  721.         if ($fp{
  722.         if ($this->_fileLocking@flock($fpLOCK_SH);
  723.             clearstatcache();
  724.             $length @filesize($this->_file);
  725.             $mqr get_magic_quotes_runtime();
  726.             if ($mqr{
  727.                 set_magic_quotes_runtime(0);
  728.             }
  729.             if ($this->_readControl{
  730.                 $hashControl @fread($fp32);
  731.                 $length $length - 32;
  732.             }
  733.  
  734.             if ($length{
  735.                 $data '';
  736.                 // See https://bugs.php.net/bug.php?id=30936
  737.                 // The 8192 magic number is the chunk size used internally by PHP.
  738.                 while(!feof($fp)) $data .= fread($fp8192);
  739.             else {
  740.                 $data '';
  741.             }
  742.             if ($mqr{
  743.                 set_magic_quotes_runtime($mqr);
  744.             }
  745.             if ($this->_fileLocking@flock($fpLOCK_UN);
  746.             @fclose($fp);
  747.             if ($this->_readControl{
  748.                 $hashData $this->_hash($data$this->_readControlType);
  749.                 if ($hashData != $hashControl{
  750.                     if (!(is_null($this->_lifeTime))) {
  751.                         @touch($this->_filetime(- 2*abs($this->_lifeTime))
  752.                     else {
  753.                         @unlink($this->_file);
  754.                     }
  755.                     return false;
  756.                 }
  757.             }
  758.             return $data;
  759.         }
  760.         return $this->raiseError('Cache_Lite : Unable to read cache !'-2)
  761.     }
  762.     
  763.     /**
  764.     * Write the given data in the cache file
  765.     *
  766.     * @param string $data data to put in cache
  767.     * @return boolean true if ok (a PEAR_Error object else)
  768.     * @access private
  769.     */
  770.     function _write($data)
  771.     {
  772.         if ($this->_hashedDirectoryLevel > 0{
  773.             $hash md5($this->_fileName);
  774.             $root $this->_cacheDir;
  775.             for ($i=0 ; $i<$this->_hashedDirectoryLevel $i++{
  776.                 $root $root 'cache_' substr($hash0$i + 1'/';
  777.                 if (!(@is_dir($root))) {
  778.                     @mkdir($root$this->_hashedDirectoryUmask);
  779.                 }
  780.             }
  781.         }
  782.         $fp @fopen($this->_file"wb");
  783.         if ($fp{
  784.             if ($this->_fileLocking@flock($fpLOCK_EX);
  785.             if ($this->_readControl{
  786.                 @fwrite($fp$this->_hash($data$this->_readControlType)32);
  787.             }
  788.             $mqr get_magic_quotes_runtime();
  789.             if ($mqr{
  790.                 set_magic_quotes_runtime(0);
  791.             }
  792.             @fwrite($fp$data);
  793.             if ($mqr{
  794.                 set_magic_quotes_runtime($mqr);
  795.             }
  796.             if ($this->_fileLocking@flock($fpLOCK_UN);
  797.             @fclose($fp);
  798.             return true;
  799.         }      
  800.         return $this->raiseError('Cache_Lite : Unable to write cache file : '.$this->_file-1);
  801.     }
  802.        
  803.     /**
  804.     * Write the given data in the cache file and control it just after to avoir corrupted cache entries
  805.     *
  806.     * @param string $data data to put in cache
  807.     * @return boolean true if the test is ok (else : false or a PEAR_Error object)
  808.     * @access private
  809.     */
  810.     function _writeAndControl($data)
  811.     {
  812.         $result $this->_write($data);
  813.         if (is_object($result)) {
  814.             return $result# We return the PEAR_Error object
  815.         }
  816.         $dataRead $this->_read();
  817.         if (is_object($dataRead)) {
  818.             return $dataRead# We return the PEAR_Error object
  819.         }
  820.         if ((is_bool($dataRead)) && (!$dataRead)) {
  821.             return false; 
  822.         }
  823.         return ($dataRead==$data);
  824.     }
  825.     
  826.     /**
  827.     * Make a control key with the string containing datas
  828.     *
  829.     * @param string $data data
  830.     * @param string $controlType type of control 'md5', 'crc32' or 'strlen'
  831.     * @return string control key
  832.     * @access private
  833.     */
  834.     function _hash($data$controlType)
  835.     {
  836.         switch ($controlType{
  837.         case 'md5':
  838.             return md5($data);
  839.         case 'crc32':
  840.             return sprintf('% 32d'crc32($data));
  841.         case 'strlen':
  842.             return sprintf('% 32d'strlen($data));
  843.         default:
  844.             return $this->raiseError('Unknown controlType ! (available values are only \'md5\', \'crc32\', \'strlen\')'-5);
  845.         }
  846.     }
  847.     
  848. }

Documentation generated on Thu, 24 May 2012 08:00:03 +0000 by phpDocumentor 1.4.3. PEAR Logo Copyright © PHP Group 2004.