<?php
/////////////////////////////////////////////////////////////////////////////////
/// getID3() by James Heinrich <info@getid3.org>                               //
//  available at http://getid3.sourceforge.net                                 //
//            or http://www.getid3.org                                         //
//          also https://github.com/JamesHeinrich/getID3                       //
/////////////////////////////////////////////////////////////////////////////////
///                                                                            //
// getid3.dirscan.php - tool for batch media file processing with getID3()     //
//                                                                            ///
/////////////////////////////////////////////////////////////////////////////////
///                                                                            //
//  Directory Scanning and Caching CLI tool by Karl G. Holz <newaeon├śmac*com>  //
//                                                                            ///
/////////////////////////////////////////////////////////////////////////////////
/**
* This is a directory scanning and caching cli tool for getID3().
*
* use like so for the default sqlite3 database, which is hidden:
*
* cd <path you want to start scanning from>
* php <path to getid3 files>/getid3.dirscan.php
*
* or
*
* php <path to getid3 files>/getid3.dirscan.php <dir to scan> <file ext in csv list>
*
* Supported Cache Types    (this extension)
*
*   SQL Databases:
*
*   cache_type
*   -------------------------------------------------------------------
*    mysql

$cache='mysql';
$database['host']='';
$database['database']='';
$database['username']='';
$database['password']='';
$database['table']='';

*    sqlite3

$cache='sqlite3';
$database['table']='getid3_cache';
$database['hide']=true;

*/
$dir      $_SERVER['PWD'];
$media    = array('mp4''m4v''mov''mp3''m4a''jpg''png''gif');
$database = array();
/**
* configure the database bellow
*/
// sqlite3
$cache             'sqlite3';
$database['table'] = 'getid3_cache';
$database['hide']  = true;
/**
 * mysql
$cache                = 'mysql';
$database['host']     = '';
$database['database'] = '';
$database['username'] = '';
$database['password'] = '';
$database['table']    = '';
*/

/**
* id3 tags class file
*/
require_once(dirname(__FILE__).'/getid3.php');
/**
* dirscan scans all directories for files that match your selected filetypes into the cache database
* this is useful for a lot of media files
*
*
* @package dirscan
* @author Karl Holz
*
*/

class dirscan {
    
/**
    * type_brace()  * Might not work on Solaris and other non GNU systems *
    *
    * Configures a filetype list for use with glob searches,
    * will match uppercase or lowercase extensions only, no mixing
    * @param string $dir directory to use
    * @param mixed cvs list of extentions or an array
    * @return string or null if checks fail
    */
    
private function type_brace($dir$search=array()) {
        
$dir str_replace(array('///''//'), array('/''/'), $dir);
        if (!
is_dir($dir)) {
            return 
null;
        }
        if (!
is_array($search)) {
            
$e explode(','$search);
        } elseif (
count($search) < 1) {
            return 
null;
        } else {
            
$e $search;
        }
        
$ext = array();
        foreach (
$e as $new) {
            
$ext[] = strtolower(trim($new));
            
$ext[] = strtoupper(trim($new));
        }
        
$b $dir.'/*.{'.implode(','$ext).'}';
        return 
$b;
    }

    
/**
    * this function will search 4 levels deep for directories
    * will return null on failure
    * @param string $root
    * @return array return an array of dirs under root
    * @todo figure out how to block tabo directories with ease
    */
    
private function getDirs($root) {
        switch (
$root) { // return null on tabo directories, add as needed -> case {dir to block }:   this is not perfect yet
            
case '/':
            case 
'/var':
            case 
'/etc':
            case 
'/home':
            case 
'/usr':
            case 
'/root':
            case 
'/private/etc':
            case 
'/private/var':
            case 
'/etc/apache2':
            case 
'/home':
            case 
'/tmp':
            case 
'/var/log':
                return 
null;
                break;
            default: 
// scan 4 directories deep
                
if (!is_dir($root)) {
                    return 
null;
                }
                
$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));
                break;
        }
        if (
count($dirs) < 1) {
            
$dirs = array($root);
        }
        return 
$dirs;
    }

    
/**
    *  file_check() check the number of file that are found that match the brace search
    *
    * @param string $search
    * @return mixed
    */
    
private function file_check($search) {
        
$t = array();
        
$s glob($searchGLOB_BRACE);
        foreach (
$s as $file) {
            
$t[] = str_replace(array('///''//'), array('/''/'), $file);
        }
        if (
count($t) > 0) {
            return 
$t;
        }
        return 
null;
    }

    function 
getTime() {
        return 
microtime(true);
        
// old method for PHP < 5
        //$a = explode(' ', microtime());
        //return (double) $a[0] + $a[1];
    
}


    
/**
    *
    * @param type $dir
    * @param type $match  search type name extentions, can be an array or csv list
    * @param type $cache caching extention, select one of sqlite3, mysql, dbm
    * @param array $opt database options,
    */
    
function scan_files($dir$match$cache='sqlite3'$opt=array('table'=>'getid3_cache''hide'=>true)) {
        
$Start self::getTime();
        switch (
$cache) { // load the caching module
            
case 'sqlite3':
                if (!
class_exists('getID3_cached_sqlite3')) {
                    require_once(
dirname(__FILE__)).'/extension.cache.sqlite3.php';
                }
                
$id3 = new getID3_cached_sqlite3($opt['table'], $opt['hide']);
                break;
            case 
'mysql':
                if (!
class_exists('getID3_cached_mysql')) {
                    require_once(
dirname(__FILE__)).'/extension.cache.mysql.php';
                }
                
$id3 = new getID3_cached_mysql($opt['host'], $opt['database'], $opt['username'], $opt['password'], $opt['table']);
                break;
        
// I'll leave this for some one else
            //case 'dbm':
            //    if (!class_exists('getID3_cached_dbm')) {
            //        require_once(dirname(__FILE__)).'/extension.cache.dbm.php';
            //    }
            //    die(' This has not be implemented, sorry for the inconvenience');
            //    break;
            
default:
                die(
' You have selected an Invalid cache type, only "sqlite3" and "mysql" are valid'."\n");
                break;
        }
        
$count = array('dir'=>0'file'=>0);
        
$dirs self::getDirs($dir);
        if (
$dirs !== null) {
            foreach (
$dirs as $d) {
                echo 
' Scanning: '.$d."\n";
                
$search self::type_brace($d$match);
                if (
$search !== null) {
                    
$files self::file_check($search);
                    if (
$files !== null) {
                        foreach (
$files as $f) {
                            echo 
' * Analyzing '.$f.' '."\n";
                            
$id3->analyze($f);
                            
$count['file']++;
                        }
                        
$count['dir']++;
                    } else {
                        echo 
'Failed to get files '."\n";
                    }
                } else {
                    echo 
'Failed to create match string '."\n";
                }
            }
            echo 
'**************************************'."\n";
            echo 
'* Finished Scanning your directories '."\n*\n";
            echo 
'* Directories '.$count['dir']."\n";
            echo 
'* Files '.$count['file']."\n";
            
$End self::getTime();
            
$t number_format(($End $Start) / 602);
            echo 
'* Time taken to scan '.$dir.' '.$t.' min '."\n";
            echo 
'**************************************'."\n";
        } else {
            echo 
' failed to get directories '."\n";
        }
    }
}

if (
PHP_SAPI === 'cli') {
    if (
count($argv) == 2) {
        if (
is_dir($argv[1])) {
            
$dir $argv[1];
        }
        if (
count(explode(','$argv[2])) > 0) {
            
$media $arg[2];
        }
    }
    echo 
' * Starting to scan directory: '.$dir."\n";
    echo 
' * Using default media types: '.implode(','$media)."\n";
    
dirscan::scan_files($dir$media$cache$database);
}