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

Source for file Container.php

Documentation is available at Container.php

  1. <?php
  2. // +----------------------------------------------------------------------+
  3. // | PEAR :: Cache                                                        |
  4. // +----------------------------------------------------------------------+
  5. // | Copyright (c) 1997-2003 The PHP Group                                |
  6. // +----------------------------------------------------------------------+
  7. // | This source file is subject to version 2.0 of the PHP license,       |
  8. // | that is bundled with this package in the file LICENSE, and is        |
  9. // | available at through the world-wide-web at                           |
  10. // | http://www.php.net/license/2_02.txt.                                 |
  11. // | If you did not receive a copy of the PHP license and are unable to   |
  12. // | obtain it through the world-wide-web, please send a note to          |
  13. // | license@php.net so we can mail you a copy immediately.               |
  14. // +----------------------------------------------------------------------+
  15. // | Authors: Ulf Wendel <ulf.wendel@phpdoc.de>                           |
  16. // |          Sebastian Bergmann <sb@sebastian-bergmann.de>               |
  17. // |          Christian Stocker <chregu@phant.ch>                         |
  18. // +----------------------------------------------------------------------+
  19. //
  20. // $Id: Container.php 315102 2011-08-17 19:38:20Z cweiske $
  21.  
  22. require_once 'Cache/Error.php';
  23.  
  24. /**
  25. * Common base class of all cache storage container.
  26. *
  27. * To speed up things we do a preload you should know about, otherwise it might
  28. * play you a trick. The Cache controller classes (Cache/Cache, Cache/Output, ...)
  29. * usually do something like is (isCached($id) && !isExpired($id)) return $container->load($id).
  30. * if you implement isCached(), isExpired() and load() straight ahead, each of this
  31. * functions will result in a storage medium (db, file,...) access. This generates too much load.
  32. * Now, a simple speculative preload should saves time in most cases. Whenever
  33. * one of the mentioned methods is invoked we preload the cached dataset into class variables.
  34. * That means that we have only one storage medium access for the sequence
  35. *  (isCached($id) && !isExpired($id)) return $container->load($id).
  36. * The bad thing is that the preloaded data might be outdated meanwhile, which is
  37. * unlikely but for you power users, be warned. If you do not want the preload
  38. * you should switch it off by setting the class variable $preload to false. Anyway, this is
  39. * not recommended!
  40. *
  41. @author   Ulf Wendel <ulf.wendel@phpdoc.de>
  42. @version  $Id: Container.php 315102 2011-08-17 19:38:20Z cweiske $
  43. @package  Cache
  44. @access   public
  45. @abstract
  46. */
  47. {
  48.  
  49.     /**
  50.     * Flag indicating wheter to preload datasets.
  51.     *
  52.     * See the class description for more details.
  53.     *
  54.     * @var  boolean 
  55.     */
  56.     var $preload = true;
  57.  
  58.     /**
  59.     * ID of a preloaded dataset
  60.     *
  61.     * @var  string 
  62.     */
  63.     var $id = '';
  64.  
  65.     /**
  66.     * Cache group of a preloaded dataset
  67.     *
  68.     * @var  string 
  69.     */
  70.     var $group = '';
  71.  
  72.     /**
  73.     * Expiration timestamp of a preloaded dataset.
  74.     *
  75.     * @var  integer 0 means never, endless
  76.     */
  77.     var $expires = 0;
  78.  
  79.     /**
  80.     * Value of a preloaded dataset.
  81.     *
  82.     * @var  string 
  83.     */
  84.     var $cachedata = '';
  85.  
  86.     /**
  87.     * Preloaded userdata field.
  88.     *
  89.     * @var  string 
  90.     */
  91.     var $userdata = '';
  92.  
  93.     /**
  94.     * Flag indicating that the dataset requested for preloading is unknown.
  95.     *
  96.     * @var  boolean 
  97.     */
  98.     var $unknown = true;
  99.  
  100.     /**
  101.     * Encoding mode for cache data: base64 or addslashes() (slash).
  102.     *
  103.     * @var  string  base64 or slash
  104.     */
  105.     var $encoding_mode = 'base64';
  106.  
  107.     /**
  108.     * Highwater mark - maximum space required by all cache entries.
  109.     *
  110.     * Whenever the garbage collection runs it checks the amount of space
  111.     * required by all cache entries. If it's more than n (highwater) bytes
  112.     * the garbage collection deletes as many entries as necessary to reach the
  113.     * lowwater mark.
  114.     *
  115.     * @var  int 
  116.     * @see  lowwater
  117.     */
  118.     var $highwater = 2048000;
  119.  
  120.  
  121.     /**
  122.     * Lowwater mark
  123.     *
  124.     * @var  int 
  125.     * @see  highwater
  126.     */
  127.     var $lowwater = 1536000;
  128.  
  129.  
  130.     /**
  131.     * Options that can be set in every derived class using it's constructor.
  132.     *
  133.     * @var  array 
  134.     */
  135.     var $allowed_options = array('encoding_mode''highwater''lowwater');
  136.  
  137.  
  138.     /**
  139.     * Loads a dataset from the cache.
  140.     *
  141.     * @param    string  dataset ID
  142.     * @param    string  cache group
  143.     * @return   mixed   dataset value or null on failure
  144.     * @access   public
  145.     */
  146.     function load($id$group)
  147.     {
  148.         if ($this->preload{
  149.             if ($this->id != $id || $this->group != $group{
  150.                 $this->preload($id$group);
  151.             }
  152.             return $this->cachedata;
  153.         }
  154.  
  155.         $ret $this->fetch($id$group);
  156.         if (PEAR::isError($ret)) {
  157.             return $ret;
  158.         }
  159.  
  160.         list$data$ret;
  161.         return $data;
  162.     // end func load
  163.  
  164.     /**
  165.     * Returns the userdata field of a cached data set.
  166.     *
  167.     * @param    string  dataset ID
  168.     * @param    string  cache group
  169.     * @return   string  userdata
  170.     * @access   public
  171.     */
  172.     function getUserdata($id$group)
  173.     {
  174.         if ($this->preload{
  175.             if ($this->id != $id || $this->group != $group{
  176.                 $this->preload($id$group);
  177.             }
  178.             return $this->userdata;
  179.         }
  180.  
  181.         $ret $this->fetch($id$group);
  182.         if (PEAR::isError($ret)) {
  183.             return $ret;
  184.         }
  185.  
  186.         list, , $userdata$ret;
  187.         return $userdata;
  188.     // end func getUserdata
  189.  
  190.     /**
  191.     * Checks if a dataset is expired.
  192.     *
  193.     * @param    string  dataset ID
  194.     * @param    string  cache group
  195.     * @param    integer maximum age timestamp
  196.     * @return   boolean 
  197.     * @access   public
  198.     */
  199.     function isExpired($id$group$max_age)
  200.     {
  201.         if ($this->preload{
  202.             if ($this->id != $id || $this->group != $group{
  203.                 $this->preload($id$group);
  204.             }
  205.             if ($this->unknown{
  206.                 return false;
  207.             }
  208.         else {
  209.             // check if at all it is cached
  210.             if (!$this->isCached($id$group)) {
  211.                 return false;
  212.             }
  213.             // I'm lazy...
  214.             $ret $this->fetch($id$group);
  215.             if (PEAR::isError($ret)) {
  216.                 return $ret;
  217.             }
  218.  
  219.             list($this->expires, , $ret;
  220.         }
  221.  
  222.         // endless
  223.         if (0 == $this->expires{
  224.             return false;
  225.         }
  226.         // you feel fine, Ulf?
  227.         if ($expired  ($this->expires <= time(|| ($max_age && ($this->expires <= $max_age))) ) {
  228.  
  229.            $this->remove($id$group);
  230.            $this->flushPreload();
  231.         }
  232.         return $expired;
  233.     // end func isExpired
  234.  
  235.     /**
  236.     * Checks if a dataset is cached.
  237.     *
  238.     * @param    string  dataset ID
  239.     * @param    string  cache group
  240.     * @return   boolean 
  241.     */
  242.     function isCached($id$group)
  243.     {
  244.         if ($this->preload{
  245.             if ($this->id != $id || $this->group != $group{
  246.                 $this->preload($id$group);
  247.             }
  248.             return !($this->unknown);
  249.         }
  250.         return $this->idExists($id$group);
  251.     // end func isCached
  252.  
  253.     //
  254.     // abstract methods
  255.     //
  256.  
  257.     /**
  258.     * Fetches a dataset from the storage medium.
  259.     *
  260.     * @param    string  dataset ID
  261.     * @param    string  cache group
  262.     * @return   array   format: [expire date, cached data, user data]
  263.     * @throws   Cache_Error
  264.     * @abstract
  265.     */
  266.     function fetch($id$group)
  267.     {
  268.         return array(nullnullnull);
  269.     // end func fetch
  270.  
  271.     /**
  272.     * Stores a dataset.
  273.     *
  274.     * @param    string  dataset ID
  275.     * @param    mixed   data to store
  276.     * @param    mixed   userdefined expire date
  277.     * @param    string  cache group
  278.     * @param    string  additional userdefined data
  279.     * @return   boolean 
  280.     * @throws   Cache_Error
  281.     * @access   public
  282.     * @abstract
  283.     */
  284.     function save($id$data$expire$group$userdata)
  285.     {
  286.         // QUESTION: Should we update the preload buffer instead?
  287.         // Don't think so as the sequence save()/load() is unlikely.
  288.         $this->flushPreload($id$group);
  289.         return null;
  290.     // end func save
  291.  
  292.     /**
  293.     * Removes a dataset.
  294.     *
  295.     * @param    string  dataset ID
  296.     * @param    string  cache group
  297.     * @return   boolean 
  298.     * @access   public
  299.     * @abstract
  300.     */
  301.     function remove($id$group)
  302.     {
  303.         $this->flushPreload($id$group);
  304.         return null;
  305.     // end func remove
  306.  
  307.     /**
  308.     * Flushes the cache - removes all caches datasets from the cache.
  309.     *
  310.     * @param    string      If a cache group is given only the group will be flushed
  311.     * @return   integer     Number of removed datasets, -1 on failure
  312.     * @access   public
  313.     * @abstract
  314.     */
  315.     function flush($group)
  316.     {
  317.         $this->flushPreload();
  318.         return null;
  319.     // end func flush
  320.  
  321.     /**
  322.     * Checks if a dataset exists.
  323.     *
  324.     * @param    string  dataset ID
  325.     * @param    string  cache group
  326.     * @return   boolean 
  327.     * @access   public
  328.     * @abstract
  329.     */
  330.     function idExists($id$group)
  331.     {
  332.         return null;
  333.     // end func idExists
  334.  
  335.     /**
  336.     * Starts the garbage collection.
  337.     *
  338.     * @param int $gc_maxlifetime The maximum lifetime (seconds) for a cache
  339.     *                             entry. Implemented by containers,
  340.     *
  341.     * @access   public
  342.     * @abstract
  343.     */
  344.     function garbageCollection($gc_maxlifetime)
  345.     {
  346.         $this->flushPreload();
  347.     // end func garbageCollection
  348.  
  349.     /**
  350.     * Does a speculative preload of a dataset
  351.     *
  352.     * @param    string  dataset ID
  353.     * @param    string  cache group
  354.     * @return   boolean 
  355.     */
  356.     function preload($id$group)
  357.     {
  358.         // whatever happens, remember the preloaded ID
  359.         $this->id = $id;
  360.         $this->group = $group;
  361.  
  362.         $ret $this->fetch($id$group);
  363.         if (PEAR::isError($ret)) {
  364.             return $ret;
  365.         }
  366.  
  367.         list($this->expires$this->cachedata$this->userdata$ret;
  368.         if ($this->expires === null{
  369.             // Uuups, unknown ID
  370.             $this->flushPreload();
  371.             return false;
  372.         }
  373.  
  374.         $this->unknown = false;
  375.  
  376.         return true;
  377.     // end func preload
  378.  
  379.     /**
  380.     * Flushes the internal preload buffer.
  381.     *
  382.     * save(), remove() and flush() must call this method
  383.     * to preevent differences between the preloaded values and
  384.     * the real cache contents.
  385.     *
  386.     * @param    string  dataset ID, if left out the preloaded values will be flushed.
  387.     *                    If given the preloaded values will only be flushed if they are
  388.     *                    equal to the given id and group
  389.     * @param    string  cache group
  390.     * @see  preload()
  391.     */
  392.     function flushPreload($id ''$group 'default')
  393.     {
  394.         if (!$id || ($this->id == $id && $this->group == $group)) {
  395.             // clear the internal preload values
  396.             $this->id = '';
  397.             $this->group = '';
  398.             $this->cachedata = '';
  399.             $this->userdata = '';
  400.             $this->expires = -1;
  401.             $this->unknown = true;
  402.         }
  403.     // end func flushPreload
  404.  
  405.     /**
  406.     * Imports the requested datafields as object variables if allowed
  407.     *
  408.     * @param array $requested list of fields to be imported
  409.     *
  410.     * @return boolean True if all parametes in arg are accepted
  411.     * @access protected
  412.     */
  413.     function setOptions($requested)
  414.     {
  415.         $wasAccepted = true;
  416.         foreach ($this->getAllowedOptions(as $field{
  417.             if (isset($requested[$field])) {
  418.                 $this->$field $requested[$field];
  419.             else {
  420.                 $wasAccepted = false;
  421.             }
  422.         }
  423.         return $wasAccepted;
  424.     // end func setOptions
  425.  
  426.     /**
  427.      * Set the Allowed Parameters to Container Type
  428.      *
  429.      * @param array $allowedOptions the Array with allowed parameters
  430.      *
  431.      * @return boolean 
  432.      * @access protected
  433.      */
  434.     function setAllowedOptions($allowedOptions)
  435.     {
  436.         if (is_array($allowedOptions)) {
  437.             $this->allowed_options = $allowedOptions;
  438.             return true;
  439.         }
  440.         return false;
  441.     }
  442.  
  443.     /**
  444.      * Verify that a configuration option has been set
  445.      *
  446.      * @param string $optionName the option name
  447.      *
  448.      * @return boolean 
  449.      * @access protected
  450.      */
  451.     function hasBeenSet($optionName)
  452.     {
  453.         return isset($this->$optionName);
  454.     }
  455.  
  456.     /**
  457.      * Getter to allowed Configurations Options
  458.      *
  459.      * @return array The options you can set to Container
  460.      * @access protected
  461.      */
  462.     function getAllowedOptions()
  463.     {
  464.         return $this->allowed_options;
  465.     }
  466.  
  467.     /**
  468.     * Encodes the data for the storage container.
  469.     *
  470.     * @var  mixed data to encode
  471.     */
  472.     function encode($data)
  473.     {
  474.         if ($this->encoding_mode == 'base64'{
  475.             return base64_encode(serialize($data));
  476.         else {
  477.             return serialize($data);
  478.         }
  479.     // end func encode
  480.  
  481.  
  482.     /**
  483.     * Decodes the data from the storage container.
  484.     *
  485.     * @var  mixed 
  486.     */
  487.     function decode($data)
  488.     {
  489.         if ($this->encoding_mode == 'base64'{
  490.             return unserialize(base64_decode($data));
  491.         else {
  492.             return unserialize($data);
  493.         }
  494.     // end func decode
  495.  
  496.  
  497.     /**
  498.     * Translates human readable/relative times in unixtime
  499.     *
  500.     * @param  mixed   can be in the following formats:
  501.     *                human readable          : yyyymmddhhmm[ss]] eg: 20010308095100
  502.     *                relative in seconds (1) : +xx              eg: +10
  503.     *                relative in seconds (2) : x <  946681200   eg: 10
  504.     *                absolute unixtime       : x < 2147483648   eg: 2147483648
  505.     *                see comments in code for details
  506.     * @return integer unix timestamp
  507.     */
  508.     function getExpiresAbsolute($expires)
  509.     {
  510.         if (!$expires{
  511.             return 0;
  512.         }
  513.         //for api-compatibility, one has not to provide a "+",
  514.         // if integer is < 946681200 (= Jan 01 2000 00:00:00)
  515.         if ($expires[0== '+' || $expires < 946681200{
  516.             return(time($expires);
  517.         elseif ($expires < 100000000000{
  518.             //if integer is < 100000000000 (= in 3140 years),
  519.             // it must be an absolut unixtime
  520.             // (since the "human readable" definition asks for a higher number)
  521.             return $expires;
  522.         else {
  523.             // else it's "human readable";
  524.             $year substr($expires04);
  525.             $month substr($expires42);
  526.             $day substr($expires62);
  527.             $hour substr($expires82);
  528.             $minute substr($expires102);
  529.             $second substr($expires122);
  530.             return mktime($hour$minute$second$month$day$year);
  531.         }
  532.  
  533.     // end func getExpireAbsolute
  534.  
  535. // end class Container
  536. ?>

Documentation generated on Mon, 11 Mar 2019 15:44:49 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.