<?php
namespace App\V4\Form\Type\Task;
use ApiPlatform\Core\DataProvider\CollectionDataProviderInterface;
use App\Form\Type\AbstractViewOrderAwareType;
use App\Form\Type\Compare\DateCompareType;
use App\Form\Type\SubresourceChoicesTrait;
use App\Listing\Transformer\ListingResponseTransformer;
use App\Model\IriNormalizableInterface;
use App\Model\Traits\TimeStampableFormType;
use App\Model\ViewOrder\ViewOrder;
use App\Security\SecurityConfig;
use App\Service\ApiWebServiceFilterBuilder\ListWithEmptyFilterBuilder;
use App\Service\Cache\CacheManager;
use App\V4\Form\AsyncSubresourceChoicesLoader;
use App\V4\Form\Type\IdSearchTypeTrait;
use App\V4\Form\Type\ManagedByFilterTrait;
use App\V4\Form\Type\SectionNameFilterTrait;
use App\V4\Logger\SentryLogger;
use App\V4\Model\Contact\Contact;
use App\V4\Model\Task\Task;
use App\V4\Model\Task\TaskSearch;
use App\V4\Model\TaskType\TaskType;
use Psr\Cache\CacheException;
use Psr\Cache\InvalidArgumentException;
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\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Component\Security\Core\Security;
use Symfony\Contracts\Translation\TranslatorInterface;
class TaskSearchType extends AbstractViewOrderAwareType
{
use ManagedByFilterTrait;
use SectionNameFilterTrait;
use TimeStampableFormType;
use SubresourceChoicesTrait {
getEntityChoices as private getEntityChoicesTrait;
}
use IdSearchTypeTrait;
/**
* @var CollectionDataProviderInterface
*/
private $collectionDataProvider;
/**
* @var CacheManager
*/
private $cacheManager;
/**
* @var Security
*/
private $security;
/**
* @var RouterInterface
*/
private $router;
/**
* @var TranslatorInterface
*/
private $translator;
/**
* @var SentryLogger
*/
private $sentryLogger;
/**
* @param CollectionDataProviderInterface $collectionDataProvider
* @param CacheManager $cacheManager
* @param Security $security
* @param RouterInterface $router
* @param TranslatorInterface $translator
* @param SentryLogger $sentryLogger
*/
public function __construct(
CollectionDataProviderInterface $collectionDataProvider,
CacheManager $cacheManager,
Security $security,
RouterInterface $router,
TranslatorInterface $translator,
SentryLogger $sentryLogger
) {
$this->collectionDataProvider = $collectionDataProvider;
$this->cacheManager = $cacheManager;
$this->security = $security;
$this->router = $router;
$this->translator = $translator;
$this->sentryLogger = $sentryLogger;
}
/**
* @param FormBuilderInterface $builder
* @param array $options
*
* @return void
*
* @throws CacheException
* @throws InvalidArgumentException
*/
public function buildForm(FormBuilderInterface $builder, array $options): void
{
parent::buildForm($builder, $options);
$this->addIdsField($builder);
$builder
->add('name', TextType::class, [
'label' => 'task_object',
'attr' => [
'data-get-url' => $this->router->generate('get_task_names'),
'data-field' => 'name',
'type' => 'autocomplete',
],
])
->add('taskType', ChoiceType::class, [
'choices' => $this->getEntityChoices(TaskType::class, [], 'name'),
'choice_label' => 'name',
'choice_value' => 'id',
'multiple' => true,
])
->add('contactsConcerned', ChoiceType::class, [
'label' => 'contactsConcerned',
'choice_label' => 'name',
'choice_value' => 'id',
'choice_loader' => new AsyncSubresourceChoicesLoader(
$this->collectionDataProvider,
$this->cacheManager,
$this->sentryLogger,
Contact::class
),
'multiple' => true,
'attr' => [
'type' => 'autocomplete',
'autocomplete_entity' => 'contact',
ListingResponseTransformer::FORM_FILTER_KEY => 'contacts',
],
])
->add('taskPeriod', ChoiceType::class, [
'label' => 'taskPeriod',
'choices' => [
$this->translator->trans('of_day') => 'day',
$this->translator->trans('of_week') => 'week',
$this->translator->trans('of_month') => 'month',
$this->translator->trans('all') => 'all',
],
])
->add('createdAt', DateCompareType::class, [
'label' => 'createdAt_task',
'attr' => [
'type' => 'date_compare',
],
])
->add('beginAt', DateCompareType::class, [
'label' => 'beginAt_task',
'attr' => [
'type' => 'date_compare',
],
])
->add('updatedAt', DateCompareType::class, [
'label' => 'updatedAt_task',
'attr' => [
'type' => 'date_compare',
],
])
->add('myTasks', CheckboxType::class, [
'false_values' => [null, '0', 0, false, '', 'false'],
'data' => $this->security->isGranted(SecurityConfig::MY_TASK_BY_DEFAULT),
])
->add('managedBy', ChoiceType::class, [
'choices' => $this->getManagedByChoices(),
'multiple' => true,
])
->add('closed', ChoiceType::class, [
'label' => 'closed',
'choices' => [
'no' => 'no',
'yes' => 'yes',
'all' => 'all',
],
'attr' => [
'is-expanded' => true,
],
])
->add('readState', ChoiceType::class, [
'label' => 'readState',
'choices' => [
'no' => 'no',
'yes' => 'yes',
'all' => 'all',
],
'attr' => [
'is-expanded' => true,
],
])
->add('hitState', ChoiceType::class, [
'label' => 'hitState',
'choices' => [
'no' => 'no',
'yes' => 'yes',
'all' => 'all',
],
'attr' => [
'is-expanded' => true,
],
])
->add('sectionName', ChoiceType::class, [
'choices' => $this->getSectionNameChoices(),
])
->add('prospectIds', ChoiceType::class, [
'label' => 'prospectIds',
'attr' => [
'type' => 'hidden',
ListingResponseTransformer::FORM_FILTER_KEY => 'prospect',
],
'multiple' => 'true',
])
->add('contactIds', ChoiceType::class, [
'label' => 'contactIds',
'attr' => [
'type' => 'hidden',
ListingResponseTransformer::FORM_FILTER_KEY => 'contacts',
],
'multiple' => 'true',
])
->add('fileLabel', TextType::class, [
'label' => 'task_search_file_label',
])
->add('isDraft', ChoiceType::class, [
'label' => 'taskSearch_isDraft',
'choices' => [
'no' => 'no',
'yes' => 'yes',
'all' => 'all',
],
'attr' => [
'is-expanded' => true,
],
])
;
//La recherche enchainée des contacts est prioritaire sur le champ de recherche contacts classique
$builder->addEventListener(FormEvents::PRE_SUBMIT, function (FormEvent $event) {
$data = $event->getData();
if (!empty($data['contactIds'])) {
$data['contactsConcerned'] = $data['contactIds'];
$data['contactIds'] = [];
$event->setData($data);
}
});
$builder->get('prospectIds')->resetViewTransformers();
$builder->get('contactIds')->resetViewTransformers();
$this->addTimeStampableFields($builder, '_task');
}
/**
* @param OptionsResolver $resolver
*
* @return void
*/
public function configureOptions(OptionsResolver $resolver): void
{
parent::configureOptions($resolver);
$resolver->setDefaults([
'contactsConcerned' => [],
'csrf_protection' => false,
'data_class' => TaskSearch::class,
'required' => false,
self::FORM_CONFIG_VIEW_ORDER_ENTITY => Task::class,
self::FORM_CONFIG_VIEW_ORDER_TYPE => ViewOrder::VIEWORDER_TYPE_SEARCH,
self::FORM_CONFIG_SPECIFIC_FIELD_ENTITY => Task::class,
self::FORM_CONFIG_VIEW_ORDER_ENTITY_TYPE => null,
]);
}
/**
* @param string $entityFQCN
* @param string $labelProperty
* @param string $valueProperty
*
* @return array<string, object>
*
* @throws CacheException
* @throws InvalidArgumentException
* @noinspection PhpParameterNameChangedDuringInheritanceInspection
*/
private function getEntityChoices(string $entityFQCN, array $filters = [], string $labelProperty = 'value', string $valueProperty = 'id'): array
{
$choices = $this->getEntityChoicesTrait(
$this->collectionDataProvider,
$this->cacheManager,
$this->sentryLogger,
$entityFQCN,
$filters
);
$valueSetter = 'set'.ucfirst($valueProperty);
$labelSetter = 'set'.ucfirst($labelProperty);
$emptyValue = (new $entityFQCN())
->$valueSetter(ListWithEmptyFilterBuilder::EMPTY_VALUE)
->$labelSetter('(Vide)')
;
if ($emptyValue instanceof IriNormalizableInterface) {
$emptyValue->setNormalizeAsIRI(true);
}
$choices[] = $emptyValue;
return $choices;
}
}