astrXbian/www/jukebox/getid3/extension.cache.sqlite3.php

266 lines
9.4 KiB
PHP

<?php
/////////////////////////////////////////////////////////////////////////////////
/// getID3() by James Heinrich <info@getid3.org> //
// available at http://getid3.sourceforge.net //
// or http://www.getid3.org //
// also https://github.com/JamesHeinrich/getID3 //
/////////////////////////////////////////////////////////////////////////////////
/// //
// extension.cache.sqlite3.php - part of getID3() //
// Please see readme.txt for more information //
// ///
/////////////////////////////////////////////////////////////////////////////////
/// //
// MySQL extension written by Allan Hansen <ahØartemis*dk> //
// Table name mod by Carlo Capocasa <calroØcarlocapocasa*com> //
// MySQL extension was reworked for SQLite3 by Karl G. Holz <newaeonØmac*com> //
// ///
/////////////////////////////////////////////////////////////////////////////////
/**
* 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.
*
* <Files ~ "^\.ht">
* Order allow,deny
* Deny from all
* Satisfy all
* </Files>
*
********************************************************************************
*
* -------------------------------------------------------------------
* 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 {
/**
* __construct()
* @param string $table holds name of sqlite table
* @return type
*/
public function __construct($table='getid3_cache', $hide=false) {
$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->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();
}
return parent::__construct();
}
/**
* close the database connection
*/
public function __destruct() {
$db=$this->db;
$db->close();
}
/**
* hold the sqlite db
* @var SQLite Resource
*/
private $db;
/**
* table to use for caching
* @var string $table
*/
private $table;
/**
* clear the cache
* @access private
* @return type
*/
private function clear_cache() {
$db = $this->db;
$sql = $this->delete_cache;
$db->exec($sql);
$sql = $this->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 type $filename
* @return boolean
*/
public function analyze($filename, $filesize=null, $original_filename='') {
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->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);
// Save result
$sql = $this->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 type
*/
private function create_table() {
$db = $this->db;
$sql = $this->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.
*
* @access public
* @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->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;
}
/**
* use the magical __get() for sql queries
*
* access as easy as $this->{case name}, returns NULL if query is not found
*/
public function __get($name) {
switch($name) {
case 'version_check':
return "SELECT val FROM $this->table WHERE filename = :filename AND filesize = '-1' AND filetime = '-1' AND analyzetime = '-1'";
break;
case 'delete_cache':
return "DELETE FROM $this->table";
break;
case 'set_version':
return "INSERT INTO $this->table (filename, dirname, filesize, filetime, analyzetime, val) VALUES (:filename, :dirname, -1, -1, -1, :val)";
break;
case 'get_id3_data':
return "SELECT val FROM $this->table WHERE filename = :filename AND filesize = :filesize AND filetime = :filetime";
break;
case 'cache_file':
return "INSERT INTO $this->table (filename, dirname, filesize, filetime, analyzetime, val) VALUES (:filename, :dirname, :filesize, :filetime, :atime, :val)";
break;
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))";
break;
case 'get_cached_dir':
return "SELECT val FROM $this->table WHERE dirname = :dirname";
break;
}
return null;
}
}