fannie/classlib2.0/data/DataCache.php
<?php
/*******************************************************************************
Copyright 2013 Whole Foods Co-op
This file is part of CORE-POS.
IT CORE is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
IT CORE is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
in the file license.txt along with IT CORE; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*********************************************************************************/
namespace COREPOS\Fannie\API\data;
/**
@class DataCache
Store data for later. This is a more generic caching option
based on FannieReportPage. Data is automatically keyed by
URL (hint: use GET parameters instead of POST). In theory
you can cache any serializable data structure. It's typically
used for caching query results.
*/
class DataCache
{
/**
Generate default hash value for caching.
Uses request URI excluding output formatting options
@return md5 string
*/
static public function genKey()
{
$hash = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : $_SERVER['PHP_SELF'];
$hash = str_replace("&excel=xls", "", $hash);
$hash = str_replace("&excel=csv", "", $hash);
$hash = str_replace("&no-cache=1", "", $hash);
$hash = md5($hash);
return $hash;
}
/**
Look for cached data
Data is stored in the archive database, reportDataCache table.
The default key column is an MD5 hash of the current URL (minus the excel
parameter, if present). This means your forms should use type GET
if caching is enabled. If a key argument is provided, that key
is hashed instead.
The data is stored as a serialized, gzcompressed string.
*/
static public function check($key=false)
{
$FANNIE_ARCHIVE_DB = \FannieConfig::factory()->get('ARCHIVE_DB');
$dbc = \FannieDB::get($FANNIE_ARCHIVE_DB, $current_db);
$table = $FANNIE_ARCHIVE_DB.$dbc->sep()."reportDataCache";
$hash = $key ? $key : self::genKey();
$query = $dbc->prepare("SELECT report_data FROM $table WHERE
hash_key=? AND expires >= ".$dbc->now());
$result = $dbc->execute($query,array($hash));
if (!empty($current_db)) {
// restore selected database
$dbc = \FannieDB::get($current_db);
}
if ($dbc->num_rows($result) > 0) {
$ret = $dbc->fetch_row($result);
$serial = gzuncompress($ret[0]);
if ($serial === false) {
return false;
} else {
return unserialize($serial);
}
} else {
return false;
}
}
/**
Store data in the cache
@param $data the data
@param $ttl how long data is valid. Options are 'day' and 'month'
@param $key [optional] custom lookup key
@return True or False based on success
See check() for details
*/
static public function freshen($data, $ttl='day', $key=false)
{
$FANNIE_ARCHIVE_DB = \FannieConfig::factory()->get('ARCHIVE_DB');
$dbc = \FannieDB::get($FANNIE_ARCHIVE_DB, $current_db);
if ($ttl != 'day' && $ttl != 'month') {
return false;
}
$table = $FANNIE_ARCHIVE_DB.$dbc->sep()."reportDataCache";
$hash = $key ? $key : self::genKey();
$expires = '';
if ($ttl == 'day') {
$expires = date('Y-m-d',mktime(0,0,0,date('n'),date('j')+1,date('Y')));
} elseif ($ttl == 'month') {
$expires = date('Y-m-d',mktime(0,0,0,date('n')+1,date('j'),date('Y')));
}
$delQ = $dbc->prepare("DELETE FROM $table WHERE hash_key=?");
$dbc->execute($delQ,array($hash));
$saveStr = gzcompress(serialize($data));
$ret = true;
if (strlen($saveStr) > 65535) {
// too big to store, probably
$ret = false;
} else {
$upQ = $dbc->prepare("INSERT INTO $table (hash_key, report_data, expires)
VALUES (?,?,?)");
$dbc->execute($upQ, array($hash, $saveStr, $expires));
}
if (!empty($current_db)) {
// restore selected database
$dbc = \FannieDB::get($current_db);
}
return $ret;
}
/**
Get info from filesystem cache
@param $ttl [string] daily or monthly
@param $key [optional] use custom key
@return cached content or false
*/
static public function getFile($ttl, $key=false)
{
$type = self::validateTTL($ttl);
if ($type === false) {
return false;
}
$key = ($key !== false) ? md5($key) : self::genKey();
$cache_dir = self::fileCacheDir($type);
if ($cache_dir && file_exists($cache_dir . '/' . $key)) {
return file_get_contents($cache_dir . '/' . $key);
} else {
return false;
}
}
/**
Store info to filesystem cache
@param $ttl [string] monthly or daily
@param $content [string] content to cache
@param $key [optional] custom key
@return [boolean] true or false
*/
static public function putFile($ttl, $content, $key=false)
{
$type = self::validateTTL($ttl);
if ($type === false) {
return false;
}
$key = ($key !== false) ? md5($key) : self::genKey();
$cache_dir = self::fileCacheDir($type);
if ($cache_dir) {
$fp = fopen($cache_dir . '/' . $key, 'w');
fwrite($fp, $content);
fclose($fp);
return true;
} else {
return false;
}
}
static private function validateTTL($ttl)
{
$type = strtolower($ttl);
if ($type[0] == 'm') {
return 'monthly';
} elseif ($type[0] == 'd') {
return 'daily';
} elseif (strtolower($ttl) == 'forever') {
return 'forever';
} else {
return false;
}
}
/**
Get filesystem path for storing cache data
Auto-creates directories as needed
@param $type [string] monthly or daily
@return [string] path or false
*/
static public function fileCacheDir($type)
{
if ($type !== 'monthly' && $type !== 'daily' && $type !== 'forever') {
return false;
}
$tmp = sys_get_temp_dir();
if (!is_dir($tmp . '/fannie_cache/')) {
if (!mkdir($tmp . '/fannie_cache')) {
return false;
}
}
if (!is_dir($tmp . '/fannie_cache/' . $type)) {
if (!mkdir($tmp . '/fannie_cache/' . $type)) {
return false;
}
}
return realpath($tmp . '/fannie_cache/' . $type);
}
}