mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-06-12 13:24:25 +00:00
refactor centerType
This commit is contained in:
parent
05b9476a71
commit
a8edef13a3
@ -19,7 +19,11 @@
|
|||||||
|
|
||||||
namespace Chill\MainBundle\Form\Type;
|
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\AbstractType;
|
||||||
|
use Symfony\Component\Form\CallbackTransformer;
|
||||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||||
use Symfony\Component\Form\FormBuilderInterface;
|
use Symfony\Component\Form\FormBuilderInterface;
|
||||||
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
|
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 Chill\MainBundle\Form\Type\DataTransformer\CenterTransformer;
|
||||||
use Symfony\Component\Form\Extension\Core\Type\HiddenType;
|
use Symfony\Component\Form\Extension\Core\Type\HiddenType;
|
||||||
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
|
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
|
class CenterType extends AbstractType
|
||||||
{
|
{
|
||||||
/**
|
protected AuthorizationHelperInterface $authorizationHelper;
|
||||||
* The user linked with this type.
|
|
||||||
*
|
|
||||||
* @var \Chill\MainBundle\Entity\User
|
|
||||||
*/
|
|
||||||
protected $user;
|
|
||||||
|
|
||||||
/**
|
protected Security $security;
|
||||||
* associative array where keys are center.id and
|
|
||||||
* value are center objects
|
|
||||||
*
|
|
||||||
* @var Center[]
|
|
||||||
*/
|
|
||||||
protected $reachableCenters = array();
|
|
||||||
|
|
||||||
/**
|
protected CenterRepository $centerRepository;
|
||||||
*
|
|
||||||
* @var CenterTransformer
|
|
||||||
*/
|
|
||||||
protected $transformer;
|
|
||||||
|
|
||||||
public function __construct(TokenStorageInterface $tokenStorage,
|
public function __construct(
|
||||||
CenterTransformer $transformer)
|
AuthorizationHelperInterface $authorizationHelper,
|
||||||
{
|
Security $security,
|
||||||
$this->user = $tokenStorage->getToken()->getUser();
|
CenterRepository $centerRepository
|
||||||
$this->transformer = $transformer;
|
) {
|
||||||
$this->prepareReachableCenterByUser();
|
$this->authorizationHelper = $authorizationHelper;
|
||||||
|
$this->security = $security;
|
||||||
|
$this->centerRepository = $centerRepository;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -72,6 +67,7 @@ class CenterType extends AbstractType
|
|||||||
* @return string
|
* @return string
|
||||||
* @throws \RuntimeException if the user is not associated with any center
|
* @throws \RuntimeException if the user is not associated with any center
|
||||||
*/
|
*/
|
||||||
|
/*
|
||||||
public function getParent()
|
public function getParent()
|
||||||
{
|
{
|
||||||
$nbReachableCenters = count($this->reachableCenters);
|
$nbReachableCenters = count($this->reachableCenters);
|
||||||
@ -82,6 +78,7 @@ class CenterType extends AbstractType
|
|||||||
return EntityType::class;
|
return EntityType::class;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* configure default options, i.e. add choices if user can reach multiple
|
* 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)
|
public function configureOptions(OptionsResolver $resolver)
|
||||||
{
|
{
|
||||||
if (count($this->reachableCenters) > 1) {
|
$resolver
|
||||||
$resolver->setDefault('class', Center::class)
|
->setDefault('class', Center::class)
|
||||||
->setDefault('choices', $this->reachableCenters)
|
->setRequired('role')
|
||||||
->setDefault('placeholder', 'Pick a center')
|
->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)
|
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||||
{
|
{
|
||||||
if ($this->getParent() === HiddenType::class) {
|
$centers = $this->getReachableCenters($options['role'], $options['scopes']);
|
||||||
$builder->addModelTransformer($this->transformer);
|
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'];
|
||||||
|
}
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private function getReachableCenters(string $role, iterable $scopes): array
|
||||||
* populate reachableCenters as an associative array where
|
|
||||||
* keys are center.id and value are center entities.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
private function prepareReachableCenterByUser()
|
|
||||||
{
|
{
|
||||||
$groupCenters = $this->user->getGroupCenters();
|
if (0 < count($scopes)) {
|
||||||
|
$centers = [];
|
||||||
|
|
||||||
foreach ($groupCenters as $groupCenter) {
|
foreach($scopes as $scope) {
|
||||||
|
foreach ($this->authorizationHelper
|
||||||
$center = $groupCenter->getCenter();
|
->getReachableCenters($this->security->getUser(), $role, $scope) as $center) {
|
||||||
|
$centers[spl_object_hash($center)] = $center;
|
||||||
if (!array_key_exists($center->getId(),
|
}
|
||||||
$this->reachableCenters)) {
|
|
||||||
$this->reachableCenters[$center->getId()] = $center;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return \array_values($centers);
|
||||||
|
} else {
|
||||||
|
return $this->authorizationHelper
|
||||||
|
->getReachableCenters($this->security->getUser(), $role);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,36 +20,57 @@
|
|||||||
namespace Chill\MainBundle\Form\Type\DataTransformer;
|
namespace Chill\MainBundle\Form\Type\DataTransformer;
|
||||||
|
|
||||||
use Chill\MainBundle\Entity\Center;
|
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 Doctrine\ORM\EntityManagerInterface;
|
||||||
use Symfony\Component\Form\DataTransformerInterface;
|
use Symfony\Component\Form\DataTransformerInterface;
|
||||||
use Symfony\Component\Form\Exception\TransformationFailedException;
|
use Symfony\Component\Form\Exception\TransformationFailedException;
|
||||||
|
use Symfony\Component\Form\Exception\UnexpectedTypeException;
|
||||||
|
|
||||||
class CenterTransformer implements DataTransformerInterface
|
class CenterTransformer implements DataTransformerInterface
|
||||||
{
|
{
|
||||||
private EntityManagerInterface $em;
|
private CenterRepository $centerRepository;
|
||||||
|
private bool $multiple = false;
|
||||||
|
|
||||||
public function __construct(EntityManagerInterface $em)
|
public function __construct(
|
||||||
{
|
CenterRepository $centerRepository,
|
||||||
$this->em = $em;
|
bool $multiple = false
|
||||||
|
) {
|
||||||
|
$this->centerRepository = $centerRepository;
|
||||||
|
$this->multiple = $multiple;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function reverseTransform($id)
|
public function reverseTransform($id)
|
||||||
{
|
{
|
||||||
if ($id === NULL) {
|
if ($id === NULL) {
|
||||||
return NULL;
|
if ($this->multiple) {
|
||||||
|
return new ArrayCollection();
|
||||||
|
} else {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$center = $this
|
if ($this->multiple) {
|
||||||
->em
|
$ids = \explode(',', $id);
|
||||||
->getRepository(Center::class)
|
} else {
|
||||||
->find($id);
|
$ids[] = (int) $id;
|
||||||
|
}
|
||||||
|
|
||||||
if ($center === NULL) {
|
$centers = $this
|
||||||
|
->centerRepository
|
||||||
|
->findBy(['id' => $ids ]);
|
||||||
|
|
||||||
|
if ([] === $centers || count($ids) > count($centers)) {
|
||||||
throw new TransformationFailedException(sprintf(
|
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)
|
public function transform($center)
|
||||||
@ -58,7 +79,21 @@ class CenterTransformer implements DataTransformerInterface
|
|||||||
return '';
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -41,9 +41,8 @@ use Chill\MainBundle\Entity\RoleScope;
|
|||||||
*
|
*
|
||||||
* Provides methods for user and entities information.
|
* Provides methods for user and entities information.
|
||||||
*
|
*
|
||||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
|
||||||
*/
|
*/
|
||||||
class AuthorizationHelper
|
class AuthorizationHelper implements AuthorizationHelperInterface
|
||||||
{
|
{
|
||||||
protected RoleHierarchyInterface $roleHierarchy;
|
protected RoleHierarchyInterface $roleHierarchy;
|
||||||
|
|
||||||
@ -203,9 +202,9 @@ class AuthorizationHelper
|
|||||||
* @param User $user
|
* @param User $user
|
||||||
* @param string|Role $role
|
* @param string|Role $role
|
||||||
* @param null|Scope $scope
|
* @param null|Scope $scope
|
||||||
* @return Center[]
|
* @return Center[]|array
|
||||||
*/
|
*/
|
||||||
public function getReachableCenters(User $user, $role, Scope $scope = null)
|
public function getReachableCenters(User $user, string $role, ?Scope $scope = null): array
|
||||||
{
|
{
|
||||||
if ($role instanceof Role) {
|
if ($role instanceof Role) {
|
||||||
$role = $role->getRole();
|
$role = $role->getRole();
|
||||||
@ -267,9 +266,9 @@ class AuthorizationHelper
|
|||||||
* @param User $user
|
* @param User $user
|
||||||
* @param string role
|
* @param string role
|
||||||
* @param Center|Center[] $center
|
* @param Center|Center[] $center
|
||||||
* @return Scope[]
|
* @return Scope[]|array
|
||||||
*/
|
*/
|
||||||
public function getReachableScopes(User $user, $role, $center)
|
public function getReachableScopes(User $user, string $role, $center): array
|
||||||
{
|
{
|
||||||
if ($role instanceof Role) {
|
if ($role instanceof Role) {
|
||||||
$role = $role->getRole();
|
$role = $role->getRole();
|
||||||
|
@ -0,0 +1,32 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Chill\MainBundle\Security\Authorization;
|
||||||
|
|
||||||
|
use Chill\MainBundle\Entity\Center;
|
||||||
|
use Chill\MainBundle\Entity\Scope;
|
||||||
|
use Chill\MainBundle\Entity\User;
|
||||||
|
use Symfony\Component\Security\Core\Role\Role;
|
||||||
|
|
||||||
|
interface AuthorizationHelperInterface
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get reachable Centers for the given user, role,
|
||||||
|
* and optionnaly Scope
|
||||||
|
*
|
||||||
|
* @param User $user
|
||||||
|
* @param string|Role $role
|
||||||
|
* @param null|Scope $scope
|
||||||
|
* @return Center[]
|
||||||
|
*/
|
||||||
|
public function getReachableCenters(User $user, string $role, ?Scope $scope = null): array;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param User $user
|
||||||
|
* @param string $role
|
||||||
|
* @param Center|Center[]|array $center
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getReachableScopes(User $user, string $role, $center): array;
|
||||||
|
|
||||||
|
}
|
@ -60,11 +60,6 @@ services:
|
|||||||
tags:
|
tags:
|
||||||
- { name: twig.extension }
|
- { name: twig.extension }
|
||||||
|
|
||||||
chill.main.form.data_transformer.center_transformer:
|
|
||||||
class: Chill\MainBundle\Form\Type\DataTransformer\CenterTransformer
|
|
||||||
arguments:
|
|
||||||
- "@doctrine.orm.entity_manager"
|
|
||||||
|
|
||||||
chill.main.validator.role_scope_scope_presence:
|
chill.main.validator.role_scope_scope_presence:
|
||||||
class: Chill\MainBundle\Validation\Validator\RoleScopeScopePresence
|
class: Chill\MainBundle\Validation\Validator\RoleScopeScopePresence
|
||||||
arguments:
|
arguments:
|
||||||
|
@ -36,13 +36,9 @@ services:
|
|||||||
tags:
|
tags:
|
||||||
- { name: form.type, alias: select2_chill_language }
|
- { name: form.type, alias: select2_chill_language }
|
||||||
|
|
||||||
chill.main.form.type.center:
|
Chill\MainBundle\Form\Type\CenterType:
|
||||||
class: Chill\MainBundle\Form\Type\CenterType
|
autowire: true
|
||||||
arguments:
|
autoconfigure: true
|
||||||
- "@security.token_storage"
|
|
||||||
- "@chill.main.form.data_transformer.center_transformer"
|
|
||||||
tags:
|
|
||||||
- { name: form.type, alias: center }
|
|
||||||
|
|
||||||
chill.main.form.type.composed_role_scope:
|
chill.main.form.type.composed_role_scope:
|
||||||
class: Chill\MainBundle\Form\Type\ComposedRoleScopeType
|
class: Chill\MainBundle\Form\Type\ComposedRoleScopeType
|
||||||
@ -97,6 +93,10 @@ services:
|
|||||||
arguments:
|
arguments:
|
||||||
- '@Chill\MainBundle\Export\ExportManager'
|
- '@Chill\MainBundle\Export\ExportManager'
|
||||||
|
|
||||||
|
Chill\MainBundle\Form\Type\DataTransformer\CenterTransformer:
|
||||||
|
autowire: true
|
||||||
|
autoconfigure: true
|
||||||
|
|
||||||
chill.main.form.advanced_search_type:
|
chill.main.form.advanced_search_type:
|
||||||
class: Chill\MainBundle\Form\AdvancedSearchType
|
class: Chill\MainBundle\Form\AdvancedSearchType
|
||||||
autowire: true
|
autowire: true
|
||||||
|
@ -38,6 +38,7 @@ services:
|
|||||||
autowire: true
|
autowire: true
|
||||||
autoconfigure: true
|
autoconfigure: true
|
||||||
Chill\MainBundle\Security\Authorization\AuthorizationHelper: '@chill.main.security.authorization.helper'
|
Chill\MainBundle\Security\Authorization\AuthorizationHelper: '@chill.main.security.authorization.helper'
|
||||||
|
Chill\MainBundle\Security\Authorization\AuthorizationHelperInterface: '@chill.main.security.authorization.helper'
|
||||||
|
|
||||||
chill.main.role_provider:
|
chill.main.role_provider:
|
||||||
class: Chill\MainBundle\Security\RoleProvider
|
class: Chill\MainBundle\Security\RoleProvider
|
||||||
|
Loading…
x
Reference in New Issue
Block a user