. */ declare(strict_types=1); namespace FireflyIII\Rules; use FireflyIII\Exceptions\FireflyException; use FireflyIII\Models\Account; use FireflyIII\Models\Bill; use FireflyIII\Models\Budget; use FireflyIII\Models\Category; use FireflyIII\Models\PiggyBank; use Illuminate\Contracts\Validation\Rule; /** * Class BelongsUser */ class BelongsUser implements Rule { /** * Create a new rule instance. * * @return void */ public function __construct() { // } /** * Get the validation error message. * * @return string */ public function message(): string { return (string)trans('validation.belongs_user'); } /** * Determine if the validation rule passes. * * @param string $attribute * @param mixed $value * * @return bool * @throws FireflyException * * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ public function passes($attribute, $value): bool { $attribute = $this->parseAttribute($attribute); if (!auth()->check()) { return true; // @codeCoverageIgnore } $attribute = (string)$attribute; switch ($attribute) { case 'piggy_bank_id': return $this->validatePiggyBankId((int)$value); case 'piggy_bank_name': return $this->validatePiggyBankName($value); case 'bill_id': return $this->validateBillId((int)$value); case 'bill_name': return $this->validateBillName($value); case 'budget_id': return $this->validateBudgetId((int)$value); case 'category_id': return $this->validateCategoryId((int)$value); case 'budget_name': return $this->validateBudgetName($value); case 'source_id': case 'destination_id': return $this->validateAccountId((int)$value); default: throw new FireflyException(sprintf('Rule BelongUser cannot handle "%s"', $attribute)); // @codeCoverageIgnore } } /** * @param string $class * @param string $field * @param string $value * * @return int * * @SuppressWarnings(PHPMD.CyclomaticComplexity) */ protected function countField(string $class, string $field, string $value): int { $objects = []; // get all objects belonging to user: if (PiggyBank::class === $class) { $objects = PiggyBank::leftJoin('accounts', 'accounts.id', '=', 'piggy_banks.account_id') ->where('accounts.user_id', '=', auth()->user()->id)->get(['piggy_banks.*']); } if (PiggyBank::class !== $class) { $objects = $class::where('user_id', '=', auth()->user()->id)->get(); } $count = 0; foreach ($objects as $object) { if (trim((string)$object->$field) === trim($value)) { $count++; } } return $count; } /** * @param string $attribute * * @return string */ private function parseAttribute(string $attribute): string { $parts = explode('.', $attribute); if (1 === \count($parts)) { return $attribute; } if (3 === \count($parts)) { return $parts[2]; } return $attribute; // @codeCoverageIgnore } /** * @param int $value * * @return bool */ private function validateAccountId(int $value): bool { $count = Account::where('id', '=', $value)->where('user_id', '=', auth()->user()->id)->count(); return 1 === $count; } /** * @param int $value * * @return bool */ private function validateBillId(int $value): bool { $count = Bill::where('id', '=', $value)->where('user_id', '=', auth()->user()->id)->count(); return 1 === $count; } /** * @param string $value * * @return bool */ private function validateBillName(string $value): bool { $count = $this->countField(Bill::class, 'name', $value); return 1 === $count; } /** * @param int $value * * @return bool */ private function validateBudgetId(int $value): bool { $count = Budget::where('id', '=', $value)->where('user_id', '=', auth()->user()->id)->count(); return 1 === $count; } /** * @param string $value * * @return bool */ private function validateBudgetName(string $value): bool { $count = $this->countField(Budget::class, 'name', $value); return 1 === $count; } /** * @param int $value * * @return bool */ private function validateCategoryId(int $value): bool { $count = Category::where('id', '=', $value)->where('user_id', '=', auth()->user()->id)->count(); return 1 === $count; } /** * @param int $value * * @return bool */ private function validatePiggyBankId(int $value): bool { $count = PiggyBank::leftJoin('accounts', 'accounts.id', '=', 'piggy_banks.account_id') ->where('piggy_banks.id', '=', $value) ->where('accounts.user_id', '=', auth()->user()->id)->count(); return 1 === $count; } /** * @param string $value * * @return bool */ private function validatePiggyBankName(string $value): bool { $count = $this->countField(PiggyBank::class, 'name', $value); return 1 === $count; } }