public static function parseQuery($query, $pageSize = -1, $pageNum = 0) { global $DEBUG; /* OVERKILL? // We change this so that we keep a TREE of possible parses. $root = new ParseNode($query, 1.0, array(), array()); */ $query = trim($query); // first thing we do is see if this is a movie title: $movieList = \Query::byTitle($query); $resultsToUnion = self::getRelevanceByTitle($movieList, $query); // TODO test this // rest of the stuff we compose / intersect movie lists $movieListToFilter = array(); // QResult 's $constraints = array(); // Constraint 's # TODO commented out 'cuz I can't connect to rotten tomatoes # self::updateData($movieListToFilter, self::trySimilarMovies($query)); // -- we don't have a title; analyze for tokens $queryC = strtolower($query); // TODO could find names by capital letter maybe // $queryC = str_replace(" with ", " and ", $queryC); $queryC = str_replace(" but ", " and ", $queryC); // first turn emotions to genres (this should be done before cleaning) self::updateData($constraints, self::emotionsToGenres($queryC)); self::applyGenreAliases($queryC); $queryC = self::cleanQuery($queryC); $queryC = addslashes($queryC); self::updateData($constraints, Constraint::findDateRangeConstraints($queryC)); self::updateData($constraints, Constraint::findLengthConstraints($queryC)); self::updateData($constraints, Constraint::findFamilyConstraints($queryC)); self::updateData($constraints, Constraint::findGenreConstraints($queryC)); // TODO these two should be moved down for the more intense type of analysis. // self::updateData($constraints, Constraint::findDirectorConstraints($queryC)); // self::updateData($constraints, Constraint::findActorConstraints($queryC)); // clean some more again ? list($words, $tokenLim, $categories) = self::tokenize($queryC); $numWords = count($words); if ($DEBUG) { // we represent it as a string now echo "{$queryC}\n"; echo self::getStringRepOfCats($categories, $tokenLim, $numWords); echo "\nconstraints:\n"; foreach ($constraints as $const) { echo "- {$const->type}: " . $const->getSQLCondition() . "\n"; } } // now find continuous sections self::updateData($constraints, self::examineSections($words, $tokenLim, $categories)); $filteredResults = self::findMovieByConstraint($movieListToFilter, $constraints); // TODO changing type of filter $results = array_merge($resultsToUnion, $filteredResults); return self::getPage($results, $pageSize, $pageNum); }
public function getSQLCondition() { $q = "("; switch ($this->type) { case "dateRange": $other = false; if (!is_null($this->data["start"])) { $q .= "year >= " . $this->data["start"]; $other = true; } if (!is_null($this->data["end"])) { if ($other) { $q .= " AND "; } $q .= "year <= " . $this->data["end"]; } break; case "length": $other = false; if (!is_null($this->data["min"])) { $q .= "runtime >= " . $this->data["min"]; $other = true; } if (!is_null($this->data["max"])) { if ($other) { $q .= " AND "; } $q .= "runtime <= " . $this->data["max"]; } break; case "famRating": $oklist = Constraint::getFamilyFriendly($this->data["lastAcceptable"]); foreach ($oklist as $ok) { $q .= "fRating=\"" . $ok . "\" OR "; } $q .= SQL_FALSE; break; case "genre": // TODO at the moment only one is set any time... later make safer if (isset($this->data["acceptable"])) { foreach ($this->data["acceptable"] as $okg) { $q .= "genre LIKE '%" . $okg . "%' OR "; } $q .= SQL_FALSE; } if (isset($this->data["not_acceptable"])) { foreach ($this->data["not_acceptable"] as $okg) { $q .= "genre NOT LIKE '%" . $okg . "%' AND "; } $q .= SQL_TRUE; } break; case "director": $q .= "directors LIKE '%" . $this->data["name"] . "%'"; break; case "actor": foreach ($this->data as $actor) { $q .= "(actors LIKE '%" . $actor . "%')"; $q .= " OR "; $q .= "(directors LIKE '%" . $actor . "%')"; // hack, also check for directors $q .= " OR "; } $q .= SQL_FALSE; break; default: throw new Exception("Invalid constraint type " . $this->type . " given for SQL condition"); } $q .= ")"; return $q; }