mirror of
https://code.mensbeam.com/MensBeam/Arsse.git
synced 2024-12-22 13:12:41 +00:00
Add text search exclusions
This commit is contained in:
parent
89f25d7b91
commit
677e33e518
2 changed files with 24 additions and 10 deletions
|
@ -159,8 +159,9 @@ class Database {
|
|||
*
|
||||
* @param string[] $terms The terms to search for
|
||||
* @param string[] $cols The columns to match against; these are -not- sanitized, so much -not- come directly from user input
|
||||
* @param boolean $matchAny Whether the search is successful when it matches any (true) or all (false) terms
|
||||
*/
|
||||
protected function generateSearch(array $terms, array $cols): array {
|
||||
protected function generateSearch(array $terms, array $cols, bool $matchAny = false): array {
|
||||
$clause = [];
|
||||
$types = [];
|
||||
$values = [];
|
||||
|
@ -176,7 +177,8 @@ class Database {
|
|||
}
|
||||
$clause[] = "(".implode(" or ", $spec).")";
|
||||
}
|
||||
$clause = "(".implode(" and ", $clause).")";
|
||||
$glue = $matchAny ? "or" : "and";
|
||||
$clause = "(".implode(" $glue ", $clause).")";
|
||||
return [$clause, $types, $values];
|
||||
}
|
||||
|
||||
|
@ -382,7 +384,7 @@ class Database {
|
|||
*
|
||||
* @param string $uer The user whose folders are to be listed
|
||||
* @param integer|null $parent Restricts the list to the descendents of the specified folder identifier
|
||||
* @param boolean $recursive Whether to list all descendents, or only direct children
|
||||
* @param boolean $recursive Whether to list all descendents (true) or only direct children (false)
|
||||
*/
|
||||
public function folderList(string $user, $parent = null, bool $recursive = true): Db\Result {
|
||||
// if the user isn't authorized to perform this action then throw an exception.
|
||||
|
@ -500,7 +502,7 @@ class Database {
|
|||
*
|
||||
* @param string $user The user who owns the folder to be validated
|
||||
* @param integer|null $id The identifier of the folder to validate; null or zero represent the implied root folder
|
||||
* @param boolean $subject Whether the folder is the subject rather than the object of the operation being performed; this only affects the semantics of the error message if validation fails
|
||||
* @param boolean $subject Whether the folder is the subject (true) rather than the object (false) of the operation being performed; this only affects the semantics of the error message if validation fails
|
||||
*/
|
||||
protected function folderValidateId(string $user, $id = null, bool $subject = false): array {
|
||||
// if the specified ID is not a non-negative integer (or null), this will always fail
|
||||
|
@ -839,7 +841,7 @@ class Database {
|
|||
*
|
||||
* @param string $user The user who owns the subscription to be validated
|
||||
* @param integer|null $id The identifier of the subscription to validate
|
||||
* @param boolean $subject Whether the subscription is the subject rather than the object of the operation being performed; this only affects the semantics of the error message if validation fails
|
||||
* @param boolean $subject Whether the subscription is the subject (true) rather than the object (false) of the operation being performed; this only affects the semantics of the error message if validation fails
|
||||
*/
|
||||
protected function subscriptionValidateId(string $user, $id, bool $subject = false): array {
|
||||
if (!ValueInfo::id($id)) {
|
||||
|
@ -1199,7 +1201,6 @@ class Database {
|
|||
"unread" => ["unread", "=", "bool", "", 1],
|
||||
"starred" => ["starred", "=", "bool", "", 1],
|
||||
];
|
||||
$optionsSeen = [];
|
||||
foreach ($options as $m => list($col, $op, $type, $pair, $max)) {
|
||||
|
||||
if (!$context->$m()) {
|
||||
|
@ -1273,12 +1274,13 @@ class Database {
|
|||
$q->setWhere("arsse_subscriptions.folder in (select folder from folders)");
|
||||
}
|
||||
// handle text-matching context options
|
||||
foreach ([
|
||||
$options = [
|
||||
"titleTerms" => [10, ["arsse_articles.title"]],
|
||||
"searchTerms" => [20, ["arsse_articles.title", "arsse_articles.content"]],
|
||||
"authorTerms" => [10, ["arsse_articles.author"]],
|
||||
"annotationTerms" => [20, ["arsse_marks.note"]],
|
||||
] as $m => list($max, $cols)) {
|
||||
];
|
||||
foreach ($options as $m => list($max, $cols)) {
|
||||
if (!$context->$m()) {
|
||||
continue;
|
||||
} elseif (!$context->$m) {
|
||||
|
@ -1288,6 +1290,17 @@ class Database {
|
|||
}
|
||||
$q->setWhere(...$this->generateSearch($context->$m, $cols));
|
||||
}
|
||||
// further handle exclusionary text-matching context options
|
||||
foreach ($options as $m => list($max, $cols)) {
|
||||
if (!$context->not->$m()) {
|
||||
continue;
|
||||
} elseif (!$context->not->$m) {
|
||||
continue;
|
||||
} elseif (sizeof($context->not->$m) > $max) {
|
||||
throw new Db\ExceptionInput("tooLong", ['field' => "$m (not)", 'action' => $this->caller(), 'max' => $max]);
|
||||
}
|
||||
$q->setWhereNot(...$this->generateSearch($context->not->$m, $cols, true));
|
||||
}
|
||||
// return the query
|
||||
return $q;
|
||||
}
|
||||
|
@ -1503,7 +1516,7 @@ class Database {
|
|||
*
|
||||
* @param string $user The user whose labels are to be listed
|
||||
* @param integer $id The numeric identifier of the article whose labels are to be listed
|
||||
* @param boolean $byName Whether to return the label names instead of the numeric label identifiers
|
||||
* @param boolean $byName Whether to return the label names (true) instead of the numeric label identifiers (false)
|
||||
*/
|
||||
public function articleLabelsGet(string $user, $id, bool $byName = false): array {
|
||||
if (!Arsse::$user->authorize($user, __FUNCTION__)) {
|
||||
|
@ -1903,7 +1916,7 @@ class Database {
|
|||
* @param integer|string $id The numeric identifier or name of the label to validate
|
||||
* @param boolean $byName Whether to interpret the $id parameter as the label's name (true) or identifier (false)
|
||||
* @param boolean $checkDb Whether to check whether the label exists (true) or only if the identifier or name is syntactically valid (false)
|
||||
* @param boolean $subject Whether the label is the subject rather than the object of the operation being performed; this only affects the semantics of the error message if validation fails
|
||||
* @param boolean $subject Whether the label is the subject (true) rather than the object (false) of the operation being performed; this only affects the semantics of the error message if validation fails
|
||||
*/
|
||||
protected function labelValidateId(string $user, $id, bool $byName, bool $checkDb = true, bool $subject = false): array {
|
||||
if (!$byName && !ValueInfo::id($id)) {
|
||||
|
|
|
@ -452,6 +452,7 @@ trait SeriesArticle {
|
|||
"Folder tree 1 excluding articles 7 and 8" => [(new Context)->folder(1)->not->articles([7,8]), [5,6]],
|
||||
"Folder tree 1 excluding no articles" => [(new Context)->folder(1)->not->articles([]), [5,6,7,8]],
|
||||
"Marked or labelled between 2000 and 2015 excluding in 2010" => [(new Context)->markedSince("2000-01-01T00:00:00Z")->notMarkedSince("2015-12-31T23:59:59")->not->markedSince("2010-01-01T00:00:00Z")->not->notMarkedSince("2010-12-31T23:59:59Z"), [1,3,5,7,8]],
|
||||
"Search with exclusion" => [(new Context)->searchTerms(["Article"])->not->searchTerms(["one", "two"]), [3]],
|
||||
];
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue