<?php
/**
 * @author     Thomas Meyer
 * @licence    http://creativecommons.org/licenses/by-nc-sa/2.5/
 * @package    yana
 * @subpackage plugins
 */

/**
 * @access     public
 * @package    yana
 * @subpackage plugins
 */
class plugin_search extends plugin 
{

    /* private */ var $search_string = "";
    /* private */ var $cache         = array();

    /**
     * Default event handler
     *
     * @access public
     * @param string $event name of the called event in lower-case
     * @param array $ARGS array of params passed to the function
     * @return boolean
     */
    function _default($event, $ARGS)
    {
        return true;
    }

    /**
     * Type: read
     * Permission: 0
     * Templates:
     *
     * @access public
     * @param array $ARGS array of params passed to the function
     * @return boolean
     */
    function search_stats ($ARGS) {
        settype($ARGS, "array");
        global $YANA;

        $statistik = new counter($this->name);
        $zahlen    = $statistik->get();
        if (!empty($zahlen)) {
            uasort($zahlen, array($this, "_sort"));
            $YANA->setVar("STATS", $zahlen);
        }

        return true;
        
    }


    /**
     * Type: read
     * Permission: 0
     * Templates:
     *
     * @access public
     * @param array $ARGS array of params passed to the function
     * @return boolean
     */
    function search_start ($ARGS) {

        global $YANA;
        settype($ARGS['target'], "string");

        $this->search_string = preg_replace("/[^\s\w\däöüß&;]/i", "", $ARGS['target']);

        if (empty($this->search_string)) {
            return true;
        }

        $statistik = new counter($this->name);
        $temp = explode(" ", strtolower($this->search_string));
        for ($i=0; $i<count($temp); $i++) 
        {
            $statistik->count($this->_encode($temp[$i]),$temp[$i]);
        }

        $trefferliste = $this->_from_cache($this->search_string);
        if (empty($trefferliste))
        $trefferliste = $this->_commit($this->search_string);

        $YANA->setVar("SUBJECT", $this->search_string);
        $target = $YANA->getVar("PROFILE.SEARCH.TARGET"); 
        if (empty($target)) {
            $target = "_self";
        }
        $prefix = $YANA->getVar("PROFILE.SEARCH.PREFIX");

        $script = "";
        for ($i=0; $i<count($trefferliste); $i++) 
        {
            if (count($trefferliste[$i])>0 && isset($trefferliste[$i][0]) && $trefferliste[$i][0] != "\n") {
                $script .= '  trefferliste[trefferliste.length] = \''.preg_replace("/%/", "#", rawurlencode('<P CLASS="ACOMMENT"><B><A HREF="'.$prefix. htmlentities(preg_replace("/^.\//", "", preg_replace("/^\n/", "", $trefferliste[$i][0]))) .'" TARGET="'.$target.'">'. $trefferliste[$i][1] .'</A></B><BR><SPAN CLASS="BESCHREIBUNG">'. $trefferliste[$i][2] .'</SPAN></P>')).'\';'."\n";
            }
        }

        $YANA->setVar("SCRIPT", $script);

        return true;

    }

    /**
     * @access private
     */
    function _from_cache($subject)
    {

        global $YANA;

        $id = $YANA->getVar('ID');
        if (empty($id)) {
            $id = "default";
        }
        $cacheFile = $YANA->getVar('TEMPDIR')."$id.cache";
        $trefferliste = array();
    
        if (file_exists($cacheFile) && is_readable($cacheFile)) {
            $this->cache = file($cacheFile);
        } else {
            return false;
        }

        $this->_cache_id($subject);
        $temp = "";
        for ($i=0;$i<sizeOf($this->cache);$i++) 
        {
            if (preg_match("/^".$subject."=/i", $this->cache[$i])) {
                $temp = preg_replace("/^".$subject."=/", "", $this->cache[$i]);
                break;
            }
        }

        if (!empty($temp)) {
            $temp = explode(";", $temp);
            $this->search_string = rawurldecode($temp[0]);
            for ($i=1;$i<sizeOf($temp);$i++) 
            {
                $trefferliste[count($trefferliste)] = explode(',',rawurldecode($temp[$i]));
            }
            return $trefferliste;
        } else {
            return false;
        }
    }

    /**
     * @access private
     */
    function _commit($subject)
    {
        global $YANA;
        $gefunden = 0; $treffer = array(); $trefferliste = array();

        $anfrage   = explode(" ", $subject);

        $keywords  = $YANA->plugins->get($this->name, "KEYWORDS");
        $documents = $YANA->plugins->get($this->name, "DOCUMENTS");

        if (!$keywords->exists() || !$documents->exists()) {
            $YANA->message("error", "search_failed");
        }

        $keywords->read();
        $KEYS = preg_replace("/\n/", "", $keywords->get());
        $KEYS = explode(", ", $KEYS);

        for ($i = 0; $i < count($anfrage); $i++) 
        {
            $enc_string  = $this->_encode($anfrage[$i]);
            $gefunden    = false;
            $max         = count($KEYS)-1;
            $min         = 0;
            $n           = floor($max /2);
            $prev_n      = array(-1,-1);

            while (!$gefunden && $max != $min) 
            {
                $temp2 = preg_replace("/=.*/i", "", $KEYS[$n]);
                $temp2 = strcasecmp($temp2, $enc_string);
                if ($temp2>0) {
                    $max = $n;
                } else if ($temp2<0) {
                    $min = $n;
                } else {
                    $treffer[$anfrage[$i]]=explode("\"", preg_replace("/.*=/i", "", $KEYS[$n]));
                    $whatsRelated = trim(preg_replace("/\|/", " ", preg_replace("/~/", $enc_string, $treffer[$anfrage[$i]][0])));
                    $whatsRelated = preg_replace("/\s\s/", " ", $whatsRelated);
                    $this->search_string .= '<div style="font-size: 10px;">' . ( $treffer[$anfrage[$i]][0] != "" && $anfrage[$i] != $whatsRelated ? '&nbsp;<a href="javascript:whatsRelated()" target="_self">%LANGUAGE.RELATED%&nbsp;&quot;' .$anfrage[$i]. '&quot;:</a> <span style="font-weight: normal">' . $whatsRelated . '</span></div>' : '' );
                    $gefunden = true;
                }

                array_shift($prev_n);
                $prev_n[count($prev_n)] = $n;

                if ($min!=$n) {
                        $n = $min + floor( ($max-$min) /2 );
                } else {
                        $n = $min + ceil( ($max-$min) /2 );
                }

                if ($prev_n[0]==$n||$prev_n[1]==$n) { 
                    $treffer[$anfrage[$i]][0]= ""; break; 
                }

            } /* end while */

        } /* for */

        if (count($treffer)>0) {
             array_shift($treffer[$anfrage[0]]); /* 0th is always empty - so drop it */
             $trefferliste=$treffer[$anfrage[0]];
        }

        /* BEGIN logical AND */
        for ($i=1;$i<count($anfrage);$i++) 
        {
            $myTemp = array();
            for ($j=1;$j<count($treffer[$anfrage[$i]]);$j++) 
            {
                if(in_array($treffer[$anfrage[$i]][$j], $trefferliste)) {
                    $myTemp[count($myTemp)] = $treffer[$anfrage[$i]][$j];
                }
            }
            $trefferliste = $myTemp;
        }
        /* END logical AND */
        
        /* BEGIN load list if documents */
        $zeile=0; $buffer = "";

        $file = fopen($documents->getFilename(), "r");
        flock($file,1);
        while (!feof($file)) 
        {
            $temp = fgetc($file);
            if ($temp == ']') {
                if (in_array((int) $zeile, $trefferliste)) {
                    $dokumente[$zeile] = explode(',',$buffer);
                }
                $buffer="";
                $zeile++;
            } else {
                $buffer .= $temp;
            }
        }
        flock($file, 3);
        fclose($file);
        /* END load list if documents */
    
        if (count($trefferliste)>=1) {
            /* resolve Ids */
            sort($anfrage);
            $this->_to_cache(implode(" ", $anfrage), $trefferliste, $dokumente);
            for ($i=0; $i<count($trefferliste); $i++) {
                if (isset($trefferliste[$i]) && $trefferliste[$i] != "") {
                    $trefferliste[$i] = $dokumente[(int) $trefferliste[$i]];
                }
            }
        }

        return $trefferliste;
    }

    /**
     * @access private
     */
    function _to_cache($subject, &$value, &$dokumente)
    {
        global $YANA;

        $id = $YANA->getVar('ID');
        if (empty($id)) {
            $id = "default";
        }
        $cacheFile = $YANA->getVar('TEMPDIR')."$id.cache";
        if (sizeOf($this->cache)>30) {
            array_pop($this->cache); 
        }
        
        $this->_cache_id($subject);
        $text = $subject.'='.rawurlencode($this->search_string).";";
    
        for ($i=0; $i<count($value); $i++) 
        {
            if (isset($dokumente[$value[$i]])) {
                $text .= rawurlencode(trim(preg_replace("/\s/s", " ", implode(",", $dokumente[$value[$i]])))).";";
            }
        }
    
        $text .= "\n" . implode("", $this->cache);
    
        if (! file_exists($cacheFile)) {
            $datei = fopen($cacheFile, "w+"); flock($datei, 2);
            fwrite($datei, $text);
            flock($datei, 3); fclose($datei);
        } else if (is_writeable($cacheFile)) {
            $datei = fopen($cacheFile, "w+"); flock($datei, 2);
            fwrite($datei, $text);
            flock($datei, 3); fclose($datei);
        } else {
            return false;
        }
    
        return true;

    }

    /**
     * @access private
     */
    function _cache_id(&$subject) {
        settype($subject, "string");
        $temp = explode(" ", $subject);
        for ($i=0;$i<sizeOf($temp);$i++) {
            $temp[$i] = $this->_encode($temp[$i]);
        }
        sort($temp);
        $subject = implode(" ", $temp);
    }

    /**
     * @access private
     */
    function _sort($A, $B) {
        if        ($A['COUNT'] < $B['COUNT']) {
            return +1;
        } else if ($A['COUNT'] > $B['COUNT']) {
            return -1;
        } else if ($A['INFO']  < $B['INFO']) {
            return -1;
        } else if ($A['INFO']  > $B['INFO']) {
            return +1;
        } else {
            return 0;
        }
    }

    /**
     * @access private
     */
    function _encode($inputString) {
    
        $inputString = strtolower($inputString);
    
        $inputString = preg_replace("/Ä/", 'a', $inputString);
        $inputString = preg_replace("/ä/", 'a', $inputString);
        $inputString = preg_replace("/\&Auml;/i", 'a', $inputString);
        $inputString = preg_replace("/\&auml;/i", 'a', $inputString);
        $inputString = preg_replace("/Ü/", 'u', $inputString);
        $inputString = preg_replace("/ü/", 'u', $inputString);
        $inputString = preg_replace("/\&Uuml;/i", 'u', $inputString);
        $inputString = preg_replace("/\&uuml;/i", 'u', $inputString);
        $inputString = preg_replace("/Ö/", 'o', $inputString);
        $inputString = preg_replace("/ö/", 'o', $inputString);
        $inputString = preg_replace("/\&Ouml;/i", 'o', $inputString);
        $inputString = preg_replace("/\&ouml;/i", 'o', $inputString);
        $inputString = preg_replace("/ß/i", 'ss', $inputString);
        $inputString = preg_replace("/\&szlig;/i", 'ss', $inputString);
        $inputString = preg_replace("/\&nbsp;/i", ' ', $inputString);
        $inputString = preg_replace("/[^\w_\s]/Ui", '', $inputString);

        global $YANA;
        $grammar = $YANA->plugins->getVar($this->name, 'GRAMMAR');

        if (in_array($inputString, $grammar['STOPWORDS'])) {
                $inputString = "";
        } else {
            foreach ($grammar['START_WORD'] as $word)
            {
                if ($inputString != $word) {
                    if (preg_match("/^$word/", $inputString)) {
                        $inputString = preg_replace("/^$word/", "", $inputString, 1);
                        break;
                    }
                }
            }
            foreach ($grammar['END_WORD'] as $word)
            {
                if ($inputString != $word) {
                    if (preg_match("/$word$/", $inputString)) {
                        $inputString = preg_replace("/$word$/", "", $inputString, 1);
                        break;
                    }
                }
            }
            $inputString = preg_replace("/ /", "", $inputString);
        }
    
        return trim($inputString);
    
    }

}

// © 2006, Thomas Meyer www.All-Community.de
// Copyright Hinweis nicht entfernen!
?>