First negative search query

This commit is contained in:
James Cole 2022-09-24 18:06:01 +02:00
parent a9f2741282
commit 80a732b32b
No known key found for this signature in database
GPG Key ID: B49A324B7EAD6D80
5 changed files with 57 additions and 7 deletions

View File

@ -408,6 +408,23 @@ trait MetaCollection
return $this;
}
/**
* Limit the search to a specific bunch of categories.
*
* @param Collection $categories
*
* @return GroupCollectorInterface
*/
public function setNotCategories(Collection $categories): GroupCollectorInterface
{
if ($categories->count() > 0) {
$this->withCategoryInformation();
$this->query->whereNotIn('categories.id', $categories->pluck('id')->toArray());
}
return $this;
}
/**
* Will include category ID + name, if any.
*

View File

@ -571,6 +571,15 @@ interface GroupCollectorInterface
*/
public function setCategories(Collection $categories): GroupCollectorInterface;
/**
* Limit the search not to have a specific bunch of categories.
*
* @param Collection $categories
*
* @return GroupCollectorInterface
*/
public function setNotCategories(Collection $categories): GroupCollectorInterface;
/**
* Limit the search to a specific category.
*

View File

@ -38,6 +38,7 @@ use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
use FireflyIII\Repositories\Tag\TagRepositoryInterface;
use FireflyIII\Support\ParseDateString;
use FireflyIII\User;
use Gdbots\QueryParser\Enum\BoolOperator;
use Gdbots\QueryParser\Node\Date;
use Gdbots\QueryParser\Node\Emoji;
use Gdbots\QueryParser\Node\Emoticon;
@ -206,14 +207,18 @@ class OperatorQuerySearch implements SearchInterface
Log::debug(sprintf('Now handle Node class %s', $class));
/** @var Field $searchNode */
// used to search for x:y
$operator = strtolower($searchNode->getValue());
$value = $searchNode->getNode()->getValue();
$operator = strtolower($searchNode->getValue());
$value = $searchNode->getNode()->getValue();
$prohibited = $searchNode->getBoolOperator()->equals(BoolOperator::PROHIBITED()->getValue());
// must be valid operator:
if (in_array($operator, $this->validOperators, true) && $this->updateCollector($operator, (string) $value)) {
if (
in_array($operator, $this->validOperators, true) &&
$this->updateCollector($operator, (string) $value, $prohibited)) {
$this->operators->push(
[
'type' => self::getRootOperator($operator),
'value' => (string) $value,
'type' => self::getRootOperator($operator),
'value' => (string) $value,
'prohibited' => $prohibited,
]
);
Log::debug(sprintf('Added operator type "%s"', $operator));
@ -236,8 +241,12 @@ class OperatorQuerySearch implements SearchInterface
* @return bool
* @throws FireflyException
*/
private function updateCollector(string $operator, string $value): bool
private function updateCollector(string $operator, string $value, bool $prohibited): bool
{
if ($prohibited) {
$operator = sprintf('!%s', $operator);
}
Log::debug(sprintf('Now in updateCollector("%s", "%s")', $operator, $value));
// check if alias, replace if necessary:
@ -476,6 +485,15 @@ class OperatorQuerySearch implements SearchInterface
$this->collector->findNothing();
}
break;
case '!category_contains':
$result = $this->categoryRepository->searchCategory($value, 1337);
if ($result->count() > 0) {
$this->collector->setNotCategories($result);
}
if (0 === $result->count()) {
$this->collector->findNothing();
}
break;
//
// budgets
//

View File

@ -404,6 +404,7 @@ return [
'search_modifier_account_nr_ends' => 'Either account number / IBAN ends with ":value"',
'search_modifier_account_nr_starts' => 'Either account number / IBAN starts with ":value"',
'search_modifier_category_contains' => 'Category contains ":value"',
'search_modifier_not_category_contains' => 'Category does not contain ":value"',
'search_modifier_category_ends' => 'Category ends with ":value"',
'search_modifier_category_starts' => 'Category starts with ":value"',
'search_modifier_budget_contains' => 'Budget contains ":value"',

View File

@ -57,7 +57,12 @@
<p>{{ trans('firefly.modifiers_applies_are') }}</p>
<ul>
{% for operator in operators %}
<li>{{ trans('firefly.search_modifier_'~operator.type, {value: operator.value}) }}</li>
{% if operator.prohibited %}
<li>{{ trans('firefly.search_modifier_not_'~operator.type, {value: operator.value}) }}</li>
{% endif %}
{% if not operator.prohibited %}
<li>{{ trans('firefly.search_modifier_'~operator.type, {value: operator.value}) }}</li>
{% endif %}
{% endfor %}
</ul>
{% endif %}