feat: add videodb media index with Docker stack
- Add videodb PHP/MySQL media collection manager (Blu-ray, DVD, CD) - Dockerfile: PHP 8.1 + Apache with GD/mysqli/exif extensions - docker-compose.yml: app on port 6761 + MySQL 8.0 with health checks - docker-entrypoint.sh: auto-generates config.inc.php from env vars, waits for MySQL, initializes DB schema idempotently - init-db.php: CLI schema installer using app's own prefix_query() logic - Persistent volumes for DB, cache, and cover images Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
196
videodb/core/cache.php
Normal file
196
videodb/core/cache.php
Normal file
@@ -0,0 +1,196 @@
|
||||
<?php
|
||||
/**
|
||||
* File caching functions
|
||||
*
|
||||
* @package Core
|
||||
* @author Andreas Goetz <cpuidle@gmx.de>
|
||||
* @version $Id: cache.php,v 1.11 2013/04/26 15:09:35 andig2 Exp $
|
||||
*/
|
||||
|
||||
// define cache folder
|
||||
if (!defined('CACHE')) define('CACHE', 'cache');
|
||||
|
||||
/**
|
||||
* Get the hashed filename
|
||||
*
|
||||
* @param string url of the item
|
||||
* @param string $cache_folder name ob the sub-cache to adress
|
||||
* @param string ext file extension of the cache file
|
||||
*/
|
||||
function cache_get_filename($url, $cache_folder, $ext = '')
|
||||
{
|
||||
$hash = md5($url) . (($ext) ? '.'.$ext : '');
|
||||
$cache_file = cache_get_folder($cache_folder, $hash) . $hash;
|
||||
|
||||
return $cache_file;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get name of the cache folder
|
||||
*
|
||||
* @TODO decouple from global config options
|
||||
*
|
||||
* @param string $cache_folder name ob the sub-cache to adress
|
||||
* @param string $cache_filename name of the item to be cached for use with hierarchical caches
|
||||
* @return string cache folder path including trailing /
|
||||
*/
|
||||
function cache_get_folder($cache_folder, $cache_filename = '')
|
||||
{
|
||||
global $config;
|
||||
|
||||
$cache_folder = CACHE.'/' .
|
||||
(($cache_folder) ? $cache_folder.'/' : '');
|
||||
|
||||
if ($cache_filename)
|
||||
$cache_folder .= substr($cache_filename, 0, @(int)$config['hierarchical']).'/';
|
||||
|
||||
return $cache_folder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleanup a single cache folder
|
||||
*
|
||||
* @param string $cache_folder path to cache folder
|
||||
* @param int $cache_max_age maximum age of cached items in seconds
|
||||
* @param bool $force_prune force cache pruning even if not due according to schedule
|
||||
*/
|
||||
function cache_prune_folder($cache_folder, $cache_max_age, $force_prune = false, $simulate = false, $pattern = '*')
|
||||
{
|
||||
if (!preg_match('#/$#', $cache_folder)) $cache_folder .= '/';
|
||||
$stamp = $cache_folder.'cache_last_purge';
|
||||
$cache_mtime = @filemtime($stamp); // get time the cache was last purged (once a day)
|
||||
|
||||
// if cache was last purged a day or more ago
|
||||
if ($force_prune || ((time() - $cache_mtime) > ($cache_max_age / 24))) # 86400)
|
||||
{
|
||||
foreach (glob($cache_folder.$pattern, GLOB_NOSORT) as $file)
|
||||
{
|
||||
// avoid hidden files and directories
|
||||
if (is_file($file) &! preg_match("/^\./", $file) && time() - filemtime($file) > $cache_max_age)
|
||||
{
|
||||
if ($simulate)
|
||||
$files[] = $file; // add to list of potentially purged files
|
||||
else
|
||||
@unlink($file); // purge cache
|
||||
}
|
||||
}
|
||||
|
||||
if ($simulate) return $files;
|
||||
|
||||
@touch($stamp); // mark purge as having occurred
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleanup a cache folder hierarchy
|
||||
*
|
||||
* @TODO decouple from global config options
|
||||
*
|
||||
* @param string $cache_folder path to cache folder
|
||||
* @param int $cache_max_age maximum age of cached items in seconds
|
||||
* @param bool $force_prune force cache pruning even if not due according to schedule
|
||||
*/
|
||||
function cache_prune_folders($cache_folder, $cache_max_age, $force_prune = false, $simulate = false, $pattern = '*', $levels = 0)
|
||||
{
|
||||
global $config;
|
||||
|
||||
// root folder
|
||||
cache_prune_folder($cache_folder, $cache_max_age, $force_prune, $simulate, $pattern, $levels);
|
||||
|
||||
// descent hierarchy
|
||||
if ($levels > 0)
|
||||
{
|
||||
if (!isset($error))
|
||||
{
|
||||
$error = '';
|
||||
}
|
||||
for ($i=0; $i<16; $i++)
|
||||
$error .= cache_prune_folders($cache_folder.dechex($i).'/', $cache_max_age, $force_prune, $simulate, $pattern, $levels-1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create cache folders
|
||||
*
|
||||
* Check individual cache folder for existance, check if folder is writable and create folder if it doesn't exist
|
||||
*/
|
||||
function cache_create_folders($dir, $levels = 0)
|
||||
{
|
||||
$error = '';
|
||||
if (!is_dir($dir))
|
||||
{
|
||||
if (!@mkdir($dir, 0700)) $error = 'Directory <code>'.$dir.'</code> does not exist.<br/>';
|
||||
}
|
||||
elseif (!is_writable($dir))
|
||||
{
|
||||
$error = 'Directory <code>'.$dir.'</code> is not writable.<br/>';
|
||||
}
|
||||
|
||||
// check hierarchical folders
|
||||
if (empty($error) && ($levels > 0))
|
||||
{
|
||||
for ($i=0; $i<16; $i++)
|
||||
$error .= cache_create_folders($dir.'/'.dechex($i), $levels-1);
|
||||
}
|
||||
|
||||
return $error;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify existance of cached file for given url/ extension
|
||||
*
|
||||
* @author Andreas Goetz <cpuidle@gmx.de>
|
||||
* @param string url of the item
|
||||
* @param string ext file extension of the cache file
|
||||
* @param string file result: URL to the cached image if exists
|
||||
* @return bool result of check
|
||||
*/
|
||||
function cache_file_exists($url, &$cache_file, $cache_folder, $ext = '')
|
||||
{
|
||||
$cache_file = cache_get_filename($url, $cache_folder, $ext);
|
||||
// Small performance fix
|
||||
$result = file_exists($cache_file) && filesize($cache_file);
|
||||
# $result = filesize($cache_file) > 0;
|
||||
|
||||
return($result);
|
||||
}
|
||||
|
||||
function cache_get($url, $cache_folder, $cache_max_age, $serialize = false)
|
||||
{
|
||||
$data = false;
|
||||
|
||||
if ($cache_max_age > 0)
|
||||
{
|
||||
if (cache_file_exists($url, $cache_file, $cache_folder))
|
||||
{
|
||||
if (time() - filemtime($cache_file) < $cache_max_age)
|
||||
{
|
||||
$data = file_get_contents($cache_file);
|
||||
if (($data !== false) && $serialize) $data = unserialize($data);
|
||||
}
|
||||
// TODO Check if outdated cache files should really be auto-deleted
|
||||
else @unlink($cache_file);
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
function cache_put($url, $data, $cache_folder, $cache_max_age, $serialize = false)
|
||||
{
|
||||
// only put file to cache if caching is enabled
|
||||
if ($cache_max_age > 0)
|
||||
{
|
||||
// get the cache file name
|
||||
$cache_file = cache_get_filename($url, $cache_folder);
|
||||
|
||||
// commit to disk
|
||||
if ($serialize) $data = serialize($data);
|
||||
file_put_contents($cache_file, $data);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
Reference in New Issue
Block a user