searchtype = $searchtype;
if ($id) {
$info = $this->get_info($id);
foreach ($info as $key=>$value) {
$this->$key = $value;
}
$this->rules = unserialize($this->rules);
}
// Define our basetypes
$this->basetypes['numeric'][] = array(
'name' => 'gte',
'description' => T_('is greater than or equal to'),
'sql' => '>='
);
$this->basetypes['numeric'][] = array(
'name' => 'lte',
'description' => T_('is less than or equal to'),
'sql' => '<='
);
$this->basetypes['numeric'][] = array(
'name' => 'equal',
'description' => T_('is'),
'sql' => '<=>'
);
$this->basetypes['numeric'][] = array(
'name' => 'ne',
'description' => T_('is not'),
'sql' => '<>'
);
$this->basetypes['numeric'][] = array(
'name' => 'gt',
'description' => T_('is greater than'),
'sql' => '>'
);
$this->basetypes['numeric'][] = array(
'name' => 'lt',
'description' => T_('is less than'),
'sql' => '<'
);
$this->basetypes['boolean'][] = array(
'name' => 'true',
'description' => T_('is true')
);
$this->basetypes['boolean'][] = array(
'name' => 'false',
'description' => T_('is false')
);
$this->basetypes['text'][] = array(
'name' => 'contain',
'description' => T_('contains'),
'sql' => 'LIKE',
'preg_match' => array('/^/','/$/'),
'preg_replace' => array('%', '%')
);
$this->basetypes['text'][] = array(
'name' => 'notcontain',
'description' => T_('does not contain'),
'sql' => 'NOT LIKE',
'preg_match' => array('/^/','/$/'),
'preg_replace' => array('%', '%')
);
$this->basetypes['text'][] = array(
'name' => 'start',
'description' => T_('starts with'),
'sql' => 'LIKE',
'preg_match' => '/$/',
'preg_replace' => '%'
);
$this->basetypes['text'][] = array(
'name' => 'end',
'description' => T_('ends with'),
'sql' => 'LIKE',
'preg_match' => '/^/',
'preg_replace' => '%'
);
$this->basetypes['text'][] = array(
'name' => 'equal',
'description' => T_('is'),
'sql' => '='
);
$this->basetypes['text'][] = array(
'name' => 'sounds',
'description' => T_('sounds like'),
'sql' => 'SOUNDS LIKE'
);
$this->basetypes['text'][] = array(
'name' => 'notsounds',
'description' => T_('does not sound like'),
'sql' => 'NOT SOUNDS LIKE'
);
$this->basetypes['boolean_numeric'][] = array(
'name' => 'equal',
'description' => T_('is'),
'sql' => '<=>'
);
$this->basetypes['boolean_numeric'][] = array(
'name' => 'ne',
'description' => T_('is not'),
'sql' => '<>'
);
$this->basetypes['boolean_subsearch'][] = array(
'name' => 'equal',
'description' => T_('is'),
'sql' => ''
);
$this->basetypes['boolean_subsearch'][] = array(
'name' => 'ne',
'description' => T_('is not'),
'sql' => 'NOT'
);
$this->basetypes['date'][] = array(
'name' => 'lt',
'description' => T_('before'),
'sql' => '<'
);
$this->basetypes['date'][] = array(
'name' => 'gt',
'description' => T_('after'),
'sql' => '>'
);
switch ($searchtype) {
case 'song':
$this->types[] = array(
'name' => 'anywhere',
'label' => T_('Any searchable text'),
'type' => 'text',
'widget' => array('input', 'text')
);
$this->types[] = array(
'name' => 'title',
'label' => T_('Title'),
'type' => 'text',
'widget' => array('input', 'text')
);
$this->types[] = array(
'name' => 'album',
'label' => T_('Album'),
'type' => 'text',
'widget' => array('input', 'text')
);
$this->types[] = array(
'name' => 'artist',
'label' => T_('Artist'),
'type' => 'text',
'widget' => array('input', 'text')
);
$this->types[] = array(
'name' => 'comment',
'label' => T_('Comment'),
'type' => 'text',
'widget' => array('input', 'text')
);
$this->types[] = array(
'name' => 'tag',
'label' => T_('Tag'),
'type' => 'text',
'widget' => array('input', 'text')
);
$this->types[] = array(
'name' => 'file',
'label' => T_('Filename'),
'type' => 'text',
'widget' => array('input', 'text')
);
$this->types[] = array(
'name' => 'year',
'label' => T_('Year'),
'type' => 'numeric',
'widget' => array('input', 'text')
);
$this->types[] = array(
'name' => 'time',
'label' => T_('Length (in minutes)'),
'type' => 'numeric',
'widget' => array('input', 'text')
);
if (Config::get('ratings')) {
$this->types[] = array(
'name' => 'rating',
'label' => T_('Rating'),
'type' => 'numeric',
'widget' => array(
'select',
array(
'1 Star',
'2 Stars',
'3 Stars',
'4 Stars',
'5 Stars'
)
)
);
}
$this->types[] = array(
'name' => 'bitrate',
'label' => T_('Bitrate'),
'type' => 'numeric',
'widget' => array(
'select',
array(
'32',
'40',
'48',
'56',
'64',
'80',
'96',
'112',
'128',
'160',
'192',
'224',
'256',
'320'
)
)
);
$this->types[] = array(
'name' => 'played',
'label' => T_('Played'),
'type' => 'boolean',
'widget' => array('input', 'hidden')
);
$this->types[] = array(
'name' => 'added',
'label' => T_('Added'),
'type' => 'date',
'widget' => array('input', 'text')
);
$this->types[] = array(
'name' => 'updated',
'label' => T_('Updated'),
'type' => 'date',
'widget' => array('input', 'text')
);
$catalogs = array();
foreach (Catalog::get_catalogs() as $catid) {
$catalog = new Catalog($catid);
$catalog->format();
$catalogs[$catid] = $catalog->f_name;
}
$this->types[] = array(
'name' => 'catalog',
'label' => T_('Catalog'),
'type' => 'boolean_numeric',
'widget' => array('select', $catalogs)
);
$playlists = array();
foreach (Playlist::get_playlists() as $playlistid) {
$playlist = new Playlist($playlistid);
$playlist->format();
$playlists[$playlistid] = $playlist->f_name;
}
$this->types[] = array(
'name' => 'playlist',
'label' => T_('Playlist'),
'type' => 'boolean_numeric',
'widget' => array('select', $playlists)
);
$playlists = array();
foreach (Search::get_searches() as $playlistid) {
// Slightly different from the above so we don't instigate
// a vicious loop.
$playlists[$playlistid] = Search::get_name_byid($playlistid);
}
$this->types[] = array(
'name' => 'smartplaylist',
'label' => T_('Smart Playlist'),
'type' => 'boolean_subsearch',
'widget' => array('select', $playlists)
);
break;
case 'album':
$this->types[] = array(
'name' => 'title',
'label' => T_('Title'),
'type' => 'text',
'widget' => array('input', 'text')
);
$this->types[] = array(
'name' => 'year',
'label' => T_('Year'),
'type' => 'numeric',
'widget' => array('input', 'text')
);
if (Config::get('ratings')) {
$this->types[] = array(
'name' => 'rating',
'label' => T_('Rating'),
'type' => 'numeric',
'widget' => array(
'select',
array(
'1 Star',
'2 Stars',
'3 Stars',
'4 Stars',
'5 Stars'
)
)
);
}
$catalogs = array();
foreach (Catalog::get_catalogs() as $catid) {
$catalog = new Catalog($catid);
$catalog->format();
$catalogs[$catid] = $catalog->f_name;
}
$this->types[] = array(
'name' => 'catalog',
'label' => T_('Catalog'),
'type' => 'boolean_numeric',
'widget' => array('select', $catalogs)
);
$this->types[] = array(
'name' => 'tag',
'label' => T_('Tag'),
'type' => 'text',
'widget' => array('input', 'text')
);
break;
case 'video':
$this->types[] = array(
'name' => 'filename',
'label' => T_('Filename'),
'type' => 'text',
'widget' => array('input', 'text')
);
break;
case 'artist':
$this->types[] = array(
'name' => 'name',
'label' => T_('Name'),
'type' => 'text',
'widget' => array('input', 'text')
);
$this->types[] = array(
'name' => 'tag',
'label' => T_('Tag'),
'type' => 'text',
'widget' => array('input', 'text')
);
break;
} // end switch on searchtype
} // end constructor
/**
* clean_request
*
* Sanitizes raw search data
*/
public static function clean_request($data) {
foreach ($data as $key => $value) {
$prefix = substr($key, 0, 4);
$value = trim($value);
if ($prefix == 'rule' && strlen($value)) {
$request[$key] = Dba::escape($value);
}
}
// Figure out if they want an AND based search or an OR based search
switch($data['operator']) {
case 'or':
$request['operator'] = 'OR';
break;
default:
$request['operator'] = 'AND';
break;
}
// Verify the type
switch($data['type']) {
case 'album':
case 'artist':
case 'video':
case 'song':
$request['type'] = $data['type'];
break;
default:
$request['type'] = 'song';
break;
}
return $request;
} // end clean_request
/**
* get_name_byid
*
* Returns the name of the saved search corresponding to the given ID
*/
public static function get_name_byid($id) {
$sql = "SELECT `name` FROM `search` WHERE `id` = '$id'";
$db_results = Dba::read($sql);
$r = Dba::fetch_assoc($db_results);
return $r['name'];
}
/**
* get_searches
*
* Return the IDs of all saved searches accessible by the current user.
*/
public static function get_searches() {
$sql = "SELECT `id` from `search` WHERE `type`='public' OR " .
"`user`='" . $GLOBALS['user']->id . "' ORDER BY `name`";
$db_results = Dba::read($sql);
$results = array();
while ($row = Dba::fetch_assoc($db_results)) {
$results[] = $row['id'];
}
return $results;
}
/**
* run
*
* This function actually runs the search and returns an array of the
* results.
*/
public static function run($data) {
$limit = intval($data['limit']);
$data = Search::clean_request($data);
$search = new Search($data['type']);
$search->parse_rules($data);
// Generate BASE SQL
if ($limit > 0) {
$limit_sql = ' LIMIT ' . $limit;
}
$search_info = $search->to_sql();
$sql = $search_info['base'] . ' ' . $search_info['table_sql'] .
' WHERE ' . $search_info['where_sql'] . " $limit_sql";
$db_results = Dba::read($sql);
$results = array();
while ($row = Dba::fetch_assoc($db_results)) {
$results[] = $row['id'];
}
return $results;
}
/**
* delete
*
* Does what it says on the tin.
*/
public function delete() {
$id = Dba::escape($this->id);
$sql = "DELETE FROM `search` WHERE `id`='$id'";
$db_results = Dba::write($sql);
return true;
}
/**
* format
* Gussy up the data
*/
public function format() {
parent::format();
$this->f_link = '' . $this->f_name . '';
}
/**
* get_items
*
* Return an array of the items output by our search (part of the
* playlist interface).
*/
public function get_items() {
$results = array();
$sql = $this->to_sql();
$sql = $sql['base'] . ' ' . $sql['table_sql'] . ' WHERE ' .
$sql['where_sql'];
$db_results = Dba::read($sql);
while ($row = Dba::fetch_assoc($db_results)) {
$results[] = array(
'object_id' => $row['id'],
'object_type' => $this->searchtype
);
}
return $results;
}
/**
* get_random_items
*
* Returns a randomly sorted array (with an optional limit) of the items
* output by our search (part of the playlist interface)
*/
public function get_random_items($limit = null) {
$results = array();
$sql = $this->to_sql();
$sql = $sql['base'] . ' ' . $sql['table_sql'] .
' WHERE ' . $sql['where_sql'];
$sql .= ' ORDER BY RAND()';
$sql .= $limit ? ' LIMIT ' . intval($limit) : '';
$db_results = Dba::read($sql);
while ($row = Dba::fetch_assoc($db_results)) {
$results[] = array(
'object_id' => $row['id'],
'object_type' => $this->searchtype
);
}
return $results;
}
/**
* name_to_basetype
*
* Iterates over our array of types to find out the basetype for
* the passed string.
*/
public function name_to_basetype($name) {
foreach ($this->types as $type) {
if ($type['name'] == $name) {
return $type['type'];
}
}
return false;
}
/**
* parse_rules
*
* Takes an array of sanitized search data from the form and generates
* our real array from it.
*/
public function parse_rules($data) {
$this->rules = array();
foreach ($data as $rule => $value) {
if (preg_match('/^rule_(\d+)$/', $rule, $ruleID)) {
$ruleID = $ruleID[1];
foreach (explode('|', $data['rule_' . $ruleID . '_input']) as $input) {
$this->rules[] = array(
$value,
$this->basetypes[$this->name_to_basetype($value)][$data['rule_' . $ruleID . '_operator']]['name'],
$input
);
}
}
}
$this->logic_operator = $data['operator'];
}
/**
* save
*
* Save this search to the database for use as a smart playlist
*/
public function save() {
// Make sure we have a unique name
if (! $this->name) {
$this->name = $GLOBALS['user']->username . ' - ' . date('Y-m-d H:i:s', time());
}
$sql = "SELECT `id` FROM `search` WHERE `name`='$this->name'";
$db_results = Dba::read($sql);
if (Dba::num_rows($db_results)) {
$this->name .= uniqid('', true);
}
// clean up variables for insert
$name = Dba::escape($this->name);
$user = Dba::escape($GLOBALS['user']->id);
$type = Dba::escape($this->type);
$rules = serialize($this->rules);
$logic_operator = $this->logic_operator;
$sql = "INSERT INTO `search` (`name`, `type`, `user`, `rules`, `logic_operator`) VALUES ('$name', '$type', '$user', '$rules', '$logic_operator')";
$db_results = Dba::write($sql);
$insert_id = Dba::insert_id();
$this->id = $insert_id;
return $insert_id;
}
/**
* to_js
*
* Outputs the javascript necessary to re-show the current set of rules.
*/
public function to_js() {
foreach ($this->rules as $rule) {
$js .= '';
}
return $js;
}
/**
* to_sql
*
* Call the appropriate real function.
*/
public function to_sql() {
return call_user_func(array($this, $this->searchtype . "_to_sql"));
}
/**
* update
*
* This function updates the saved version with the current settings.
*/
public function update() {
if (!$this->id) {
return false;
}
$name = Dba::escape($this->name);
$user = Dba::escape($GLOBALS['user']->id);
$type = Dba::escape($this->type);
$rules = serialize($this->rules);
$logic_operator = $this->logic_operator;
$sql = "UPDATE `search` SET `name`='$name', `type`='$type', `rules`='$rules', `logic_operator`='$logic_operator' WHERE `id`='" . Dba::escape($this->id) . "'";
$db_results = Dba::write($sql);
return $db_results;
}
/**
* _mangle_data
*
* Private convenience function. Mangles the input according to a set
* of predefined rules so that we don't have to include this logic in
* foo_to_sql.
*/
private function _mangle_data($data, $type, $operator) {
if ($operator['preg_match']) {
$data = preg_replace(
$operator['preg_match'],
$operator['preg_replace'],
$data
);
}
if ($type == 'numeric') {
return intval($data);
}
if ($type == 'boolean') {
return make_bool($input);
}
return $data;
}
/**
* album_to_sql
*
* Handles the generation of the SQL for album searches.
*/
private function album_to_sql() {
$sql_logic_operator = $this->logic_operator;
$where = array();
$table = array();
$join = array();
$join['tag'] = array();
foreach ($this->rules as $rule) {
$type = $this->name_to_basetype($rule[0]);
foreach ($this->basetypes[$type] as $operator) {
if ($operator['name'] == $rule[1]) {
break;
}
}
$input = $this->_mangle_data($rule[2], $type, $operator);
$sql_match_operator = $operator['sql'];
switch ($rule[0]) {
case 'title':
$where[] = "`album`.`name` $sql_match_operator '$input'";
break;
case 'year':
$where[] = "`album`.`year` $sql_match_operator '$input'";
break;
case 'rating':
$where[] = "COALESCE(`rating`.`rating`,0) $sql_match_operator '$input'";
$join['rating'] = true;
break;
case 'catalog':
$where[] = "`song`.`catalog` $sql_match_operator '$input'";
$join['song'] = true;
break;
case 'tag':
$key = md5($input . $sql_match_operator);
$where[] = "`realtag_$key`.`match` > 0";
$join['tag'][$key] = "$sql_match_operator '$input'";
break;
default:
// Nae laird!
break;
} // switch on ruletype
} // foreach rule
$where_sql = implode(" $sql_logic_operator ", $where);
foreach ($join['tag'] as $key => $value) {
$table['tag_' . $key] =
"LEFT JOIN (" .
"SELECT `object_id`, COUNT(`name`) AS `match` ".
"FROM `tag` LEFT JOIN `tag_map` " .
"ON `tag`.`id`=`tag_map`.`tag_id` " .
"WHERE `tag_map`.`object_type`='album' " .
"AND `tag`.`name` $value GROUP BY `object_id`" .
") AS realtag_$key " .
"ON `album`.`id`=`realtag_$key`.`object_id`";
}
if ($join['song']) {
$table['song'] = "LEFT JOIN `song` ON `song`.`album`=`album`.`id`";
}
if ($join['rating']) {
$userid = $GLOBALS['user']->id;
$table['rating'] = "LEFT JOIN `rating` ON " .
"`rating`.`object_type`='album' " .
"AND `rating`.`user`='$userid' " .
"AND `rating`.`object_id`=`album`.`id`";
}
$table_sql = implode(' ', $table);
return array(
'base' => 'SELECT DISTINCT(`album`.`id`) FROM `album`',
'join' => $join,
'where' => $where,
'where_sql' => $where_sql,
'table' => $table,
'table_sql' => $table_sql
);
}
/**
* artist_to_sql
*
* Handles the generation of the SQL for artist searches.
*/
private function artist_to_sql() {
$sql_logic_operator = $this->logic_operator;
$where = array();
$table = array();
$join = array();
$join['tag'] = array();
foreach ($this->rules as $rule) {
$type = $this->name_to_basetype($rule[0]);
foreach ($this->basetypes[$type] as $operator) {
if ($operator['name'] == $rule[1]) {
break;
}
}
$input = $this->_mangle_data($rule[2], $type, $operator);
$sql_match_operator = $operator['sql'];
switch ($rule[0]) {
case 'name':
$where[] = "`artist`.`name` $sql_match_operator '$input'";
break;
case 'tag':
$key = md5($input . $sql_match_operator);
$where[] = "`realtag_$key`.`match` > 0";
$join['tag'][$key] = "$sql_match_operator '$input'";
break;
default:
// Nihil
break;
} // switch on ruletype
} // foreach rule
$where_sql = implode(" $sql_logic_operator ", $where);
foreach ($join['tag'] as $key => $value) {
$table['tag_' . $key] =
"LEFT JOIN (" .
"SELECT `object_id`, COUNT(`name`) AS `match` ".
"FROM `tag` LEFT JOIN `tag_map` " .
"ON `tag`.`id`=`tag_map`.`tag_id` " .
"WHERE `tag_map`.`object_type`='artist' " .
"AND `tag`.`name` $value GROUP BY `object_id`" .
") AS realtag_$key " .
"ON `artist`.`id`=`realtag_$key`.`object_id`";
}
$table_sql = implode(' ', $table);
return array(
'base' => 'SELECT DISTINCT(`artist`.`id`) FROM `artist`',
'join' => $join,
'where' => $where,
'where_sql' => $where_sql,
'table' => $table,
'table_sql' => $table_sql
);
}
/**
* song_to_sql
* Handles the generation of the SQL for song searches.
*/
private function song_to_sql() {
$sql_logic_operator = $this->logic_operator;
$where = array();
$table = array();
$join = array();
$join['tag'] = array();
foreach ($this->rules as $rule) {
$type = $this->name_to_basetype($rule[0]);
foreach ($this->basetypes[$type] as $operator) {
if ($operator['name'] == $rule[1]) {
break;
}
}
$input = $this->_mangle_data($rule[2], $type, $operator);
$sql_match_operator = $operator['sql'];
switch ($rule[0]) {
case 'anywhere':
$where[] = "(`artist`.`name` $sql_match_operator '$input' OR `album`.`name` $sql_match_operator '$input' OR `song_data`.`comment` $sql_match_operator '$input' OR `song`.`file` $sql_match_operator '$input' OR `song`.`title` $sql_match_operator '$input')";
$join['album'] = true;
$join['artist'] = true;
$join['song_data'] = true;
break;
case 'tag':
$key = md5($input . $sql_match_operator);
$where[] = "`realtag_$key`.`match` > 0";
$join['tag'][$key] = "$sql_match_operator '$input'";
break;
case 'title':
$where[] = "`song`.`title` $sql_match_operator '$input'";
break;
case 'album':
$where[] = "`album`.`name` $sql_match_operator '$input'";
$join['album'] = true;
break;
case 'artist':
$where[] = "`artist`.`name` $sql_match_operator '$input'";
$join['artist'] = true;
break;
case 'time':
$input = $input * 60;
$where[] = "`song`.`time` $sql_match_operator '$input'";
break;
case 'file':
$where[] = "`song`.`file` $sql_match_operator '$input'";
break;
case 'year':
$where[] = "`song`.`year` $sql_match_operator '$input'";
break;
case 'comment':
$where[] = "`song_data`.`comment` $sql_match_operator '$input'";
$join['song_data'] = true;
break;
case 'played':
$where[] = " `song`.`played` = '$input'";
break;
case 'bitrate':
$input = $input * 1000;
$where[] = "`song`.`bitrate` $sql_match_operator '$input'";
break;
case 'rating':
$where[] = "COALESCE(`rating`.`rating`,0) $sql_match_operator '$input'";
$join['rating'] = true;
break;
case 'catalog':
$where[] = "`song`.`catalog` $sql_match_operator '$input'";
break;
case 'playlist':
$join['playlist_data'] = true;
$where[] = "`playlist_data`.`playlist` $sql_match_operator '$input'";
break;
case 'smartplaylist':
$subsearch = new Search('song', $input);
$subsql = $subsearch->to_sql();
$where[] = "$sql_match_operator (" . $subsql['where_sql'] . ")";
// HACK: array_merge would potentially lose tags, since it
// overwrites. Save our merged tag joins in a temp variable,
// even though that's ugly.
$tagjoin = array_merge($subsql['join']['tag'], $join['tag']);
$join = array_merge($subsql['join'], $join);
$join['tag'] = $tagjoin;
break;
case 'added':
$input = strtotime($input);
$where[] = "`song`.`addition_time` $sql_match_operator $input";
break;
case 'updated':
$input = strtotime($input);
$where[] = "`song`.`update_time` $sql_match_operator $input";
default:
// NOSSINK!
break;
} // switch on type
} // foreach over rules
$where_sql = implode(" $sql_logic_operator ", $where);
// now that we know which things we want to JOIN...
if ($join['artist']) {
$table['artist'] = "LEFT JOIN `artist` ON `song`.`artist`=`artist`.`id`";
}
if ($join['album']) {
$table['album'] = "LEFT JOIN `album` ON `song`.`album`=`album`.`id`";
}
if ($join['song_data']) {
$table['song_data'] = "LEFT JOIN `song_data` ON `song`.`id`=`song_data`.`song_id`";
}
foreach ($join['tag'] as $key => $value) {
$table['tag_' . $key] =
"LEFT JOIN (" .
"SELECT `object_id`, COUNT(`name`) AS `match` ".
"FROM `tag` LEFT JOIN `tag_map` " .
"ON `tag`.`id`=`tag_map`.`tag_id` " .
"WHERE `tag_map`.`object_type`='song' " .
"AND `tag`.`name` $value GROUP BY `object_id`" .
") AS realtag_$key " .
"ON `song`.`id`=`realtag_$key`.`object_id`";
}
if ($join['rating']) {
$userid = $GLOBALS['user']->id;
$table['rating'] = "LEFT JOIN `rating` ON " .
"`rating`.`object_type`='song' AND " .
"`rating`.`user`='$userid' AND " .
"`rating`.`object_id`=`song`.`id`";
}
if ($join['playlist_data']) {
$table['playlist_data'] = "LEFT JOIN `playlist_data` ON `song`.`id`=`playlist_data`.`object_id` AND `playlist_data`.`object_type`='song'";
}
$table_sql = implode(' ', $table);
return array(
'base' => 'SELECT DISTINCT(`song`.`id`) FROM `song`',
'join' => $join,
'where' => $where,
'where_sql' => $where_sql,
'table' => $table,
'table_sql' => $table_sql
);
}
/**
* video_to_sql
*
* Handles the generation of the SQL for video searches.
*/
private function video_to_sql() {
$sql_logic_operator = $this->logic_operator;
$where = array();
foreach ($this->rules as $rule) {
$type = $this->name_to_basetype($rule[0]);
foreach ($this->basetypes[$type] as $operator) {
if ($operator['name'] == $rule[1]) {
break;
}
}
$input = $this->_mangle_data($rule[2], $type, $operator);
$sql_match_operator = $operator['sql'];
switch ($rule[0]) {
case 'filename':
$where[] = "`video`.`file` $sql_match_operator '$input'";
break;
default:
// WE WILLNA BE FOOLED AGAIN!
} // switch on ruletype
} // foreach rule
$where_sql = implode(" $sql_logic_operator ", $where);
return array(
'base' => 'SELECT DISTINCT(`video`.`id`) FROM `video`',
'where' => $where,
'where_sql' => $where_sql
);
}
}
?>