1 <?php
  2 /**
  3  * @package     Joomla.Platform
  4  * @subpackage  Cache
  5  *
  6  * @copyright   Copyright (C) 2005 - 2017 Open Source Matters, Inc. All rights reserved.
  7  * @license     GNU General Public License version 2 or later; see LICENSE
  8  */
  9 
 10 defined('JPATH_PLATFORM') or die;
 11 
 12 /**
 13  * XCache cache storage handler
 14  *
 15  * @link   http://xcache.lighttpd.net/
 16  * @since  11.1
 17  */
 18 class JCacheStorageXcache extends JCacheStorage
 19 {
 20     /**
 21      * Check if the cache contains data stored by ID and group
 22      *
 23      * @param   string  $id     The cache data ID
 24      * @param   string  $group  The cache data group
 25      *
 26      * @return  boolean
 27      *
 28      * @since   3.7.0
 29      */
 30     public function contains($id, $group)
 31     {
 32         return xcache_isset($this->_getCacheId($id, $group));
 33     }
 34 
 35     /**
 36      * Get cached data by ID and group
 37      *
 38      * @param   string   $id         The cache data ID
 39      * @param   string   $group      The cache data group
 40      * @param   boolean  $checkTime  True to verify cache time expiration threshold
 41      *
 42      * @return  mixed  Boolean false on failure or a cached data object
 43      *
 44      * @since   11.1
 45      */
 46     public function get($id, $group, $checkTime = true)
 47     {
 48         // Make sure XCache is configured properly
 49         if (static::isSupported() == false)
 50         {
 51             return false;
 52         }
 53 
 54         $cache_id = $this->_getCacheId($id, $group);
 55         $cache_content = xcache_get($cache_id);
 56 
 57         if ($cache_content === null)
 58         {
 59             return false;
 60         }
 61 
 62         return $cache_content;
 63     }
 64 
 65     /**
 66      * Get all cached data
 67      *
 68      * @return  mixed  Boolean false on failure or a cached data object
 69      *
 70      * @since   11.1
 71      * @note    This requires the php.ini setting xcache.admin.enable_auth = Off.
 72      */
 73     public function getAll()
 74     {
 75         // Make sure XCache is configured properly
 76         if (static::isSupported() == false)
 77         {
 78             return array();
 79         }
 80 
 81         $allinfo = xcache_list(XC_TYPE_VAR, 0);
 82         $keys    = $allinfo['cache_list'];
 83         $secret  = $this->_hash;
 84 
 85         $data = array();
 86 
 87         foreach ($keys as $key)
 88         {
 89             $namearr = explode('-', $key['name']);
 90 
 91             if ($namearr !== false && $namearr[0] == $secret && $namearr[1] == 'cache')
 92             {
 93                 $group = $namearr[2];
 94 
 95                 if (!isset($data[$group]))
 96                 {
 97                     $item = new JCacheStorageHelper($group);
 98                 }
 99                 else
100                 {
101                     $item = $data[$group];
102                 }
103 
104                 $item->updateSize($key['size']);
105 
106                 $data[$group] = $item;
107             }
108         }
109 
110         return $data;
111     }
112 
113     /**
114      * Store the data to cache by ID and group
115      *
116      * @param   string  $id     The cache data ID
117      * @param   string  $group  The cache data group
118      * @param   string  $data   The data to store in cache
119      *
120      * @return  boolean
121      *
122      * @since   11.1
123      */
124     public function store($id, $group, $data)
125     {
126         // Make sure XCache is configured properly
127         if (static::isSupported() == false)
128         {
129             return false;
130         }
131 
132         return xcache_set($this->_getCacheId($id, $group), $data, $this->_lifetime);
133     }
134 
135     /**
136      * Remove a cached data entry by ID and group
137      *
138      * @param   string  $id     The cache data ID
139      * @param   string  $group  The cache data group
140      *
141      * @return  boolean
142      *
143      * @since   11.1
144      */
145     public function remove($id, $group)
146     {
147         // Make sure XCache is configured properly
148         if (static::isSupported() == false)
149         {
150             return false;
151         }
152 
153         $cache_id = $this->_getCacheId($id, $group);
154 
155         if (!xcache_isset($cache_id))
156         {
157             return true;
158         }
159 
160         return xcache_unset($cache_id);
161     }
162 
163     /**
164      * Clean cache for a group given a mode.
165      *
166      * group mode    : cleans all cache in the group
167      * notgroup mode : cleans all cache not in the group
168      *
169      * @param   string  $group  The cache data group
170      * @param   string  $mode   The mode for cleaning cache [group|notgroup]
171      *
172      * @return  boolean
173      *
174      * @since   11.1
175      */
176     public function clean($group, $mode = null)
177     {
178         // Make sure XCache is configured properly
179         if (static::isSupported() == false)
180         {
181             return true;
182         }
183 
184         $allinfo = xcache_list(XC_TYPE_VAR, 0);
185         $keys    = $allinfo['cache_list'];
186         $secret  = $this->_hash;
187 
188         foreach ($keys as $key)
189         {
190             if (strpos($key['name'], $secret . '-cache-' . $group . '-') === 0 xor $mode != 'group')
191             {
192                 xcache_unset($key['name']);
193             }
194         }
195 
196         return true;
197     }
198 
199     /**
200      * Test to see if the storage handler is available.
201      *
202      * @return  boolean
203      *
204      * @since   12.1
205      */
206     public static function isSupported()
207     {
208         if (extension_loaded('xcache'))
209         {
210             // XCache Admin must be disabled for Joomla to use XCache
211             $xcache_admin_enable_auth = ini_get('xcache.admin.enable_auth');
212 
213             // Some extensions ini variables are reported as strings
214             if ($xcache_admin_enable_auth == 'Off')
215             {
216                 return true;
217             }
218 
219             // We require a string with contents 0, not a null value because it is not set since that then defaults to On/True
220             if ($xcache_admin_enable_auth === '0')
221             {
222                 return true;
223             }
224 
225             // In some enviorments empty is equivalent to Off; See JC: #34044 && Github: #4083
226             if ($xcache_admin_enable_auth === '')
227             {
228                 return true;
229             }
230         }
231 
232         // If the settings are not correct, give up
233         return false;
234     }
235 }
236