mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-08-20 14:43:49 +00:00
Merge branch '106_tasks_to_parcours'
This commit is contained in:
@@ -23,6 +23,7 @@ use Chill\MainBundle\Controller\AddressApiController;
|
||||
use Chill\MainBundle\Controller\LocationController;
|
||||
use Chill\MainBundle\Controller\LocationTypeController;
|
||||
use Chill\MainBundle\Controller\UserController;
|
||||
use Chill\MainBundle\Doctrine\DQL\JsonbArrayLength;
|
||||
use Chill\MainBundle\Doctrine\DQL\STContains;
|
||||
use Chill\MainBundle\Doctrine\DQL\StrictWordSimilarityOPS;
|
||||
use Chill\MainBundle\Entity\User;
|
||||
@@ -96,6 +97,10 @@ class ChillMainExtension extends Extension implements PrependExtensionInterface,
|
||||
$configuration = $this->getConfiguration($configs, $container);
|
||||
$config = $this->processConfiguration($configuration, $configs);
|
||||
|
||||
// replace all config with a main key:
|
||||
$container->setParameter('chill_main', $config);
|
||||
|
||||
// legacy config
|
||||
$container->setParameter('chill_main.installation_name',
|
||||
$config['installation_name']);
|
||||
|
||||
@@ -199,6 +204,7 @@ class ChillMainExtension extends Extension implements PrependExtensionInterface,
|
||||
'OVERLAPSI' => OverlapsI::class,
|
||||
'STRICT_WORD_SIMILARITY_OPS' => StrictWordSimilarityOPS::class,
|
||||
'ST_CONTAINS' => STContains::class,
|
||||
'JSONB_ARRAY_LENGTH' => JsonbArrayLength::class,
|
||||
],
|
||||
],
|
||||
'hydrators' => [
|
||||
|
@@ -16,23 +16,23 @@ use Symfony\Component\HttpFoundation\Request;
|
||||
*/
|
||||
class Configuration implements ConfigurationInterface
|
||||
{
|
||||
|
||||
|
||||
use AddWidgetConfigurationTrait;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @var ContainerBuilder
|
||||
*/
|
||||
private $containerBuilder;
|
||||
|
||||
|
||||
public function __construct(array $widgetFactories = array(),
|
||||
|
||||
public function __construct(array $widgetFactories = array(),
|
||||
ContainerBuilder $containerBuilder)
|
||||
{
|
||||
$this->setWidgetFactories($widgetFactories);
|
||||
$this->containerBuilder = $containerBuilder;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@@ -97,6 +97,14 @@ class Configuration implements ConfigurationInterface
|
||||
->end()
|
||||
->end()
|
||||
->end()
|
||||
->arrayNode('acl')
|
||||
->addDefaultsIfNotSet()
|
||||
->children()
|
||||
->booleanNode('form_show_scopes')
|
||||
->defaultTrue()
|
||||
->end()
|
||||
->end()
|
||||
->end()
|
||||
->arrayNode('redis')
|
||||
->children()
|
||||
->scalarNode('host')
|
||||
@@ -247,7 +255,7 @@ class Configuration implements ConfigurationInterface
|
||||
->end() // end of root
|
||||
;
|
||||
|
||||
|
||||
|
||||
return $treeBuilder;
|
||||
}
|
||||
}
|
||||
|
35
src/Bundle/ChillMainBundle/Doctrine/DQL/JsonbArrayLength.php
Normal file
35
src/Bundle/ChillMainBundle/Doctrine/DQL/JsonbArrayLength.php
Normal file
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
/*
|
||||
*
|
||||
*
|
||||
*/
|
||||
namespace Chill\MainBundle\Doctrine\DQL;
|
||||
|
||||
use Doctrine\ORM\Query\AST\Functions\FunctionNode;
|
||||
use Doctrine\ORM\Query\Lexer;
|
||||
use Doctrine\ORM\Query\Parser;
|
||||
use Doctrine\ORM\Query\SqlWalker;
|
||||
|
||||
/**
|
||||
* Return the length of an array
|
||||
*/
|
||||
class JsonbArrayLength extends FunctionNode
|
||||
{
|
||||
private $expr1;
|
||||
|
||||
public function getSql(SqlWalker $sqlWalker): string
|
||||
{
|
||||
return sprintf(
|
||||
'jsonb_array_length(%s)',
|
||||
$this->expr1->dispatch($sqlWalker),
|
||||
);
|
||||
}
|
||||
|
||||
public function parse(Parser $parser): void
|
||||
{
|
||||
$parser->match(Lexer::T_IDENTIFIER);
|
||||
$parser->match(Lexer::T_OPEN_PARENTHESIS);
|
||||
$this->expr1 = $parser->StringPrimary();
|
||||
$parser->match(Lexer::T_CLOSE_PARENTHESIS);
|
||||
}
|
||||
}
|
@@ -1,7 +1,7 @@
|
||||
<?php
|
||||
/*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
namespace Chill\MainBundle\Doctrine\DQL;
|
||||
|
||||
@@ -11,19 +11,18 @@ use Doctrine\ORM\Query\Parser;
|
||||
use Doctrine\ORM\Query\SqlWalker;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
@author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
*/
|
||||
class JsonbExistsInArray extends FunctionNode
|
||||
{
|
||||
private $expr1;
|
||||
private $expr2;
|
||||
|
||||
|
||||
public function getSql(SqlWalker $sqlWalker): string
|
||||
{
|
||||
return sprintf(
|
||||
'jsonb_exists(%s, %s)',
|
||||
'%s ?? %s',
|
||||
$this->expr1->dispatch($sqlWalker),
|
||||
$sqlWalker->walkInputParameter($this->expr2)
|
||||
);
|
||||
|
@@ -3,9 +3,12 @@
|
||||
namespace Chill\MainBundle\Form\Type\Listing;
|
||||
|
||||
use Chill\MainBundle\Templating\Listing\FilterOrderHelper;
|
||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\HiddenType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\SearchType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\Form\FormInterface;
|
||||
use Symfony\Component\Form\FormView;
|
||||
use Symfony\Component\HttpFoundation\RequestStack;
|
||||
|
||||
final class FilterOrderType extends \Symfony\Component\Form\AbstractType
|
||||
@@ -29,9 +32,32 @@ final class FilterOrderType extends \Symfony\Component\Form\AbstractType
|
||||
]);
|
||||
}
|
||||
|
||||
$checkboxesBuilder = $builder->create('checkboxes', null, [ 'compound' => true ]);
|
||||
foreach ($helper->getCheckboxes() as $name => $c) {
|
||||
|
||||
$choices = \array_combine(
|
||||
\array_map(function($c, $t) {
|
||||
if ($t !== NULL) { return $t; }
|
||||
else { return $c; }
|
||||
}, $c['choices'], $c['trans']),
|
||||
$c['choices']
|
||||
);
|
||||
|
||||
$checkboxesBuilder->add($name, ChoiceType::class, [
|
||||
'choices' => $choices,
|
||||
'expanded' => true,
|
||||
'multiple' => true,
|
||||
]);
|
||||
}
|
||||
|
||||
if (0 < count($helper->getCheckboxes())) {
|
||||
$builder->add($checkboxesBuilder);
|
||||
}
|
||||
|
||||
foreach ($this->requestStack->getCurrentRequest()->query->getIterator() as $key => $value) {
|
||||
switch($key) {
|
||||
case 'q':
|
||||
case 'checkboxes'.$key:
|
||||
break;
|
||||
case 'page':
|
||||
$builder->add($key, HiddenType::class, [
|
||||
@@ -47,6 +73,17 @@ final class FilterOrderType extends \Symfony\Component\Form\AbstractType
|
||||
}
|
||||
}
|
||||
|
||||
public function buildView(FormView $view, FormInterface $form, array $options)
|
||||
{
|
||||
/** @var FilterOrderHelper $helper */
|
||||
$helper = $options['helper'];
|
||||
$view->vars['has_search_box'] = $helper->hasSearchBox();
|
||||
$view->vars['checkboxes'] = [];
|
||||
foreach ($helper->getCheckboxes() as $name => $c) {
|
||||
$view->vars['checkboxes'][$name] = [];
|
||||
}
|
||||
}
|
||||
|
||||
public function configureOptions(\Symfony\Component\OptionsResolver\OptionsResolver $resolver)
|
||||
{
|
||||
$resolver->setRequired('helper')
|
||||
|
@@ -23,7 +23,9 @@ use Chill\MainBundle\Entity\Scope;
|
||||
use Chill\MainBundle\Entity\User;
|
||||
use Chill\MainBundle\Form\DataMapper\ScopePickerDataMapper;
|
||||
use Chill\MainBundle\Repository\ScopeRepository;
|
||||
use Chill\MainBundle\Repository\UserACLAwareRepositoryInterface;
|
||||
use Chill\MainBundle\Security\Authorization\AuthorizationHelper;
|
||||
use Chill\MainBundle\Security\Authorization\AuthorizationHelperInterface;
|
||||
use Chill\MainBundle\Templating\TranslatableStringHelper;
|
||||
use Doctrine\ORM\EntityRepository;
|
||||
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
|
||||
@@ -36,6 +38,7 @@ use Symfony\Component\OptionsResolver\Options;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
|
||||
use Symfony\Component\Security\Core\Role\Role;
|
||||
use Symfony\Component\Security\Core\Security;
|
||||
|
||||
/**
|
||||
* Allow to pick amongst available scope for the current
|
||||
@@ -46,14 +49,10 @@ use Symfony\Component\Security\Core\Role\Role;
|
||||
* - `center`: the center of the entity
|
||||
* - `role` : the role of the user
|
||||
*
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
*/
|
||||
class ScopePickerType extends AbstractType
|
||||
{
|
||||
/**
|
||||
* @var AuthorizationHelper
|
||||
*/
|
||||
protected $authorizationHelper;
|
||||
protected AuthorizationHelperInterface $authorizationHelper;
|
||||
|
||||
/**
|
||||
* @var TokenStorageInterface
|
||||
@@ -70,22 +69,26 @@ class ScopePickerType extends AbstractType
|
||||
*/
|
||||
protected $translatableStringHelper;
|
||||
|
||||
protected Security $security;
|
||||
|
||||
public function __construct(
|
||||
AuthorizationHelper $authorizationHelper,
|
||||
AuthorizationHelperInterface $authorizationHelper,
|
||||
TokenStorageInterface $tokenStorage,
|
||||
ScopeRepository $scopeRepository,
|
||||
Security $security,
|
||||
TranslatableStringHelper $translatableStringHelper
|
||||
) {
|
||||
$this->authorizationHelper = $authorizationHelper;
|
||||
$this->tokenStorage = $tokenStorage;
|
||||
$this->scopeRepository = $scopeRepository;
|
||||
$this->security = $security;
|
||||
$this->translatableStringHelper = $translatableStringHelper;
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
{
|
||||
$query = $this->buildAccessibleScopeQuery($options['center'], $options['role']);
|
||||
$items = $query->getQuery()->execute();
|
||||
$items = $this->authorizationHelper->getReachableScopes($this->security->getUser(),
|
||||
$options['role'], $options['center']);
|
||||
|
||||
if (1 !== count($items)) {
|
||||
$builder->add('scope', EntityType::class, [
|
||||
@@ -94,9 +97,7 @@ class ScopePickerType extends AbstractType
|
||||
'choice_label' => function (Scope $c) {
|
||||
return $this->translatableStringHelper->localize($c->getName());
|
||||
},
|
||||
'query_builder' => function () use ($options) {
|
||||
return $this->buildAccessibleScopeQuery($options['center'], $options['role']);
|
||||
},
|
||||
'choices' => $items,
|
||||
]);
|
||||
$builder->setDataMapper(new ScopePickerDataMapper());
|
||||
} else {
|
||||
@@ -121,19 +122,22 @@ class ScopePickerType extends AbstractType
|
||||
$resolver
|
||||
// create `center` option
|
||||
->setRequired('center')
|
||||
->setAllowedTypes('center', [Center::class])
|
||||
->setAllowedTypes('center', [Center::class, 'array', 'null'])
|
||||
// create ``role` option
|
||||
->setRequired('role')
|
||||
->setAllowedTypes('role', ['string', Role::class]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Center|array|Center[] $center
|
||||
* @param string $role
|
||||
* @return \Doctrine\ORM\QueryBuilder
|
||||
*/
|
||||
protected function buildAccessibleScopeQuery(Center $center, Role $role)
|
||||
protected function buildAccessibleScopeQuery($center, $role)
|
||||
{
|
||||
$roles = $this->authorizationHelper->getParentRoles($role);
|
||||
$roles[] = $role;
|
||||
$centers = $center instanceof Center ? [$center]: $center;
|
||||
|
||||
$qb = $this->scopeRepository->createQueryBuilder('s');
|
||||
$qb
|
||||
@@ -142,8 +146,8 @@ class ScopePickerType extends AbstractType
|
||||
->join('rs.permissionsGroups', 'pg')
|
||||
->join('pg.groupCenters', 'gc')
|
||||
// add center constraint
|
||||
->where($qb->expr()->eq('IDENTITY(gc.center)', ':center'))
|
||||
->setParameter('center', $center->getId())
|
||||
->where($qb->expr()->in('IDENTITY(gc.center)', ':centers'))
|
||||
->setParameter('centers', \array_map(fn(Center $c) => $c->getId(), $centers))
|
||||
// role constraints
|
||||
->andWhere($qb->expr()->in('rs.role', ':roles'))
|
||||
->setParameter('roles', $roles)
|
||||
|
@@ -17,6 +17,8 @@
|
||||
*/
|
||||
namespace Chill\MainBundle\Form\Type;
|
||||
|
||||
use Chill\MainBundle\Entity\Scope;
|
||||
use Chill\MainBundle\Repository\UserACLAwareRepositoryInterface;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Chill\MainBundle\Security\Authorization\AuthorizationHelper;
|
||||
use Doctrine\ORM\EntityRepository;
|
||||
@@ -56,14 +58,18 @@ class UserPickerType extends AbstractType
|
||||
|
||||
protected UserRepository $userRepository;
|
||||
|
||||
protected UserACLAwareRepositoryInterface $userACLAwareRepository;
|
||||
|
||||
public function __construct(
|
||||
AuthorizationHelper $authorizationHelper,
|
||||
TokenStorageInterface $tokenStorage,
|
||||
UserRepository $userRepository
|
||||
UserRepository $userRepository,
|
||||
UserACLAwareRepositoryInterface $userACLAwareRepository
|
||||
) {
|
||||
$this->authorizationHelper = $authorizationHelper;
|
||||
$this->tokenStorage = $tokenStorage;
|
||||
$this->userRepository = $userRepository;
|
||||
$this->userACLAwareRepository = $userACLAwareRepository;
|
||||
}
|
||||
|
||||
|
||||
@@ -72,7 +78,7 @@ class UserPickerType extends AbstractType
|
||||
$resolver
|
||||
// create `center` option
|
||||
->setRequired('center')
|
||||
->setAllowedTypes('center', [\Chill\MainBundle\Entity\Center::class ])
|
||||
->setAllowedTypes('center', [\Chill\MainBundle\Entity\Center::class, 'null', 'array' ])
|
||||
// create ``role` option
|
||||
->setRequired('role')
|
||||
->setAllowedTypes('role', ['string', \Symfony\Component\Security\Core\Role\Role::class ])
|
||||
@@ -86,17 +92,19 @@ class UserPickerType extends AbstractType
|
||||
->setDefault('choice_label', function(User $u) {
|
||||
return $u->getUsername();
|
||||
})
|
||||
->setDefault('scope', null)
|
||||
->setAllowedTypes('scope', [Scope::class, 'array', 'null'])
|
||||
->setNormalizer('choices', function(Options $options) {
|
||||
|
||||
$users = $this->authorizationHelper
|
||||
->findUsersReaching($options['role'], $options['center']);
|
||||
|
||||
|
||||
$users = $this->userACLAwareRepository
|
||||
->findUsersByReachedACL($options['role'], $options['center'], $options['scope'], true);
|
||||
|
||||
if (NULL !== $options['having_permissions_group_flag']) {
|
||||
return $this->userRepository
|
||||
->findUsersHavingFlags($options['having_permissions_group_flag'], $users)
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
return $users;
|
||||
})
|
||||
;
|
||||
|
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
namespace Chill\MainBundle\Repository;
|
||||
|
||||
use Chill\MainBundle\Entity\Center;
|
||||
use Chill\MainBundle\Entity\Scope;
|
||||
use Chill\MainBundle\Entity\User;
|
||||
use Chill\MainBundle\Security\Authorization\AuthorizationHelper;
|
||||
|
||||
class UserACLAwareRepository implements UserACLAwareRepositoryInterface
|
||||
{
|
||||
|
||||
private AuthorizationHelper $authorizationHelper;
|
||||
|
||||
public function findUsersByReachedACL(string $role, $center, $scope = null, bool $onlyEnabled = true): array
|
||||
{
|
||||
$parents = $this->authorizationHelper->getParentRoles($role);
|
||||
$parents[] = $role;
|
||||
|
||||
$qb = $this->em->createQueryBuilder();
|
||||
|
||||
$qb
|
||||
->select('u')
|
||||
->from(User::class, 'u')
|
||||
->join('u.groupCenters', 'gc')
|
||||
->join('gc.permissionsGroup', 'pg')
|
||||
->join('pg.roleScopes', 'rs')
|
||||
->where($qb->expr()->in('rs.role', $parents))
|
||||
;
|
||||
|
||||
if ($onlyEnabled) {
|
||||
$qb->andWhere($qb->expr()->eq('u.enabled', "'TRUE'"));
|
||||
}
|
||||
|
||||
if (NULL !== $center) {
|
||||
$centers = $center instanceof Center ? [$center] : $center;
|
||||
$qb
|
||||
->andWhere($qb->expr()->in('gc.center', ':centers'))
|
||||
->setParameter('centers', $centers)
|
||||
;
|
||||
}
|
||||
|
||||
if (NULL !== $scope) {
|
||||
$scopes = $scope instanceof Scope ? [$scope] : $scope;
|
||||
$qb
|
||||
->andWhere($qb->expr()->in('rs.scope', ':scopes'))
|
||||
->setParameter('scopes', $scopes)
|
||||
;
|
||||
}
|
||||
|
||||
return $qb->getQuery()->getResult();
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace Chill\MainBundle\Repository;
|
||||
|
||||
use Chill\MainBundle\Entity\Center;
|
||||
use Chill\MainBundle\Entity\Scope;
|
||||
use Chill\MainBundle\Entity\User;
|
||||
|
||||
interface UserACLAwareRepositoryInterface
|
||||
{
|
||||
/**
|
||||
* Find the users reaching the given center and scope, for the given role
|
||||
*
|
||||
* @param string $role
|
||||
* @param Center|Center[]|array $center
|
||||
* @param Scope|Scope[]|array|null $scope
|
||||
* @param bool $onlyActive true if get only active users
|
||||
*
|
||||
* @return User[]
|
||||
*/
|
||||
public function findUsersByReachedACL(string $role, $center, $scope = null, bool $onlyActive = true): array;
|
||||
}
|
@@ -1,12 +1,39 @@
|
||||
{{ form_start(form) }}
|
||||
<div class="chill_filter_order container">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div class="input-group mb-3">
|
||||
{{ form_widget(form.q)}}
|
||||
<button type="submit" class="btn btn-chill-l-gray"><i class="fa fa-search"></i></button>
|
||||
{% if form.vars.has_search_box %}
|
||||
<div class="col-md-12">
|
||||
<div class="input-group mb-3">
|
||||
{{ form_widget(form.q)}}
|
||||
<button type="submit" class="btn btn-chill-l-gray"><i class="fa fa-search"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% if form.checkboxes|length > 0 %}
|
||||
{% for checkbox_name, options in form.checkboxes %}
|
||||
<div class="row gx-0">
|
||||
<div class="col-md-12">
|
||||
{% for c in form['checkboxes'][checkbox_name].children %}
|
||||
<div class="form-check form-check-inline">
|
||||
{{ form_widget(c) }}
|
||||
{{ form_label(c) }}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% if loop.last %}
|
||||
<div class="row gx-0">
|
||||
<div class="col-md-12">
|
||||
<ul class="record_actions">
|
||||
<li>
|
||||
<button type="submit" class="btn btn-misc"><i class="fa fa-filter"></i></button>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</div>
|
||||
{{ form_end(form) }}
|
||||
|
@@ -8,7 +8,7 @@
|
||||
|
||||
{{ form_start(form) }}
|
||||
|
||||
<ul class="record_actions">
|
||||
<ul class="record_actions sticky-form-buttons">
|
||||
<li class="cancel">
|
||||
<a href="{{ path(cancel_route, cancel_parameters|default( { } ) ) }}" class="btn btn-cancel">
|
||||
{{ 'Cancel'|trans }}
|
||||
@@ -18,5 +18,5 @@
|
||||
{{ form_widget(form.submit, { 'attr' : { 'class' : "btn btn-delete" } } ) }}
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
{{ form_end(form) }}
|
||||
|
||||
{{ form_end(form) }}
|
||||
|
@@ -23,6 +23,8 @@ use Chill\MainBundle\Entity\User;
|
||||
use Chill\MainBundle\Entity\Center;
|
||||
use Chill\MainBundle\Entity\HasCenterInterface;
|
||||
use Chill\MainBundle\Entity\HasScopeInterface;
|
||||
use Chill\MainBundle\Repository\UserACLAwareRepository;
|
||||
use Chill\MainBundle\Repository\UserACLAwareRepositoryInterface;
|
||||
use Chill\MainBundle\Security\Resolver\CenterResolverDispatcher;
|
||||
use Chill\MainBundle\Security\Resolver\ScopeResolverDispatcher;
|
||||
use Chill\MainBundle\Security\Resolver\ScopeResolverInterface;
|
||||
@@ -62,6 +64,8 @@ class AuthorizationHelper implements AuthorizationHelperInterface
|
||||
|
||||
protected LoggerInterface $logger;
|
||||
|
||||
private UserACLAwareRepositoryInterface $userACLAwareRepository;
|
||||
|
||||
public function __construct(
|
||||
RoleHierarchyInterface $roleHierarchy,
|
||||
ParameterBagInterface $parameterBag,
|
||||
@@ -320,33 +324,15 @@ class AuthorizationHelper implements AuthorizationHelperInterface
|
||||
|
||||
/**
|
||||
*
|
||||
* @deprecated use UserACLAwareRepositoryInterface::findUsersByReachedACL instead
|
||||
* @param Center|Center[]|array $center
|
||||
* @param Scope|Scope[]|array|null $scope
|
||||
* @param bool $onlyActive true if get only active users
|
||||
* @return User[]
|
||||
*/
|
||||
public function findUsersReaching(string $role, Center $center, Scope $circle = null): array
|
||||
public function findUsersReaching(string $role, $center, $scope = null, bool $onlyEnabled = true): array
|
||||
{
|
||||
$parents = $this->getParentRoles($role);
|
||||
$parents[] = $role;
|
||||
|
||||
$qb = $this->em->createQueryBuilder();
|
||||
$qb
|
||||
->select('u')
|
||||
->from(User::class, 'u')
|
||||
->join('u.groupCenters', 'gc')
|
||||
->join('gc.permissionsGroup', 'pg')
|
||||
->join('pg.roleScopes', 'rs')
|
||||
->where('gc.center = :center')
|
||||
->andWhere($qb->expr()->in('rs.role', $parents))
|
||||
;
|
||||
|
||||
$qb->setParameter('center', $center);
|
||||
|
||||
if ($circle !== null) {
|
||||
$qb->andWhere('rs.scope = :circle')
|
||||
->setParameter('circle', $circle)
|
||||
;
|
||||
}
|
||||
|
||||
return $qb->getQuery()->getResult();
|
||||
return $this->userACLAwareRepository->findUsersByReachedACL($role, $center, $scope, $onlyEnabled);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -12,6 +12,12 @@ class FilterOrderHelper
|
||||
private FormFactoryInterface $formFactory;
|
||||
private RequestStack $requestStack;
|
||||
private ?array $searchBoxFields = null;
|
||||
private array $checkboxes = [];
|
||||
private ?array $submitted = null;
|
||||
private ?string $formName = 'filter';
|
||||
private string $formType = FilterOrderType::class;
|
||||
private array $formOptions = [];
|
||||
|
||||
|
||||
public function __construct(
|
||||
FormFactoryInterface $formFactory,
|
||||
@@ -28,6 +34,32 @@ class FilterOrderHelper
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function addCheckbox(string $name, array $choices, ?array $default = [], ?array $trans = []): self
|
||||
{
|
||||
$missing = count($choices) - count($trans) - 1;
|
||||
$this->checkboxes[$name] = [
|
||||
'choices' => $choices, 'default' => $default,
|
||||
'trans' =>
|
||||
\array_merge(
|
||||
$trans,
|
||||
0 < $missing ?
|
||||
array_fill(0, $missing, null) : []
|
||||
)
|
||||
];
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getCheckboxData(string $name): array
|
||||
{
|
||||
return $this->getFormData()['checkboxes'][$name];
|
||||
}
|
||||
|
||||
public function getCheckboxes(): array
|
||||
{
|
||||
return $this->checkboxes;
|
||||
}
|
||||
|
||||
public function hasSearchBox(): bool
|
||||
{
|
||||
return $this->searchBoxFields !== null;
|
||||
@@ -35,26 +67,41 @@ class FilterOrderHelper
|
||||
|
||||
private function getFormData(): array
|
||||
{
|
||||
return [
|
||||
'q' => $this->getQueryString()
|
||||
];
|
||||
if (NULL === $this->submitted) {
|
||||
$this->submitted = $this->buildForm()
|
||||
->getData();
|
||||
}
|
||||
|
||||
return $this->submitted;
|
||||
}
|
||||
|
||||
private function getDefaultData(): array
|
||||
{
|
||||
$r = [];
|
||||
|
||||
if ($this->hasSearchBox()) {
|
||||
$r['q'] = '';
|
||||
}
|
||||
foreach ($this->checkboxes as $name => $c) {
|
||||
$r['checkboxes'][$name] = $c['default'];
|
||||
}
|
||||
|
||||
return $r;
|
||||
}
|
||||
|
||||
public function getQueryString(): ?string
|
||||
{
|
||||
$q = $this->requestStack->getCurrentRequest()
|
||||
->query->get('q', null);
|
||||
|
||||
return empty($q) ? NULL : $q;
|
||||
return $this->getFormData()['q'];
|
||||
}
|
||||
|
||||
public function buildForm($name = null, string $type = FilterOrderType::class, array $options = []): FormInterface
|
||||
public function buildForm(): FormInterface
|
||||
{
|
||||
return $this->formFactory
|
||||
->createNamed($name, $type, $this->getFormData(), \array_merge([
|
||||
->createNamed($this->formName, $this->formType, $this->getDefaultData(), \array_merge([
|
||||
'helper' => $this,
|
||||
'method' => 'GET',
|
||||
'csrf_protection' => false,
|
||||
], $options));
|
||||
], $this->formOptions))
|
||||
->handleRequest($this->requestStack->getCurrentRequest());
|
||||
}
|
||||
}
|
||||
|
@@ -8,6 +8,7 @@ use Symfony\Component\HttpFoundation\RequestStack;
|
||||
class FilterOrderHelperBuilder
|
||||
{
|
||||
private ?array $searchBoxFields = null;
|
||||
private array $checkboxes = [];
|
||||
private FormFactoryInterface $formFactory;
|
||||
private RequestStack $requestStack;
|
||||
|
||||
@@ -26,6 +27,13 @@ class FilterOrderHelperBuilder
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function addCheckbox(string $name, array $choices, ?array $default = [], ?array $trans = []): self
|
||||
{
|
||||
$this->checkboxes[$name] = [ 'choices' => $choices, 'default' => $default, 'trans' => $trans];
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function build(): FilterOrderHelper
|
||||
{
|
||||
$helper = new FilterOrderHelper(
|
||||
@@ -34,6 +42,13 @@ class FilterOrderHelperBuilder
|
||||
);
|
||||
|
||||
$helper->setSearchBox($this->searchBoxFields);
|
||||
foreach ($this->checkboxes as $name => [
|
||||
'choices' => $choices,
|
||||
'default' => $default,
|
||||
'trans' => $trans
|
||||
]) {
|
||||
$helper->addCheckbox($name, $choices, $default, $trans);
|
||||
}
|
||||
|
||||
return $helper;
|
||||
}
|
||||
|
@@ -11,6 +11,8 @@ services:
|
||||
autowire: true
|
||||
autoconfigure: true
|
||||
|
||||
Chill\MainBundle\Repository\UserACLAwareRepositoryInterface: '@Chill\MainBundle\Repository\UserACLAwareRepository'
|
||||
|
||||
Chill\MainBundle\Serializer\Normalizer\:
|
||||
resource: '../Serializer/Normalizer'
|
||||
autoconfigure: true
|
||||
|
Reference in New Issue
Block a user