adrema/app/Pdf/PdfRepositoryFactory.php

111 lines
3.2 KiB
PHP

<?php
namespace App\Pdf;
use App\Member\Member;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Collection;
use Illuminate\Support\Str;
class PdfRepositoryFactory
{
/**
* @var array<int, class-string<PdfRepository>>
*/
private array $types = [
BillType::class,
RememberType::class,
];
/**
* @return Collection<int, PdfRepository>
*/
public function getTypes(): Collection
{
return collect(array_map(fn ($classString) => new $classString(collect()), $this->types));
}
public function fromSingleRequest(string $type, Member $member): ?LetterRepository
{
$members = $this->singleMemberCollection($member, $type);
if ($members->isEmpty()) {
return null;
}
$repo = $this->resolve($type, $members);
$firstMember = $members->first()->first();
return $repo->setFilename(
Str::slug("{$repo->getSubject()} für {$firstMember->lastname}"),
);
}
public function forAll(string $type, string $billKind): ?PdfRepository
{
$members = $this->toMemberGroup($this->allMemberCollection($type, $billKind));
if ($members->isEmpty()) {
return null;
}
return $this->resolve($type, $members)->setFilename('alle-rechnungen');
}
public function repoCollection(string $type, string $billKind): Collection
{
$members = $this->toMemberGroup($this->allMemberCollection($type, $billKind));
return $members->map(function (Collection $members) use ($type) {
$repo = $this->resolve($type, collect([$members]));
return $repo->setFilename(Str::slug("{$repo->getSubject()} für {$members->first()->lastname}"));
});
}
public function afterSingle(LetterRepository $repo): void
{
foreach ($repo->allPayments() as $payment) {
$repo->afterSingle($payment);
}
}
public function afterAll(string $type, string $billKind): void
{
$members = $this->allMemberCollection($type, $billKind);
$repo = $this->resolve($type, $this->toMemberGroup($members));
$this->afterSingle($repo);
}
public function singleMemberCollection(Member $member, string $type): Collection
{
$members = Member::where($member->only(['lastname', 'address', 'zip', 'location']))
->get()
->filter(fn (Member $member) => app($type)->createable($member));
return $this->toMemberGroup($members);
}
private function allMemberCollection(string $type, string $billKind): Collection
{
return Member::whereHas('billKind', fn (Builder $q) => $q->where('name', $billKind))
->get()
->filter(fn (Member $member) => app($type)->createable($member));
}
private function resolve(string $kind, Collection $members): LetterRepository
{
return new $kind($members);
}
private function toMemberGroup(Collection $members): Collection
{
return $members->groupBy(
fn ($member) => Str::slug(
"{$member->lastname}{$member->address}{$member->zip}{$member->location}",
),
);
}
}