WIP change animator field

This commit is contained in:
Julie Lenaerts 2025-06-19 13:35:17 +02:00
parent cd4fcda208
commit fab03d7c33
7 changed files with 272 additions and 14 deletions

View File

@ -221,9 +221,6 @@ final class EventController extends AbstractController
{ {
$role = 'CHILL_EVENT_CREATE'; $role = 'CHILL_EVENT_CREATE';
/**
* @var Center $centers
*/
$centers = $this->authorizationHelper->getReachableCenters($this->getUser(), $role); $centers = $this->authorizationHelper->getReachableCenters($this->getUser(), $role);
if (1 === \count($centers)) { if (1 === \count($centers)) {
@ -243,7 +240,7 @@ final class EventController extends AbstractController
->add('center_id', EntityType::class, [ ->add('center_id', EntityType::class, [
'class' => Center::class, 'class' => Center::class,
'choices' => $centers, 'choices' => $centers,
'placeholder' => '', 'placeholder' => $this->translator->trans('Pick a center'),
'label' => 'To which centre should the event be associated ?', 'label' => 'To which centre should the event be associated ?',
]) ])
->add('submit', SubmitType::class, [ ->add('submit', SubmitType::class, [

View File

@ -0,0 +1,127 @@
<?php
declare(strict_types=1);
/*
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\EventBundle\Entity;
use Chill\MainBundle\Entity\User;
use Chill\ThirdPartyBundle\Entity\ThirdParty;
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\Serializer\Annotation as Serializer;
/**
* Represents an animator that can be either a User or a ThirdParty.
*/
#[ORM\Entity]
#[ORM\Table(name: 'chill_event_animator')]
#[Assert\Expression(
'this.getUser() !== null or this.getThirdparty() !== null',
message: 'An animator must be either a User or a ThirdParty'
)]
class Animator
{
#[ORM\Id]
#[ORM\Column(type: Types::INTEGER)]
#[ORM\GeneratedValue(strategy: 'AUTO')]
private ?int $id = null;
#[ORM\ManyToOne(targetEntity: ThirdParty::class)]
#[ORM\JoinColumn(name: 'thirdparty_id', referencedColumnName: 'id', nullable: true)]
#[Serializer\Groups(['read'])]
private ?ThirdParty $thirdparty = null;
#[ORM\ManyToOne(targetEntity: User::class)]
#[ORM\JoinColumn(name: 'user_id', referencedColumnName: 'id', nullable: true)]
#[Serializer\Groups(['read'])]
private ?User $user = null;
#[ORM\ManyToOne(targetEntity: Event::class, inversedBy: 'animators')]
#[ORM\JoinColumn(name: 'event_id', referencedColumnName: 'id', nullable: false)]
private ?Event $event = null;
public function getId(): ?int
{
return $this->id;
}
public function getThirdparty(): ?ThirdParty
{
return $this->thirdparty;
}
public function setThirdparty(?ThirdParty $thirdparty): self
{
$this->thirdparty = $thirdparty;
if (null !== $thirdparty) {
$this->user = null;
}
return $this;
}
public function getUser(): ?User
{
return $this->user;
}
public function setUser(?User $user): self
{
$this->user = $user;
if (null !== $user) {
$this->thirdparty = null;
}
return $this;
}
public function getEvent(): ?Event
{
return $this->event;
}
public function setEvent(?Event $event): self
{
$this->event = $event;
return $this;
}
public function getAnimator(): User|ThirdParty|null
{
return $this->user ?? $this->thirdparty;
}
public function setAnimator(User|ThirdParty|null $animator): self
{
if ($animator instanceof User) {
$this->setUser($animator);
} elseif ($animator instanceof ThirdParty) {
$this->setThirdparty($animator);
} else {
$this->user = null;
$this->thirdparty = null;
}
return $this;
}
public function isUser(): bool
{
return null !== $this->user;
}
public function isThirdParty(): bool
{
return null !== $this->thirdparty;
}
}

View File

@ -61,11 +61,9 @@ class Event implements HasCenterInterface, HasScopeInterface, TrackCreationInter
private ?User $moderator = null; private ?User $moderator = null;
/** /**
* @var Collection<int, ThirdParty> * @var Collection<int, Animator>
*/ */
#[ORM\ManyToMany(targetEntity: ThirdParty::class)] #[ORM\OneToMany(mappedBy: 'event', targetEntity: Animator::class)]
#[Serializer\Groups(['read'])]
#[ORM\JoinTable('chill_event_thirdparty')]
private Collection $animators; private Collection $animators;
#[Assert\NotBlank] #[Assert\NotBlank]
@ -194,16 +192,16 @@ class Event implements HasCenterInterface, HasScopeInterface, TrackCreationInter
return $this->animators; return $this->animators;
} }
public function addAnimator(ThirdParty $tp): self public function addAnimator(ThirdParty|User $a): self
{ {
$this->animators->add($tp); $this->animators->add($a);
return $this; return $this;
} }
public function removeAnimator(ThirdParty $tp): void public function removeAnimator(ThirdParty|User $a): void
{ {
$this->animators->removeElement($tp); $this->animators->removeElement($a);
} }
public function getCenter(): Center public function getCenter(): Center

View File

@ -15,6 +15,7 @@ use Chill\DocStoreBundle\Entity\StoredObject;
use Chill\DocStoreBundle\Form\StoredObjectType; use Chill\DocStoreBundle\Form\StoredObjectType;
use Chill\EventBundle\Entity\BudgetTypeEnum; use Chill\EventBundle\Entity\BudgetTypeEnum;
use Chill\EventBundle\Entity\Event; use Chill\EventBundle\Entity\Event;
use Chill\EventBundle\Form\Type\PickAnimatorType;
use Chill\EventBundle\Form\Type\PickEventThemeType; use Chill\EventBundle\Form\Type\PickEventThemeType;
use Chill\EventBundle\Form\Type\PickEventTypeType; use Chill\EventBundle\Form\Type\PickEventTypeType;
use Chill\EventBundle\Repository\EventBudgetKindRepository; use Chill\EventBundle\Repository\EventBudgetKindRepository;
@ -67,8 +68,20 @@ class EventType extends AbstractType
->add('moderator', PickUserDynamicType::class, [ ->add('moderator', PickUserDynamicType::class, [
'label' => 'Pick a moderator', 'label' => 'Pick a moderator',
]) ])
->add('animators', PickThirdpartyDynamicType::class, [ ->add('animators', ChillCollectionType::class, [
'multiple' => true, 'entry_type' => PickAnimatorType::class,
'entry_options' => [
'label' => false,
],
'allow_add' => true,
'allow_delete' => true,
'by_reference' => false,
'prototype' => true,
'label' => 'Animators',
'help' => 'Add users or third parties who will animate this event',
'attr' => [
'data-collection' => 'true', // For JS handling
],
]) ])
->add('budgetElements', ChillCollectionType::class, [ ->add('budgetElements', ChillCollectionType::class, [
'entry_type' => AddEventBudgetElementType::class, 'entry_type' => AddEventBudgetElementType::class,

View File

@ -0,0 +1,56 @@
<?php
declare(strict_types=1);
/*
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\EventBundle\Form\Type;
use Chill\EventBundle\Form\DataTransformer\AnimatorCollectionTransformer;
use Chill\MainBundle\Form\Type\PickUserDynamicType;
use Chill\ThirdPartyBundle\Form\Type\PickThirdpartyDynamicType;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormView;
use Symfony\Component\OptionsResolver\OptionsResolver;
class PickAnimatorType extends AbstractType
{
public function __construct(
private EntityManagerInterface $entityManager,
) {}
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder->add('thirdparty', PickThirdpartyDynamicType::class, [
'required' => false,
])
->add('user', PickUserDynamicType::class, [
'required' => false,
]);
// Add the data transformer
// $builder->addModelTransformer(new AnimatorCollectionTransformer($this->entityManager));
}
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'data_class' => null,
'multiple' => false,
'placeholder' => 'Select an animator...',
'required' => false,
'by_reference' => false,
]);
$resolver->setAllowedTypes('multiple', 'bool');
$resolver->setAllowedTypes('placeholder', ['string', 'null']);
}
}

View File

@ -52,4 +52,8 @@ services:
tags: tags:
- { name: form.type } - { name: form.type }
Chill\EventBundle\Form\Type\PickAnimatorType:
tags:
- { name: form.type }

View File

@ -0,0 +1,63 @@
<?php
declare(strict_types=1);
namespace Chill\Migrations\Event;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
final class Version20250619102259 extends AbstractMigration
{
public function getDescription(): string
{
return 'Add animator entity to event module';
}
public function up(Schema $schema): void
{
$this->addSql(<<<'SQL'
CREATE SEQUENCE chill_event_animator_id_seq INCREMENT BY 1 MINVALUE 1 START 1
SQL);
$this->addSql(<<<'SQL'
CREATE TABLE chill_event_animator (id INT NOT NULL, thirdparty_id INT DEFAULT NULL, user_id INT DEFAULT NULL, event_id INT NOT NULL, PRIMARY KEY(id))
SQL);
$this->addSql(<<<'SQL'
CREATE INDEX IDX_A7FA35FEC7D3A8E6 ON chill_event_animator (thirdparty_id)
SQL);
$this->addSql(<<<'SQL'
CREATE INDEX IDX_A7FA35FEA76ED395 ON chill_event_animator (user_id)
SQL);
$this->addSql(<<<'SQL'
CREATE INDEX IDX_A7FA35FE71F7E88B ON chill_event_animator (event_id)
SQL);
$this->addSql(<<<'SQL'
ALTER TABLE chill_event_animator ADD CONSTRAINT FK_A7FA35FEC7D3A8E6 FOREIGN KEY (thirdparty_id) REFERENCES chill_3party.third_party (id) NOT DEFERRABLE INITIALLY IMMEDIATE
SQL);
$this->addSql(<<<'SQL'
ALTER TABLE chill_event_animator ADD CONSTRAINT FK_A7FA35FEA76ED395 FOREIGN KEY (user_id) REFERENCES users (id) NOT DEFERRABLE INITIALLY IMMEDIATE
SQL);
$this->addSql(<<<'SQL'
ALTER TABLE chill_event_animator ADD CONSTRAINT FK_A7FA35FE71F7E88B FOREIGN KEY (event_id) REFERENCES chill_event_event (id) NOT DEFERRABLE INITIALLY IMMEDIATE
SQL);
}
public function down(Schema $schema): void
{
$this->addSql(<<<'SQL'
DROP SEQUENCE chill_event_animator_id_seq CASCADE
SQL);
$this->addSql(<<<'SQL'
ALTER TABLE chill_event_animator DROP CONSTRAINT FK_A7FA35FEC7D3A8E6
SQL);
$this->addSql(<<<'SQL'
ALTER TABLE chill_event_animator DROP CONSTRAINT FK_A7FA35FEA76ED395
SQL);
$this->addSql(<<<'SQL'
ALTER TABLE chill_event_animator DROP CONSTRAINT FK_A7FA35FE71F7E88B
SQL);
$this->addSql(<<<'SQL'
DROP TABLE chill_event_animator
SQL);
}
}