9e4a843692fbb8ddbef2026f5faeda689045a71d
[lhc/web/www.git] / www / plugins-dist / medias / lib / getid3 / extension.cache.sqlite3.php
1 <?php
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 //
7 // //
8 // extension.cache.mysqli.php - part of getID3() //
9 // Please see readme.txt for more information //
10 // //
11 /////////////////////////////////////////////////////////////////
12 // //
13 // extension.cache.sqlite3.php - part of getID3() //
14 // Please see readme.txt for more information //
15 // //
16 /////////////////////////////////////////////////////////////////
17 /// //
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> //
22 // ///
23 /////////////////////////////////////////////////////////////////
24
25 /**
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
28 *
29 * Normal getID3 usage (example):
30 *
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');
36 *
37 * getID3_cached usage:
38 *
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');
46 *
47 *
48 * Supported Cache Types (this extension)
49 *
50 * SQL Databases:
51 *
52 * cache_type cache_options
53 * -------------------------------------------------------------------
54 * mysql host, database, username, password
55 *
56 * sqlite3 table='getid3_cache', hide=false (PHP5)
57 *
58 *
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:
63 *
64 * The following lines prevent .htaccess and .htpasswd files from being viewed by Web clients.
65 *
66 * <Files ~ "^\.ht">
67 * Order allow,deny
68 * Deny from all
69 * Satisfy all
70 * </Files>
71 *
72 ********************************************************************************
73 *
74 * -------------------------------------------------------------------
75 * DBM-Style Databases: (use extension.cache.dbm)
76 *
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)
84 *
85 * PHP must have write access to both dbm_filename and lock_filename.
86 *
87 * Recommended Cache Types
88 *
89 * Infrequent updates, many reads any DBM
90 * Frequent updates mysql
91 ********************************************************************************
92 *
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
95 *
96 *
97 */
98 class getID3_cached_sqlite3 extends getID3
99 {
100 /**
101 * hold the sqlite db
102 *
103 * @var SQLite3 Resource
104 */
105 private $db;
106
107 /**
108 * table to use for caching
109 *
110 * @var string $table
111 */
112 private $table;
113
114 /**
115 * @param string $table holds name of sqlite table
116 * @param boolean $hide
117 *
118 * @throws getid3_exception
119 * @throws Exception
120 */
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.');
125 }
126
127 $this->table = $table; // Set table
128 $file = dirname(__FILE__).'/'.basename(__FILE__, 'php').'sqlite';
129 if ($hide) {
130 $file = dirname(__FILE__).'/.ht.'.basename(__FILE__, 'php').'sqlite';
131 }
132 $this->db = new SQLite3($file);
133 $db = $this->db;
134 $this->create_table(); // Create cache table if not exists
135 $version = '';
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();
143 }
144 parent::__construct();
145 }
146
147 /**
148 * close the database connection
149 */
150 public function __destruct() {
151 $db=$this->db;
152 $db->close();
153 }
154
155 /**
156 * clear the cache
157 *
158 * @return SQLite3Result
159 */
160 private function clear_cache() {
161 $db = $this->db;
162 $sql = $this->getQuery('delete_cache');
163 $db->exec($sql);
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();
170 }
171
172 /**
173 * analyze file and cache them, if cached pull from the db
174 *
175 * @param string $filename
176 * @param integer $filesize
177 * @param string $original_filename
178 *
179 * @return mixed|false
180 */
181 public function analyze($filename, $filesize=null, $original_filename='') {
182 if (!file_exists($filename)) {
183 return false;
184 }
185 // items to track for caching
186 $filetime = filemtime($filename);
187 $filesize_real = filesize($filename);
188 // this will be saved for a quick directory lookup of analized files
189 // ... why do 50 seperate sql quries when you can do 1 for the same result
190 $dirname = dirname($filename);
191 // Lookup file
192 $db = $this->db;
193 $sql = $this->getQuery('get_id3_data');
194 $stmt = $db->prepare($sql);
195 $stmt->bindValue(':filename', $filename, SQLITE3_TEXT);
196 $stmt->bindValue(':filesize', $filesize_real, SQLITE3_INTEGER);
197 $stmt->bindValue(':filetime', $filetime, SQLITE3_INTEGER);
198 $res = $stmt->execute();
199 list($result) = $res->fetchArray();
200 if (count($result) > 0 ) {
201 return unserialize(base64_decode($result));
202 }
203 // if it hasn't been analyzed before, then do it now
204 $analysis = parent::analyze($filename, $filesize, $original_filename);
205 // Save result
206 $sql = $this->getQuery('cache_file');
207 $stmt = $db->prepare($sql);
208 $stmt->bindValue(':filename', $filename, SQLITE3_TEXT);
209 $stmt->bindValue(':dirname', $dirname, SQLITE3_TEXT);
210 $stmt->bindValue(':filesize', $filesize_real, SQLITE3_INTEGER);
211 $stmt->bindValue(':filetime', $filetime, SQLITE3_INTEGER);
212 $stmt->bindValue(':atime', time(), SQLITE3_INTEGER);
213 $stmt->bindValue(':val', base64_encode(serialize($analysis)), SQLITE3_TEXT);
214 $res = $stmt->execute();
215 return $analysis;
216 }
217
218 /**
219 * create data base table
220 * this is almost the same as MySQL, with the exception of the dirname being added
221 *
222 * @return bool
223 */
224 private function create_table() {
225 $db = $this->db;
226 $sql = $this->getQuery('make_table');
227 return $db->exec($sql);
228 }
229
230 /**
231 * get cached directory
232 *
233 * This function is not in the MySQL extention, it's ment to speed up requesting multiple files
234 * which is ideal for podcasting, playlists, etc.
235 *
236 * @param string $dir directory to search the cache database for
237 *
238 * @return array return an array of matching id3 data
239 */
240 public function get_cached_dir($dir) {
241 $db = $this->db;
242 $rows = array();
243 $sql = $this->getQuery('get_cached_dir');
244 $stmt = $db->prepare($sql);
245 $stmt->bindValue(':dirname', $dir, SQLITE3_TEXT);
246 $res = $stmt->execute();
247 while ($row=$res->fetchArray()) {
248 $rows[] = unserialize(base64_decode($row));
249 }
250 return $rows;
251 }
252
253 /**
254 * returns NULL if query is not found
255 *
256 * @param string $name
257 *
258 * @return null|string
259 */
260 public function getQuery($name)
261 {
262 switch ($name) {
263 case 'version_check':
264 return "SELECT val FROM $this->table WHERE filename = :filename AND filesize = '-1' AND filetime = '-1' AND analyzetime = '-1'";
265 break;
266 case 'delete_cache':
267 return "DELETE FROM $this->table";
268 break;
269 case 'set_version':
270 return "INSERT INTO $this->table (filename, dirname, filesize, filetime, analyzetime, val) VALUES (:filename, :dirname, -1, -1, -1, :val)";
271 break;
272 case 'get_id3_data':
273 return "SELECT val FROM $this->table WHERE filename = :filename AND filesize = :filesize AND filetime = :filetime";
274 break;
275 case 'cache_file':
276 return "INSERT INTO $this->table (filename, dirname, filesize, filetime, analyzetime, val) VALUES (:filename, :dirname, :filesize, :filetime, :atime, :val)";
277 break;
278 case 'make_table':
279 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))";
280 break;
281 case 'get_cached_dir':
282 return "SELECT val FROM $this->table WHERE dirname = :dirname";
283 break;
284 default:
285 return null;
286 }
287 }
288
289 /**
290 * use the magical __get() for sql queries
291 *
292 * access as easy as $this->{case name}, returns NULL if query is not found
293 *
294 * @param string $name
295 *
296 * @return string
297 * @deprecated use getQuery() instead
298 */
299 public function __get($name) {
300 return $this->getQuery($name);
301 }
302
303 }