Completed
Push — vendor/getid3 ( 69b815...49c253 )
by Pauli
04:26 queued 01:37
created

getID3_cached_mysqli::migrate_db_structure()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 26

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
nc 3
nop 0
dl 0
loc 26
rs 9.504
c 0
b 0
f 0
1
<?php
2
3
/////////////////////////////////////////////////////////////////
4
/// getID3() by James Heinrich <[email protected]>               //
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
73
class 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