ebs/src/Entity/Group.php
2023-12-21 08:49:38 +01:00

387 lines
9 KiB
PHP
Executable file

<?php
declare(strict_types=1);
namespace App\Entity;
use ApiPlatform\Doctrine\Orm\Filter\OrderFilter;
use ApiPlatform\Metadata\ApiFilter;
use ApiPlatform\Metadata\ApiProperty;
use App\Doctrine\Behavior\TimestampableEntity;
use App\Enum\Group\GroupMembership;
use App\Enum\Group\GroupType;
use App\Repository\GroupRepository;
use App\Validator as AppAssert;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping as ORM;
use Gedmo\Mapping\Annotation as Gedmo;
use Symfony\Bridge\Doctrine\IdGenerator\UuidGenerator;
use Symfony\Component\Uid\Uuid;
use Symfony\Component\Validator\Constraints as Assert;
#[ORM\Entity(repositoryClass: GroupRepository::class)]
#[ORM\Table(name: '`group`')] // we need escaping here, as group is a reserved word
#[ORM\Index(columns: ['type'])]
#[ApiFilter(OrderFilter::class, properties: ['name'])]
#[AppAssert\Constraints\Group\GroupParentNotSelf]
class Group implements \Stringable
{
use TimestampableEntity;
/**
* Generates a V6 uuid.
*/
#[ORM\Id]
#[ORM\Column(type: 'uuid', unique: true)]
#[ORM\GeneratedValue(strategy: 'CUSTOM')]
#[ORM\CustomIdGenerator(class: UuidGenerator::class)]
#[ApiProperty(identifier: true)]
private Uuid $id;
/**
* Optional parent for the group.
*/
#[ORM\ManyToOne(targetEntity: self::class, inversedBy: 'children')]
private ?self $parent = null;
/**
* Type of the group. Public group are accessible by anyone while a private group
* requires an invitation.
*/
#[ORM\Column(name: 'type', type: 'string', nullable: false, enumType: GroupType::class)]
#[Assert\NotBlank]
protected GroupType $type = GroupType::PUBLIC;
/**
* Short and main name of the group.
*/
#[ORM\Column(type: Types::STRING, length: 255, nullable: false)]
#[Assert\NotBlank]
#[Assert\Length(max: 255)]
private string $name;
/**
* SEO friendly group name for URLs.
*/
#[ORM\Column(length: 255, unique: true)]
#[Gedmo\Slug(fields: ['name'])]
private string $slug;
/**
* Longer description of the group.
*/
#[ORM\Column(type: Types::TEXT, nullable: true)]
#[Assert\Length(max: 2000)]
private ?string $description = null;
/**
* Optional external URL for the group.
*/
#[ORM\Column(length: 255, nullable: true)]
#[Assert\Length(max: 255)]
#[Assert\Url]
private ?string $url = null;
/**
* @var Collection<int, self> $children
*/
#[ORM\OneToMany(mappedBy: 'parent', targetEntity: self::class)]
private Collection $children;
/**
* membership of the group. It can be free or paying.
*/
#[ORM\Column(name: 'membership', type: 'string', nullable: false, enumType: GroupMembership::class)]
protected GroupMembership $membership = GroupMembership::FREE;
/**
* If true, administrators can send invitations.
*/
#[ORM\Column(type: 'boolean', nullable: false)]
private bool $invitationByAdmin = false;
/**
* @var Collection<int, UserGroup>
*/
#[ORM\OneToMany(mappedBy: 'group', targetEntity: UserGroup::class, orphanRemoval: true)]
private Collection $userGroups;
/**
* @var Collection<int, GroupOffer>
*/
#[ORM\OneToMany(mappedBy: 'group', targetEntity: GroupOffer::class, orphanRemoval: true)]
#[ORM\OrderBy(['price' => 'ASC'])]
private Collection $offers;
/**
* List of visible product in the group.
*
* @var Collection<int, Product>
*/
#[ORM\ManyToMany(targetEntity: Product::class, mappedBy: 'groups')]
private Collection $products;
public function __construct()
{
$this->children = new ArrayCollection();
$this->userGroups = new ArrayCollection();
$this->offers = new ArrayCollection();
$this->products = new ArrayCollection();
}
public function __toString(): string
{
return $this->name;
}
public function getId(): Uuid
{
return $this->id;
}
public function setId(Uuid $uuid): self
{
$this->id = $uuid;
return $this;
}
public function getParent(): ?self
{
return $this->parent;
}
public function setParent(?self $parent): self
{
$this->parent = $parent;
return $this;
}
public function getName(): string
{
return $this->name;
}
public function setName(string $name): self
{
$this->name = $name;
return $this;
}
public function setSlug(string $slug): self
{
$this->slug = $slug;
return $this;
}
public function getSlug(): string
{
return $this->slug;
}
public function getType(): GroupType
{
return $this->type;
}
public function setType(GroupType $type): Group
{
$this->type = $type;
return $this;
}
public function getDescription(): ?string
{
return $this->description;
}
public function setDescription(?string $description): self
{
$this->description = $description;
return $this;
}
public function getUrl(): ?string
{
return $this->url;
}
public function setUrl(?string $url): self
{
$this->url = $url;
return $this;
}
/**
* @return Collection<int, self>
*/
public function getChildren(): Collection
{
return $this->children;
}
public function addChild(self $group): self
{
if (!$this->children->contains($group)) {
$this->children->add($group);
$group->setParent($this);
}
return $this;
}
public function removeChild(self $group): self
{
// set the owning side to null (unless already changed)
if ($this->children->removeElement($group) && $group->getParent() === $this) {
$group->setParent(null);
}
return $this;
}
public function getMembership(): GroupMembership
{
return $this->membership;
}
public function setMembership(GroupMembership $membership): void
{
$this->membership = $membership;
}
public function isInvitationByAdmin(): bool
{
return $this->invitationByAdmin;
}
public function setInvitationByAdmin(bool $invitationByAdmin): self
{
$this->invitationByAdmin = $invitationByAdmin;
return $this;
}
/**
* @return Collection<int, UserGroup>
*/
public function getUserGroups(): Collection
{
return $this->userGroups;
}
public function addUserGroup(UserGroup $userGroup): self
{
if (!$this->userGroups->contains($userGroup)) {
$this->userGroups->add($userGroup);
$userGroup->setGroup($this);
}
return $this;
}
public function removeUserGroup(UserGroup $userGroup): self
{
$this->userGroups->removeElement($userGroup);
return $this;
}
/**
* @return Collection<int, GroupOffer>
*/
public function getOffers(): Collection
{
return $this->offers;
}
/**
* @param Collection<int, GroupOffer> $offers
*/
public function setOffers(Collection $offers): Group
{
$this->offers = $offers;
return $this;
}
/**
* @return Collection<int, Product>
*/
public function getProducts(): Collection
{
return $this->products;
}
public function addProduct(Product $product): self
{
if (!$this->products->contains($product)) {
$this->products->add($product);
$product->addGroup($this);
}
return $this;
}
public function removeProduct(Product $product): self
{
if ($this->products->removeElement($product)) {
$product->removeGroup($this);
}
return $this;
}
// End of basic 'etters ----------------------------------------------------
/**
* @return array<string, string>
*/
public function getRoutingParameters(): array
{
return [
'id' => (string) $this->getId(),
'slug' => $this->getSlug(),
];
}
/**
* Test if a given user is main admin of the group.
*/
public function isMainAdmin(User $user): bool
{
$mainAdminUserGroups = $this->userGroups->filter(
static fn (UserGroup $userGroup) => $userGroup->getUser() === $user && $userGroup->isMainAdminAccount()
);
return !$mainAdminUserGroups->isEmpty();
}
/**
* Get active offers only.
*
* @return Collection<int, GroupOffer>
*/
public function getActiveOffers(): Collection
{
/** @var Collection<int, GroupOffer> $collection */
$collection = $this->offers->filter(
static fn (GroupOffer $groupOffer) => $groupOffer->isActive()
);
return $collection;
}
public function hasActiveOffers(): bool
{
return !$this->getActiveOffers()->isEmpty();
}
}