// // available at https://github.com/JamesHeinrich/getID3 // // or https://www.getid3.org // // or http://getid3.sourceforge.net // // // // extension.cache.mysqli.php - part of getID3() // // Please see readme.txt for more information // // // ///////////////////////////////////////////////////////////////// // // // extension.cache.sqlite3.php - part of getID3() // // Please see readme.txt for more information // // // ///////////////////////////////////////////////////////////////// /// // // MySQL extension written by Allan Hansen // // Table name mod by Carlo Capocasa // // MySQL extension was reworked for SQLite3 by // // Karl G. Holz // // /// ///////////////////////////////////////////////////////////////// /** * This is a caching extension for getID3(). It works the exact same * way as the getID3 class, but return cached information much faster * * Normal getID3 usage (example): * * require_once 'getid3/getid3.php'; * $getID3 = new getID3; * $getID3->encoding = 'UTF-8'; * $info1 = $getID3->analyze('file1.flac'); * $info2 = $getID3->analyze('file2.wv'); * * getID3_cached usage: * * require_once 'getid3/getid3.php'; * require_once 'getid3/extension.cache.sqlite3.php'; * // all parameters are optional, defaults are: * $getID3 = new getID3_cached_sqlite3($table='getid3_cache', $hide=FALSE); * $getID3->encoding = 'UTF-8'; * $info1 = $getID3->analyze('file1.flac'); * $info2 = $getID3->analyze('file2.wv'); * * * Supported Cache Types (this extension) * * SQL Databases: * * cache_type cache_options * ------------------------------------------------------------------- * mysql host, database, username, password * * sqlite3 table='getid3_cache', hide=false (PHP5) * * * *** database file will be stored in the same directory as this script, * *** webserver must have write access to that directory! * *** set $hide to TRUE to prefix db file with .ht to pervent access from web client * *** this is a default setting in the Apache configuration: * * The following lines prevent .htaccess and .htpasswd files from being viewed by Web clients. * * * Order allow,deny * Deny from all * Satisfy all * * ******************************************************************************** * * ------------------------------------------------------------------- * DBM-Style Databases: (use extension.cache.dbm) * * cache_type cache_options * ------------------------------------------------------------------- * gdbm dbm_filename, lock_filename * ndbm dbm_filename, lock_filename * db2 dbm_filename, lock_filename * db3 dbm_filename, lock_filename * db4 dbm_filename, lock_filename (PHP5 required) * * PHP must have write access to both dbm_filename and lock_filename. * * Recommended Cache Types * * Infrequent updates, many reads any DBM * Frequent updates mysql ******************************************************************************** * * IMHO this is still a bit slow, I'm using this with MP4/MOV/ M4v files * there is a plan to add directory scanning and analyzing to make things work much faster * * */ class getID3_cached_sqlite3 extends getID3 { /** * hold the sqlite db * * @var SQLite3 Resource */ private $db; /** * table to use for caching * * @var string $table */ private $table; /** * @param string $table holds name of sqlite table * @param boolean $hide * * @throws getid3_exception * @throws Exception */ public function __construct($table='getid3_cache', $hide=false) { // Check for SQLite3 support if (!function_exists('sqlite_open')) { throw new Exception('PHP not compiled with SQLite3 support.'); } $this->table = $table; // Set table $file = dirname(__FILE__).'/'.basename(__FILE__, 'php').'sqlite'; if ($hide) { $file = dirname(__FILE__).'/.ht.'.basename(__FILE__, 'php').'sqlite'; } $this->db = new SQLite3($file); $db = $this->db; $this->create_table(); // Create cache table if not exists $version = ''; $sql = $this->getQuery('version_check'); $stmt = $db->prepare($sql); $stmt->bindValue(':filename', getID3::VERSION, SQLITE3_TEXT); $result = $stmt->execute(); list($version) = $result->fetchArray(); if ($version != getID3::VERSION) { // Check version number and clear cache if changed $this->clear_cache(); } parent::__construct(); } /** * close the database connection */ public function __destruct() { $db=$this->db; $db->close(); } /** * clear the cache * * @return SQLite3Result */ private function clear_cache() { $db = $this->db; $sql = $this->getQuery('delete_cache'); $db->exec($sql); $sql = $this->getQuery('set_version'); $stmt = $db->prepare($sql); $stmt->bindValue(':filename', getID3::VERSION, SQLITE3_TEXT); $stmt->bindValue(':dirname', getID3::VERSION, SQLITE3_TEXT); $stmt->bindValue(':val', getID3::VERSION, SQLITE3_TEXT); return $stmt->execute(); } /** * analyze file and cache them, if cached pull from the db * * @param string $filename * @param integer $filesize * @param string $original_filename * @param resource $fp * * @return mixed|false */ public function analyze($filename, $filesize=null, $original_filename='', $fp=null) { if (!file_exists($filename)) { return false; } // items to track for caching $filetime = filemtime($filename); $filesize_real = filesize($filename); // this will be saved for a quick directory lookup of analized files // ... why do 50 seperate sql quries when you can do 1 for the same result $dirname = dirname($filename); // Lookup file $db = $this->db; $sql = $this->getQuery('get_id3_data'); $stmt = $db->prepare($sql); $stmt->bindValue(':filename', $filename, SQLITE3_TEXT); $stmt->bindValue(':filesize', $filesize_real, SQLITE3_INTEGER); $stmt->bindValue(':filetime', $filetime, SQLITE3_INTEGER); $res = $stmt->execute(); list($result) = $res->fetchArray(); if (count($result) > 0 ) { return unserialize(base64_decode($result)); } // if it hasn't been analyzed before, then do it now $analysis = parent::analyze($filename, $filesize, $original_filename, $fp); // Save result $sql = $this->getQuery('cache_file'); $stmt = $db->prepare($sql); $stmt->bindValue(':filename', $filename, SQLITE3_TEXT); $stmt->bindValue(':dirname', $dirname, SQLITE3_TEXT); $stmt->bindValue(':filesize', $filesize_real, SQLITE3_INTEGER); $stmt->bindValue(':filetime', $filetime, SQLITE3_INTEGER); $stmt->bindValue(':atime', time(), SQLITE3_INTEGER); $stmt->bindValue(':val', base64_encode(serialize($analysis)), SQLITE3_TEXT); $res = $stmt->execute(); return $analysis; } /** * create data base table * this is almost the same as MySQL, with the exception of the dirname being added * * @return bool */ private function create_table() { $db = $this->db; $sql = $this->getQuery('make_table'); return $db->exec($sql); } /** * get cached directory * * This function is not in the MySQL extention, it's ment to speed up requesting multiple files * which is ideal for podcasting, playlists, etc. * * @param string $dir directory to search the cache database for * * @return array return an array of matching id3 data */ public function get_cached_dir($dir) { $db = $this->db; $rows = array(); $sql = $this->getQuery('get_cached_dir'); $stmt = $db->prepare($sql); $stmt->bindValue(':dirname', $dir, SQLITE3_TEXT); $res = $stmt->execute(); while ($row=$res->fetchArray()) { $rows[] = unserialize(base64_decode($row)); } return $rows; } /** * returns NULL if query is not found * * @param string $name * * @return null|string */ public function getQuery($name) { switch ($name) { case 'version_check': return "SELECT val FROM $this->table WHERE filename = :filename AND filesize = '-1' AND filetime = '-1' AND analyzetime = '-1'"; case 'delete_cache': return "DELETE FROM $this->table"; case 'set_version': return "INSERT INTO $this->table (filename, dirname, filesize, filetime, analyzetime, val) VALUES (:filename, :dirname, -1, -1, -1, :val)"; case 'get_id3_data': return "SELECT val FROM $this->table WHERE filename = :filename AND filesize = :filesize AND filetime = :filetime"; case 'cache_file': return "INSERT INTO $this->table (filename, dirname, filesize, filetime, analyzetime, val) VALUES (:filename, :dirname, :filesize, :filetime, :atime, :val)"; case 'make_table': return "CREATE TABLE IF NOT EXISTS $this->table (filename VARCHAR(255) DEFAULT '', dirname VARCHAR(255) DEFAULT '', filesize INT(11) DEFAULT '0', filetime INT(11) DEFAULT '0', analyzetime INT(11) DEFAULT '0', val text, PRIMARY KEY (filename, filesize, filetime))"; case 'get_cached_dir': return "SELECT val FROM $this->table WHERE dirname = :dirname"; default: return null; } } /** * use the magical __get() for sql queries * * access as easy as $this->{case name}, returns NULL if query is not found * * @param string $name * * @return string * @deprecated use getQuery() instead */ public function __get($name) { return $this->getQuery($name); } }