<?php
namespace Indeed\Uap;
/*
in order to view all hooks and filters you can go to : http://{yourdomain}/wp-admin/admin.php?page=ihc_manage&tab=hooks
*/
class SearchFiltersAndHooks
{
    /**
     * @var array
     */
    private $files                    = [];
    /**
     * @var array
     */
    private $hooks                    = [];
    /**
     * @var string
     */
    private $pluginName               = '';
    /**
     * @var array
     */
    private $nameShouldContain        = [];

    /**
     * @param none
     * @return none
     */
    public function __construct()
    {

    }

    /**
     * @param string
     * @return object
     */
    public function setNameShouldContain( $input='' )
    {
        if ( is_array( $input ) ){
            $this->nameShouldContain = $input;
        } else {
            $this->nameShouldContain[] = $input;
        }
        return $this;
    }

    /**
     * @param string
     * @return object
     */
    public function setPluginName( $input='' )
    {
        $this->pluginName = $input;
        return $this;
    }

    /**
     * @param string
     * @return none
     */
    public function SearchFiles( $path='' )
    {
        if ( file_exists($path) && is_dir($path) ){
            $result = scandir($path);
            $files = array_diff($result, array('.', '..'));
            if ( count( $files ) > 0){
                foreach ( $files as $file ){
                    if ( is_file( "$path/$file" ) ){
                        $this->files[] = "$path/$file";
                    } else if( is_dir( "$path/$file" ) ){
                        $this->SearchFiles( "$path/$file" );
                    }
                }
            }
        }
    }

    /**
     * @param none
     * @return object
     */
    public function getFiles()
    {
        return $this->files;
    }

    /**
     * @param none
     * @return array
     */
    public function getResults()
    {
        if ( !$this->files ){
            return [];
        }
        foreach ( $this->files as $filePath ){
            $this->searchIntoFile( $filePath );
        }
        return $this->hooks;
    }

    /**
     * @param string
     * @return none
     */
    public function searchIntoFile( $file='' )
    {
        $contents = file_get_contents( $file );
        $pluginFileName = $file;
        if ( $this->pluginName ){
            $pluginFileName = explode( $this->pluginName, $file );
            $pluginFileName = isset( $pluginFileName[1] ) ? $pluginFileName[1] : $file;
            $pluginFileName = str_replace( '//', '/', $pluginFileName );
        }

        $this->searchForHooksIntoString( $contents, 'filter', $file, $pluginFileName );
        $this->searchForHooksIntoString( $contents, 'action', $file, $pluginFileName );

        unset( $contents );
    }

    /**
     * @param string
     * @param string
     * @param object
     * @param string
     * @return object
     */
    private function searchForHooksIntoString( &$string='', $type='', $file=null, $pluginFileName='' )
    {
        if ( $type == 'filter' ){
            $search = 'apply_filters(';
        } else {
            $search = 'do_action(';
        }

        $pattern = preg_quote( $search, '/' );
        $pattern = "/^.*$pattern.*\$/m";
        if ( preg_match_all( $pattern, $string, $matches ) ){
            foreach ( $matches[0] as $match ){
                $temporary = explode( $search, $match );
                if ( empty( $temporary[1] ) ){
                    continue;
                }
                $temporary[1] = trim( $temporary[1] );
                if ( stripos( $temporary[1], "'" ) === 0 ){
                    $temporaryName = explode( "'", $temporary[1] );
                } else {
                    $temporaryName = explode( '"', $temporary[1] );
                }
                $name = isset( $temporaryName[1] ) ? $temporaryName[1] : '';
                if ( !$this->checkName( $name ) ){
                    continue;
                }
                $description = $this->getDescription( $file, $match );
                if ( isset( $this->hooks[$name] ) ){
                    $this->hooks[$name]['file'][] = $pluginFileName;
                } else {
                    $this->hooks[$name] = [
                              'file'              => [ $pluginFileName ],
                              'description'       => $description,
                              'type'              => $type,
                    ];
                }
            }
        }
    }

    /**
     * @param string
     * @return bool
     */
    private function checkName( $name='' )
    {
        if ( !$this->nameShouldContain ){
            return true;
        }
        foreach ( $this->nameShouldContain as $nameSubstring ){
            if ( stripos( $name, $nameSubstring ) !== false ){
                return true;
            }
        }
        return false;
    }

    /**
     * @param string
     * @param string
     * @return string
     */
    private function getDescription( $fileName = '', $subString='' )
    {
        $lines = file( $fileName );
        $line = -1;
        foreach ( $lines as $lineNumber => $line ) {
            if ( strpos( $line, $subString ) !== false ) {
                $line = $lineNumber;
                break;
            }
        }
        if ( $line > -1 ){
            $line++;
            $data = $lines[$line];
            $data = trim($data);
            if ( stripos( $data, '// @description' ) === 0 ){
                $data = str_replace( '// @description', '', $data );
                return $data;
            }
        }
        return '';
    }
    
}
