From 5c239c91dbd75312588653be3227d23a7467a563 Mon Sep 17 00:00:00 2001 From: Sander Kleykens Date: Thu, 6 Oct 2016 21:18:43 +0200 Subject: [PATCH] Convert raw XORs to a construct compatible with Laravel's query builder --- app/Helpers/Report/ReportHelper.php | 16 ++++++-- .../Account/AccountRepository.php | 21 ++++++++-- app/Repositories/Budget/BudgetRepository.php | 39 ++++++++++++++++--- .../Category/CategoryRepository.php | 20 ++++++++-- 4 files changed, 81 insertions(+), 15 deletions(-) diff --git a/app/Helpers/Report/ReportHelper.php b/app/Helpers/Report/ReportHelper.php index 8e9803a233..cab8f39f18 100644 --- a/app/Helpers/Report/ReportHelper.php +++ b/app/Helpers/Report/ReportHelper.php @@ -257,9 +257,19 @@ class ReportHelper implements ReportHelperInterface ->where('transaction_journals.date', '>=', $start->format('Y-m-d')) ->where('transaction_journals.date', '<=', $end->format('Y-m-d')) ->where( - function (Builder $q) use ($ids) { - $q->whereIn('source.account_id', $ids) - ->whereIn('destination.account_id', $ids, 'xor'); + // source.account_id in accountIds XOR destination.account_id in accountIds + function (Builder $sourceXorDestinationQuery) use ($ids) { + $sourceXorDestinationQuery->where( + function (Builder $inSourceButNotDestinationQuery) use ($ids) { + $inSourceButNotDestinationQuery->whereIn('source.account_id', $ids) + ->whereNotIn('destination.account_id', $ids); + } + )->orWhere( + function (Builder $inDestinationButNotSourceQuery) use ($ids) { + $inDestinationButNotSourceQuery->whereIn('destination.account_id', $ids) + ->whereNotIn('source.account_id', $ids); + } + ); } ) ->get(['tags.id', 'tags.tag', 'transaction_journals.id as journal_id', 'destination.amount']); diff --git a/app/Repositories/Account/AccountRepository.php b/app/Repositories/Account/AccountRepository.php index 9d862039fc..e8b9364705 100644 --- a/app/Repositories/Account/AccountRepository.php +++ b/app/Repositories/Account/AccountRepository.php @@ -23,6 +23,7 @@ use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\TransactionType; use FireflyIII\User; use Illuminate\Database\Eloquent\Relations\HasMany; +use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Query\JoinClause; use Illuminate\Support\Collection; use Steam; @@ -413,10 +414,24 @@ class AccountRepository implements AccountRepositoryInterface $join->on('destination.transaction_journal_id', '=', 'transaction_journals.id')->where('destination.amount', '>', 0); } ); - $set = join(', ', $accountIds); - $query->whereRaw('(source.account_id in (' . $set . ') XOR destination.account_id in (' . $set . '))'); - + $query->where( + // source.account_id in accountIds XOR destination.account_id in accountIds + function (Builder $sourceXorDestinationQuery) use ($accountIds) { + $sourceXorDestinationQuery->where( + function (Builder $inSourceButNotDestinationQuery) use ($accountIds) { + $inSourceButNotDestinationQuery->whereIn('source.account_id', $accountIds) + ->whereNotIn('destination.account_id', $accountIds); + } + )->orWhere( + function (Builder $inDestinationButNotSourceQuery) use ($accountIds) { + $inDestinationButNotSourceQuery->whereIn('destination.account_id', $accountIds) + ->whereNotIn('source.account_id', $accountIds); + } + ); + } + ); } + // that should do it: $fields = TransactionJournal::queryFields(); $complete = $query->get($fields); diff --git a/app/Repositories/Budget/BudgetRepository.php b/app/Repositories/Budget/BudgetRepository.php index d8459de23d..51e1f37a48 100644 --- a/app/Repositories/Budget/BudgetRepository.php +++ b/app/Repositories/Budget/BudgetRepository.php @@ -23,6 +23,7 @@ use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\TransactionType; use FireflyIII\User; use Illuminate\Database\Eloquent\Relations\HasMany; +use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Query\JoinClause; use Illuminate\Support\Collection; @@ -368,9 +369,22 @@ class BudgetRepository implements BudgetRepositoryInterface } if ($accounts->count() > 0) { $accountIds = $accounts->pluck('id')->toArray(); - $set = join(', ', $accountIds); - $query->whereRaw('(source.account_id in (' . $set . ') XOR destination.account_id in (' . $set . '))'); - + $query->where( + // source.account_id in accountIds XOR destination.account_id in accountIds + function (Builder $sourceXorDestinationQuery) use ($accountIds) { + $sourceXorDestinationQuery->where( + function (Builder $inSourceButNotDestinationQuery) use ($accountIds) { + $inSourceButNotDestinationQuery->whereIn('source.account_id', $accountIds) + ->whereNotIn('destination.account_id', $accountIds); + } + )->orWhere( + function (Builder $inDestinationButNotSourceQuery) use ($accountIds) { + $inDestinationButNotSourceQuery->whereIn('destination.account_id', $accountIds) + ->whereNotIn('source.account_id', $accountIds); + } + ); + } + ); } if ($budgets->count() > 0) { $budgetIds = $budgets->pluck('id')->toArray(); @@ -445,9 +459,22 @@ class BudgetRepository implements BudgetRepositoryInterface if ($accounts->count() > 0) { $accountIds = $accounts->pluck('id')->toArray(); - - $set = join(', ', $accountIds); - $query->whereRaw('(source.account_id in (' . $set . ') XOR destination.account_id in (' . $set . '))'); + $query->where( + // source.account_id in accountIds XOR destination.account_id in accountIds + function (Builder $sourceXorDestinationQuery) use ($accountIds) { + $sourceXorDestinationQuery->where( + function (Builder $inSourceButNotDestinationQuery) use ($accountIds) { + $inSourceButNotDestinationQuery->whereIn('source.account_id', $accountIds) + ->whereNotIn('destination.account_id', $accountIds); + } + )->orWhere( + function (Builder $inDestinationButNotSourceQuery) use ($accountIds) { + $inDestinationButNotSourceQuery->whereIn('destination.account_id', $accountIds) + ->whereNotIn('source.account_id', $accountIds); + } + ); + } + ); } $ids = $query->get(['transaction_journals.id'])->pluck('id')->toArray(); $sum = '0'; diff --git a/app/Repositories/Category/CategoryRepository.php b/app/Repositories/Category/CategoryRepository.php index 4f675182a5..a68c340171 100644 --- a/app/Repositories/Category/CategoryRepository.php +++ b/app/Repositories/Category/CategoryRepository.php @@ -18,6 +18,7 @@ use FireflyIII\Models\Category; use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\TransactionType; use FireflyIII\User; +use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Query\JoinClause; use Illuminate\Pagination\LengthAwarePaginator; use Illuminate\Support\Collection; @@ -487,9 +488,22 @@ class CategoryRepository implements CategoryRepositoryInterface } if ($accounts->count() > 0) { $accountIds = $accounts->pluck('id')->toArray(); - $set = join(', ', $accountIds); - $query->whereRaw('(source.account_id in (' . $set . ') XOR destination.account_id in (' . $set . '))'); - + $query->where( + // source.account_id in accountIds XOR destination.account_id in accountIds + function (Builder $sourceXorDestinationQuery) use ($accountIds) { + $sourceXorDestinationQuery->where( + function (Builder $inSourceButNotDestinationQuery) use ($accountIds) { + $inSourceButNotDestinationQuery->whereIn('source.account_id', $accountIds) + ->whereNotIn('destination.account_id', $accountIds); + } + )->orWhere( + function (Builder $inDestinationButNotSourceQuery) use ($accountIds) { + $inDestinationButNotSourceQuery->whereIn('destination.account_id', $accountIds) + ->whereNotIn('source.account_id', $accountIds); + } + ); + } + ); } if ($categories->count() > 0) { $categoryIds = $categories->pluck('id')->toArray();