Skip to content

Commit

Permalink
WIP: Zwischenstand
Browse files Browse the repository at this point in the history
  • Loading branch information
corphi committed Jan 23, 2025
1 parent 778e234 commit 84c3b37
Show file tree
Hide file tree
Showing 10 changed files with 400 additions and 0 deletions.
Empty file removed webservice/src/Core/.gitignore
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php

declare(strict_types=1);

namespace App\Core\MessageRecipient\Model;

use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\Types\UlidType;
use Symfony\Component\Uid\Ulid;

#[ORM\Entity]
#[ORM\Table(name: 'message_recipient')]
#[ORM\InheritanceType('SINGLE_TABLE')]
#[ORM\DiscriminatorMap([
Group::DISCRIMINATOR => Group::class,
Person::DISCRIMINATOR => Person::class,
Role::DISCRIMINATOR => Role::class,
])]
abstract class AbstractMessageRecipient implements MessageRecipient
{
#[ORM\Column(type: UlidType::NAME)]
#[ORM\Id]
public readonly Ulid $id;

#[ORM\Column]
public string $name;

/**
* @var Collection<int, Group>
*/
#[ORM\ManyToMany(Group::class, mappedBy: 'members')]
private Collection $groups;

public function __construct(string $name, ?Ulid $id = null)
{
$this->id = $id ?? new Ulid();
$this->name = $name;
$this->groups = new ArrayCollection();
}

/**
* @return list<Group>
*/
public function getGroups(): array
{
return $this->groups->getValues();
}
}
15 changes: 15 additions & 0 deletions webservice/src/Core/MessageRecipient/Model/Delegated.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

declare(strict_types=1);

namespace App\Core\MessageRecipient\Model;

interface Delegated
{
public function canResolve(): bool;

/**
* @return list<MessageRecipient>
*/
public function resolve(): array;
}
77 changes: 77 additions & 0 deletions webservice/src/Core/MessageRecipient/Model/Group.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
<?php

declare(strict_types=1);

namespace App\Core\MessageRecipient\Model;

use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use LogicException;
use Symfony\Component\Uid\Ulid;
use Traversable;

#[ORM\Entity]
class Group extends AbstractMessageRecipient implements Delegated
{
final public const DISCRIMINATOR = 'group';

/**
* @var Collection<int, AbstractMessageRecipient>
*/
#[ORM\ManyToMany(AbstractMessageRecipient::class, inversedBy: 'groups')]
private Collection $members;

public function __construct(string $name, ?Ulid $id = null)
{
parent::__construct($name, $id);

$this->members = new ArrayCollection();
}

public function addMember(AbstractMessageRecipient $member): void
{
$this->members->add($member);
}

public function removeMember(AbstractMessageRecipient $member): void
{
$this->members->removeElement($member);
}

/**
* @return list<AbstractMessageRecipient>
*/
public function getMembers(): array
{
return $this->members->getValues();
}

/**
* @return Traversable<AbstractMessageRecipient>
*/
public function getMembersRecursively(): Traversable
{
foreach ($this->members as $member) {
if ($member instanceof self) {
yield from $member->getMembersRecursively();
} else {
yield $member;
}
}
}

public function canResolve(): bool
{
return !$this->members->isEmpty();
}

public function resolve(): array
{
if ($this->members->isEmpty()) {
throw new LogicException();
}

return $this->members->getValues();
}
}
15 changes: 15 additions & 0 deletions webservice/src/Core/MessageRecipient/Model/MessageRecipient.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

declare(strict_types=1);

namespace App\Core\MessageRecipient\Model;

use Symfony\Component\Uid\Ulid;

/**
* @property-read Ulid $id
* @property string $name
*/
interface MessageRecipient
{
}
39 changes: 39 additions & 0 deletions webservice/src/Core/MessageRecipient/Model/Person.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?php

declare(strict_types=1);

namespace App\Core\MessageRecipient\Model;

use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Uid\Ulid;

#[ORM\Entity]
class Person extends AbstractMessageRecipient
{
final public const DISCRIMINATOR = 'person';

/**
* @var Collection<int, Role>
*/
#[ORM\OneToMany(Role::class, mappedBy: 'person')]
private Collection $roles;

public function __construct(
string $name,
?Ulid $id = null,
) {
parent::__construct($name, $id);

$this->roles = new ArrayCollection();
}

/**
* @return list<Role>
*/
public function getRoles(): array
{
return $this->roles->getValues();
}
}
38 changes: 38 additions & 0 deletions webservice/src/Core/MessageRecipient/Model/Role.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?php

declare(strict_types=1);

namespace App\Core\MessageRecipient\Model;

use Doctrine\ORM\Mapping as ORM;
use LogicException;
use Symfony\Component\Uid\Ulid;

#[ORM\Entity]
class Role extends AbstractMessageRecipient implements Delegated
{
final public const DISCRIMINATOR = 'role';

public function __construct(
string $name,
#[ORM\ManyToOne(Person::class, inversedBy: 'roles')]
public ?Person $person,
?Ulid $id = null,
) {
parent::__construct($name, $id);
}

public function canResolve(): bool
{
return null !== $this->person;
}

public function resolve(): array
{
if (null === $this->person) {
throw new LogicException();
}

return [$this->person];
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php

declare(strict_types=1);

namespace App\Tests\Core\MessageRecipient\Model;

use App\Core\MessageRecipient\Model\AbstractMessageRecipient;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\Attributes\Small;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Uid\Ulid;

#[CoversClass(AbstractMessageRecipient::class)]
#[Small()]
final class AbstractMessageRecipientTest extends TestCase
{
/**
* @return array{0: string, 1: ?Ulid}[]
*/
public static function constructorProvider(): array
{
return [
['Dustin', null],
['Nilpferd', new Ulid()],
];
}

#[DataProvider('constructorProvider')]
public function testConstructor(string $name, ?Ulid $id): void
{
$recipient = new class($name, $id) extends AbstractMessageRecipient {};

if (null === $id) {
$recipient->id->toString();
} else {
self::assertSame($id, $recipient->id);
}
self::assertSame($name, $recipient->name);
self::assertSame([], $recipient->getGroups());
}
}
42 changes: 42 additions & 0 deletions webservice/tests/Core/MessageRecipient/Model/PersonTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php

declare(strict_types=1);

namespace App\Tests\Core\MessageRecipient\Model;

use App\Core\MessageRecipient\Model\Person;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\Attributes\Small;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Uid\Ulid;

#[CoversClass(Person::class)]
#[Small()]
final class PersonTest extends TestCase
{
/**
* @return array{0: string, 1: ?Ulid}[]
*/
public static function constructorProvider(): array
{
return [
['Dustin', null],
['Nilpferd', new Ulid()],
];
}

#[DataProvider('constructorProvider')]
public function testConstructor(string $name, ?Ulid $id): void
{
$person = new Person($name, $id);

if (null === $id) {
$person->id->toString();
} else {
self::assertSame($id, $person->id);
}
self::assertSame($name, $person->name);
self::assertSame([], $person->getRoles());
}
}
Loading

0 comments on commit 84c3b37

Please sign in to comment.