2 /////////////////////////////////////////////////////////////////
3 /// getID3() by James Heinrich <info@getid3.org> //
4 // available at https://github.com/JamesHeinrich/getID3 //
5 // or https://www.getid3.org //
6 // or http://getid3.sourceforge.net //
8 // extension.cache.mysqli.php - part of getID3() //
9 // Please see readme.txt for more information //
11 /////////////////////////////////////////////////////////////////
13 // extension.cache.sqlite3.php - part of getID3() //
14 // Please see readme.txt for more information //
16 /////////////////////////////////////////////////////////////////
18 // MySQL extension written by Allan Hansen <ahØartemis*dk> //
19 // Table name mod by Carlo Capocasa <calroØcarlocapocasa*com> //
20 // MySQL extension was reworked for SQLite3 by //
21 // Karl G. Holz <newaeonØmac*com> //
23 /////////////////////////////////////////////////////////////////
26 * This is a caching extension for getID3(). It works the exact same
27 * way as the getID3 class, but return cached information much faster
29 * Normal getID3 usage (example):
31 * require_once 'getid3/getid3.php';
32 * $getID3 = new getID3;
33 * $getID3->encoding = 'UTF-8';
34 * $info1 = $getID3->analyze('file1.flac');
35 * $info2 = $getID3->analyze('file2.wv');
37 * getID3_cached usage:
39 * require_once 'getid3/getid3.php';
40 * require_once 'getid3/extension.cache.sqlite3.php';
41 * // all parameters are optional, defaults are:
42 * $getID3 = new getID3_cached_sqlite3($table='getid3_cache', $hide=FALSE);
43 * $getID3->encoding = 'UTF-8';
44 * $info1 = $getID3->analyze('file1.flac');
45 * $info2 = $getID3->analyze('file2.wv');
48 * Supported Cache Types (this extension)
52 * cache_type cache_options
53 * -------------------------------------------------------------------
54 * mysql host, database, username, password
56 * sqlite3 table='getid3_cache', hide=false (PHP5)
59 * *** database file will be stored in the same directory as this script,
60 * *** webserver must have write access to that directory!
61 * *** set $hide to TRUE to prefix db file with .ht to pervent access from web client
62 * *** this is a default setting in the Apache configuration:
64 * The following lines prevent .htaccess and .htpasswd files from being viewed by Web clients.
72 ********************************************************************************
74 * -------------------------------------------------------------------
75 * DBM-Style Databases: (use extension.cache.dbm)
77 * cache_type cache_options
78 * -------------------------------------------------------------------
79 * gdbm dbm_filename, lock_filename
80 * ndbm dbm_filename, lock_filename
81 * db2 dbm_filename, lock_filename
82 * db3 dbm_filename, lock_filename
83 * db4 dbm_filename, lock_filename (PHP5 required)
85 * PHP must have write access to both dbm_filename and lock_filename.
87 * Recommended Cache Types
89 * Infrequent updates, many reads any DBM
90 * Frequent updates mysql
91 ********************************************************************************
93 * IMHO this is still a bit slow, I'm using this with MP4/MOV/ M4v files
94 * there is a plan to add directory scanning and analyzing to make things work much faster
98 class getID3_cached_sqlite3
extends getID3
103 * @var SQLite3 Resource
108 * table to use for caching
115 * @param string $table holds name of sqlite table
116 * @param boolean $hide
118 * @throws getid3_exception
121 public function __construct($table='getid3_cache', $hide=false) {
122 // Check for SQLite3 support
123 if (!function_exists('sqlite_open')) {
124 throw new Exception('PHP not compiled with SQLite3 support.');
127 $this->table
= $table; // Set table
128 $file = dirname(__FILE__
).'/'.basename(__FILE__
, 'php').'sqlite';
130 $file = dirname(__FILE__
).'/.ht.'.basename(__FILE__
, 'php').'sqlite';
132 $this->db
= new SQLite3($file);
134 $this->create_table(); // Create cache table if not exists
136 $sql = $this->getQuery('version_check');
137 $stmt = $db->prepare($sql);
138 $stmt->bindValue(':filename', getID3
::VERSION
, SQLITE3_TEXT
);
139 $result = $stmt->execute();
140 list($version) = $result->fetchArray();
141 if ($version != getID3
::VERSION
) { // Check version number and clear cache if changed
142 $this->clear_cache();
144 parent
::__construct();
148 * close the database connection
150 public function __destruct() {
158 * @return SQLite3Result
160 private function clear_cache() {
162 $sql = $this->getQuery('delete_cache');
164 $sql = $this->getQuery('set_version');
165 $stmt = $db->prepare($sql);
166 $stmt->bindValue(':filename', getID3
::VERSION
, SQLITE3_TEXT
);
167 $stmt->bindValue(':dirname', getID3
::VERSION
, SQLITE3_TEXT
);
168 $stmt->bindValue(':val', getID3
::VERSION
, SQLITE3_TEXT
);
169 return $stmt->execute();
173 * analyze file and cache them, if cached pull from the db
175 * @param string $filename
176 * @param integer $filesize
177 * @param string $original_filename
178 * @param resource $fp
180 * @return mixed|false
182 public function analyze($filename, $filesize=null, $original_filename='', $fp=null) {
183 if (!file_exists($filename)) {
186 // items to track for caching
187 $filetime = filemtime($filename);
188 $filesize_real = filesize($filename);
189 // this will be saved for a quick directory lookup of analized files
190 // ... why do 50 seperate sql quries when you can do 1 for the same result
191 $dirname = dirname($filename);
194 $sql = $this->getQuery('get_id3_data');
195 $stmt = $db->prepare($sql);
196 $stmt->bindValue(':filename', $filename, SQLITE3_TEXT
);
197 $stmt->bindValue(':filesize', $filesize_real, SQLITE3_INTEGER
);
198 $stmt->bindValue(':filetime', $filetime, SQLITE3_INTEGER
);
199 $res = $stmt->execute();
200 list($result) = $res->fetchArray();
201 if (count($result) > 0 ) {
202 return unserialize(base64_decode($result));
204 // if it hasn't been analyzed before, then do it now
205 $analysis = parent
::analyze($filename, $filesize, $original_filename, $fp);
207 $sql = $this->getQuery('cache_file');
208 $stmt = $db->prepare($sql);
209 $stmt->bindValue(':filename', $filename, SQLITE3_TEXT
);
210 $stmt->bindValue(':dirname', $dirname, SQLITE3_TEXT
);
211 $stmt->bindValue(':filesize', $filesize_real, SQLITE3_INTEGER
);
212 $stmt->bindValue(':filetime', $filetime, SQLITE3_INTEGER
);
213 $stmt->bindValue(':atime', time(), SQLITE3_INTEGER
);
214 $stmt->bindValue(':val', base64_encode(serialize($analysis)), SQLITE3_TEXT
);
215 $res = $stmt->execute();
220 * create data base table
221 * this is almost the same as MySQL, with the exception of the dirname being added
225 private function create_table() {
227 $sql = $this->getQuery('make_table');
228 return $db->exec($sql);
232 * get cached directory
234 * This function is not in the MySQL extention, it's ment to speed up requesting multiple files
235 * which is ideal for podcasting, playlists, etc.
237 * @param string $dir directory to search the cache database for
239 * @return array return an array of matching id3 data
241 public function get_cached_dir($dir) {
244 $sql = $this->getQuery('get_cached_dir');
245 $stmt = $db->prepare($sql);
246 $stmt->bindValue(':dirname', $dir, SQLITE3_TEXT
);
247 $res = $stmt->execute();
248 while ($row=$res->fetchArray()) {
249 $rows[] = unserialize(base64_decode($row));
255 * returns NULL if query is not found
257 * @param string $name
259 * @return null|string
261 public function getQuery($name)
264 case 'version_check':
265 return "SELECT val FROM $this->table WHERE filename = :filename AND filesize = '-1' AND filetime = '-1' AND analyzetime = '-1'";
267 return "DELETE FROM $this->table";
269 return "INSERT INTO $this->table (filename, dirname, filesize, filetime, analyzetime, val) VALUES (:filename, :dirname, -1, -1, -1, :val)";
271 return "SELECT val FROM $this->table WHERE filename = :filename AND filesize = :filesize AND filetime = :filetime";
273 return "INSERT INTO $this->table (filename, dirname, filesize, filetime, analyzetime, val) VALUES (:filename, :dirname, :filesize, :filetime, :atime, :val)";
275 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))";
276 case 'get_cached_dir':
277 return "SELECT val FROM $this->table WHERE dirname = :dirname";
284 * use the magical __get() for sql queries
286 * access as easy as $this->{case name}, returns NULL if query is not found
288 * @param string $name
291 * @deprecated use getQuery() instead
293 public function __get($name) {
294 return $this->getQuery($name);