PageRenderTime 41ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/php-getid3-2.0.0b5/sample_apps/morg/morg/morg.php

#
PHP | 416 lines | 222 code | 101 blank | 93 comment | 30 complexity | 4d5cdf806280c200be49ea72e4b5a79c MD5 | raw file
Possible License(s): GPL-2.0
  1. <?php
  2. // +----------------------------------------------------------------------+
  3. // | PHP version 5.1.4 |
  4. // +----------------------------------------------------------------------+
  5. // | Placed in public domain by Allan Hansen, 2006. Share and enjoy! |
  6. // +----------------------------------------------------------------------+
  7. // | morg.php |
  8. // | MORG abstract application. |
  9. // +----------------------------------------------------------------------+
  10. // | Authors: Allan Hansen <ah@artemis.dk> |
  11. // +----------------------------------------------------------------------+
  12. //
  13. // $Id: morg.php,v 1.2 2006/12/26 01:11:14 ah Exp $
  14. require_once 'morg/application.php';
  15. require_once 'morg/mysql.php';
  16. abstract class morg extends application
  17. {
  18. const version = '4.0beta1';
  19. /**
  20. * Regular Expression match for files.
  21. * Read: NN*TTTTT.EXT NN=track number, TTTTT=title, *=seperators: dots, spaces or minuses, EXT = file extention
  22. *
  23. * Example: "Rebel Yell.mp3"
  24. * Example: "01. Rebel Yell.mp3"
  25. * Example: "01 Rebel Yell.mp3"
  26. * Example: "01 - Rebel Yell.mp3"
  27. * Example: "001 Rebel Yell.mp3"
  28. */
  29. const filename_pattern = '/^([0-9]{0,3})[\. -]+(.*)\.([a-z0-9]{2,4})$/i';
  30. /**
  31. * Regular Expression match dor directories.
  32. * Read: TTTTT (YYYYL) TTTTT=title, YYYY=year, L=letter - a = first record this year, b = second record ...
  33. *
  34. * Example: "Easy Action (1970)" - only one record in 1970
  35. * Example: "Love It to Death (1971a)" - first record in 1971
  36. * Example: "Killer (1971b)" - secondt record in 1971
  37. */
  38. const directory_pattern = '/^(.+) \(([1-2][0-9]{3}[a-d]{0,1})\)$/i';
  39. protected $password;
  40. protected $server_cp;
  41. protected $client_cp;
  42. protected $client_type;
  43. protected $client_params;
  44. protected $locale;
  45. protected $playlist_format;
  46. protected $toc_columns;
  47. protected $browser_behaviour;
  48. protected $assume1;
  49. protected $assume2;
  50. protected $assume3;
  51. protected $assume4;
  52. protected $assume5;
  53. protected $assume6;
  54. protected $assume7;
  55. protected $category_prefix;
  56. /**
  57. * Constructor - test ennviroment and configuration.
  58. */
  59. public function __construct()
  60. {
  61. // require PHP 5.1.4
  62. if (strnatcmp(phpversion(), '5.1.4') == -1) {
  63. $this->fail('PHP version 5.1.4 or newer is required.');
  64. }
  65. // require safe mode = Off
  66. if (get_cfg_var('safe_mode')) {
  67. $this->fail('PHP is being run in safe mode. Change in php.ini.');
  68. }
  69. // require mysql support in PHP
  70. if (!extension_loaded('mysql')) {
  71. $this->fail('PHP is missing the required mysql extention.');
  72. }
  73. // require iconv support in PHP
  74. if (!extension_loaded('iconv')) {
  75. $this->fail('PHP is missing the required iconv extention.');
  76. }
  77. // require mbstring support in PHP
  78. if (!extension_loaded('mbstring')) {
  79. $this->fail('PHP is missing the required mbstring extention.');
  80. }
  81. if (!file_exists('config.php')) {
  82. $this->fail('config.php is missing. Run the install tool.');
  83. }
  84. // connect to mysql
  85. require_once 'config.php';
  86. $this->db_server = MYSQL_SERVER;
  87. $this->db_database = MYSQL_DATABASE;
  88. $this->db_username = MYSQL_USERNAME;
  89. $this->db_password = MYSQL_PASSWORD;
  90. try {
  91. $this->db_connect();
  92. }
  93. catch (exception $e) {
  94. $this->fail('Could not connect to mysql database');
  95. }
  96. // check mysql version
  97. $this->dbh->query('select @@version');
  98. $this->dbh->next_record();
  99. if (strnatcmp($this->dbh->f('@@version'), '5.0.19') == -1) {
  100. $this->fail('MySQL 5.0.19 or newer is required.');
  101. }
  102. // check for innodb support in mysql
  103. $this->dbh->query('select @@have_innodb');
  104. $this->dbh->next_record();
  105. if ($this->dbh->f('@@have_innodb') != 'YES') {
  106. $this->fail('MySQL does not have the required InnoDB support.');
  107. }
  108. // check for empty database
  109. $this->dbh->query('show tables');
  110. $this->dbh->next_record();
  111. if (!$this->dbh->num_rows()) {
  112. $this->fail('Please import morg.sql mysql database.');
  113. }
  114. // read configuration
  115. $this->dbh->query('select * from morg_config');
  116. if ($this->dbh->next_record()) {
  117. $this->password = $this->dbh->f('password');
  118. $this->server_cp = $this->dbh->f('server_cp');
  119. $this->client_cp = $this->dbh->f('client_cp');
  120. $this->client_type = $this->dbh->f('client_type');
  121. $this->client_params = $this->dbh->f('client_params');
  122. $this->locale = $this->dbh->f('locale');
  123. $this->playlist_format = $this->dbh->f('playlist_format');
  124. $this->toc_columns = $this->dbh->f('toc_columns');
  125. $this->browser_behaviour = $this->dbh->f('browser_behaviour');
  126. $this->assume1 = $this->dbh->f('assume1');
  127. $this->assume2 = $this->dbh->f('assume2');
  128. $this->assume3 = $this->dbh->f('assume3');
  129. $this->assume4 = $this->dbh->f('assume4');
  130. $this->assume5 = $this->dbh->f('assume5');
  131. $this->assume6 = $this->dbh->f('assume6');
  132. $this->assume7 = $this->dbh->f('assume7');
  133. $this->category_prefix = $this->dbh->f('category_prefix');
  134. }
  135. // localised sortorder and strtoupper
  136. setlocale(LC_COLLATE, $this->locale . '.UTF-8');
  137. setlocale(LC_CTYPE, $this->locale . '.UTF-8');
  138. }
  139. /**
  140. * Get array with roots.
  141. *
  142. * @return array of (root_id => server_path)
  143. */
  144. protected function roots()
  145. {
  146. static $result = array ();
  147. if ($result) {
  148. return $result;
  149. }
  150. $this->dbh->query('select id, server_path from morg_config_root');
  151. while ($this->dbh->next_record()) {
  152. $result[$this->dbh->f('id')] = $this->dbh->f('server_path');
  153. }
  154. return $result;
  155. }
  156. /**
  157. * Get root from path (server)
  158. */
  159. function get_root($path)
  160. {
  161. foreach ($this->roots() as $server_path) {
  162. if (strstr('/'.$path, '/'.$server_path)) {
  163. return $server_path;
  164. }
  165. }
  166. }
  167. /**
  168. * Get root id from path (server)
  169. */
  170. function get_root_id($path)
  171. {
  172. foreach ($this->roots() as $id => $server_path) {
  173. if (strstr('/'.$path, '/'.$server_path)) {
  174. return $id;
  175. }
  176. }
  177. }
  178. /**
  179. * Remove root from path.
  180. */
  181. function remove_root($path)
  182. {
  183. return str_replace($this->get_root($path), '', $path);
  184. }
  185. /**
  186. * Analyze file with getid3 and return mysql file_id.
  187. */
  188. protected function analyze_file($filename)
  189. {
  190. // get filesize (>2Gb files not supported)
  191. if (!$filesize = @filesize($filename)) {
  192. return 0;
  193. }
  194. // get date file last modified
  195. $filemtime = filemtime($filename);
  196. // extract dir- and basename in utf8 and add slashes for mysql
  197. $path_info = pathinfo(@iconv($this->server_cp, 'UTF-8', $filename));
  198. $filename_sls = addslashes($path_info['basename']);
  199. $dirname_sls = addslashes($path_info['dirname']);
  200. // get directory_id from dirname_sls
  201. $this->dbh->query("select id from getid3_directory where filename='$dirname_sls'");
  202. if ($this->dbh->next_record()) {
  203. $directory_id = $this->dbh->f('id');
  204. }
  205. else {
  206. $root_id = $this->get_root_id($filename);
  207. $this->dbh->query("insert into getid3_directory (root_id, filename) values ($root_id, '$dirname_sls')");
  208. $directory_id = $this->dbh->insert_id();
  209. }
  210. // cached? - determined by directory_id, filename and filemtime
  211. $this->dbh->query("select id from getid3_file where directory_id = $directory_id and filename = '$filename_sls' and filemtime = $filemtime and filesize = $filesize");
  212. if ($this->dbh->next_record()) {
  213. // great - return id
  214. return $this->dbh->f('id');
  215. }
  216. // not cached - analyze file with getid3
  217. require_once 'getid3/getid3.php';
  218. // initialize getID3 engine
  219. $getid3 = new getID3;
  220. $getid3->encoding = 'UTF-8';
  221. $getid3->option_md5_data = true;
  222. $getid3->option_md5_data_source = true;
  223. try {
  224. $getid3->Analyze($filename);
  225. }
  226. catch (getid3_exception $e) {
  227. // non media files (garbage)
  228. if ($e->getmessage() == 'Unable to determine file format') {
  229. // insert in database - no need to analyse again
  230. $this->dbh->query("replace into getid3_file (filemtime, directory_id, filename) values ($filemtime, $directory_id, '$filename_sls')");
  231. return $this->dbh->insert_id();
  232. }
  233. // rethrow
  234. else {
  235. throw $e;
  236. }
  237. }
  238. $format_name = @$getid3->info['fileformat'] . (@$getid3->info['audio']['dataformat'] != @$getid3->info['fileformat'] ? '/' . @$getid3->info['audio']['dataformat'] : '' );
  239. $format_name_id = $this->getid3_lookup_format_name_id($format_name, @$getid3->info['mime_type']);
  240. // skip for non audio files - i.e. images
  241. if (@$getid3->info['audio']) {
  242. $encoder_version_id = $this->getid3_lookup_id(@$getid3->info['audio']['encoder'], 'encoder_version');
  243. $encoder_options_id = $this->getid3_lookup_id(@$getid3->info['audio']['encoder_options'], 'encoder_options');
  244. $bitrate_mode_id = $this->getid3_lookup_id(@$getid3->info['audio']['bitrate_mode'], 'bitrate_mode');
  245. $channel_mode_id = $this->getid3_lookup_id(@$getid3->info['audio']['channelmode'], 'channel_mode');
  246. $sample_rate = (int)@$getid3->info['audio']['sample_rate'];
  247. $bits_per_sample = (int)@$getid3->info['audio']['bits_per_sample'];
  248. $channels = (int)@$getid3->info['audio']['channels'];
  249. $lossless = (int)@$getid3->info['audio']['lossless'];
  250. $playtime = (float)@$getid3->info['playtime_seconds'];
  251. $avg_bit_rate = (float)@$getid3->info['bitrate'];
  252. $rg_track_gain = isset($getid3->info['replay_gain']['track']['adjustment']) ? (float)$getid3->info['replay_gain']['track']['adjustment'] : 'null';
  253. $rg_album_gain = isset($getid3->info['replay_gain']['album']['adjustment']) ? (float)$getid3->info['replay_gain']['album']['adjustment'] : 'null';
  254. $md5_data = $getid3->info['md5_data'];
  255. // insert audio file entry
  256. $this->dbh->query("replace into getid3_file (directory_id, filename, filemtime, filesize, format_name_id, encoder_version_id, encoder_options_id, bitrate_mode_id, channel_mode_id, sample_rate, bits_per_sample, channels, lossless, playtime, avg_bit_rate, replaygain_track_gain, replaygain_album_gain, md5_data) values ($directory_id, '$filename_sls', $filemtime, $filesize, $format_name_id, 0$encoder_version_id, 0$encoder_options_id, 0$bitrate_mode_id, 0$channel_mode_id, $sample_rate, $bits_per_sample, $channels, $lossless, $playtime, $avg_bit_rate, $rg_track_gain, $rg_album_gain, '$md5_data')");
  257. }
  258. // insert non-audio file entry
  259. else {
  260. // insert audio file entry
  261. $this->dbh->query("replace into getid3_file (directory_id, filename, filemtime, filesize, format_name_id) values ($directory_id, '$filename_sls', $filemtime, $filesize, $format_name_id)");
  262. }
  263. $file_id = $this->dbh->insert_id();
  264. // loop thru tags
  265. if (@$getid3->info['tags']) {
  266. foreach ($getid3->info['tags'] as $tag_name => $tag_data) {
  267. // loop thru fields
  268. foreach ($tag_data as $field_name => $values) {
  269. // loop thru values
  270. foreach ($values as $value) {
  271. $field_id = $this->getid3_lookup_id($field_name, 'field');
  272. $value_id = $this->getid3_lookup_id($value, 'value');
  273. // insert comments entry
  274. $this->dbh->query("replace into getid3_comment (file_id, field_id, value_id) values ($file_id, $field_id, $value_id)");
  275. }
  276. }
  277. }
  278. }
  279. return $file_id;
  280. }
  281. /**
  282. * Look up or insert value in getid3_format_name table
  283. */
  284. function getid3_lookup_format_name_id($name, $mime_type) {
  285. // NOTE: It might be a very good idea to use some memory for caching in order to save queries.
  286. // truncate name to 255 (limit in mysql index)
  287. $name = addslashes(substr($name, 0, 255));
  288. $this->dbh->query("select id from getid3_format_name where name='$name'");
  289. if ($this->dbh->next_record()) {
  290. return $this->dbh->f('id');
  291. }
  292. $mime_type = addslashes($mime_type);
  293. $this->dbh->query("replace into getid3_format_name (name, mime_type) values ('$name', '$mime_type')");
  294. return $this->dbh->insert_id();
  295. }
  296. /**
  297. * Look up or insert value in "getid3_lookup" table
  298. */
  299. function getid3_lookup_id($name, $table) {
  300. // NOTE: It might be a very good idea to use some memory for caching in order to save queries.
  301. // truncate name to 255 (limit in mysql index)
  302. $name = addslashes(substr($name, 0, 255));
  303. $this->dbh->query("select id from getid3_$table where name='$name'");
  304. if ($this->dbh->next_record()) {
  305. return $this->dbh->f('id');
  306. }
  307. $this->dbh->query("replace into getid3_$table (name) values ('$name')");
  308. return $this->dbh->insert_id();
  309. }
  310. /**
  311. * Abstract error handling.
  312. */
  313. abstract protected function fail($message);
  314. }
  315. ?>