mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-08-30 19:43:49 +00:00
Merge branch 'rector/rules-up-to-php82' into rector/rules-symfony
This commit is contained in:
@@ -0,0 +1,91 @@
|
||||
<?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\MainBundle\Templating\Listing;
|
||||
|
||||
use Chill\MainBundle\Templating\Entity\UserRender;
|
||||
use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
|
||||
use Symfony\Component\PropertyAccess\PropertyPathInterface;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
|
||||
final readonly class FilterOrderGetActiveFilterHelper
|
||||
{
|
||||
public function __construct(
|
||||
private TranslatorInterface $translator,
|
||||
private PropertyAccessorInterface $propertyAccessor,
|
||||
private UserRender $userRender,
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all the data required to display the active filters
|
||||
*
|
||||
* @return array<array{label: string, value: string, position: string, name: string}>
|
||||
*/
|
||||
public function getActiveFilters(FilterOrderHelper $filterOrderHelper): array
|
||||
{
|
||||
$result = [];
|
||||
|
||||
if ($filterOrderHelper->hasSearchBox() && '' !== $filterOrderHelper->getQueryString()) {
|
||||
$result[] = ['label' => '', 'value' => $filterOrderHelper->getQueryString(), 'position' => FilterOrderPositionEnum::SearchBox->value, 'name' => 'q'];
|
||||
}
|
||||
|
||||
foreach ($filterOrderHelper->getDateRanges() as $name => ['label' => $label]) {
|
||||
$base = ['position' => FilterOrderPositionEnum::DateRange->value, 'name' => $name, 'label' => (string)$label];
|
||||
|
||||
if (null !== ($from = $filterOrderHelper->getDateRangeData($name)['from'] ?? null)) {
|
||||
$result[] = ['value' => $this->translator->trans('filter_order.by_date.From', ['from_date' => $from]), ...$base];
|
||||
}
|
||||
if (null !== ($to = $filterOrderHelper->getDateRangeData($name)['to'] ?? null)) {
|
||||
$result[] = ['value' => $this->translator->trans('filter_order.by_date.To', ['to_date' => $to]), ...$base];
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($filterOrderHelper->getCheckboxes() as $name => ['choices' => $choices, 'trans' => $trans]) {
|
||||
$translatedChoice = array_combine($choices, [...$trans]);
|
||||
foreach ($filterOrderHelper->getCheckboxData($name) as $keyChoice) {
|
||||
$result[] = ['value' => $this->translator->trans($translatedChoice[$keyChoice]), 'label' => '', 'position' => FilterOrderPositionEnum::Checkboxes->value, 'name' => $name];
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($filterOrderHelper->getEntityChoices() as $name => ['label' => $label, 'class' => $class, 'choices' => $choices, 'options' => $options]) {
|
||||
foreach ($filterOrderHelper->getEntityChoiceData($name) as $selected) {
|
||||
if (is_callable($options['choice_label'])) {
|
||||
$value = call_user_func($options['choice_label'], $selected);
|
||||
} elseif ($options['choice_label'] instanceof PropertyPathInterface || is_string($options['choice_label'])) {
|
||||
$value = $this->propertyAccessor->getValue($selected, $options['choice_label']);
|
||||
} else {
|
||||
if (!$selected instanceof \Stringable) {
|
||||
throw new \UnexpectedValueException(sprintf("we are not able to transform the value of %s to a string. Implements \\Stringable or add a 'choice_label' option to the filterFormBuilder", $selected::class));
|
||||
}
|
||||
|
||||
$value = (string)$selected;
|
||||
}
|
||||
|
||||
$result[] = ['value' => $this->translator->trans($value), 'label' => $label, 'position' => FilterOrderPositionEnum::EntityChoice->value, 'name' => $name];
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($filterOrderHelper->getUserPickers() as $name => ['label' => $label, 'options' => $options]) {
|
||||
foreach ($filterOrderHelper->getUserPickerData($name) as $user) {
|
||||
$result[] = ['value' => $this->userRender->renderString($user, []), 'label' => (string) $label, 'position' => FilterOrderPositionEnum::UserPicker->value, 'name' => $name];
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($filterOrderHelper->getSingleCheckbox() as $name => ['label' => $label]) {
|
||||
if (true === $filterOrderHelper->getSingleCheckboxData($name)) {
|
||||
$result[] = ['label' => '', 'value' => $this->translator->trans($label), 'position' => FilterOrderPositionEnum::SingleCheckbox->value, 'name' => $name];
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
@@ -11,6 +11,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace Chill\MainBundle\Templating\Listing;
|
||||
|
||||
use Chill\MainBundle\Entity\User;
|
||||
use Chill\MainBundle\Form\Type\Listing\FilterOrderType;
|
||||
use DateTimeImmutable;
|
||||
use Symfony\Component\Form\FormFactoryInterface;
|
||||
@@ -18,15 +19,19 @@ use Symfony\Component\Form\FormInterface;
|
||||
use Symfony\Component\HttpFoundation\RequestStack;
|
||||
|
||||
use function array_merge;
|
||||
use function count;
|
||||
|
||||
class FilterOrderHelper
|
||||
final class FilterOrderHelper
|
||||
{
|
||||
private array $checkboxes = [];
|
||||
|
||||
/**
|
||||
* @var array<string, array{label: string}>
|
||||
*/
|
||||
private array $singleCheckbox = [];
|
||||
|
||||
private array $dateRanges = [];
|
||||
|
||||
private ?string $formName = 'f';
|
||||
public const FORM_NAME = 'f';
|
||||
|
||||
private array $formOptions = [];
|
||||
|
||||
@@ -36,20 +41,63 @@ class FilterOrderHelper
|
||||
|
||||
private ?array $submitted = null;
|
||||
|
||||
public function __construct(private readonly FormFactoryInterface $formFactory, private readonly RequestStack $requestStack)
|
||||
{
|
||||
/**
|
||||
* @var array<string, array{label: string, choices: array, options: array}>
|
||||
*/
|
||||
private array $entityChoices = [];
|
||||
|
||||
/**
|
||||
* @var array<string, array{label: string, options: array}>
|
||||
*/
|
||||
private array $userPickers = [];
|
||||
|
||||
public function __construct(
|
||||
private readonly FormFactoryInterface $formFactory,
|
||||
private readonly RequestStack $requestStack,
|
||||
) {
|
||||
}
|
||||
|
||||
public function addCheckbox(string $name, array $choices, ?array $default = [], ?array $trans = []): self
|
||||
public function addSingleCheckbox(string $name, string $label): self
|
||||
{
|
||||
$missing = count($choices) - count($trans) - 1;
|
||||
$this->singleCheckbox[$name] = ['label' => $label];
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param class-string $class
|
||||
*/
|
||||
public function addEntityChoice(string $name, string $class, string $label, array $choices, array $options = []): self
|
||||
{
|
||||
$this->entityChoices[$name] = ['label' => $label, 'class' => $class, 'choices' => $choices, 'options' => $options];
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getEntityChoices(): array
|
||||
{
|
||||
return $this->entityChoices;
|
||||
}
|
||||
|
||||
public function addUserPicker(string $name, ?string $label = null, array $options = []): self
|
||||
{
|
||||
$this->userPickers[$name] = ['label' => $label, 'options' => $options];
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
public function addCheckbox(string $name, array $choices, ?array $default = [], ?array $trans = [], array $options = []): self
|
||||
{
|
||||
if ([] === $trans) {
|
||||
$trans = $choices;
|
||||
}
|
||||
|
||||
$this->checkboxes[$name] = [
|
||||
'choices' => $choices, 'default' => $default,
|
||||
'trans' => array_merge(
|
||||
$trans,
|
||||
0 < $missing ?
|
||||
array_fill(0, $missing, null) : []
|
||||
),
|
||||
'choices' => $choices,
|
||||
'default' => $default,
|
||||
'trans' => $trans,
|
||||
...$options,
|
||||
];
|
||||
|
||||
return $this;
|
||||
@@ -65,7 +113,7 @@ class FilterOrderHelper
|
||||
public function buildForm(): FormInterface
|
||||
{
|
||||
return $this->formFactory
|
||||
->createNamed($this->formName, $this->formType, $this->getDefaultData(), array_merge([
|
||||
->createNamed(self::FORM_NAME, $this->formType, $this->getDefaultData(), array_merge([
|
||||
'helper' => $this,
|
||||
'method' => 'GET',
|
||||
'csrf_protection' => false,
|
||||
@@ -73,18 +121,74 @@ class FilterOrderHelper
|
||||
->handleRequest($this->requestStack->getCurrentRequest());
|
||||
}
|
||||
|
||||
public function getUserPickers(): array
|
||||
{
|
||||
return $this->userPickers;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return list<User>
|
||||
*/
|
||||
public function getUserPickerData(string $name): array
|
||||
{
|
||||
return $this->getFormData()['user_pickers'][$name];
|
||||
}
|
||||
|
||||
public function hasCheckboxData(string $name): bool
|
||||
{
|
||||
return array_key_exists($name, $this->checkboxes);
|
||||
}
|
||||
|
||||
public function getCheckboxData(string $name): array
|
||||
{
|
||||
return $this->getFormData()['checkboxes'][$name];
|
||||
}
|
||||
|
||||
public function hasSingleCheckboxData(string $name): bool
|
||||
{
|
||||
return array_key_exists($name, $this->singleCheckbox);
|
||||
}
|
||||
|
||||
public function getSingleCheckboxData(string $name): ?bool
|
||||
{
|
||||
return $this->getFormData()['single_checkboxes'][$name];
|
||||
}
|
||||
|
||||
public function hasEntityChoice(string $name): bool
|
||||
{
|
||||
return array_key_exists($name, $this->entityChoices);
|
||||
}
|
||||
|
||||
public function getEntityChoiceData($name): mixed
|
||||
{
|
||||
return $this->getFormData()['entity_choices'][$name];
|
||||
}
|
||||
|
||||
public function getCheckboxes(): array
|
||||
{
|
||||
return $this->checkboxes;
|
||||
}
|
||||
|
||||
public function hasCheckBox(string $name): bool
|
||||
{
|
||||
return array_key_exists($name, $this->checkboxes);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<'to': DateTimeImmutable, 'from': DateTimeImmutable>
|
||||
* @return array<string, array{label: string}>
|
||||
*/
|
||||
public function getSingleCheckbox(): array
|
||||
{
|
||||
return $this->singleCheckbox;
|
||||
}
|
||||
|
||||
public function hasDateRangeData(string $name): bool
|
||||
{
|
||||
return array_key_exists($name, $this->dateRanges);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array{to: ?DateTimeImmutable, from: ?DateTimeImmutable}
|
||||
*/
|
||||
public function getDateRangeData(string $name): array
|
||||
{
|
||||
@@ -115,7 +219,13 @@ class FilterOrderHelper
|
||||
|
||||
private function getDefaultData(): array
|
||||
{
|
||||
$r = [];
|
||||
$r = [
|
||||
'checkboxes' => [],
|
||||
'dateRanges' => [],
|
||||
'single_checkboxes' => [],
|
||||
'entity_choices' => [],
|
||||
'user_pickers' => []
|
||||
];
|
||||
|
||||
if ($this->hasSearchBox()) {
|
||||
$r['q'] = '';
|
||||
@@ -130,6 +240,18 @@ class FilterOrderHelper
|
||||
$r['dateRanges'][$name]['to'] = $defaults['to'];
|
||||
}
|
||||
|
||||
foreach ($this->singleCheckbox as $name => $c) {
|
||||
$r['single_checkboxes'][$name] = false;
|
||||
}
|
||||
|
||||
foreach ($this->entityChoices as $name => $c) {
|
||||
$r['entity_choices'][$name] = ($c['options']['multiple'] ?? true) ? [] : null;
|
||||
}
|
||||
|
||||
foreach ($this->userPickers as $name => $u) {
|
||||
$r['user_pickers'][$name] = ($u['options']['multiple'] ?? true) ? [] : null;
|
||||
}
|
||||
|
||||
return $r;
|
||||
}
|
||||
|
||||
|
@@ -14,6 +14,8 @@ namespace Chill\MainBundle\Templating\Listing;
|
||||
use DateTimeImmutable;
|
||||
use Symfony\Component\Form\FormFactoryInterface;
|
||||
use Symfony\Component\HttpFoundation\RequestStack;
|
||||
use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
|
||||
class FilterOrderHelperBuilder
|
||||
{
|
||||
@@ -23,10 +25,32 @@ class FilterOrderHelperBuilder
|
||||
|
||||
private ?array $searchBoxFields = null;
|
||||
|
||||
/**
|
||||
* @var array<string, array{label: string}>
|
||||
*/
|
||||
private array $singleCheckboxes = [];
|
||||
|
||||
/**
|
||||
* @var array<string, array{label: string, class: class-string, choices: array, options: array}>
|
||||
*/
|
||||
private array $entityChoices = [];
|
||||
|
||||
/**
|
||||
* @var array<string, array{label: string, options: array}>
|
||||
*/
|
||||
private array $userPickers = [];
|
||||
|
||||
public function __construct(private readonly FormFactoryInterface $formFactory, private readonly RequestStack $requestStack)
|
||||
{
|
||||
}
|
||||
|
||||
public function addSingleCheckbox(string $name, string $label): self
|
||||
{
|
||||
$this->singleCheckboxes[$name] = ['label' => $label];
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function addCheckbox(string $name, array $choices, ?array $default = [], ?array $trans = []): self
|
||||
{
|
||||
$this->checkboxes[$name] = ['choices' => $choices, 'default' => $default, 'trans' => $trans];
|
||||
@@ -34,6 +58,16 @@ class FilterOrderHelperBuilder
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param class-string $class
|
||||
*/
|
||||
public function addEntityChoice(string $name, string $label, string $class, array $choices, ?array $options = []): self
|
||||
{
|
||||
$this->entityChoices[$name] = ['label' => $label, 'class' => $class, 'choices' => $choices, 'options' => $options];
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function addDateRange(string $name, ?string $label = null, ?DateTimeImmutable $from = null, ?DateTimeImmutable $to = null): self
|
||||
{
|
||||
$this->dateRanges[$name] = ['from' => $from, 'to' => $to, 'label' => $label];
|
||||
@@ -48,11 +82,18 @@ class FilterOrderHelperBuilder
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function addUserPicker(string $name, ?string $label = null, ?array $options = []): self
|
||||
{
|
||||
$this->userPickers[$name] = ['label' => $label, 'options' => $options];
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function build(): FilterOrderHelper
|
||||
{
|
||||
$helper = new FilterOrderHelper(
|
||||
$this->formFactory,
|
||||
$this->requestStack
|
||||
$this->requestStack,
|
||||
);
|
||||
|
||||
$helper->setSearchBox($this->searchBoxFields);
|
||||
@@ -67,6 +108,18 @@ class FilterOrderHelperBuilder
|
||||
$helper->addCheckbox($name, $choices, $default, $trans);
|
||||
}
|
||||
|
||||
foreach (
|
||||
$this->singleCheckboxes as $name => ['label' => $label]
|
||||
) {
|
||||
$helper->addSingleCheckbox($name, $label);
|
||||
}
|
||||
|
||||
foreach (
|
||||
$this->entityChoices as $name => ['label' => $label, 'class' => $class, 'choices' => $choices, 'options' => $options]
|
||||
) {
|
||||
$helper->addEntityChoice($name, $class, $label, $choices, $options);
|
||||
}
|
||||
|
||||
foreach (
|
||||
$this->dateRanges as $name => [
|
||||
'from' => $from,
|
||||
@@ -77,6 +130,17 @@ class FilterOrderHelperBuilder
|
||||
$helper->addDateRange($name, $label, $from, $to);
|
||||
}
|
||||
|
||||
|
||||
foreach (
|
||||
$this->userPickers as $name => [
|
||||
'label' => $label,
|
||||
'options' => $options
|
||||
]
|
||||
) {
|
||||
$helper->addUserPicker($name, $label, $options);
|
||||
}
|
||||
|
||||
|
||||
return $helper;
|
||||
}
|
||||
}
|
||||
|
@@ -13,6 +13,8 @@ namespace Chill\MainBundle\Templating\Listing;
|
||||
|
||||
use Symfony\Component\Form\FormFactoryInterface;
|
||||
use Symfony\Component\HttpFoundation\RequestStack;
|
||||
use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
|
||||
class FilterOrderHelperFactory implements FilterOrderHelperFactoryInterface
|
||||
{
|
||||
|
@@ -0,0 +1,22 @@
|
||||
<?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\MainBundle\Templating\Listing;
|
||||
|
||||
enum FilterOrderPositionEnum: string
|
||||
{
|
||||
case SearchBox = 'search_box';
|
||||
case Checkboxes = 'checkboxes';
|
||||
case DateRange = 'date_range';
|
||||
case EntityChoice = 'entity_choice';
|
||||
case SingleCheckbox = 'single_checkbox';
|
||||
case UserPicker = 'user_picker';
|
||||
}
|
@@ -11,13 +11,24 @@ declare(strict_types=1);
|
||||
|
||||
namespace Chill\MainBundle\Templating\Listing;
|
||||
|
||||
use Chill\MainBundle\Pagination\PaginatorFactory;
|
||||
use Symfony\Component\HttpFoundation\RequestStack;
|
||||
use Twig\Environment;
|
||||
use Twig\Error\LoaderError;
|
||||
use Twig\Error\RuntimeError;
|
||||
use Twig\Error\SyntaxError;
|
||||
use Twig\Extension\AbstractExtension;
|
||||
use Twig\TwigFilter;
|
||||
|
||||
class Templating extends AbstractExtension
|
||||
{
|
||||
public function getFilters()
|
||||
public function __construct(
|
||||
private readonly RequestStack $requestStack,
|
||||
private readonly FilterOrderGetActiveFilterHelper $filterOrderGetActiveFilterHelper,
|
||||
) {
|
||||
}
|
||||
|
||||
public function getFilters(): array
|
||||
{
|
||||
return [
|
||||
new TwigFilter('chill_render_filter_order_helper', $this->renderFilterOrderHelper(...), [
|
||||
@@ -26,16 +37,42 @@ class Templating extends AbstractExtension
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws SyntaxError
|
||||
* @throws RuntimeError
|
||||
* @throws LoaderError
|
||||
*/
|
||||
public function renderFilterOrderHelper(
|
||||
Environment $environment,
|
||||
FilterOrderHelper $helper,
|
||||
?string $template = '@ChillMain/FilterOrder/base.html.twig',
|
||||
?array $options = []
|
||||
) {
|
||||
): string {
|
||||
$otherParameters = [];
|
||||
|
||||
foreach ($this->requestStack->getCurrentRequest()->query->getIterator() as $key => $value) {
|
||||
switch ($key) {
|
||||
case FilterOrderHelper::FORM_NAME:
|
||||
break;
|
||||
|
||||
case PaginatorFactory::DEFAULT_CURRENT_PAGE_KEY:
|
||||
// when filtering, go back to page 1
|
||||
$otherParameters[PaginatorFactory::DEFAULT_CURRENT_PAGE_KEY] = 1;
|
||||
|
||||
break;
|
||||
default:
|
||||
$otherParameters[$key] = $value;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $environment->render($template, [
|
||||
'helper' => $helper,
|
||||
'active' => $this->filterOrderGetActiveFilterHelper->getActiveFilters($helper),
|
||||
'form' => $helper->buildForm()->createView(),
|
||||
'options' => $options,
|
||||
'otherParameters' => $otherParameters,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user