1<?php 2 3///////////////////////////////////////////////////////////////// 4/// getID3() by James Heinrich <info@getid3.org> // 5// available at https://github.com/JamesHeinrich/getID3 // 6// or https://www.getid3.org // 7// or http://getid3.sourceforge.net // 8// // 9// extension.cache.mysqli.php - part of getID3() // 10// Please see readme.txt for more information // 11// // 12///////////////////////////////////////////////////////////////// 13// // 14// This extension written by Allan Hansen <ahØartemis*dk> // 15// Table name mod by Carlo Capocasa <calroØcarlocapocasa*com> // 16// /// 17///////////////////////////////////////////////////////////////// 18 19 20/** 21* This is a caching extension for getID3(). It works the exact same 22* way as the getID3 class, but return cached information very fast 23* 24* Example: (see also demo.cache.mysql.php in /demo/) 25* 26* Normal getID3 usage (example): 27* 28* require_once 'getid3/getid3.php'; 29* $getID3 = new getID3; 30* $getID3->encoding = 'UTF-8'; 31* $info1 = $getID3->analyze('file1.flac'); 32* $info2 = $getID3->analyze('file2.wv'); 33* 34* getID3_cached usage: 35* 36* require_once 'getid3/getid3.php'; 37* require_once 'getid3/getid3/extension.cache.mysqli.php'; 38* // 5th parameter (tablename) is optional, default is 'getid3_cache' 39* $getID3 = new getID3_cached_mysqli('localhost', 'database', 'username', 'password', 'tablename'); 40* $getID3->encoding = 'UTF-8'; 41* $info1 = $getID3->analyze('file1.flac'); 42* $info2 = $getID3->analyze('file2.wv'); 43* 44* 45* Supported Cache Types (this extension) 46* 47* SQL Databases: 48* 49* cache_type cache_options 50* ------------------------------------------------------------------- 51* mysqli host, database, username, password 52* 53* 54* DBM-Style Databases: (use extension.cache.dbm) 55* 56* cache_type cache_options 57* ------------------------------------------------------------------- 58* gdbm dbm_filename, lock_filename 59* ndbm dbm_filename, lock_filename 60* db2 dbm_filename, lock_filename 61* db3 dbm_filename, lock_filename 62* db4 dbm_filename, lock_filename (PHP5 required) 63* 64* PHP must have write access to both dbm_filename and lock_filename. 65* 66* 67* Recommended Cache Types 68* 69* Infrequent updates, many reads any DBM 70* Frequent updates mysqli 71*/ 72 73class getID3_cached_mysqli extends getID3 74{ 75 /** 76 * @var mysqli 77 */ 78 private $mysqli; 79 80 /** 81 * @var mysqli_result 82 */ 83 private $cursor; 84 85 /** 86 * @var string 87 */ 88 private $table; 89 90 /** 91 * @var bool 92 */ 93 private $db_structure_check; 94 95 96 /** 97 * constructor - see top of this file for cache type and cache_options 98 * 99 * @param string $host 100 * @param string $database 101 * @param string $username 102 * @param string $password 103 * @param string $table 104 * 105 * @throws Exception 106 * @throws getid3_exception 107 */ 108 public function __construct($host, $database, $username, $password, $table='getid3_cache') { 109 110 // Check for mysqli support 111 if (!function_exists('mysqli_connect')) { 112 throw new Exception('PHP not compiled with mysqli support.'); 113 } 114 115 // Connect to database 116 $this->mysqli = new mysqli($host, $username, $password); 117 if ($this->mysqli->connect_error) { 118 throw new Exception('Connect Error (' . $this->mysqli->connect_errno . ') ' . $this->mysqli->connect_error); 119 } 120 121 // Select database 122 if (!$this->mysqli->select_db($database)) { 123 throw new Exception('Cannot use database '.$database); 124 } 125 126 // Set table 127 $this->table = $table; 128 129 // Create cache table if not exists 130 $this->create_table(); 131 132 $this->db_structure_check = true; // set to false if you know your table structure has already been migrated to use `hash` as the primary key to avoid 133 $this->migrate_db_structure(); 134 135 // Check version number and clear cache if changed 136 $version = ''; 137 $SQLquery = 'SELECT `value`'; 138 $SQLquery .= ' FROM `'.$this->mysqli->real_escape_string($this->table).'`'; 139 $SQLquery .= ' WHERE (`filename` = \''.$this->mysqli->real_escape_string(getID3::VERSION).'\')'; 140 $SQLquery .= ' AND (`hash` = \'getID3::VERSION\')'; 141 if ($this->cursor = $this->mysqli->query($SQLquery)) { 142 list($version) = $this->cursor->fetch_array(); 143 } 144 if ($version != getID3::VERSION) { 145 $this->clear_cache(); 146 } 147 148 parent::__construct(); 149 } 150 151 152 /** 153 * clear cache 154 */ 155 public function clear_cache() { 156 $this->mysqli->query('TRUNCATE TABLE `'.$this->mysqli->real_escape_string($this->table).'`'); 157 $this->mysqli->query('INSERT INTO `'.$this->mysqli->real_escape_string($this->table).'` (`hash`, `filename`, `filesize`, `filetime`, `analyzetime`, `value`) VALUES (\'getID3::VERSION\', \''.getID3::VERSION.'\', -1, -1, -1, \''.getID3::VERSION.'\')'); 158 } 159 160 161 /** 162 * migrate database structure if needed 163 */ 164 public function migrate_db_structure() { 165 // Check for table structure 166 if ($this->db_structure_check) { 167 $SQLquery = 'SHOW COLUMNS'; 168 $SQLquery .= ' FROM `'.$this->mysqli->real_escape_string($this->table).'`'; 169 $SQLquery .= ' LIKE \'hash\''; 170 $this->cursor = $this->mysqli->query($SQLquery); 171 if ($this->cursor->num_rows == 0) { 172 // table has not been migrated, add column, add hashes, change index 173 $SQLquery = 'ALTER TABLE `getid3_cache` DROP PRIMARY KEY, ADD `hash` CHAR(32) NOT NULL DEFAULT \'\' FIRST, ADD PRIMARY KEY(`hash`)'; 174 $this->mysqli->query($SQLquery); 175 176 $SQLquery = 'UPDATE `getid3_cache` SET'; 177 $SQLquery .= ' `hash` = MD5(`filename`, `filesize`, `filetime`)'; 178 $SQLquery .= ' WHERE (`filesize` > -1)'; 179 $this->mysqli->query($SQLquery); 180 181 $SQLquery = 'UPDATE `getid3_cache` SET'; 182 $SQLquery .= ' `hash` = \'getID3::VERSION\''; 183 $SQLquery .= ' WHERE (`filesize` = -1)'; 184 $SQLquery .= ' AND (`filetime` = -1)'; 185 $SQLquery .= ' AND (`filetime` = -1)'; 186 $this->mysqli->query($SQLquery); 187 } 188 } 189 } 190 191 192 /** 193 * analyze file 194 * 195 * @param string $filename 196 * @param int $filesize 197 * @param string $original_filename 198 * @param resource $fp 199 * 200 * @return mixed 201 */ 202 public function analyze($filename, $filesize=null, $original_filename='', $fp=null) { 203 204 $filetime = 0; 205 if (file_exists($filename)) { 206 207 // Short-hands 208 $filetime = filemtime($filename); 209 $filesize = filesize($filename); 210 211 // Lookup file 212 $SQLquery = 'SELECT `value`'; 213 $SQLquery .= ' FROM `'.$this->mysqli->real_escape_string($this->table).'`'; 214 $SQLquery .= ' WHERE (`hash` = \''.$this->mysqli->real_escape_string(md5($filename.$filesize.$filetime)).'\')'; 215 $this->cursor = $this->mysqli->query($SQLquery); 216 if ($this->cursor->num_rows > 0) { 217 // Hit 218 list($result) = $this->cursor->fetch_array(); 219 return unserialize(base64_decode($result)); 220 } 221 } 222 223 // Miss 224 $analysis = parent::analyze($filename, $filesize, $original_filename, $fp); 225 226 // Save result 227 if (file_exists($filename)) { 228 $SQLquery = 'INSERT INTO `'.$this->mysqli->real_escape_string($this->table).'` (`hash`, `filename`, `filesize`, `filetime`, `analyzetime`, `value`) VALUES ('; 229 $SQLquery .= '\''.$this->mysqli->real_escape_string(md5($filename.$filesize.$filetime)).'\''; 230 $SQLquery .= ', \''.$this->mysqli->real_escape_string($filename).'\''; 231 $SQLquery .= ', \''.$this->mysqli->real_escape_string($filesize).'\''; 232 $SQLquery .= ', \''.$this->mysqli->real_escape_string($filetime).'\''; 233 $SQLquery .= ', UNIX_TIMESTAMP()'; 234 $SQLquery .= ', \''.$this->mysqli->real_escape_string(base64_encode(serialize($analysis))).'\''; 235 $SQLquery .= ')'; 236 $this->cursor = $this->mysqli->query($SQLquery); 237 } 238 return $analysis; 239 } 240 241 242 /** 243 * (re)create mysqli table 244 * 245 * @param bool $drop 246 */ 247 private function create_table($drop=false) { 248 if ($drop) { 249 $SQLquery = 'DROP TABLE IF EXISTS `'.$this->mysqli->real_escape_string($this->table).'`'; 250 $this->mysqli->query($SQLquery); 251 } 252 $SQLquery = 'CREATE TABLE IF NOT EXISTS `'.$this->mysqli->real_escape_string($this->table).'` ('; 253 $SQLquery .= '`hash` CHAR(32) NOT NULL DEFAULT \'\''; 254 $SQLquery .= ', `filename` VARCHAR(1000) NOT NULL DEFAULT \'\''; 255 $SQLquery .= ', `filesize` INT(11) NOT NULL DEFAULT \'0\''; 256 $SQLquery .= ', `filetime` INT(11) NOT NULL DEFAULT \'0\''; 257 $SQLquery .= ', `analyzetime` INT(11) NOT NULL DEFAULT \'0\''; 258 $SQLquery .= ', `value` LONGTEXT NOT NULL'; 259 $SQLquery .= ', PRIMARY KEY (`hash`))'; 260 $this->cursor = $this->mysqli->query($SQLquery); 261 echo $this->mysqli->error; 262 } 263} 264