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// /demo/demo.dirscan.php - part of getID3() // 9// Directory Scanning and Caching CLI tool for batch media // 10// file processing with getID3() // 11// by Karl G. Holz <newaeonØmac*com> // 12// /// 13///////////////////////////////////////////////////////////////// 14 15/** 16* This is a directory scanning and caching cli tool for getID3(). 17* 18* use like so for the default sqlite3 database, which is hidden: 19* 20* cd <path you want to start scanning from> 21* php <path to getid3 files>/demo.dirscan.php 22* 23* or 24* 25* php <path to getid3 files>/demo.dirscan.php <dir to scan> <file ext in csv list> 26* 27* Supported Cache Types (this extension) 28* 29* SQL Databases: 30* 31* cache_type 32* ------------------------------------------------------------------- 33* mysql 34 35$cache='mysql'; 36$database['host']=''; 37$database['database']=''; 38$database['username']=''; 39$database['password']=''; 40$database['table']=''; 41 42* sqlite3 43 44$cache='sqlite3'; 45$database['table']='getid3_cache'; 46$database['hide']=true; 47 48*/ 49$dir = $_SERVER['PWD']; 50$media = array('mp4', 'm4v', 'mov', 'mp3', 'm4a', 'jpg', 'png', 'gif'); 51$database = array(); 52/** 53* configure the database bellow 54*/ 55// sqlite3 56$cache = 'sqlite3'; 57$database['table'] = 'getid3_cache'; 58$database['hide'] = true; 59/** 60 * mysql 61$cache = 'mysql'; 62$database['host'] = ''; 63$database['database'] = ''; 64$database['username'] = ''; 65$database['password'] = ''; 66$database['table'] = ''; 67*/ 68 69/** 70* id3 tags class file 71*/ 72require_once(dirname(__FILE__).'/getid3.php'); 73/** 74* dirscan scans all directories for files that match your selected filetypes into the cache database 75* this is useful for a lot of media files 76* 77* 78* @package dirscan 79* @author Karl Holz 80* 81*/ 82 83class dirscan { 84 /** 85 * type_brace() * Might not work on Solaris and other non GNU systems * 86 * 87 * Configures a filetype list for use with glob searches, 88 * will match uppercase or lowercase extensions only, no mixing 89 * @param string $dir directory to use 90 * @param mixed $search cvs list of extentions or an array 91 * @return string or null if checks fail 92 */ 93 private function type_brace($dir, $search=array()) { 94 $dir = str_replace(array('///', '//'), array('/', '/'), $dir); 95 if (!is_dir($dir)) { 96 return null; 97 } 98 if (!is_array($search)) { 99 $e = explode(',', $search); 100 } elseif (count($search) < 1) { 101 return null; 102 } else { 103 $e = $search; 104 } 105 $ext = array(); 106 foreach ($e as $new) { 107 $ext[] = strtolower(trim($new)); 108 $ext[] = strtoupper(trim($new)); 109 } 110 $b = $dir.'/*.{'.implode(',', $ext).'}'; 111 return $b; 112 } 113 114 /** 115 * this function will search 4 levels deep for directories 116 * will return null on failure 117 * @param string $root 118 * @return array return an array of dirs under root 119 * @todo figure out how to block tabo directories with ease 120 */ 121 private function getDirs($root) { 122 switch ($root) { // return null on tabo directories, add as needed -> case {dir to block }: this is not perfect yet 123 case '/': 124 case '/var': 125 case '/etc': 126 case '/home': 127 case '/usr': 128 case '/root': 129 case '/private/etc': 130 case '/private/var': 131 case '/etc/apache2': 132 case '/home': 133 case '/tmp': 134 case '/var/log': 135 return null; 136 break; 137 default: // scan 4 directories deep 138 if (!is_dir($root)) { 139 return null; 140 } 141 $dirs = array_merge(glob($root.'/*', GLOB_ONLYDIR), glob($root.'/*/*', GLOB_ONLYDIR), glob($root.'/*/*/*', GLOB_ONLYDIR), glob($root.'/*/*/*/*', GLOB_ONLYDIR), glob($root.'/*/*/*/*/*', GLOB_ONLYDIR), glob($root.'/*/*/*/*/*/*', GLOB_ONLYDIR), glob($root.'/*/*/*/*/*/*/*', GLOB_ONLYDIR)); 142 break; 143 } 144 if (count($dirs) < 1) { 145 $dirs = array($root); 146 } 147 return $dirs; 148 } 149 150 /** 151 * file_check() check the number of file that are found that match the brace search 152 * 153 * @param string $search 154 * @return mixed 155 */ 156 private function file_check($search) { 157 $t = array(); 158 $s = glob($search, GLOB_BRACE); 159 foreach ($s as $file) { 160 $t[] = str_replace(array('///', '//'), array('/', '/'), $file); 161 } 162 if (count($t) > 0) { 163 return $t; 164 } 165 return null; 166 } 167 168 function getTime() { 169 return microtime(true); 170 // old method for PHP < 5 171 //$a = explode(' ', microtime()); 172 //return (double) $a[0] + $a[1]; 173 } 174 175 176 /** 177 * 178 * @param string $dir 179 * @param mixed $match search type name extentions, can be an array or csv list 180 * @param string $cache caching extention, select one of sqlite3, mysql, dbm 181 * @param array $opt database options, 182 */ 183 function scan_files($dir, $match, $cache='sqlite3', $opt=array('table'=>'getid3_cache', 'hide'=>true)) { 184 $Start = self::getTime(); 185 switch ($cache) { // load the caching module 186 case 'sqlite3': 187 if (!class_exists('getID3_cached_sqlite3')) { 188 require_once(dirname(__FILE__)).'/extension.cache.sqlite3.php'; 189 } 190 $id3 = new getID3_cached_sqlite3($opt['table'], $opt['hide']); 191 break; 192 case 'mysql': 193 if (!class_exists('getID3_cached_mysql')) { 194 require_once(dirname(__FILE__)).'/extension.cache.mysql.php'; 195 } 196 $id3 = new getID3_cached_mysql($opt['host'], $opt['database'], $opt['username'], $opt['password'], $opt['table']); 197 break; 198 // I'll leave this for some one else 199 //case 'dbm': 200 // if (!class_exists('getID3_cached_dbm')) { 201 // require_once(dirname(__FILE__)).'/extension.cache.dbm.php'; 202 // } 203 // die(' This has not be implemented, sorry for the inconvenience'); 204 // break; 205 default: 206 die(' You have selected an Invalid cache type, only "sqlite3" and "mysql" are valid'."\n"); 207 break; 208 } 209 $count = array('dir'=>0, 'file'=>0); 210 $dirs = self::getDirs($dir); 211 if ($dirs !== null) { 212 foreach ($dirs as $d) { 213 echo ' Scanning: '.$d."\n"; 214 $search = self::type_brace($d, $match); 215 if ($search !== null) { 216 $files = self::file_check($search); 217 if ($files !== null) { 218 foreach ($files as $f) { 219 echo ' * Analyzing '.$f.' '."\n"; 220 $id3->analyze($f); 221 $count['file']++; 222 } 223 $count['dir']++; 224 } else { 225 echo 'Failed to get files '."\n"; 226 } 227 } else { 228 echo 'Failed to create match string '."\n"; 229 } 230 } 231 echo '**************************************'."\n"; 232 echo '* Finished Scanning your directories '."\n*\n"; 233 echo '* Directories '.$count['dir']."\n"; 234 echo '* Files '.$count['file']."\n"; 235 $End = self::getTime(); 236 $t = number_format(($End - $Start) / 60, 2); 237 echo '* Time taken to scan '.$dir.' '.$t.' min '."\n"; 238 echo '**************************************'."\n"; 239 } else { 240 echo ' failed to get directories '."\n"; 241 } 242 } 243} 244 245if (PHP_SAPI === 'cli') { 246 if (count($argv) == 2) { 247 if (is_dir($argv[1])) { 248 $dir = $argv[1]; 249 } 250 if (count(explode(',', $argv[2])) > 0) { 251 $media = $arg[2]; 252 } 253 } 254 echo ' * Starting to scan directory: '.$dir."\n"; 255 echo ' * Using default media types: '.implode(',', $media)."\n"; 256 dirscan::scan_files($dir, $media, $cache, $database); 257} 258