Apache Zeta Components Manual :: File Source for file.php

Source for file file.php

Documentation is available at file.php

  1. <?php
  2. /**
  3.  * File containing the ezcCacheStorageFile class.
  4.  *
  5.  * Licensed to the Apache Software Foundation (ASF) under one
  6.  * or more contributor license agreements.  See the NOTICE file
  7.  * distributed with this work for additional information
  8.  * regarding copyright ownership.  The ASF licenses this file
  9.  * to you under the Apache License, Version 2.0 (the
  10.  * "License"); you may not use this file except in compliance
  11.  * with the License.  You may obtain a copy of the License at
  12.  * 
  13.  *   http://www.apache.org/licenses/LICENSE-2.0
  14.  * 
  15.  * Unless required by applicable law or agreed to in writing,
  16.  * software distributed under the License is distributed on an
  17.  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  18.  * KIND, either express or implied.  See the License for the
  19.  * specific language governing permissions and limitations
  20.  * under the License.
  21.  *
  22.  * @package Cache
  23.  * @version //autogentag//
  24.  * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
  25.  * @filesource
  26.  */
  27.  
  28. /**
  29.  * This class implements most of the methods which have been declared abstract
  30.  * in {@link ezcCacheStorage}, but also declares 2 new methods abstract, which
  31.  * have to be implemented by storage driver itself.
  32.  *
  33.  * This class is a common base class for all file system based storage classes.
  34.  * To implement a file system based cache storage, you simply have to derive
  35.  * from this class and implement the {@link ezcCacheStorageFile::fetchData()}
  36.  * and {@link ezcCacheStorageFile::prepareData()} methods. Everything else is
  37.  * done for you by the ezcCacheStorageFile base class.
  38.  *
  39.  * For example code of using a cache storage, see {@link ezcCacheManager}.
  40.  *
  41.  * The Cache package already contains several implementations of
  42.  * {@link ezcCacheStorageFile}. As there are:
  43.  *
  44.  * - ezcCacheStorageFileArray
  45.  * - ezcCacheStorageFileEvalArray
  46.  * - ezcCacheStorageFilePlain
  47.  *
  48.  * @package Cache
  49.  * @version //autogentag//
  50.  */
  51. {
  52.     /**
  53.      * Resource used for the lock file.
  54.      *
  55.      * @var resource(file) 
  56.      */
  57.     protected $lockResource = false;
  58.  
  59.     /**
  60.      * Creates a new cache storage in the given location.
  61.      * Creates a new cache storage for a given location. The location in case
  62.      * of this storage class is a valid file system directory.
  63.      *
  64.      * Options can contain the 'ttl' ( Time-To-Life ). This is per default set
  65.      * to 1 day. The option 'permissions' can be used to define the file
  66.      * permissions of created cache items. Specific ezcCacheStorageFile
  67.      * implementations can have additional options.
  68.      *
  69.      * For details about the options see {@link ezcCacheStorageFileOptions}.
  70.      *
  71.      * @param string $location               Path to the cache location
  72.      * @param array(string=>string) $options Options for the cache.
  73.      *
  74.      * @throws ezcBaseFileNotFoundException
  75.      *          If the storage location does not exist. This should usually not
  76.      *          happen, since {@link ezcCacheManager::createCache()} already
  77.      *          performs sanity checks for the cache location. In case this
  78.      *          exception is thrown, your cache location has been corrupted
  79.      *          after the cache was configured.
  80.      * @throws ezcBaseFileNotFoundException
  81.      *          If the storage location is not a directory. This should usually
  82.      *          not happen, since {@link ezcCacheManager::createCache()} already
  83.      *          performs sanity checks for the cache location. In case this
  84.      *          exception is thrown, your cache location has been corrupted
  85.      *          after the cache was configured.
  86.      * @throws ezcBaseFilePermissionException
  87.      *          If the storage location is not writeable. This should usually not
  88.      *          happen, since {@link ezcCacheManager::createCache()} already
  89.      *          performs sanity checks for the cache location. In case this
  90.      *          exception is thrown, your cache location has been corrupted
  91.      *          after the cache was configured.
  92.      * @throws ezcBasePropertyNotFoundException
  93.      *          If you tried to set a non-existent option value. The accepted
  94.      *          options depend on the ezcCacheStorage implementation and may
  95.      *          vary.
  96.      */
  97.     public function __construct$location$options array() )
  98.     {
  99.         // Sanity check location
  100.         if !file_exists$location || !is_dir$location ) )
  101.         {
  102.             throw new ezcBaseFileNotFoundException(
  103.                 $location,
  104.                 'cache location',
  105.                 'Does not exist or is no directory.'
  106.             );
  107.         }
  108.         if !is_readable$location ) )
  109.         {
  110.             throw new ezcBaseFilePermissionException(
  111.                 $location,
  112.                 ezcBaseFileException::READ,
  113.                 'Cache location is not readable.'
  114.             );
  115.         }
  116.         if !is_writeable$location ) )
  117.         {
  118.             throw new ezcBaseFilePermissionException(
  119.                 $location,
  120.                 ezcBaseFileException::WRITE,
  121.                 'Cache location is not writeable.'
  122.             );
  123.         }
  124.  
  125.         parent::__construct$location );
  126.         // Overwrite parent set options with new ezcCacheFileStorageOptions
  127.         $this->properties['options'new ezcCacheStorageFileOptions$options );
  128.     }
  129.     /**
  130.      * Fetch data from the cache.
  131.      * This method does the fetching of the data itself. In this case, the
  132.      * method simply includes the file and returns the value returned by the
  133.      * include ( or false on failure ).
  134.      *
  135.      * @param string $filename The file to fetch data from.
  136.      * @return mixed The fetched data or false on failure.
  137.      */
  138.     abstract protected function fetchData$filename );
  139.  
  140.     /**
  141.      * Serialize the data for storing.
  142.      * Serializes a PHP variable ( except type resource and object ) to a
  143.      * executable PHP code representation string.
  144.      *
  145.      * @param mixed $data Simple type or array
  146.      * @return string The serialized data
  147.      *
  148.      * @throws ezcCacheInvalidDataException
  149.      *          If the data submitted can not be handled by the implementation
  150.      *          of {@link ezcCacheStorageFile}. Most implementations can not
  151.      *          handle objects and resources.
  152.      */
  153.     abstract protected function prepareData$data );
  154.  
  155.     /**
  156.      * Store data to the cache storage.
  157.      * This method stores the given cache data into the cache, assigning the
  158.      * ID given to it.
  159.      *
  160.      * The type of cache data which is expected by a ezcCacheStorage depends on
  161.      * its implementation. In most cases strings and arrays will be accepted,
  162.      * in some rare cases only strings might be accepted.
  163.      *
  164.      * Using attributes you can describe your cache data further. This allows
  165.      * you to deal with multiple cache data at once later. Some ezcCacheStorage
  166.      * implementations also use the attributes for storage purposes. Attributes
  167.      * form some kind of "extended ID".
  168.      *
  169.      * @param string $id                        Unique identifier for the data.
  170.      * @param mixed $data                       The data to store.
  171.      * @param array(string=>string) $attributes Attributes describing the
  172.      *                                           cached data.
  173.      *
  174.      * @return string The ID string of the newly cached data.
  175.      *
  176.      * @throws ezcBaseFilePermissionException
  177.      *          If an already existsing cache file could not be unlinked to
  178.      *          store the new data (may occur, when a cache item's TTL
  179.      *          has expired and the file should be stored with more actual
  180.      *          data). This exception means most likely that your cache directory
  181.      *          has been corrupted by external influences (file permission
  182.      *          change).
  183.      * @throws ezcBaseFilePermissionException
  184.      *          If the directory to store the cache file could not be created.
  185.      *          This exception means most likely that your cache directory
  186.      *          has been corrupted by external influences (file permission
  187.      *          change).
  188.      * @throws ezcBaseFileIoException
  189.      *          If an error occured while writing the data to the cache. If this
  190.      *          exception occurs, a serious error occured and your storage might
  191.      *          be corruped (e.g. broken network connection, file system broken,
  192.      *          ...).
  193.      * @throws ezcCacheInvalidDataException
  194.      *          If the data submitted can not be handled by the implementation
  195.      *          of {@link ezcCacheStorageFile}. Most implementations can not
  196.      *          handle objects and resources.
  197.      */
  198.     public function store$id$data$attributes array() )
  199.     {
  200.         $filename $this->properties['location']
  201.                   . $this->generateIdentifier$id$attributes );
  202.         if file_exists$filename ) )
  203.         {
  204.             if unlink$filename === false )
  205.             {
  206.                 throw new ezcBaseFilePermissionException(
  207.                     $filename,
  208.                     ezcBaseFileException::WRITE,
  209.                     'Could not delete existsing cache file.'
  210.                 );
  211.             }
  212.         }
  213.         $dataStr $this->prepareData$data );
  214.         $dirname dirname$filename );
  215.         if !is_dir$dirname && !mkdir$dirname0777true ) )
  216.         {
  217.             throw new ezcBaseFilePermissionException(
  218.                 $dirname,
  219.                 ezcBaseFileException::WRITE,
  220.                 'Could not create directory to stor cache file.'
  221.             );
  222.         }
  223.  
  224.         $this->storeRawData$filename$dataStr );
  225.  
  226.         if ezcBaseFeatures::os(!== "Windows" )
  227.         {
  228.             chmod$filename$this->options->permissions );
  229.         }
  230.         return $id;
  231.     }
  232.  
  233.     /**
  234.      * Actually stores the given data.
  235.      *
  236.      * @param string $filename 
  237.      * @param string $data 
  238.      * @return void 
  239.      *
  240.      * @throws ezcBaseFileIoException
  241.      *          if the store fails.
  242.      */
  243.     protected function storeRawData$filename$data )
  244.     {
  245.         if file_put_contents$filename$data !== strlen$data ) )
  246.         {
  247.             throw new ezcBaseFileIoException(
  248.                 $filename,
  249.                 ezcBaseFileException::WRITE,
  250.                 'Could not write data to cache file.'
  251.             );
  252.         }
  253.     }
  254.  
  255.     /**
  256.      * Restore data from the cache.
  257.      * Restores the data associated with the given cache and
  258.      * returns it. Please see {@link ezcCacheStorage::store()}
  259.      * for more detailed information of cachable datatypes.
  260.      *
  261.      * During access to cached data the caches are automatically
  262.      * expired. This means, that the ezcCacheStorage object checks
  263.      * before returning the data if it's still actual. If the cache
  264.      * has expired, data will be deleted and false is returned.
  265.      *
  266.      * You should always provide the attributes you assigned, although
  267.      * the cache storages must be able to find a cache ID even without
  268.      * them. BEWARE: Finding cache data only by ID can be much
  269.      * slower than finding it by ID and attributes.
  270.      *
  271.      * Note that with the {@link ezcCacheStorageFilePlain} all restored data
  272.      * will be of type string. If you expect a different data type you need to
  273.      * perform a cast after restoring.
  274.      *
  275.      * @param string $id                         The item ID to restore.
  276.      * @param array(string=>string) $attributes  Attributes describing the
  277.      *                                            data to restore.
  278.      * @param bool $search                       Whether to search for items
  279.      *                                            if not found directly.
  280.      *
  281.      * @return mixed|boolThe cached data on success, otherwise false.
  282.      *
  283.      * @throws ezcBaseFilePermissionException
  284.      *          If an already existsing cache file could not be unlinked.
  285.      *          This exception means most likely that your cache directory
  286.      *          has been corrupted by external influences (file permission
  287.      *          change).
  288.      */
  289.     public function restore$id$attributes array()$search false )
  290.     {
  291.         $filename $this->properties['location']
  292.                   . $this->generateIdentifier$id$attributes );
  293.         if file_exists$filename === false )
  294.         {
  295.             if $search === true
  296.                  && count$files $this->search$id$attributes ) ) === )
  297.             {
  298.                 $filename $files[0];
  299.             }
  300.             else
  301.             {
  302.                 return false;
  303.             }
  304.         }
  305.         // No cached data
  306.         if file_exists$filename === false )
  307.         {
  308.             return false;
  309.         }
  310.         // Cached data outdated, purge it.
  311.         if $this->calcLifetime$filename == 0
  312.              && $this->properties['options']['ttl'!== false )
  313.         {
  314.             $this->delete$id$attributes );
  315.             return false;
  316.         }
  317.         return $this->fetchData$filename ) );
  318.     }
  319.  
  320.     /**
  321.      * Delete data from the cache.
  322.      * Purges the cached data for a given ID and or attributes. Using an ID
  323.      * purges only the cache data for just this ID.
  324.      *
  325.      * Additional attributes provided will matched additionally. This can give
  326.      * you an immense speed improvement against just searching for ID ( see
  327.      * {@link ezcCacheStorage::restore()} ).
  328.      *
  329.      * If you only provide attributes for deletion of cache data, all cache
  330.      * data matching these attributes will be purged.
  331.      *
  332.      * @param string $id                         The item ID to purge.
  333.      * @param array(string=>string) $attributes  Attributes describing the
  334.      *                                            data to restore.
  335.      * @param bool $search                       Whether to search for items
  336.      *                                            if not found directly.
  337.      * @return void 
  338.      *
  339.      * @throws ezcBaseFilePermissionException
  340.      *          If an already existsing cache file could not be unlinked.
  341.      *          This exception means most likely that your cache directory
  342.      *          has been corrupted by external influences (file permission
  343.      *          change).
  344.      */
  345.     public function delete$id null$attributes array()$search false )
  346.     {
  347.         $filename $this->properties['location']
  348.                   . $this->generateIdentifier$id$attributes );
  349.  
  350.         $filesToDelete array();
  351.         if file_exists$filename ) )
  352.         {
  353.             $filesToDelete[$filename;
  354.         }
  355.         else if $search === true )
  356.         {
  357.             $filesToDelete $this->search$id$attributes );
  358.         }
  359.  
  360.         $deletedIds array();
  361.         foreach $filesToDelete as $filename )
  362.         {
  363.             if unlink$filename === false )
  364.             {
  365.                 throw new ezcBaseFilePermissionException(
  366.                     $filename,
  367.                     ezcBaseFileException::WRITE,
  368.                     'Could not unlink cache file.'
  369.                 );
  370.             }
  371.             $deleted      $this->extractIdentifier$filename );
  372.             $deletedIds[$deleted['id'];
  373.         }
  374.         return $deletedIds;
  375.     }
  376.  
  377.     /**
  378.      * Return the number of items in the cache matching a certain criteria.
  379.      * This method determines if cache data described by the given ID and/or
  380.      * attributes exists. It returns the number of cache data items found.
  381.      *
  382.      * @param string $id                         The item ID.
  383.      * @param array(string=>string) $attributes  Attributes describing the
  384.      *                                            data to restore.
  385.      * @return int Number of data items matching the criteria.
  386.      */
  387.     public function countDataItems$id null$attributes array() )
  388.     {
  389.         return count$this->search$id$attributes ) );
  390.     }
  391.  
  392.     /**
  393.      * Returns the time ( in seconds ) which remains for a cache object,
  394.      * before it gets outdated. In case the cache object is already
  395.      * outdated or does not exist, this method returns 0.
  396.      *
  397.      * @param string $id                         The item ID.
  398.      * @param array(string=>string) $attributes  Attributes describing the
  399.      *                                            data to restore.
  400.      * @access public
  401.      * @return int The remaining lifetime (0 if nonexists or oudated).
  402.      */
  403.     public function getRemainingLifetime$id$attributes array() )
  404.     {
  405.         if count$objects $this->search$id$attributes ) ) )
  406.         {
  407.             return $this->calcLifetime$objects[0);
  408.         }
  409.         return 0;
  410.     }
  411.  
  412.     /**
  413.      * Purges the given number of cache items.
  414.      *
  415.      * This method minimally purges the $limit number of outdated cache items
  416.      * from the storage. If limit is left out, all outdated items are purged.
  417.      * The purged item IDs are returned.
  418.      *
  419.      * @param int $limit 
  420.      * @return array(string) 
  421.      */
  422.     public function purge$limit null )
  423.     {
  424.         $purgeCount 0;
  425.         return $this->purgeRecursive$this->properties['location']$limit$purgeCount );
  426.     }
  427.  
  428.     /**
  429.      * Recursively purge cache items.
  430.      *
  431.      * Recursively purges $dir until $limit is reached. $purgeCount is the
  432.      * number of already purged items.
  433.      *
  434.      * @param string $dir 
  435.      * @param int $limit 
  436.      * @param int $purgeCount 
  437.      */
  438.     private function purgeRecursive$dir$limit&$purgeCount )
  439.     {
  440.         $purgedIds array();
  441.  
  442.         // Deal with files in the directory
  443.         if ( ( $files glob"{$dir}*{$this->properties['options']->extension}) ) === false )
  444.         {
  445.             throw new ezcBaseFileNotFoundException(
  446.                 $dir,
  447.                 'cache location',
  448.                 'Produced an error while globbing for files.'
  449.             );
  450.         }
  451.  
  452.         foreach $files as $file )
  453.         {
  454.             if $this->calcLifetime$file == )
  455.             {
  456.                 if @unlink$file === false )
  457.                 {
  458.                     throw new ezcBaseFilePermissionException(
  459.                         $file,
  460.                         ezcBaseFileException::WRITE,
  461.                         'Could not unlink cache file.'
  462.                     );
  463.                 }
  464.                 $fileInfo    $this->extractIdentifier$file );
  465.                 $purgedIds[$fileInfo['id'];
  466.                 ++$purgeCount;
  467.             }
  468.             // Stop purging if limit is reached
  469.             if $limit !== null && $purgeCount >= $limit )
  470.             {
  471.                 return $purgedIds;
  472.             }
  473.         }
  474.  
  475.         // Deal with sub dirs, this function expects them to be marked with a
  476.         // slash because of the property $location
  477.         if ( ( $dirs glob"$dir*"GLOB_ONLYDIR GLOB_MARK ) ) === false )
  478.         {
  479.             throw new ezcBaseFileNotFoundException(
  480.                 $dir,
  481.                 'cache location',
  482.                 'Produced an error while globbing for directories.'
  483.             );
  484.         }
  485.         foreach $dirs as $dir )
  486.         {
  487.             $purgedIds array_merge(
  488.                 $purgedIds,
  489.                 $this->purgeRecursive$dir$limit$purgeCount )
  490.             );
  491.             // Stop purging if limit is reached
  492.             if $limit !== null && $purgeCount >= $limit )
  493.             {
  494.                 return $purgedIds;
  495.             }
  496.         }
  497.  
  498.         // Finished purging, return IDs.
  499.         return $purgedIds;
  500.     }
  501.  
  502.     /**
  503.      * Resets the whole storage.
  504.      *
  505.      * Deletes all data in the storage including {@link ezcCacheStackMetaData}
  506.      * that was stored using {@link storeMetaData()}.
  507.      */
  508.     public function reset()
  509.     {
  510.         $files glob"{$this->properties['location']}*);
  511.         foreach $files as $file )
  512.         {
  513.             if is_dir$file ) )
  514.             {
  515.                 ezcBaseFile::removeRecursive$file );
  516.             }
  517.             else
  518.             {
  519.                 if @unlink$file === false )
  520.                 {
  521.                     throw new ezcBaseFilePermissionException(
  522.                         $file,
  523.                         ezcBaseFileException::REMOVE,
  524.                         'Could not unlink cache file.'
  525.                     );
  526.                 }
  527.             }
  528.         }
  529.     }
  530.  
  531.     /**
  532.      * Search the storage for data.
  533.      *
  534.      * @param string $id                         An item ID.
  535.      * @param array(string=>string) $attributes  Attributes describing the
  536.      *                                            data to restore.
  537.      * @return array(int=>string) Found cache items.
  538.      */
  539.     protected function search$id null$attributes array() )
  540.     {
  541.         $globArr explode"-"$this->generateIdentifier$id$attributes ));
  542.         if sizeof$globArr )
  543.         {
  544.             $glob $globArr[0]  "-" strtr$globArr[1]array'-' => '*''.' => '*' ) );
  545.         }
  546.         else
  547.         {
  548.             $glob strtr$globArr[0]array'-' => '*''.' => '*' ) );
  549.         }
  550.         $glob $id === null '*' '' $glob;
  551.         return $this->searchRecursive$glob$this->properties['location');
  552.     }
  553.  
  554.     /**
  555.      * Search the storage for data recursively.
  556.      *
  557.      * @param string $pattern  Pattern used with {@link glob()}.
  558.      * @param mixed $directory Directory to search in.
  559.      * @return array(int=>string) Found cache items.
  560.      */
  561.     protected function searchRecursive$pattern$directory )
  562.     {
  563.         $itemArr glob$directory $pattern );
  564.         $dirArr glob$directory "*"GLOB_ONLYDIR );
  565.         foreach $dirArr as $dirEntry )
  566.         {
  567.             $result $this->searchRecursive$pattern"$dirEntry/);
  568.             $itemArr array_merge$itemArr$result );
  569.         }
  570.         return $itemArr;
  571.     }
  572.  
  573.     /**
  574.      * Checks the path in the location property exists, and is read-/writable. It
  575.      * throws an exception if not.
  576.      *
  577.      * @throws ezcBaseFileNotFoundException
  578.      *          If the storage location does not exist. This should usually not
  579.      *          happen, since {@link ezcCacheManager::createCache()} already
  580.      *          performs sanity checks for the cache location. In case this
  581.      *          exception is thrown, your cache location has been corrupted
  582.      *          after the cache was configured.
  583.      * @throws ezcBaseFileNotFoundException
  584.      *          If the storage location is not a directory. This should usually
  585.      *          not happen, since {@link ezcCacheManager::createCache()} already
  586.      *          performs sanity checks for the cache location. In case this
  587.      *          exception is thrown, your cache location has been corrupted
  588.      *          after the cache was configured.
  589.      * @throws ezcBaseFilePermissionException
  590.      *          If the storage location is not writeable. This should usually not
  591.      *          happen, since {@link ezcCacheManager::createCache()} already
  592.      *          performs sanity checks for the cache location. In case this
  593.      *          exception is thrown, your cache location has been corrupted
  594.      *          after the cache was configured.
  595.      */
  596.     protected function validateLocation()
  597.     {
  598.         if file_exists$this->properties['location'=== false )
  599.         {
  600.             throw new ezcBaseFileNotFoundException(
  601.                 $this->properties['location'],
  602.                 'cache location'
  603.             );
  604.         }
  605.  
  606.         if is_dir$this->properties['location'=== false )
  607.         {
  608.             throw new ezcBaseFileNotFoundException(
  609.                 $this->properties['location'],
  610.                 'cache location',
  611.                 'Cache location not a directory.'
  612.             );
  613.         }
  614.  
  615.         if is_writeable$this->properties['location'=== false )
  616.         {
  617.             throw new ezcBaseFilePermissionException(
  618.                 $this->properties['location'],
  619.                 ezcBaseFileException::WRITE,
  620.                 'Cache location is not a directory.'
  621.             );
  622.         }
  623.     }
  624.  
  625.     /**
  626.      * Generate the storage internal identifier from ID and attributes.
  627.      *
  628.      * Generates the storage internal identifier out of the provided ID and the
  629.      * attributes. This is the default implementation and can be overloaded if
  630.      * necessary.
  631.      *
  632.      * @param string $id                         The ID.
  633.      * @param array(string=>string) $attributes  Attributes describing the
  634.      *                                            data to restore.
  635.      * @return string              The generated identifier
  636.      */
  637.     public function generateIdentifier$id$attributes null )
  638.     {
  639.         $filename = (string) $id;
  640.         $illegalFileNameChars array(
  641.             ' '  => '_',
  642.             '/'  => DIRECTORY_SEPARATOR,
  643.             '\\' => DIRECTORY_SEPARATOR,
  644.         );
  645.         $filename strtr$filename$illegalFileNameChars );
  646.  
  647.         // Chars used for filename concatination
  648.         $illegalChars array(
  649.             '-' => '#',
  650.             ' ' => '%',
  651.             '=' => '+',
  652.             '.' => '+',
  653.         );
  654.         if is_array$attributes && count$attributes )
  655.         {
  656.             ksort$attributes );
  657.             foreach $attributes as $key => $val )
  658.             {
  659.                 $attrStr '-' strtr$key$illegalChars )
  660.                          . '=' strtr$val$illegalChars );
  661.                 if strlen$filename $attrStr 250 )
  662.                 {
  663.                     // Max filename length
  664.                     break;
  665.                 }
  666.                 $filename .= $attrStr;
  667.             }
  668.         }
  669.         else
  670.         {
  671.             $filename .= '-';
  672.         }
  673.         return $filename $this->properties['options']['extension'];
  674.     }
  675.  
  676.     /**
  677.      * Restores and returns the meta data struct.
  678.      *
  679.      * This method fetches the meta data stored in the storage and returns the
  680.      * according struct of type {@link ezcCacheStackMetaData}. The meta data
  681.      * must be stored inside the storage, but should not be visible as normal
  682.      * cache items to the user.
  683.      *
  684.      * @return ezcCacheStackMetaData|null
  685.      */
  686.     public function restoreMetaData()
  687.     {
  688.         // Silence require warnings. It's ok that meta data does not exist.
  689.         $dataArr @$this->fetchData(
  690.             $this->properties['location'$this->properties['options']->metaDataFile
  691.         );
  692.  
  693.         $result null;
  694.         if $dataArr !== false )
  695.         {
  696.             $result new $dataArr['class']();
  697.             $result->setState$dataArr['data');
  698.         }
  699.         return $result;
  700.     }
  701.  
  702.     /**
  703.      * Stores the given meta data struct.
  704.      *
  705.      * This method stores the given $metaData inside the storage. The data must
  706.      * be stored with the same mechanism that the storage itself uses. However,
  707.      * it should not be stored as a normal cache item, if possible, to avoid
  708.      * accedental user manipulation.
  709.      *
  710.      * @param ezcCacheStackMetaData $metaData 
  711.      * @return void 
  712.      */
  713.     public function storeMetaDataezcCacheStackMetaData $metaData )
  714.     {
  715.         $dataArr array(
  716.             'class' => get_class$metaData ),
  717.             'data'  => $metaData->getState(),
  718.         );
  719.         $this->storeRawData(
  720.             $this->properties['location'$this->properties['options']->metaDataFile,
  721.             $this->prepareData$dataArr )
  722.         );
  723.     }
  724.  
  725.     /**
  726.      * Acquire a lock on the storage.
  727.      *
  728.      * This method acquires a lock on the storage. If locked, the storage must
  729.      * block all other method calls until the lock is freed again using {@link }
  730.      * ezcCacheStackMetaDataStorage::unlock()}. Methods that are called within
  731.      * the request that successfully acquired the lock must succeed as usual.
  732.      *
  733.      * @return void 
  734.      */
  735.     public function lock()
  736.     {
  737.         $lockFile $this->properties['location'$this->properties['options']->lockFile;
  738.  
  739.         while $this->lockResource === false )
  740.         {
  741.             clearstatcache();
  742.             $this->lockResource = @fopen$lockFile'x' );
  743.  
  744.             // Wait for lock to get freed
  745.             if $this->lockResource === false )
  746.             {
  747.                 usleep$this->properties['options']->lockWaitTime );
  748.             }
  749.  
  750.             // Check if lock is to be considered dead. Might result in a 
  751.             // nonrelevant race condition if the lock file disappears between 
  752.             // fs calls. To avoid warnings in this case, the calls are 
  753.             // silenced.
  754.             if file_exists$lockFile && time(@filemtime$lockFile ) ) $this->properties['options']->maxLockTime )
  755.             {
  756.                 @unlink$lockFile );
  757.             }
  758.         }
  759.     }
  760.  
  761.     /**
  762.      * Release a lock on the storage.
  763.      *
  764.      * This method releases the lock of the storage, that has been acquired via
  765.      * {@link ezcCacheStackMetaDataStorage::lock()}. After this method has been
  766.      * called, blocked method calls (including calls to lock()) can suceed
  767.      * again.
  768.      *
  769.      * @return void 
  770.      */
  771.     public function unlock()
  772.     {
  773.         // If the resource is already removed, nothing to do
  774.         if $this->lockResource !== false )
  775.         {
  776.             fclose$this->lockResource );
  777.             @unlink(
  778.                 $this->properties['location'$this->properties['options']->lockFile
  779.             );
  780.             $this->lockResource = false;
  781.         }
  782.     }
  783.  
  784.     /**
  785.      * Set new options.
  786.      * This method allows you to change the options of a cache file storage. Change
  787.      * of options take effect directly after this method has been called. The
  788.      * available options depend on the ezcCacheStorageFile implementation. All
  789.      * implementations have to offer the following options:
  790.      *
  791.      * - ttl         The time-to-life. After this time span, a cache item becomes
  792.      *               invalid and will be purged. The
  793.      *               {@link ezcCacheStorage::restore()} method will then return
  794.      *               false.
  795.      * - extension   The "extension" for your cache items. This is usually the
  796.      *               file name extension, when you deal with file system based
  797.      *               caches or e.g. a database ID extension.
  798.      * - permissions The file permissions to set for new files.
  799.      *
  800.      * The usage of ezcCacheStorageOptions and arrays for setting options is
  801.      * deprecated, but still supported. You should migrate to
  802.      * ezcCacheStorageFileOptions.
  803.      *
  804.      * @param ezcCacheStorageFileOptions $options The options to set (accepts
  805.      *                                             ezcCacheStorageOptions or
  806.      *                                             array for compatibility
  807.      *                                             reasons, too).
  808.      *
  809.      * @throws ezcBasePropertyNotFoundException
  810.      *          If you tried to set a non-existent option value. The accepted
  811.      *          options depend on the ezcCacheStorage implementation and may
  812.      *          vary.
  813.      * @throws ezcBaseValueException
  814.      *          If the value is not valid for the desired option.
  815.      * @throws ezcBaseValueException
  816.      *          If you submit neither an instance of ezcCacheStorageFileOptions,
  817.      *          nor an instance of ezcCacheStorageOptions nor an array.
  818.      */
  819.     public function setOptions$options )
  820.     {
  821.         if is_array$options ) )
  822.         {
  823.             $this->properties['options']->merge$options );
  824.         }
  825.         else if $options instanceof ezcCacheStorageFileOptions )
  826.         {
  827.             $this->properties['options'$options;
  828.         }
  829.         else if $options instanceof ezcCacheStorageOptions )
  830.         {
  831.             $this->properties['options']->mergeStorageOptions$options );
  832.         }
  833.         else
  834.         {
  835.             throw new ezcBaseValueException(
  836.                 'options',
  837.                 $options,
  838.                 'instance of ezcCacheStorageFileOptions or (deprecated) ezcCacheStorageOptions'
  839.             );
  840.         }
  841.     }
  842.  
  843.     /**
  844.      * Property write access.
  845.      *
  846.      * @param string $propertyName Name of the property.
  847.      * @param mixed $val  The value for the property.
  848.      *
  849.      * @throws ezcBaseValueException
  850.      *          If the value for the property options is not an instance of
  851.      *          ezcCacheStorageOptions.
  852.      * @ignore
  853.      */
  854.     public function __set$propertyName$val )
  855.     {
  856.         switch $propertyName )
  857.         {
  858.             case 'options':
  859.                 if $val instanceof ezcCacheStorageFileOptions )
  860.                 {
  861.                     $this->properties['options'$val;
  862.                     return;
  863.                 }
  864.                 if $val instanceof ezcCacheStorageOptions )
  865.                 {
  866.                     $this->properties['options']->mergeStorageOptions$val );
  867.                     return;
  868.                 }
  869.                 throw new ezcBaseValueException(
  870.                     $propertyName,
  871.                     $val,
  872.                     'instance of ezcCacheStorageFileOptions'
  873.                 );
  874.         }
  875.         throw new ezcBasePropertyNotFoundException$propertyName );
  876.     }
  877.  
  878.     /**
  879.      * Calculates the lifetime remaining for a cache object.
  880.      *
  881.      * This calculates the time a cached object stays valid and returns it. In
  882.      * case the TTL is set to false, this method always returns a value of 1.
  883.      *
  884.      * @param string $file The file to calculate the remaining lifetime for.
  885.      * @return int The remaining lifetime in seconds (0 if no time remaining).
  886.      */
  887.     protected function calcLifetime$file )
  888.     {
  889.         $ttl $this->options->ttl;
  890.         if file_exists$file && $modTime filemtime$file ) ) !== false )
  891.         {
  892.             if $ttl === false )
  893.             {
  894.                 return 1;
  895.             }
  896.             return (
  897.                 $lifeTime time($modTime $ttl
  898.                 ? $ttl $lifeTime
  899.                 : 0
  900.             );
  901.         }
  902.         return 0;
  903.     }
  904.  
  905.     /**
  906.      * Extracts ID, attributes and the file extension from a filename.
  907.      *
  908.      * @param string $filename 
  909.      * @return array('id'=>string,'attributes'=>string,'ext'=>string) 
  910.      */
  911.     private function extractIdentifier$filename )
  912.     {
  913.         // Regex to split up the file name into id, attributes and extension
  914.         $regex '(
  915.             (?:' preg_quote$this->properties['location'')
  916.             (?P<id>.*)
  917.             (?P<attr>(?:-[^-=]+=[^-]+)*)
  918.             -? # This is added if no attributes are supplied. For whatever reason...
  919.             (?P<ext>' preg_quote$this->options->extension ')
  920.         )Ux';
  921.  
  922.         if preg_match$regex$filename$matches !== )
  923.         {
  924.             // @TODO: Should this be an exception?
  925.             return array(
  926.                 'id'         => '',
  927.                 'attributes' => '',
  928.                 'extension'  => $this->options->extension,
  929.             );
  930.         }
  931.         else
  932.         {
  933.             // Successfully split
  934.             return array(
  935.                 'id'         => $matches['id'],
  936.                 'attributes' => $matches['attr'],
  937.                 'extension'  => $matches['ext'],
  938.             );
  939.         }
  940.     }
  941. }
  942. ?>
Documentation generated by phpDocumentor 1.4.3