<?

# class to turn keyword queries into sql queries
# Copyright (c) Adriane Boyd

# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA

# Use:

# $ktosql = new KeywordToSQL($querystring);
# $varnames = array("title", "notes");
# $sqlquery = $ktosql->getSQL($varnames, "or", "regexp", "[[:<:]]", "[[:>:]]");

# getSQL arguments: array of column names, string to join sets of column
#  expressions, relation for expression (like, regexp, etc.), string to put
#  before each word, string to put after each word (e.g. "%", "[[:<:]]")

# result: ($varname regexp '[[:<:]]$wordfromquerystring[[:>:]]') or $varname ...

require_once("Token.php");

# name of file containing stopwords (one per line)
$stopfile "stopwords.txt";

class 
KeywordToSQL
{
    var 
$query;    # keyword query
    
var $tarray;    # array of tokens from query

    # constructor sets up query
    
function KeywordToSQL($kquery)
    {
        
$this->query $kquery;
    }

    function 
setQuery($kquery)
    {
        
$this->query $kquery;
    }

    function 
getQuery()
    {
        return 
$this->query;
    }

    function 
getCount()
    {
        if(!
$this->getTokens())
        {
            return 
0;
        }
        
$this->deleteStopWords();
        return 
count($this->tarray);
    }

    
# tokenize the query
    
function getTokens()
    {
        
$str $this->query;
        
$str preg_replace("/[\{\}\[\]\(\)]/"""$str);
        
$t 0;
        while(
$str != "")
        {
            
$str trim($str);
            
$c substr($str01);
            if(
$c == "\"" || $c == "'")
            {
                
preg_match("/^$c([^$c]*)$c/"$str$matches);
                
$val preg_quote($matches[1]);
                
$str preg_replace("/^$c$val$c/"""$str);
                
$token = new Token($matches[1]);
            }
            else
            {
                
preg_match("/^([^\s\(\)\"\']+)/"$str$matches);
                
$val preg_quote($matches[1]);
                
$str preg_replace("/^$val/"""$str);
                
$token = new Token($matches[1]);
            }
            
$this->tarray[$t] = $token;
            
$t++;
            
# if too many terms, truncate
            
if($t 50)
            {
                return 
1;
            }
        }
        return 
1;
    }

    
# print a token array for debugging purposes
    
function printTokens($array)
    {
        for(
$i 0$i count($array); $i++)
        {
            print 
"$i: " $array[$i]->isOperator() . " " $array[$i]->getValue() . "<br>\n";
        }
    }

    
# given an array of variable names (table columns), a string to join
    # each variable set with, the relation operator, and the strings to
    # place before and after each query token in the string:
    # '$pre$word$post'
    
function getSQL($varnames$join$rel$pre$post)
    {
        if(!
$this->getTokens())
        {
            return 
0;
        }
        if(
count($this->tarray) < || count($varnames) < 1)
        {
            return 
0;
        }

        
$this->deleteStopWords();
        
$wclause $this->createWhere($varnames[0], $this->tarray$rel$pre$post);
        for(
$i 1$i count($varnames); $i++)
        {
            
$wclause .= " $join " .$this->createWhere($varnames[$i], $this->tarray$rel$pre$post);
        }
        return 
$wclause;
    }

    
# create the section of the where clause for column $varname given
    # an array of keywords, the relation operator, and pre and post
    # strings which surround the word in the expression
    
function createWhere($varname$array$rel$pre$post)
    {
        if(
count($array) == 0)
        {
            return 
0;
        }

        
$tok array_shift($array);
        
$val $tok->getEValue($rel);

        
$str "($varname $rel '$pre$val$post') ";
        while(
count($array) > 0)
        {
            
$tok array_shift($array);
            
$val $tok->getEValue($rel);
            
$str .= "and ($varname $rel '$pre$val$post') ";
        }
        return 
"( $str )";
    }

    
# read the stopword file specified at the top and delete all stopwords
    # from the array of tokens
    # if the stopword file can't be read, do nothing
    
function deleteStopWords()
    {
        global 
$stopfile;
        
$stopwords = array();
        if(!
$FILE fopen("$stopfile""r"))
        {
            return;
        }
        
$i 0;
        while(!
feof($FILE))
        {
            
$word trim(fgets($FILE30));
            
$stopwords[$word] = 1;
        }

        for(
$i 0$i count($this->tarray); $i++)
        {
            
$word strtolower($this->tarray[$i]->getValue());
            if(
$stopwords[$word] == 1)
            {
                
array_splice($this->tarray$i1);
                
$i--;
            }
        }
    }
}

?>