feat(search): ✨ add proper DB tag searching
This commit is contained in:
parent
f9cfb81079
commit
22c953793c
4 changed files with 147 additions and 20 deletions
|
@ -80,6 +80,16 @@ interface PostdataInterface {
|
|||
$order_by = 'path');
|
||||
|
||||
public function get_post_markdown($id);
|
||||
|
||||
|
||||
// Returns an array of PostData information
|
||||
// based on the tag search list
|
||||
//
|
||||
// Tag searchlist is comprised of space-separated
|
||||
// tags. Each tag can have a weighting prefix,
|
||||
// and some special tags exist (such as limit:N,
|
||||
// order:S).
|
||||
public function search_posts($taglist);
|
||||
}
|
||||
|
||||
?>
|
|
@ -3,23 +3,7 @@
|
|||
require_once 'analytics_interface.php';
|
||||
require_once 'db_interface.php';
|
||||
|
||||
function taglist_escape_tag($tag) {
|
||||
return preg_replace_callback('/[\WZ]/', function($match) {
|
||||
return "Z" . ord($match[0]);
|
||||
}, strtolower($tag));
|
||||
}
|
||||
|
||||
function taglist_to_sql_string($post_tags) {
|
||||
$post_tags = array_unique($post_tags);
|
||||
$post_tags = array_map(function($val) {
|
||||
return taglist_escape_tag($val);
|
||||
}, $post_tags);
|
||||
|
||||
asort($post_tags);
|
||||
$post_tags = join(' ', $post_tags);
|
||||
|
||||
return $post_tags;
|
||||
}
|
||||
require_once 'mysql_taglist_handling.php';
|
||||
|
||||
class MySQLHandler
|
||||
implements PostdataInterface {
|
||||
|
@ -128,7 +112,7 @@ class MySQLHandler
|
|||
$post_path,
|
||||
substr_count($post_path, "/"),
|
||||
$data['title'],
|
||||
taglist_to_sql_string($post_tags),
|
||||
TagList\create_db_str($post_tags),
|
||||
$data['brief'] ?? null
|
||||
];
|
||||
|
||||
|
@ -292,8 +276,8 @@ class MySQLHandler
|
|||
'path DESC' => true,
|
||||
'created_at' => true,
|
||||
'created_at DESC' => true,
|
||||
'modified_at' => true,
|
||||
'modified_at DESC' => true
|
||||
'updated_at' => true,
|
||||
'updated_at DESC' => true
|
||||
];
|
||||
|
||||
if(!isset($allowed_ordering[$order_by])) {
|
||||
|
@ -342,6 +326,52 @@ class MySQLHandler
|
|||
|
||||
return $data['post_markdown'];
|
||||
}
|
||||
|
||||
public function search_posts($taglist) {
|
||||
$qry = "
|
||||
SELECT *
|
||||
FROM posts
|
||||
WHERE MATCH(post_tags) AGAINST (? IN BOOLEAN MODE)
|
||||
";
|
||||
|
||||
$search_data = TagList\create_db_search($taglist);
|
||||
|
||||
$order_by = $search_data['modifiers']['order_by'] ?? 'updated_at';
|
||||
$limit = intval($search_data['modifiers']['limit'] ?? 20);
|
||||
$offset = intval($search_data['modifiers']['offset'] ?? 0);
|
||||
|
||||
if($limit > 100) {
|
||||
throw new Exception('Search limit above maximum (max 100 results per search)');
|
||||
}
|
||||
|
||||
$allowed_ordering = [
|
||||
'path' => true,
|
||||
'path DESC' => true,
|
||||
'created_at' => true,
|
||||
'created_at DESC' => true,
|
||||
'updated_at' => true,
|
||||
'updated_at DESC' => true
|
||||
];
|
||||
// TODO move this to a class var
|
||||
|
||||
if(!isset($allowed_ordering[$order_by])) {
|
||||
throw new Exception('Search order not allowed');
|
||||
}
|
||||
$order_by = 'post_' . $order_by;
|
||||
|
||||
$qry = $qry . " ORDER BY " . $order_by . " LIMIT ? OFFSET ?";
|
||||
|
||||
$search_results = $this->_exec($qry, "sii", $search_data['parameter_string'],
|
||||
$limit, $offset)->fetch_all(MYSQLI_ASSOC);
|
||||
|
||||
$outdata = [];
|
||||
foreach($search_results AS $post_element) {
|
||||
$outdata []=
|
||||
$this->process_postdata($post_element);
|
||||
}
|
||||
|
||||
return $outdata;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
76
www/src/db_handler/mysql_taglist_handling.php
Normal file
76
www/src/db_handler/mysql_taglist_handling.php
Normal file
|
@ -0,0 +1,76 @@
|
|||
<?php
|
||||
namespace TagList;
|
||||
|
||||
function escape_entry($tag) {
|
||||
return preg_replace_callback('/[\WZ]/', function($match) {
|
||||
return "Z" . ord($match[0]);
|
||||
}, strtolower($tag));
|
||||
}
|
||||
|
||||
function escape_search_entry($tag) {
|
||||
preg_match("/^([\+\-]?)([^\*]*)(\*?)$/", $tag, $matches);
|
||||
|
||||
if(!isset($matches[1])) {
|
||||
echo "Problem with tag!";
|
||||
var_dump($tag);
|
||||
}
|
||||
|
||||
return $matches[1] . escape_entry($matches[2]) . $matches[3];
|
||||
}
|
||||
|
||||
function _str_to_raw_taglist($taglist) {
|
||||
$split_list = explode(' ', $taglist);
|
||||
|
||||
$split_list = array_filter($split_list, function($entry) {
|
||||
return !preg_match('/^\s*$/', $entry);
|
||||
});
|
||||
|
||||
return $split_list;
|
||||
}
|
||||
|
||||
function create_db_str($taglist) {
|
||||
if(gettype($taglist) == 'string') {
|
||||
$taglist = _str_to_raw_taglist($taglist);
|
||||
}
|
||||
|
||||
$taglist = array_unique($taglist);
|
||||
$taglist = array_map(function($val) {
|
||||
return escape_entry($val);
|
||||
}, $taglist);
|
||||
|
||||
asort($taglist);
|
||||
$taglist = join(' ', $taglist);
|
||||
|
||||
return $taglist;
|
||||
}
|
||||
|
||||
function create_db_search($taglist) {
|
||||
if(gettype($taglist) == 'string') {
|
||||
$taglist = _str_to_raw_taglist($taglist);
|
||||
}
|
||||
|
||||
$search_params = [];
|
||||
$search_modifiers = [];
|
||||
|
||||
foreach($taglist as $tag) {
|
||||
if(preg_match('/^(order|limit):(.*)$/i', $tag, $match)) {
|
||||
$search_modifiers[$match[1]] = $match[2];
|
||||
} else {
|
||||
array_push($search_params, $tag);
|
||||
}
|
||||
}
|
||||
|
||||
$search_params = array_map(function($val) {
|
||||
return escape_search_entry($val);
|
||||
}, $search_params);
|
||||
|
||||
asort($search_params);
|
||||
$search_params = join(' ', $search_params);
|
||||
|
||||
return [
|
||||
'modifiers' => $search_modifiers,
|
||||
'parameter_string' => $search_params
|
||||
];
|
||||
}
|
||||
|
||||
?>
|
|
@ -56,6 +56,17 @@ class PostHandler {
|
|||
|
||||
return $out_list;
|
||||
}
|
||||
|
||||
public function search_posts($search_query) {
|
||||
$search_results = $this->db->search_posts($search_query);
|
||||
|
||||
$out_list = [];
|
||||
foreach($search_results as $search_result) {
|
||||
array_push($out_list, new Post($this, $search_result, $this->site_defaults));
|
||||
}
|
||||
|
||||
return $out_list;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
Loading…
Add table
Add a link
Reference in a new issue