ernestwisniewski/kbin

View on GitHub
src/Entity/Domain.php

Summary

Maintainability
A
1 hr
Test Coverage
F
58%
<?php

// SPDX-FileCopyrightText: 2023 /kbin contributors <https://kbin.pub/>
//
// SPDX-License-Identifier: AGPL-3.0-only

declare(strict_types=1);

namespace App\Entity;

use App\Entity\Contracts\DomainInterface;
use App\Kbin\Domain\DomainShouldRatio;
use App\Repository\DomainRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\Common\Collections\Criteria;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\ORM\Mapping\Column;
use Doctrine\ORM\Mapping\Entity;
use Doctrine\ORM\Mapping\GeneratedValue;
use Doctrine\ORM\Mapping\Id;
use Doctrine\ORM\Mapping\OneToMany;
use Doctrine\ORM\Mapping\Table;

#[Entity(repositoryClass: DomainRepository::class)]
#[Table]
#[ORM\UniqueConstraint(name: 'domain_name_idx', columns: ['name'])]
class Domain
{
    #[OneToMany(mappedBy: 'domain', targetEntity: Entry::class)]
    public Collection $entries;
    #[Column(type: 'string')]
    public string $name;
    #[Column(type: 'integer')]
    public int $entryCount = 0;
    #[Column(type: 'integer', options: ['default' => 0])]
    public int $subscriptionsCount = 0;
    #[OneToMany(mappedBy: 'domain', targetEntity: DomainSubscription::class, cascade: [
        'persist',
        'remove',
    ], orphanRemoval: true)]
    public Collection $subscriptions;
    #[Id]
    #[GeneratedValue]
    #[Column(type: 'integer')]
    private int $id;

    public function __construct(DomainInterface $entry, string $name)
    {
        $this->name = $name;
        $this->entries = new ArrayCollection();
        $this->subscriptions = new ArrayCollection();

        $this->addEntry($entry);
    }

    public function addEntry(DomainInterface $subject): self
    {
        if (!$this->entries->contains($subject)) {
            $this->entries->add($subject);
            $subject->setDomain($this);
        }

        $this->updateCounts();

        return $this;
    }

    public function updateCounts(): void
    {
        $this->entryCount = $this->entries->count();
    }

    public function getId(): ?int
    {
        return $this->id;
    }

    public function removeEntry(DomainInterface $subject): self
    {
        if ($this->entries->removeElement($subject)) {
            if ($subject->getDomain() === $this) {
                $subject->setDomain(null);
            }
        }

        $this->updateCounts();

        return $this;
    }

    public function subscribe(User $user): self
    {
        if (!$this->isSubscribed($user)) {
            $this->subscriptions->add($sub = new DomainSubscription($user, $this));
            $sub->domain = $this;
        }

        $this->updateSubscriptionsCount();

        return $this;
    }

    public function isSubscribed(User $user): bool
    {
        $criteria = Criteria::create()
            ->where(Criteria::expr()->eq('user', $user));

        return $this->subscriptions->matching($criteria)->count() > 0;
    }

    private function updateSubscriptionsCount(): void
    {
        $this->subscriptionsCount = $this->subscriptions->count();
    }

    public function unsubscribe(User $user): void
    {
        $criteria = Criteria::create()
            ->where(Criteria::expr()->eq('user', $user));

        $subscription = $this->subscriptions->matching($criteria)->first();

        if ($this->subscriptions->removeElement($subscription)) {
            if ($subscription->domain === $this) {
                $subscription->domain = null;
            }
        }

        $this->updateSubscriptionsCount();
    }

    public function shouldRatio(): bool
    {
        return DomainShouldRatio::check($this->name);
    }

    public function __sleep()
    {
        return [];
    }
}