1<?php 2/** 3 * Copyright 2011-2017 Horde LLC (http://www.horde.org/) 4 * 5 * See the enclosed file COPYING for license information (LGPL). If you 6 * did not receive this file, see http://www.horde.org/licenses/lgpl21. 7 * 8 * @author Jan Schneider <jan@horde.org> 9 * @author Michael Slusarz <slusarz@horde.org> 10 * @category Horde 11 * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 12 * @package Autoloader_Cache 13 */ 14 15/** 16 * Bootstrap cache storage driver. 17 * 18 * Used for caching autoloader data before the full autoloader environment is 19 * setup. Transparently compresses the data if possible also. 20 * 21 * @author Jan Schneider <jan@horde.org> 22 * @author Michael Slusarz <slusarz@horde.org> 23 * @category Horde 24 * @copyright 2011-2017 Horde LLC 25 * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 26 * @package Autoloader_Cache 27 * @since 2.1.0 28 */ 29class Horde_Autoloader_Cache_Bootstrap 30{ 31 /* Cache types. */ 32 const APC = 1; 33 const XCACHE = 2; 34 const EACCELERATOR = 4; 35 const TEMPFILE = 8; 36 37 /* Compress types. */ 38 const LZ4 = 16; 39 const LZF = 32; 40 41 /* Serialize types. */ 42 const MSGPACK = 64; 43 const JSON = 128; 44 45 /** 46 * The storage parameters mask. 47 * 48 * @var array 49 */ 50 protected $_mask = 0; 51 52 /** 53 * Temporary directory. 54 * 55 * @var string 56 */ 57 protected $_tempdir; 58 59 /** 60 * Constructor. 61 * 62 * @param array $opts Options: 63 * - tempdir: (string) Use this path as the temporary directory. 64 */ 65 public function __construct(array $opts = array()) 66 { 67 if (extension_loaded('apc')) { 68 $this->_mask |= self::APC; 69 } elseif (extension_loaded('xcache')) { 70 $this->_mask |= self::XCACHE; 71 } elseif (extension_loaded('eaccelerator')) { 72 $this->_mask |= self::EACCELERATOR; 73 } else{ 74 $tempdir = isset($opts['tempdir']) 75 ? $opts['tempdir'] 76 : sys_get_temp_dir(); 77 if (is_readable($tempdir)) { 78 $this->_tempdir = $tempdir; 79 $this->_mask |= self::TEMPFILE; 80 } 81 } 82 83 if (extension_loaded('horde_lz4')) { 84 $this->_mask |= self::LZ4; 85 } elseif (extension_loaded('lzf')) { 86 $this->_mask |= self::LZF; 87 } 88 89 $this->_mask |= extension_loaded('msgpack') 90 ? self::MSGPACK 91 : self::JSON; 92 } 93 94 /** 95 * Return cached data. 96 * 97 * @param string $key Cache key. 98 * 99 * @return mixed Cache data, or false if not found. 100 */ 101 public function get($key) 102 { 103 if ($this->_mask & self::APC) { 104 $data = apc_fetch($key); 105 } elseif ($this->_mask & self::XCACHE) { 106 $data = xcache_get($key); 107 } elseif ($this->_mask & self::EACCELERATOR) { 108 $data = eaccelerator_get($key); 109 } elseif ($this->_mask & self::TEMPFILE) { 110 $data = @file_get_contents($this->_tempdir . '/' . $key); 111 if ($data === false) { 112 unlink($this->_tempdir . '/' . $key); 113 } 114 } else { 115 return false; 116 } 117 118 if ($data) { 119 if ($this->_mask & self::LZ4) { 120 $data = @horde_lz4_uncompress($data); 121 } elseif ($this->_mask & self::LZF) { 122 $data = @lzf_decompress($data); 123 } 124 } 125 126 return ($data === false) 127 ? false 128 : ($this->_mask & self::MSGPACK) 129 ? msgpack_unpack($data) 130 : @json_decode($data, true); 131 } 132 133 /** 134 * Set cached data. 135 * 136 * @param string $key Cache key. 137 * @param mixed $data Data to store. 138 * 139 * @return boolean True on success, false on failure. 140 */ 141 public function set($key, $data) 142 { 143 $data = ($this->_mask & self::MSGPACK) 144 ? msgpack_pack($data) 145 : json_encode($data); 146 147 if ($this->_mask & self::LZ4) { 148 $data = @horde_lz4_compress($data); 149 } elseif ($this->_mask & self::LZF) { 150 $data = lzf_compress($data); 151 } 152 153 if ($this->_mask & self::APC) { 154 return apc_store($key, $data); 155 } elseif ($this->_mask & self::XCACHE) { 156 return xcache_set($key, $data); 157 } elseif ($this->_mask & self::EACCELERATOR) { 158 eaccelerator_put($key, $data); 159 return true; 160 } elseif ($this->_mask & self::TEMPFILE) { 161 return file_put_contents($this->_tempdir . '/' . $key, $data); 162 } 163 164 return false; 165 } 166 167 /** 168 * Delete a key. 169 * 170 * @param string $key Cache key. 171 */ 172 public function delete($key) 173 { 174 if ($this->_mask & self::APC) { 175 apc_delete($key); 176 } elseif ($this->_mask & self::XCACHE) { 177 xcache_unset($key); 178 } elseif ($this->_mask & self::EACCELERATOR) { 179 eaccelerator_rm($key); 180 } elseif ($this->_mask & self::TEMPFILE) { 181 @unlink($this->_tempdir . '/' . $key); 182 } 183 } 184 185} 186