[SPIP] ~maj v3.2.9-->v3.2.11
[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 * @param resource $fp
179 *
180 * @return mixed|false
181 */
182 public function analyze($filename, $filesize=null, $original_filename='', $fp=null) {
183 if (!file_exists($filename)) {
184 return false;
185 }
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);
192 // Lookup file
193 $db = $this->db;
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));
203 }
204 // if it hasn't been analyzed before, then do it now
205 $analysis = parent::analyze($filename, $filesize, $original_filename, $fp);
206 // Save result
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();
216 return $analysis;
217 }
218
219 /**
220 * create data base table
221 * this is almost the same as MySQL, with the exception of the dirname being added
222 *
223 * @return bool
224 */
225 private function create_table() {
226 $db = $this->db;
227 $sql = $this->getQuery('make_table');
228 return $db->exec($sql);
229 }
230
231 /**
232 * get cached directory
233 *
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.
236 *
237 * @param string $dir directory to search the cache database for
238 *
239 * @return array return an array of matching id3 data
240 */
241 public function get_cached_dir($dir) {
242 $db = $this->db;
243 $rows = array();
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));
250 }
251 return $rows;
252 }
253
254 /**
255 * returns NULL if query is not found
256 *
257 * @param string $name
258 *
259 * @return null|string
260 */
261 public function getQuery($name)
262 {
263 switch ($name) {
264 case 'version_check':
265 return "SELECT val FROM $this->table WHERE filename = :filename AND filesize = '-1' AND filetime = '-1' AND analyzetime = '-1'";
266 case 'delete_cache':
267 return "DELETE FROM $this->table";
268 case 'set_version':
269 return "INSERT INTO $this->table (filename, dirname, filesize, filetime, analyzetime, val) VALUES (:filename, :dirname, -1, -1, -1, :val)";
270 case 'get_id3_data':
271 return "SELECT val FROM $this->table WHERE filename = :filename AND filesize = :filesize AND filetime = :filetime";
272 case 'cache_file':
273 return "INSERT INTO $this->table (filename, dirname, filesize, filetime, analyzetime, val) VALUES (:filename, :dirname, :filesize, :filetime, :atime, :val)";
274 case 'make_table':
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";
278 default:
279 return null;
280 }
281 }
282
283 /**
284 * use the magical __get() for sql queries
285 *
286 * access as easy as $this->{case name}, returns NULL if query is not found
287 *
288 * @param string $name
289 *
290 * @return string
291 * @deprecated use getQuery() instead
292 */
293 public function __get($name) {
294 return $this->getQuery($name);
295 }
296
297 }