From ddabf6a246f4ab8a379060b16bcb00d19274cf4a Mon Sep 17 00:00:00 2001 From: James Cole Date: Tue, 3 Sep 2019 17:06:30 +0200 Subject: [PATCH] Fixes #2464 --- app/Http/Controllers/SearchController.php | 5 +- app/Repositories/Tag/TagRepository.php | 130 ++++++++++-------- .../Tag/TagRepositoryInterface.php | 8 ++ app/Support/Search/Search.php | 75 +++++----- config/firefly.php | 5 +- 5 files changed, 127 insertions(+), 96 deletions(-) diff --git a/app/Http/Controllers/SearchController.php b/app/Http/Controllers/SearchController.php index 8e7bee00df..e93eb9833f 100644 --- a/app/Http/Controllers/SearchController.php +++ b/app/Http/Controllers/SearchController.php @@ -68,10 +68,7 @@ class SearchController extends Controller $modifiers = $searcher->getModifiers(); $subTitle = (string)trans('breadcrumbs.search_result', ['query' => $query]); - return view( - 'search.index', - compact('query', 'modifiers', 'fullQuery', 'subTitle') - ); + return view('search.index', compact('query', 'modifiers', 'fullQuery', 'subTitle')); } /** diff --git a/app/Repositories/Tag/TagRepository.php b/app/Repositories/Tag/TagRepository.php index 49d550688d..e2a14df35d 100644 --- a/app/Repositories/Tag/TagRepository.php +++ b/app/Repositories/Tag/TagRepository.php @@ -74,7 +74,7 @@ class TagRepository implements TagRepositoryInterface } /** - * @param Tag $tag + * @param Tag $tag * @param Carbon $start * @param Carbon $end * @@ -92,7 +92,7 @@ class TagRepository implements TagRepositoryInterface } /** - * @param Tag $tag + * @param Tag $tag * @param Carbon $start * @param Carbon $end * @@ -156,7 +156,7 @@ class TagRepository implements TagRepositoryInterface } /** - * @param Tag $tag + * @param Tag $tag * @param Carbon $start * @param Carbon $end * @@ -206,6 +206,20 @@ class TagRepository implements TagRepositoryInterface return $this->user->tags()->whereNotNull('date')->orderBy('date', 'ASC')->first(); } + /** + * Find one or more tags based on the query. + * + * @param string $query + * + * @return Collection + */ + public function searchTag(string $query): Collection + { + $search = sprintf('%%%s%%', $query); + + return $this->user->tags()->where('tag', 'LIKE', $search)->get(['tags.*']); + } + /** * Search the users tags. * @@ -234,7 +248,7 @@ class TagRepository implements TagRepositoryInterface } /** - * @param Tag $tag + * @param Tag $tag * @param Carbon $start * @param Carbon $end * @@ -266,7 +280,7 @@ class TagRepository implements TagRepositoryInterface } /** - * @param Tag $tag + * @param Tag $tag * @param Carbon|null $start * @param Carbon|null $end * @@ -335,7 +349,7 @@ class TagRepository implements TagRepositoryInterface foreach ($tags as $tag) { $amount = (string)$tag->amount_sum; $amount = '' === $amount ? '0' : $amount; - $amountMin = bcsub($amount, $min); + $amountMin = bcsub($amount, $min); $pointsForTag = bcmul($amountMin, $pointsPerCoin); $fontSize = bcadd($minimumFont, $pointsForTag); Log::debug(sprintf('Tag "%s": Amount is %s, so points is %s', $tag->tag, $amount, $fontSize)); @@ -352,37 +366,39 @@ class TagRepository implements TagRepositoryInterface } /** - * @param int|null $year + * @param Tag $tag + * @param Carbon $start + * @param Carbon $end * - * @return Collection + * @return array */ - private function getTagsInYear(?int $year): Collection + public function transferredInPeriod(Tag $tag, Carbon $start, Carbon $end): array { - // get all tags in the year (if present): - $tagQuery = $this->user->tags() - ->leftJoin('tag_transaction_journal', 'tag_transaction_journal.tag_id', '=', 'tags.id') - ->leftJoin('transaction_journals', 'tag_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id') - ->leftJoin('transactions', 'transaction_journals.id', '=', 'transactions.transaction_journal_id') - ->where( - function (Builder $query) { - $query->where('transactions.amount', '>', 0); - $query->orWhereNull('transactions.amount'); - } - ) - ->groupBy(['tags.id', 'tags.tag']); + /** @var GroupCollectorInterface $collector */ + $collector = app(GroupCollectorInterface::class); + $collector->setUser($this->user); + $collector->setRange($start, $end)->setTypes([TransactionType::TRANSFER])->setTag($tag); - // add date range (or not): - if (null === $year) { - Log::debug('Get tags without a date.'); - $tagQuery->whereNull('tags.date'); - } - if (null !== $year) { - Log::debug(sprintf('Get tags with year %s.', $year)); - $tagQuery->where('tags.date', '>=', $year . '-01-01 00:00:00')->where('tags.date', '<=', $year . '-12-31 23:59:59'); - } + return $collector->getExtractedJournals(); + } - return $tagQuery->get(['tags.id', 'tags.tag', DB::raw('SUM(transactions.amount) as amount_sum')]); + /** + * @param Tag $tag + * @param array $data + * + * @return Tag + */ + public function update(Tag $tag, array $data): Tag + { + $tag->tag = $data['tag']; + $tag->date = $data['date']; + $tag->description = $data['description']; + $tag->latitude = $data['latitude']; + $tag->longitude = $data['longitude']; + $tag->zoomLevel = $data['zoom_level']; + $tag->save(); + return $tag; } /** @@ -436,38 +452,36 @@ class TagRepository implements TagRepositoryInterface } /** - * @param Tag $tag - * @param Carbon $start - * @param Carbon $end + * @param int|null $year * - * @return array + * @return Collection */ - public function transferredInPeriod(Tag $tag, Carbon $start, Carbon $end): array + private function getTagsInYear(?int $year): Collection { - /** @var GroupCollectorInterface $collector */ - $collector = app(GroupCollectorInterface::class); - $collector->setUser($this->user); - $collector->setRange($start, $end)->setTypes([TransactionType::TRANSFER])->setTag($tag); + // get all tags in the year (if present): + $tagQuery = $this->user->tags() + ->leftJoin('tag_transaction_journal', 'tag_transaction_journal.tag_id', '=', 'tags.id') + ->leftJoin('transaction_journals', 'tag_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id') + ->leftJoin('transactions', 'transaction_journals.id', '=', 'transactions.transaction_journal_id') + ->where( + function (Builder $query) { + $query->where('transactions.amount', '>', 0); + $query->orWhereNull('transactions.amount'); + } + ) + ->groupBy(['tags.id', 'tags.tag']); - return $collector->getExtractedJournals(); - } + // add date range (or not): + if (null === $year) { + Log::debug('Get tags without a date.'); + $tagQuery->whereNull('tags.date'); + } + if (null !== $year) { + Log::debug(sprintf('Get tags with year %s.', $year)); + $tagQuery->where('tags.date', '>=', $year . '-01-01 00:00:00')->where('tags.date', '<=', $year . '-12-31 23:59:59'); + } - /** - * @param Tag $tag - * @param array $data - * - * @return Tag - */ - public function update(Tag $tag, array $data): Tag - { - $tag->tag = $data['tag']; - $tag->date = $data['date']; - $tag->description = $data['description']; - $tag->latitude = $data['latitude']; - $tag->longitude = $data['longitude']; - $tag->zoomLevel = $data['zoom_level']; - $tag->save(); + return $tagQuery->get(['tags.id', 'tags.tag', DB::raw('SUM(transactions.amount) as amount_sum')]); - return $tag; } } diff --git a/app/Repositories/Tag/TagRepositoryInterface.php b/app/Repositories/Tag/TagRepositoryInterface.php index a8411f31ee..93e31a5e9c 100644 --- a/app/Repositories/Tag/TagRepositoryInterface.php +++ b/app/Repositories/Tag/TagRepositoryInterface.php @@ -71,6 +71,14 @@ interface TagRepositoryInterface */ public function findByTag(string $tag): ?Tag; + /** + * Find one or more tags based on the query. + * @param string $query + * + * @return Collection + */ + public function searchTag(string $query): Collection; + /** * @param int $tagId * diff --git a/app/Support/Search/Search.php b/app/Support/Search/Search.php index 32ac58a3eb..2c9f48885a 100644 --- a/app/Support/Search/Search.php +++ b/app/Support/Search/Search.php @@ -29,6 +29,7 @@ use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Repositories\Bill\BillRepositoryInterface; use FireflyIII\Repositories\Budget\BudgetRepositoryInterface; use FireflyIII\Repositories\Category\CategoryRepositoryInterface; +use FireflyIII\Repositories\Tag\TagRepositoryInterface; use FireflyIII\User; use Illuminate\Pagination\LengthAwarePaginator; use Illuminate\Support\Collection; @@ -55,6 +56,8 @@ class Search implements SearchInterface private $originalQuery = ''; /** @var float */ private $startTime; + /** @var TagRepositoryInterface */ + private $tagRepository; /** @var User */ private $user; /** @var array */ @@ -74,6 +77,7 @@ class Search implements SearchInterface $this->categoryRepository = app(CategoryRepositoryInterface::class); $this->budgetRepository = app(BudgetRepositoryInterface::class); $this->billRepository = app(BillRepositoryInterface::class); + $this->tagRepository = app(TagRepositoryInterface::class); if ('testing' === config('app.env')) { Log::warning(sprintf('%s should not be instantiated in the TEST environment!', get_class($this))); @@ -130,22 +134,6 @@ class Search implements SearchInterface } } - /** - * @param string $string - */ - private function extractModifier(string $string): void - { - $parts = explode(':', $string); - if (2 === count($parts) && '' !== trim((string)$parts[1]) && '' !== trim((string)$parts[0])) { - $type = trim((string)$parts[0]); - $value = trim((string)$parts[1]); - if (in_array($type, $this->validModifiers, true)) { - // filter for valid type - $this->modifiers->push(['type' => $type, 'value' => $value]); - } - } - } - /** * @return float */ @@ -177,6 +165,26 @@ class Search implements SearchInterface } + /** + * @param int $limit + */ + public function setLimit(int $limit): void + { + $this->limit = $limit; + } + + /** + * @param User $user + */ + public function setUser(User $user): void + { + $this->user = $user; + $this->accountRepository->setUser($user); + $this->billRepository->setUser($user); + $this->categoryRepository->setUser($user); + $this->budgetRepository->setUser($user); + } + /** * @param GroupCollectorInterface $collector * @@ -187,7 +195,7 @@ class Search implements SearchInterface { /* * TODO: - * 'bill', + * 'bill'? */ $totalAccounts = new Collection; @@ -225,6 +233,13 @@ class Search implements SearchInterface $collector->setBills($result); } break; + case 'tag': + $result = $this->tagRepository->searchTag($modifier['value']); + if ($result->count() > 0) { + $collector->setTags($result); + } + break; + break; case 'budget': $result = $this->budgetRepository->searchBudget($modifier['value']); if ($result->count() > 0) { @@ -279,22 +294,18 @@ class Search implements SearchInterface } /** - * @param int $limit + * @param string $string */ - public function setLimit(int $limit): void + private function extractModifier(string $string): void { - $this->limit = $limit; - } - - /** - * @param User $user - */ - public function setUser(User $user): void - { - $this->user = $user; - $this->accountRepository->setUser($user); - $this->billRepository->setUser($user); - $this->categoryRepository->setUser($user); - $this->budgetRepository->setUser($user); + $parts = explode(':', $string); + if (2 === count($parts) && '' !== trim((string)$parts[1]) && '' !== trim((string)$parts[0])) { + $type = trim((string)$parts[0]); + $value = trim((string)$parts[1]); + if (in_array($type, $this->validModifiers, true)) { + // filter for valid type + $this->modifiers->push(['type' => $type, 'value' => $value]); + } + } } } diff --git a/config/firefly.php b/config/firefly.php index 53577bbe73..3a91b003b2 100644 --- a/config/firefly.php +++ b/config/firefly.php @@ -516,8 +516,9 @@ return [ 'default_currency' => 'EUR', 'default_language' => 'en_US', 'search_modifiers' => ['amount_is', 'amount', 'amount_max', 'amount_min', 'amount_less', 'amount_more', 'source', 'destination', 'category', - 'budget', 'bill', 'type', 'date', 'date_before', 'date_after', 'on', 'before', 'after','from','to'], - // tag notes has_attachments + 'budget', 'bill', 'type', 'date', 'date_before', 'date_after', 'on', 'before', 'after','from','to','tag'], + // TODO notes has_attachments + 'cer_providers' => [ 'fixer' => FixerIOv2::class, 'ratesapi' => RatesApiIOv1::class,