View Single Post
Old 30-03-2005, 14:00   #2 (permalink)
Luke Redpath
Barney army!
 
Luke Redpath's Avatar
 
Join Date: Mar 2003
Location: London
Posts: 692
I've had a bit of spare time, so here's a nice class that encapsulates what you want to do (feel free to reuse it wherever you like). It looks lengthier than it is because of the comments and doc tags but these should help you understand the class.

I've broken down the functionality so you can provide a file to search (and it will just search for the search string in that file), or a directory, in which case it will recursively scan through the directory and sub-directories and look for the search term in each file it finds.

PHP Code:
/**
 * FileSystemStringSearch
 * Searches a file or directory of files for a search string
 */
class FileSystemStringSearch
{
    
//  MEMBERS
    
    /**
     * @var string $_searchPath path to file/directory to search
     */
    
var $_searchPath;
    
    
/**
     * @var string $_searchString the string to search for
     */
    
var $_searchString;
    
    
/**
     * @var array $_searchResults holds search result information
     */
    
var $_searchResults;
    
    
//  CONSTRUCTOR
    
    /**
     * Class constructor
     * @param string $searchPath path to file or directory to search
     * @param string $searchString string to search for
     * @return void
     */
    
function FileSystemStringSearch($searchPath$searchString)
    {
        
$this->_searchPath $searchPath;
        
$this->_searchString $searchString;
        
$this->_searchResults = array();
    }
    
    
//  MANIPULATORS
    
    /**
     * Checks path is valid
     * @return bool
     */
    
function isValidPath()
    {
        if(
file_exists($this->_searchPath)) {
            return 
true;
        } else {
            return 
false;
        }
    }
    
    
/**
     * Determines if path is a file or directory
     * @return bool
     */
    
function searchPathIsFile()
    {
        
// check for trailing slash
        
if(substr($this->_searchPath, -11)=='/' ||
           
substr($this->_searchPath, -11)=='\\') {
           return 
false;
        } else {
           return 
true;
        }
    }
    
    
/**
     * Searches given file for search term
     * @param string $file the file path
     * @return void
     */
    
function searchFileForString($file)
    {
        
// open file to an array
        
$fileLines file($file);
        
        
// loop through lines and look for search term
        
$lineNumber 1;
        foreach(
$fileLines as $line) {
            
$searchCount substr_count($line$this->_searchString);
            if(
$searchCount 0) {
                
// log result
                
$this->addResult($file$line$lineNumber$searchCount);
            }
            
$lineNumber++;
        }
    }
    
    
/**
     * Adds result to the result array
     * @param string $lineContents the line itself
     * @param int $lineNumber the file line number
     * @param int $searchCount the number of occurances of the search term
     * @return void
     */
    
function addResult($filePath$lineContents$lineNumber$searchCount)
    {
        
$this->_searchResults[] = array('filePath' => $filePath,
                                        
'lineContents' => $lineContents,
                                        
'lineNumber' => $lineNumber,
                                        
'searchCount' => $searchCount);
    }
    
    
/**
     * Takes a given string (usually a line from search results)
     * and highlights the search term
     * @param string $string the string containing the search term(s)
     * @return string
     */
    
function highlightSearchTerm($string)
    {
        return 
str_replace($this->_searchString,
                           
'<strong>'.$this->_searchString.'</strong>',
                           
$string);
    }
    
    
/**
     * Recursively scan a folder and sub folders for search term
     * @param string path to the directory to search
     * @return void
     */
    
function scanDirectoryForString($dir)
    {
        
$subDirs = array();
        
$dirFiles = array();
        
        
$dh opendir($dir);
        while((
$node readdir($dh)) !== false) {
            
// ignore . and .. nodes
            
if(!($node=='.' || $node=='..')) {
                if(
is_dir($dir.$node)) {
                    
$subDirs[] = $dir.$node.'/';
                } else {
                    
$dirFiles[] = $dir.$node;
                }
            }
        }
        
        
// loop through files and search for string
        
foreach($dirFiles as $file) {
            
$this->searchFileForString($file);
        }
        
        
// if there are sub directories, scan them
        
if(count($subDirs) > 0) {
            foreach(
$subDirs as $subDir) {
                
$this->scanDirectoryForString($subDir);
            }
        }
    }
    
    
/**
     * Run the search
     * @return void
     */
    
function run()
    {
        
// check path exists
        
if($this->isValidPath()) {
        
            if(
$this->searchPathIsFile()) {
                
// run search on the file
                
$this->searchFileForString($this->_searchPath);
            } else {
                
// scan directory contents for string
                
$this->scanDirectoryForString($this->_searchPath);
            }
         
         } else {
         
            die(
'FileSystemStringSearch Error: File/Directory does not exist');
         
         }
    }
    
    
//  ACCESSORS
    
function getResults()
    {
        return 
$this->_searchResults;
    }
    
    function 
getResultCount()
    {
        
$count 0;
        foreach(
$this->_searchResults as $result) {
            
$count += $result['searchCount'];
        }
        return 
$count;
    }
    
    function 
getSearchPath()
    {
        return 
$this->_searchPath;
    }
    
    function 
getSearchString()
    {
        return 
$this->_searchString;
    }


Here's some example usage:

PHP Code:
$searcher = new FileSystemStringSearch('/path/to/some/file/or/directory/''somesearchterm');
$searcher->run();

if(
$searcher->getResultCount() > 0) {
    echo(
'<p>Searched "'.$searcher->getSearchPath().'" for string <strong>"'.$searcher->getSearchString().'":</strong></p>');
    echo(
'<p>Search term found <strong>'.$searcher->getResultCount().' times.</strong></p>');
    echo(
'<ul>');
        foreach(
$searcher->getResults() as $result) {
            echo(
'<li><em>'.$result['filePath'].', line '.$result['lineNumber'].'</em>:<br />
                                            '
.$searcher->highlightSearchTerm($result['lineContents']).'</li>');
        }
    echo(
'</ul>');
} else {
    echo(
'<p>Searched "'.$searcher->getSearchPath().'" for string <strong>"'.$searcher->getSearchString().'":</strong></p>');
    echo(
'<p>No results returned</p>');


Just one thing to remember...to search through a directory, make sure the directory path has a trailing slash (or the class will think its a file).

Hope that helps.
__________________

Last edited by Luke Redpath : 31-03-2005 at 02:37.
  Reply With Quote