<?php
namespace App\V4\Form\Type\Section;
use ApiPlatform\Core\DataProvider\CollectionDataProviderInterface;
use ApiPlatform\Core\DataProvider\ItemDataProviderInterface;
use ApiPlatform\Core\Exception\ResourceClassNotSupportedException;
use App\Model\Traits\TimeStampableFormType;
use App\Service\Cache\CacheManager;
use App\V4\Entity\SavedRequest;
use App\V4\Form\Type\LeaderMemberFilterTrait;
use App\V4\Model\Customer\Customer;
use App\V4\Model\Section\Section;
use App\V4\Model\Security\UserInfo;
use App\V4\Repository\SavedRequestRepository;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class SectionType extends AbstractType
{
use LeaderMemberFilterTrait;
use TimeStampableFormType;
/**
* @var CollectionDataProviderInterface
*/
private $collectionDataProvider;
/**
* @var CacheManager
*/
private $cacheManager;
/**
* @var ItemDataProviderInterface
*/
private $itemDataProvider;
/**
* @var SavedRequestRepository
*/
private $savedRequestRepository;
/**
* @param ItemDataProviderInterface $itemDataProvider
* @param CollectionDataProviderInterface $collectionDataProvider
* @param CacheManager $cacheManager
* @param SavedRequestRepository $savedRequestRepository
*/
public function __construct(
ItemDataProviderInterface $itemDataProvider,
CollectionDataProviderInterface $collectionDataProvider,
CacheManager $cacheManager,
SavedRequestRepository $savedRequestRepository
) {
$this->collectionDataProvider = $collectionDataProvider;
$this->cacheManager = $cacheManager;
$this->itemDataProvider = $itemDataProvider;
$this->savedRequestRepository = $savedRequestRepository;
}
/**
* @param FormBuilderInterface $builder
* @param array $options
*
* @return void
*
* @throws ResourceClassNotSupportedException
*/
public function buildForm(FormBuilderInterface $builder, array $options): void
{
parent::buildForm($builder, $options);
/** @var Section $section */
$section = $builder->getData();
$customerId = $section instanceof Section && $section->getCustomer() instanceof Customer
? $section->getCustomer()->getId()
: $options['customerId']
;
$customer = null !== $customerId ? $this->itemDataProvider->getItem(Customer::class, $customerId) : null;
$sections = [];
if ($customer instanceof Customer) {
$sections = $this->collectionDataProvider->getCollection(Section::class, null, [
'filters' => [
'customerId' => $customer->getId(),
],
]);
}
if ($section instanceof Section && null !== $section->getId()) {
foreach ($sections as $key => $sectionChoice) {
if ($section->getId() === $sectionChoice->getId()) {
unset($sections[$key]);
}
if ($sectionChoice->getParent() instanceof Section
&& !$this->isSelectableSection($section->getId(), $sectionChoice->getParent())) {
unset($sections[$key]);
}
}
}
$builder
->add('code', TextType::class, [
'required' => true,
])
->add('parent', ChoiceType::class, [
'choices' => $sections,
'choice_label' => 'code',
'choice_value' => 'id',
'data' => $section instanceof Section && $section->getParent() instanceof Section
? $section->getParent()->getId()
: null,
'required' => false,
])
->add('leaders', ChoiceType::class, [
'choices' => $customer instanceof Customer
? $this->getLeaderMemberChoices($this->collectionDataProvider, $customer->getId())
: [],
'choice_label' => 'fullname',
'choice_value' => 'id',
'data' => $section instanceof Section ? array_map(function (UserInfo $user) {
return $user->getId();
}, $section->getLeaders()->toArray()) : null,
'multiple' => true,
'required' => false,
])
->add('members', ChoiceType::class, [
'choices' => $customer instanceof Customer
? $this->getLeaderMemberChoices($this->collectionDataProvider, $customer->getId())
: [],
'choice_label' => 'fullname',
'choice_value' => 'id',
'data' => $section instanceof Section ? array_map(function (UserInfo $user) {
return $user->getId();
}, $section->getMembers()->toArray()) : null,
'multiple' => true,
'required' => false,
])
->add('isVisible', CheckboxType::class, [
'required' => false,
'false_values' => ['false', '0', '', null],
])
->add('customer', ChoiceType::class, [
'choices' => $customer ? [$customer] : [],
'choice_value' => 'id',
'data' => $customer instanceof Customer ? $customer->getId() : null,
'required' => false,
'attr' => [
'type' => 'hidden',
],
])
->add('sectionSavedRequests', ChoiceType::class, [
'choices' => $customer instanceof Customer
? $this->savedRequestRepository->findBy([
'customerId' => $customer->getId(),
'type' => SavedRequest::TYPE_SECTION_FILTER,
])
: [],
'choice_label' => 'name',
'choice_value' => 'id',
'data' => $section instanceof Section ? array_map(function (SavedRequest $savedRequest) {
return $savedRequest->getId();
}, $section->getSectionSavedRequests()->toArray()) : null,
'multiple' => true,
'required' => false,
]);
}
/**
* @param OptionsResolver $resolver
*
* @return void
*/
public function configureOptions(OptionsResolver $resolver): void
{
parent::configureOptions($resolver);
$resolver->setDefaults([
'data_class' => Section::class,
'customerId' => null,
'csrf_protection' => false,
'allow_extra_fields' => true,
]);
}
/**
* @param string|null $id
* @param Section $sectionChoice
*
* @return bool
*/
private function isSelectableSection(?string $id, Section $sectionChoice): bool
{
if ($id === $sectionChoice->getId()) {
return false;
}
if ($sectionChoice->getParent() instanceof Section) {
return $this->isSelectableSection($id, $sectionChoice->getParent());
}
return true;
}
}