Adapt ScopePicker to replace Entity field by Hidden field if only one choice

This commit is contained in:
Jean-Francois Monfort 2021-01-19 11:33:20 +01:00
parent 3d0cb12a2d
commit 84e2cc9e02
3 changed files with 127 additions and 41 deletions

View File

@ -0,0 +1,51 @@
<?php
namespace Chill\MainBundle\Form\DataMapper;
use Chill\MainBundle\Entity\Scope;
use Symfony\Component\Form\DataMapperInterface;
use Symfony\Component\Form\FormInterface;
class ScopePickerDataMapper implements DataMapperInterface
{
/**
* @var \Chill\MainBundle\Entity\Scope
*/
private $scope;
public function __construct(Scope $scope = null)
{
$this->scope = $scope;
}
public function mapDataToForms($data, $forms)
{
$forms = iterator_to_array($forms);
if ($this->scope instanceof Scope) {
$forms['scope']->setData($this->scope);
return;
}
if (null === $data) {
return;
}
if ($data instanceof Scope) {
$forms['scope']->setData($data);
}
}
public function mapFormsToData($forms, &$data)
{
$forms = iterator_to_array($forms);
if (isset($forms['scope'])) {
if ($this->scope instanceof Scope) {
$data = $this->scope;
} else {
$data = $forms['scope']->getData();
}
}
}
}

View File

@ -17,9 +17,23 @@
*/
namespace Chill\MainBundle\Form\Type;
use Chill\MainBundle\Entity\User;
use Chill\MainBundle\Form\DataMapper\ScopePickerDataMapper;
use Doctrine\ORM\QueryBuilder;
use Symfony\Component\Form\AbstractType;
use Chill\MainBundle\Security\Authorization\AuthorizationHelper;
use Doctrine\ORM\EntityRepository;
use Symfony\Component\Form\Exception\TransformationFailedException;
use Symfony\Component\Form\Exception\UnexpectedTypeException;
use Symfony\Component\Form\Extension\Core\DataMapper\RadioListMapper;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\FormType;
use Symfony\Component\Form\Extension\Core\Type\HiddenType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormView;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\OptionsResolver\Options;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
@ -43,25 +57,21 @@ use Symfony\Component\Security\Core\Role\Role;
class ScopePickerType extends AbstractType
{
/**
*
* @var AuthorizationHelper
*/
protected $authorizationHelper;
/**
*
* @var TokenStorageInterface
*/
protected $tokenStorage;
/**
*
* @var EntityRepository
*/
protected $scopeRepository;
/**
*
* @var TranslatableStringHelper
*/
protected $translatableStringHelper;
@ -78,66 +88,87 @@ class ScopePickerType extends AbstractType
$this->translatableStringHelper = $translatableStringHelper;
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
$query = $this->buildAccessibleScopeQuery($options['center'], $options['role']);
$items = $query->getQuery()->execute();
if (count($items) !== 1) {
$builder->add(
'scope', EntityType::class, [
'class' => Scope::class,
'placeholder' => 'Choose the circle',
'choice_label' => function (Scope $c) {
return $this->translatableStringHelper->localize($c->getName());
},
'query_builder' => function () use ($options) {
return $this->buildAccessibleScopeQuery($options['center'], $options['role']);
},
]
);
$builder->setDataMapper(new ScopePickerDataMapper());
} else {
$builder->add(
'scope', HiddenType::class, [
'data' => $items[0]->getId(),
]
);
$builder->setDataMapper(new ScopePickerDataMapper($items[0]));
}
}
public function buildView(FormView $view, FormInterface $form, array $options)
{
$view->vars = array_replace(
$view->vars, [
'hideLabel' => true,
]
);
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver
// create `center` option
// create `center` option
->setRequired('center')
->setAllowedTypes('center', [Center::class ])
// create ``role` option
// create ``role` option
->setRequired('role')
->setAllowedTypes('role', ['string', Role::class ])
;
$resolver
->setDefault('class', Scope::class)
->setDefault('placeholder', 'Choose the circle')
->setDefault('choice_label', function(Scope $c) {
return $this->translatableStringHelper->localize($c->getName());
})
->setNormalizer('query_builder', function(Options $options) {
return $this->buildAccessibleScopeQuery($options['center'], $options['role']);
})
;
->setAllowedTypes('role', ['string', Role::class ]);
}
public function getParent()
{
return EntityType::class;
}
/**
*
*
* @return \Doctrine\ORM\QueryBuilder
*/
protected function buildAccessibleScopeQuery(Center $center, Role $role)
{
$roles = $this->authorizationHelper->getParentRoles($role);
$roles[] = $role;
$qb = $this->scopeRepository->createQueryBuilder('s');
$qb
// jointure to center
// jointure to center
->join('s.roleScopes', 'rs')
->join('rs.permissionsGroups', 'pg')
->join('pg.groupCenters', 'gc')
// add center constraint
// add center constraint
->where($qb->expr()->eq('IDENTITY(gc.center)', ':center'))
->setParameter('center', $center->getId())
// role constraints
// role constraints
->andWhere($qb->expr()->in('rs.role', ':roles'))
->setParameter('roles', \array_map(
function(Role $role) {
->setParameter(
'roles', \array_map(
function (Role $role) {
return $role->getRole();
},
$roles
))
// user contraint
->andWhere(':user MEMBER OF gc.users')
->setParameter('user', $this->tokenStorage->getToken()->getUser())
;
)
)
// user contraint
->andWhere(':user MEMBER OF gc.users')
->setParameter('user', $this->tokenStorage->getToken()->getUser());
return $qb;
}
}

View File

@ -18,17 +18,18 @@
{% block form_row %}
{% apply spaceless %}
{% if form.vars.hideLabel is not defined or form.vars.hideLabel == false %}
<div class="container">
<div class="{% apply spaceless %}
{% if attr.class is defined and ('cf-title' in attr.class or 'cf-fields' in attr.class ) %}
{% if attr.class is defined and ('cf-title' in attr.class or 'cf-fields' in attr.class ) %}
grid-12
{% elseif attr.class is defined and 'multiple-cf-inline' in attr.class %}
{% elseif attr.class is defined and 'multiple-cf-inline' in attr.class %}
grid-2 grid-mobile-4 grid-tablet-4 mobile-clear tablet-clear
{% else %}
grid-4 clear
{% endif %}
{% endapply %}">
{% if attr.class is not defined or ('cf-title' not in attr.class and 'cf-fields' not in attr.class ) %}
{% if attr.class is not defined or ('cf-title' not in attr.class and 'cf-fields' not in attr.class ) %}
{{ form_label(form) }}
{% endif %}
</div>
@ -47,6 +48,9 @@
{{ form_errors(form) }}
</div>
</div>
{% else %}
{{ form_widget(form) }}
{% endif %}
{% endapply %}
{% endblock form_row %}
@ -182,4 +186,4 @@
<button class="chill-collection__button--add sc-button" data-collection-add-target="{{ form.vars.name|escape('html_attr') }}" data-form-prototype="{{ ('<div>' ~ form_widget(form.vars.prototype) ~ '</div>')|escape('html_attr') }}" >{{ form.vars.button_add_label|trans }}</button>
</div>
{% endif %}
{% endblock %}
{% endblock %}