mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-08-20 22:53:49 +00:00
refactor centerType
This commit is contained in:
@@ -19,7 +19,11 @@
|
||||
|
||||
namespace Chill\MainBundle\Form\Type;
|
||||
|
||||
use Chill\MainBundle\Repository\CenterRepository;
|
||||
use Chill\MainBundle\Security\Authorization\AuthorizationHelper;
|
||||
use Chill\MainBundle\Security\Authorization\AuthorizationHelperInterface;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\CallbackTransformer;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
|
||||
@@ -27,41 +31,32 @@ use Chill\MainBundle\Entity\Center;
|
||||
use Chill\MainBundle\Form\Type\DataTransformer\CenterTransformer;
|
||||
use Symfony\Component\Form\Extension\Core\Type\HiddenType;
|
||||
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
|
||||
use Symfony\Component\Security\Core\Security;
|
||||
|
||||
/**
|
||||
* Pick a center
|
||||
*
|
||||
* For a given role and, eventually, scopes, show a dropdown (if more than
|
||||
* one reachable center) or a HiddenType (if one or zero center).
|
||||
*
|
||||
*
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
*/
|
||||
class CenterType extends AbstractType
|
||||
{
|
||||
/**
|
||||
* The user linked with this type.
|
||||
*
|
||||
* @var \Chill\MainBundle\Entity\User
|
||||
*/
|
||||
protected $user;
|
||||
protected AuthorizationHelperInterface $authorizationHelper;
|
||||
|
||||
/**
|
||||
* associative array where keys are center.id and
|
||||
* value are center objects
|
||||
*
|
||||
* @var Center[]
|
||||
*/
|
||||
protected $reachableCenters = array();
|
||||
protected Security $security;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var CenterTransformer
|
||||
*/
|
||||
protected $transformer;
|
||||
protected CenterRepository $centerRepository;
|
||||
|
||||
public function __construct(TokenStorageInterface $tokenStorage,
|
||||
CenterTransformer $transformer)
|
||||
{
|
||||
$this->user = $tokenStorage->getToken()->getUser();
|
||||
$this->transformer = $transformer;
|
||||
$this->prepareReachableCenterByUser();
|
||||
public function __construct(
|
||||
AuthorizationHelperInterface $authorizationHelper,
|
||||
Security $security,
|
||||
CenterRepository $centerRepository
|
||||
) {
|
||||
$this->authorizationHelper = $authorizationHelper;
|
||||
$this->security = $security;
|
||||
$this->centerRepository = $centerRepository;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -72,6 +67,7 @@ class CenterType extends AbstractType
|
||||
* @return string
|
||||
* @throws \RuntimeException if the user is not associated with any center
|
||||
*/
|
||||
/*
|
||||
public function getParent()
|
||||
{
|
||||
$nbReachableCenters = count($this->reachableCenters);
|
||||
@@ -82,6 +78,7 @@ class CenterType extends AbstractType
|
||||
return EntityType::class;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
/**
|
||||
* configure default options, i.e. add choices if user can reach multiple
|
||||
@@ -91,13 +88,19 @@ class CenterType extends AbstractType
|
||||
*/
|
||||
public function configureOptions(OptionsResolver $resolver)
|
||||
{
|
||||
if (count($this->reachableCenters) > 1) {
|
||||
$resolver->setDefault('class', Center::class)
|
||||
->setDefault('choices', $this->reachableCenters)
|
||||
->setDefault('placeholder', 'Pick a center')
|
||||
;
|
||||
}
|
||||
|
||||
$resolver
|
||||
->setDefault('class', Center::class)
|
||||
->setRequired('role')
|
||||
->setAllowedTypes('role', [ 'string' ])
|
||||
->setDefault('scopes', [])
|
||||
->setAllowedTypes('scopes', ['iterable'])
|
||||
->setDefault('choice_options', [])
|
||||
;
|
||||
/*
|
||||
->setDefault('choices', $this->reachableCenters)
|
||||
->setDefault('placeholder', 'Pick a center')
|
||||
;
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -108,28 +111,57 @@ class CenterType extends AbstractType
|
||||
*/
|
||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
{
|
||||
if ($this->getParent() === HiddenType::class) {
|
||||
$builder->addModelTransformer($this->transformer);
|
||||
$centers = $this->getReachableCenters($options['role'], $options['scopes']);
|
||||
dump($centers);
|
||||
if (count($centers) <= 1) {
|
||||
dump($centers);
|
||||
$multiple = $options['choice_options']['multiple'] ?? false;
|
||||
$builder->add('center', HiddenType::class);
|
||||
$builder->get('center')->addModelTransformer(
|
||||
new CenterTransformer($this->centerRepository, $multiple)
|
||||
);
|
||||
} else {
|
||||
$builder->add('center', EntityType::class,
|
||||
\array_merge(
|
||||
$options['choice_options'],
|
||||
[
|
||||
'class' => Center::class,
|
||||
'choices' => $centers
|
||||
]
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
$builder
|
||||
->addModelTransformer(new CallbackTransformer(
|
||||
function($data) {
|
||||
if (NULL === $data) {
|
||||
return ['center' => null];
|
||||
}
|
||||
return ['center' => $data];
|
||||
},
|
||||
function($data) {
|
||||
return $data['center'];
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* populate reachableCenters as an associative array where
|
||||
* keys are center.id and value are center entities.
|
||||
*
|
||||
*/
|
||||
private function prepareReachableCenterByUser()
|
||||
private function getReachableCenters(string $role, iterable $scopes): array
|
||||
{
|
||||
$groupCenters = $this->user->getGroupCenters();
|
||||
if (0 < count($scopes)) {
|
||||
$centers = [];
|
||||
|
||||
foreach ($groupCenters as $groupCenter) {
|
||||
|
||||
$center = $groupCenter->getCenter();
|
||||
|
||||
if (!array_key_exists($center->getId(),
|
||||
$this->reachableCenters)) {
|
||||
$this->reachableCenters[$center->getId()] = $center;
|
||||
foreach($scopes as $scope) {
|
||||
foreach ($this->authorizationHelper
|
||||
->getReachableCenters($this->security->getUser(), $role, $scope) as $center) {
|
||||
$centers[spl_object_hash($center)] = $center;
|
||||
}
|
||||
}
|
||||
|
||||
return \array_values($centers);
|
||||
} else {
|
||||
return $this->authorizationHelper
|
||||
->getReachableCenters($this->security->getUser(), $role);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -20,36 +20,57 @@
|
||||
namespace Chill\MainBundle\Form\Type\DataTransformer;
|
||||
|
||||
use Chill\MainBundle\Entity\Center;
|
||||
use Chill\MainBundle\Repository\CenterRepository;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Symfony\Component\Form\DataTransformerInterface;
|
||||
use Symfony\Component\Form\Exception\TransformationFailedException;
|
||||
use Symfony\Component\Form\Exception\UnexpectedTypeException;
|
||||
|
||||
class CenterTransformer implements DataTransformerInterface
|
||||
{
|
||||
private EntityManagerInterface $em;
|
||||
private CenterRepository $centerRepository;
|
||||
private bool $multiple = false;
|
||||
|
||||
public function __construct(EntityManagerInterface $em)
|
||||
{
|
||||
$this->em = $em;
|
||||
public function __construct(
|
||||
CenterRepository $centerRepository,
|
||||
bool $multiple = false
|
||||
) {
|
||||
$this->centerRepository = $centerRepository;
|
||||
$this->multiple = $multiple;
|
||||
}
|
||||
|
||||
public function reverseTransform($id)
|
||||
{
|
||||
if ($id === NULL) {
|
||||
return NULL;
|
||||
if ($this->multiple) {
|
||||
return new ArrayCollection();
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
$center = $this
|
||||
->em
|
||||
->getRepository(Center::class)
|
||||
->find($id);
|
||||
if ($this->multiple) {
|
||||
$ids = \explode(',', $id);
|
||||
} else {
|
||||
$ids[] = (int) $id;
|
||||
}
|
||||
|
||||
if ($center === NULL) {
|
||||
$centers = $this
|
||||
->centerRepository
|
||||
->findBy(['id' => $ids ]);
|
||||
|
||||
if ([] === $centers || count($ids) > count($centers)) {
|
||||
throw new TransformationFailedException(sprintf(
|
||||
'No center found with id %d', $id));
|
||||
'No center found for one of those ids: %s', implode(',', $ids)));
|
||||
}
|
||||
|
||||
return $center;
|
||||
if ($this->multiple) {
|
||||
return new ArrayCollect($centers);
|
||||
} else {
|
||||
return $centers[0];
|
||||
}
|
||||
}
|
||||
|
||||
public function transform($center)
|
||||
@@ -58,7 +79,21 @@ class CenterTransformer implements DataTransformerInterface
|
||||
return '';
|
||||
}
|
||||
|
||||
return $center->getId();
|
||||
}
|
||||
if ($this->multiple) {
|
||||
if (!is_iterable($center)) {
|
||||
throw new UnexpectedTypeException($center, \Traversable::class);
|
||||
}
|
||||
$ids = [];
|
||||
foreach ($center as $c) {
|
||||
$ids[] = $c->getId();
|
||||
}
|
||||
|
||||
return implode(',', $ids);
|
||||
} else {
|
||||
if (!$center instanceof Center) {
|
||||
throw new UnexpectedTypeException($center, Center::class);
|
||||
}
|
||||
return (string) $center->getId();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user