mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-08-29 19:13:49 +00:00
Merge branch '323-related-entity-permission-give-from-workflow' into signature-app-master
This commit is contained in:
@@ -0,0 +1,32 @@
|
||||
<?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\Controller;
|
||||
|
||||
use Chill\MainBundle\CRUD\Controller\ApiController;
|
||||
use Chill\MainBundle\Pagination\PaginatorInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
class GenderApiController extends ApiController
|
||||
{
|
||||
protected function customizeQuery(string $action, Request $request, $query): void
|
||||
{
|
||||
$query
|
||||
->andWhere(
|
||||
$query->expr()->eq('e.active', "'TRUE'")
|
||||
);
|
||||
}
|
||||
|
||||
protected function orderQuery(string $action, $query, Request $request, PaginatorInterface $paginator, $_format)
|
||||
{
|
||||
return $query->addOrderBy('e.order', 'ASC');
|
||||
}
|
||||
}
|
26
src/Bundle/ChillMainBundle/Controller/GenderController.php
Normal file
26
src/Bundle/ChillMainBundle/Controller/GenderController.php
Normal file
@@ -0,0 +1,26 @@
|
||||
<?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\Controller;
|
||||
|
||||
use Chill\MainBundle\CRUD\Controller\CRUDController;
|
||||
use Chill\MainBundle\Pagination\PaginatorInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
class GenderController extends CRUDController
|
||||
{
|
||||
protected function orderQuery(string $action, $query, Request $request, PaginatorInterface $paginator)
|
||||
{
|
||||
$query->addOrderBy('e.order', 'ASC');
|
||||
|
||||
return parent::orderQuery($action, $query, $request, $paginator);
|
||||
}
|
||||
}
|
63
src/Bundle/ChillMainBundle/DataFixtures/ORM/LoadGenders.php
Normal file
63
src/Bundle/ChillMainBundle/DataFixtures/ORM/LoadGenders.php
Normal file
@@ -0,0 +1,63 @@
|
||||
<?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\DataFixtures\ORM;
|
||||
|
||||
use Chill\MainBundle\Entity\Gender;
|
||||
use Chill\MainBundle\Entity\GenderEnum;
|
||||
use Chill\MainBundle\Entity\GenderIconEnum;
|
||||
use Doctrine\Common\DataFixtures\AbstractFixture;
|
||||
use Doctrine\Common\DataFixtures\OrderedFixtureInterface;
|
||||
use Doctrine\Persistence\ObjectManager;
|
||||
|
||||
class LoadGenders extends AbstractFixture implements OrderedFixtureInterface
|
||||
{
|
||||
private array $genders = [
|
||||
[
|
||||
'label' => ['en' => 'man', 'fr' => 'homme'],
|
||||
'genderTranslation' => GenderEnum::MALE,
|
||||
'icon' => GenderIconEnum::MALE,
|
||||
],
|
||||
[
|
||||
'label' => ['en' => 'woman', 'fr' => 'femme'],
|
||||
'genderTranslation' => GenderEnum::FEMALE,
|
||||
'icon' => GenderIconEnum::FEMALE,
|
||||
],
|
||||
[
|
||||
'label' => ['en' => 'neutral', 'fr' => 'neutre'],
|
||||
'genderTranslation' => GenderEnum::NEUTRAL,
|
||||
'icon' => GenderIconEnum::NEUTRAL,
|
||||
],
|
||||
];
|
||||
|
||||
public function getOrder()
|
||||
{
|
||||
return 100;
|
||||
}
|
||||
|
||||
public function load(ObjectManager $manager)
|
||||
{
|
||||
echo "loading genders... \n";
|
||||
|
||||
foreach ($this->genders as $g) {
|
||||
echo $g['label']['fr'].' ';
|
||||
$new_g = new Gender();
|
||||
$new_g->setGenderTranslation($g['genderTranslation']);
|
||||
$new_g->setLabel($g['label']);
|
||||
$new_g->setIcon($g['icon']);
|
||||
|
||||
$this->addReference('g_'.$g['genderTranslation']->value, $new_g);
|
||||
$manager->persist($new_g);
|
||||
}
|
||||
|
||||
$manager->flush();
|
||||
}
|
||||
}
|
@@ -17,6 +17,8 @@ use Chill\MainBundle\Controller\CivilityApiController;
|
||||
use Chill\MainBundle\Controller\CivilityController;
|
||||
use Chill\MainBundle\Controller\CountryApiController;
|
||||
use Chill\MainBundle\Controller\CountryController;
|
||||
use Chill\MainBundle\Controller\GenderApiController;
|
||||
use Chill\MainBundle\Controller\GenderController;
|
||||
use Chill\MainBundle\Controller\GeographicalUnitApiController;
|
||||
use Chill\MainBundle\Controller\LanguageController;
|
||||
use Chill\MainBundle\Controller\LocationController;
|
||||
@@ -54,6 +56,7 @@ use Chill\MainBundle\Doctrine\Type\PointType;
|
||||
use Chill\MainBundle\Entity\Center;
|
||||
use Chill\MainBundle\Entity\Civility;
|
||||
use Chill\MainBundle\Entity\Country;
|
||||
use Chill\MainBundle\Entity\Gender;
|
||||
use Chill\MainBundle\Entity\GeographicalUnitLayer;
|
||||
use Chill\MainBundle\Entity\Language;
|
||||
use Chill\MainBundle\Entity\Location;
|
||||
@@ -66,6 +69,7 @@ use Chill\MainBundle\Entity\UserJob;
|
||||
use Chill\MainBundle\Form\CenterType;
|
||||
use Chill\MainBundle\Form\CivilityType;
|
||||
use Chill\MainBundle\Form\CountryType;
|
||||
use Chill\MainBundle\Form\GenderType;
|
||||
use Chill\MainBundle\Form\LanguageType;
|
||||
use Chill\MainBundle\Form\LocationFormType;
|
||||
use Chill\MainBundle\Form\LocationTypeType;
|
||||
@@ -511,6 +515,28 @@ class ChillMainExtension extends Extension implements
|
||||
],
|
||||
],
|
||||
],
|
||||
[
|
||||
'class' => Gender::class,
|
||||
'name' => 'main_gender',
|
||||
'base_path' => '/admin/main/gender',
|
||||
'base_role' => 'ROLE_ADMIN',
|
||||
'form_class' => GenderType::class,
|
||||
'controller' => GenderController::class,
|
||||
'actions' => [
|
||||
'index' => [
|
||||
'role' => 'ROLE_ADMIN',
|
||||
'template' => '@ChillMain/Gender/index.html.twig',
|
||||
],
|
||||
'new' => [
|
||||
'role' => 'ROLE_ADMIN',
|
||||
'template' => '@ChillMain/Gender/new.html.twig',
|
||||
],
|
||||
'edit' => [
|
||||
'role' => 'ROLE_ADMIN',
|
||||
'template' => '@ChillMain/Gender/edit.html.twig',
|
||||
],
|
||||
],
|
||||
],
|
||||
[
|
||||
'class' => Language::class,
|
||||
'name' => 'main_language',
|
||||
@@ -814,6 +840,21 @@ class ChillMainExtension extends Extension implements
|
||||
],
|
||||
],
|
||||
],
|
||||
[
|
||||
'class' => Gender::class,
|
||||
'name' => 'gender',
|
||||
'base_path' => '/api/1.0/main/gender',
|
||||
'base_role' => 'ROLE_USER',
|
||||
'controller' => GenderApiController::class,
|
||||
'actions' => [
|
||||
'_index' => [
|
||||
'methods' => [
|
||||
Request::METHOD_GET => true,
|
||||
Request::METHOD_HEAD => true,
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
[
|
||||
'class' => GeographicalUnitLayer::class,
|
||||
'controller' => GeographicalUnitApiController::class,
|
||||
|
104
src/Bundle/ChillMainBundle/Entity/Gender.php
Normal file
104
src/Bundle/ChillMainBundle/Entity/Gender.php
Normal file
@@ -0,0 +1,104 @@
|
||||
<?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\Entity;
|
||||
|
||||
use Chill\MainBundle\Repository\GenderRepository;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Symfony\Component\Serializer\Annotation as Serializer;
|
||||
use Symfony\Component\Validator\Constraints as Assert;
|
||||
|
||||
#[Serializer\DiscriminatorMap(typeProperty: 'type', mapping: ['chill_main_gender' => Gender::class])]
|
||||
#[ORM\Entity(repositoryClass: GenderRepository::class)]
|
||||
#[ORM\Table(name: 'chill_main_gender')]
|
||||
class Gender
|
||||
{
|
||||
#[Serializer\Groups(['read'])]
|
||||
#[ORM\Id]
|
||||
#[ORM\GeneratedValue]
|
||||
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::INTEGER)]
|
||||
private ?int $id = null;
|
||||
|
||||
#[Serializer\Groups(['read'])]
|
||||
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::JSON)]
|
||||
private array $label = [];
|
||||
|
||||
#[Serializer\Groups(['read'])]
|
||||
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::BOOLEAN)]
|
||||
private bool $active = true;
|
||||
|
||||
#[Assert\NotNull(message: 'You must choose a gender translation')]
|
||||
#[Serializer\Groups(['read'])]
|
||||
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING, enumType: GenderEnum::class)]
|
||||
private GenderEnum $genderTranslation;
|
||||
|
||||
#[Serializer\Groups(['read'])]
|
||||
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING, enumType: GenderIconEnum::class)]
|
||||
private GenderIconEnum $icon;
|
||||
|
||||
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::FLOAT, name: 'ordering', nullable: true, options: ['default' => '0.0'])]
|
||||
private float $order = 0;
|
||||
|
||||
public function getId(): int
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function getLabel(): array
|
||||
{
|
||||
return $this->label;
|
||||
}
|
||||
|
||||
public function setLabel(array $label): void
|
||||
{
|
||||
$this->label = $label;
|
||||
}
|
||||
|
||||
public function isActive(): bool
|
||||
{
|
||||
return $this->active;
|
||||
}
|
||||
|
||||
public function setActive(bool $active): void
|
||||
{
|
||||
$this->active = $active;
|
||||
}
|
||||
|
||||
public function getGenderTranslation(): GenderEnum
|
||||
{
|
||||
return $this->genderTranslation;
|
||||
}
|
||||
|
||||
public function setGenderTranslation(GenderEnum $genderTranslation): void
|
||||
{
|
||||
$this->genderTranslation = $genderTranslation;
|
||||
}
|
||||
|
||||
public function getIcon(): GenderIconEnum
|
||||
{
|
||||
return $this->icon;
|
||||
}
|
||||
|
||||
public function setIcon(GenderIconEnum $icon): void
|
||||
{
|
||||
$this->icon = $icon;
|
||||
}
|
||||
|
||||
public function getOrder(): float
|
||||
{
|
||||
return $this->order;
|
||||
}
|
||||
|
||||
public function setOrder(float $order): void
|
||||
{
|
||||
$this->order = $order;
|
||||
}
|
||||
}
|
20
src/Bundle/ChillMainBundle/Entity/GenderEnum.php
Normal file
20
src/Bundle/ChillMainBundle/Entity/GenderEnum.php
Normal file
@@ -0,0 +1,20 @@
|
||||
<?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\Entity;
|
||||
|
||||
enum GenderEnum: string
|
||||
{
|
||||
case MALE = 'man';
|
||||
case FEMALE = 'woman';
|
||||
case NEUTRAL = 'neutral';
|
||||
case UNKNOWN = 'unknown';
|
||||
}
|
22
src/Bundle/ChillMainBundle/Entity/GenderIconEnum.php
Normal file
22
src/Bundle/ChillMainBundle/Entity/GenderIconEnum.php
Normal file
@@ -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\Entity;
|
||||
|
||||
enum GenderIconEnum: string
|
||||
{
|
||||
case MALE = 'bi bi-gender-male';
|
||||
case FEMALE = 'bi bi-gender-female';
|
||||
case NEUTRAL = 'bi bi-gender-neuter';
|
||||
case AMBIGUOUS = 'bi bi-gender-ambiguous';
|
||||
case TRANS = 'bi bi-gender-trans';
|
||||
case UNKNOWN = 'bi bi-question';
|
||||
}
|
64
src/Bundle/ChillMainBundle/Form/GenderType.php
Normal file
64
src/Bundle/ChillMainBundle/Form/GenderType.php
Normal file
@@ -0,0 +1,64 @@
|
||||
<?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\Form;
|
||||
|
||||
use Chill\MainBundle\Entity\Gender;
|
||||
use Chill\MainBundle\Entity\GenderEnum;
|
||||
use Chill\MainBundle\Entity\GenderIconEnum;
|
||||
use Chill\MainBundle\Form\Type\TranslatableStringFormType;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\EnumType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\NumberType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
|
||||
class GenderType extends AbstractType
|
||||
{
|
||||
public function buildForm(FormBuilderInterface $builder, array $options): void
|
||||
{
|
||||
$builder
|
||||
->add('label', TranslatableStringFormType::class, [
|
||||
'required' => true,
|
||||
])
|
||||
->add('icon', EnumType::class, [
|
||||
'class' => GenderIconEnum::class,
|
||||
'choices' => GenderIconEnum::cases(),
|
||||
'expanded' => true,
|
||||
'multiple' => false,
|
||||
'mapped' => true,
|
||||
'choice_label' => fn (GenderIconEnum $enum) => '<i class="'.strtolower($enum->value).'"></i>',
|
||||
'choice_value' => fn (?GenderIconEnum $enum) => null !== $enum ? $enum->value : null,
|
||||
'label' => 'gender.admin.Select Gender Icon',
|
||||
'label_html' => true,
|
||||
])
|
||||
->add('genderTranslation', EnumType::class, [
|
||||
'class' => GenderEnum::class,
|
||||
'choice_label' => fn (GenderEnum $enum) => $enum->value,
|
||||
'label' => 'gender.admin.Select Gender Translation',
|
||||
])
|
||||
->add('active', ChoiceType::class, [
|
||||
'choices' => [
|
||||
'Active' => true,
|
||||
'Inactive' => false,
|
||||
],
|
||||
])
|
||||
->add('order', NumberType::class);
|
||||
}
|
||||
|
||||
public function configureOptions(OptionsResolver $resolver): void
|
||||
{
|
||||
$resolver->setDefaults([
|
||||
'data_class' => Gender::class,
|
||||
]);
|
||||
}
|
||||
}
|
47
src/Bundle/ChillMainBundle/Repository/GenderRepository.php
Normal file
47
src/Bundle/ChillMainBundle/Repository/GenderRepository.php
Normal file
@@ -0,0 +1,47 @@
|
||||
<?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\Repository;
|
||||
|
||||
use Chill\MainBundle\Entity\Gender;
|
||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
|
||||
/**
|
||||
* @extends ServiceEntityRepository<Gender>
|
||||
*/
|
||||
class GenderRepository extends ServiceEntityRepository
|
||||
{
|
||||
public function __construct(ManagerRegistry $registry)
|
||||
{
|
||||
parent::__construct($registry, Gender::class);
|
||||
}
|
||||
|
||||
public function findByActiveOrdered(): array
|
||||
{
|
||||
return $this->createQueryBuilder('g')
|
||||
->select('g')
|
||||
->where('g.active = True')
|
||||
->orderBy('g.order', 'ASC')
|
||||
->getQuery()
|
||||
->getResult();
|
||||
}
|
||||
|
||||
public function findByGenderTranslation($gender): array
|
||||
{
|
||||
return $this->createQueryBuilder('g')
|
||||
->select('g')
|
||||
->where('g.genderTranslation = :gender')
|
||||
->setParameter('gender', $gender)
|
||||
->getQuery()
|
||||
->getResult();
|
||||
}
|
||||
}
|
@@ -10,6 +10,7 @@ import Modal from 'bootstrap/js/dist/modal';
|
||||
import Collapse from 'bootstrap/js/src/collapse';
|
||||
import Carousel from 'bootstrap/js/src/carousel';
|
||||
import Popover from 'bootstrap/js/src/popover';
|
||||
import 'bootstrap-icons/font/bootstrap-icons.css';
|
||||
|
||||
//
|
||||
// Carousel: ACHeaderSlider is a small slider used in banner of AccompanyingCourse Section
|
||||
@@ -59,4 +60,4 @@ const popoverList = triggerList.map(function (el) {
|
||||
return new Popover(el, {
|
||||
html: true,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@@ -0,0 +1,11 @@
|
||||
<template>
|
||||
<i :class="gender.icon"></i>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
|
||||
const props = defineProps({
|
||||
gender: Object
|
||||
})
|
||||
|
||||
</script>
|
@@ -38,7 +38,9 @@ const messages = {
|
||||
person: "Usager",
|
||||
birthday: {
|
||||
man: "Né le",
|
||||
woman: "Née le"
|
||||
woman: "Née le",
|
||||
neutral: "Né·e le",
|
||||
unknown: "Né·e le",
|
||||
},
|
||||
deathdate: "Date de décès",
|
||||
household_without_address: "Le ménage de l'usager est sans adresse",
|
||||
|
@@ -0,0 +1,75 @@
|
||||
{% extends '@ChillMain/CRUD/Admin/index.html.twig' %}
|
||||
|
||||
{% block title %}
|
||||
{% include('@ChillMain/CRUD/_edit_title.html.twig') %}
|
||||
{% endblock %}
|
||||
|
||||
{% form_theme form _self %}
|
||||
|
||||
{% block _gender_icon_widget %}
|
||||
{% for child in form %}
|
||||
<div class="form-check">
|
||||
<input
|
||||
type="radio"
|
||||
id="{{ child.vars.id }}"
|
||||
name="{{ child.vars.full_name }}"
|
||||
value="{{ child.vars.value }}"
|
||||
{% if child.vars.checked %}checked="checked"{% endif %}
|
||||
/>
|
||||
|
||||
<label for="{{ child.vars.id }}">{{ child.vars.label|raw }}</label>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endblock %}
|
||||
|
||||
{% block admin_content %}
|
||||
{% set formId = crudMainFormId|default('crud_main_form') %}
|
||||
|
||||
{% block crud_content_header %}
|
||||
<h1 class="mb-5">{{ ('crud.'~crud_name~'.title_edit')|trans }}</h1>
|
||||
{% endblock crud_content_header %}
|
||||
|
||||
{% block crud_content_form %}
|
||||
{{ form_start(form, { 'attr' : { 'id': formId } }) }}
|
||||
|
||||
{{ form_row(form.label) }}
|
||||
{{ form_row(form.genderTranslation) }}
|
||||
{{ form_row(form.icon) }}
|
||||
{{ form_row(form.active) }}
|
||||
{{ form_row(form.order) }}
|
||||
|
||||
{{ form_end(form) }}
|
||||
{% block crud_content_after_form %}{% endblock %}
|
||||
|
||||
{% block crud_content_form_actions %}
|
||||
<ul class="record_actions sticky-form-buttons">
|
||||
{% block content_form_actions_back %}
|
||||
<li class="cancel">
|
||||
{# <a class="btn btn-cancel" href="{{ chill_return_path_or('chill_crud_'~crud_name~'_index') }}">#}
|
||||
{# {{ 'Cancel'|trans }}#}
|
||||
{# </a>#}
|
||||
</li>
|
||||
{% endblock %}
|
||||
{% block content_form_actions_before %}{% endblock %}
|
||||
{% block content_form_actions_delete %}
|
||||
{% if chill_crud_action_exists(crud_name, 'delete') %}
|
||||
{% if is_granted(chill_crud_config('role', crud_name, 'delete'), entity) %}
|
||||
<li class="">
|
||||
<a class="btn btn-small btn-delete" href="{{ chill_path_add_return_path('chill_crud_'~crud_name~'_delete', { 'id': entity.id }) }}"></a>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endblock content_form_actions_delete %}
|
||||
{% block content_form_actions_save_and_close %}
|
||||
<li class="">
|
||||
<button type="submit" name="submit" value="save-and-close" class="btn btn-update" form="{{ formId }}">
|
||||
{{ 'crud.edit.save_and_close'|trans }}
|
||||
</button>
|
||||
</li>
|
||||
{% endblock %}
|
||||
{% block content_form_actions_after %}{% endblock %}
|
||||
</ul>
|
||||
{% endblock %}
|
||||
|
||||
{% endblock %}
|
||||
{% endblock admin_content %}
|
@@ -0,0 +1,46 @@
|
||||
{% extends '@ChillMain/CRUD/Admin/index.html.twig' %}
|
||||
|
||||
{% block admin_content %}
|
||||
{% embed '@ChillMain/CRUD/_index.html.twig' %}
|
||||
{% block table_entities_thead_tr %}
|
||||
<th>id</th>
|
||||
<th>{{ 'label'|trans }}</th>
|
||||
<th>{{ 'icon'|trans }}</th>
|
||||
<th>{{ 'gender.genderTranslation'|trans }}</th>
|
||||
<th>{{ 'active'|trans }}</th>
|
||||
<th>{{ 'ordering'|trans }}</th>
|
||||
<th></th>
|
||||
{% endblock %}
|
||||
{% block table_entities_tbody %}
|
||||
{% for entity in entities %}
|
||||
<tr>
|
||||
<td>{{ entity.id }}</td>
|
||||
<td>{{ entity.label|localize_translatable_string }}</td>
|
||||
<td>{{ entity.icon|chill_entity_render_box }}</td>
|
||||
<td>{{ entity.genderTranslation.value }}</td>
|
||||
<td style="text-align:center;">
|
||||
{%- if entity.active -%}
|
||||
<i class="fa fa-check-square-o"></i>
|
||||
{%- else -%}
|
||||
<i class="fa fa-square-o"></i>
|
||||
{%- endif -%}
|
||||
</td>
|
||||
<td>{{ entity.order }}</td>
|
||||
<td>
|
||||
<ul class="record_actions">
|
||||
<li>
|
||||
<a href="{{ chill_path_add_return_path('chill_crud_main_gender_edit', { 'id': entity.id}) }}" class="btn btn-sm btn-edit btn-mini"></a>
|
||||
</li>
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
{% endblock %}
|
||||
|
||||
{% block actions_before %}
|
||||
<li class='cancel'>
|
||||
<a href="{{ path('chill_main_admin_central') }}" class="btn btn-cancel">{{'Back to the admin'|trans}}</a>
|
||||
</li>
|
||||
{% endblock %}
|
||||
{% endembed %}
|
||||
{% endblock %}
|
@@ -0,0 +1,79 @@
|
||||
{% extends '@ChillMain/CRUD/Admin/index.html.twig' %}
|
||||
|
||||
{% block title %}
|
||||
{% include('@ChillMain/CRUD/_new_title.html.twig') %}
|
||||
{% endblock %}
|
||||
|
||||
{% form_theme form _self %}
|
||||
|
||||
{% block _gender_icon_widget %}
|
||||
{% for child in form %}
|
||||
<div class="form-check">
|
||||
<input
|
||||
type="radio"
|
||||
id="{{ child.vars.id }}"
|
||||
name="{{ child.vars.full_name }}"
|
||||
value="{{ child.vars.value }}"
|
||||
{% if child.vars.checked %}checked="checked"{% endif %}
|
||||
/>
|
||||
|
||||
<label for="{{ child.vars.id }}">{{ child.vars.label|raw }}</label>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endblock %}
|
||||
|
||||
{% block admin_content %}
|
||||
{% set formId = crudMainFormId|default('crud_main_form') %}
|
||||
|
||||
{% block crud_content_header %}
|
||||
<h1>{{ ('crud.' ~ crud_name ~ '.title_new')|trans({'%crud_name%' : crud_name }) }}</h1>
|
||||
{% endblock crud_content_header %}
|
||||
|
||||
{% block crud_content_form %}
|
||||
{{ form_start(form, { 'attr' : { 'id': formId } }) }}
|
||||
{{ form_row(form.label) }}
|
||||
{{ form_row(form.genderTranslation) }}
|
||||
{{ form_row(form.icon) }}
|
||||
{{ form_row(form.active) }}
|
||||
{{ form_row(form.order) }}
|
||||
{{ form_end(form) }}
|
||||
|
||||
{% block crud_content_after_form %}{% endblock %}
|
||||
|
||||
{% block crud_content_form_actions %}
|
||||
<ul class="record_actions sticky-form-buttons">
|
||||
{% block content_form_actions_back %}
|
||||
<li class="cancel">
|
||||
<a class="btn btn-cancel" href="{{ chill_return_path_or('chill_crud_'~crud_name~'_index') }}">
|
||||
{{ 'Cancel'|trans }}
|
||||
</a>
|
||||
</li>
|
||||
{% endblock %}
|
||||
{% block content_form_actions_save_and_close %}
|
||||
<li class="">
|
||||
<button type="submit" name="submit" value="save-and-close" class="btn btn-create" form="{{ formId }}">
|
||||
{{ 'crud.new.save_and_close'|trans }}
|
||||
</button>
|
||||
</li>
|
||||
{% endblock %}
|
||||
{% block content_form_actions_save_and_show %}
|
||||
<li class="">
|
||||
<button type="submit" name="submit" value="save-and-show" class="btn btn-create" form="{{ formId }}">
|
||||
{{ 'crud.new.save_and_show'|trans }}
|
||||
</button>
|
||||
</li>
|
||||
{% endblock %}
|
||||
{% block content_form_actions_save_and_new %}
|
||||
<li class="">
|
||||
<button type="submit" name="submit" value="save-and-new" class="btn btn-create" form="{{ formId }}">
|
||||
{{ 'crud.new.save_and_new'|trans }}
|
||||
</button>
|
||||
</li>
|
||||
{% endblock %}
|
||||
</ul>
|
||||
{% endblock %}
|
||||
|
||||
{{ form_end(form) }}
|
||||
{% endblock %}
|
||||
|
||||
{% endblock admin_content %}
|
@@ -62,12 +62,12 @@ abstract class AbstractSearch implements SearchInterface
|
||||
$recomposed .= ' '.$term.':';
|
||||
$containsSpace = str_contains((string) $terms[$term], ' ');
|
||||
|
||||
if ($containsSpace) {
|
||||
if ($containsSpace || is_numeric($terms[$term])) {
|
||||
$recomposed .= '"';
|
||||
}
|
||||
$recomposed .= (false === mb_stristr(' ', (string) $terms[$term])) ? $terms[$term] : '('.$terms[$term].')';
|
||||
|
||||
if ($containsSpace) {
|
||||
if ($containsSpace || is_numeric($terms[$term])) {
|
||||
$recomposed .= '"';
|
||||
}
|
||||
}
|
||||
|
@@ -35,7 +35,7 @@ interface ChillEntityRenderInterface
|
||||
*
|
||||
* @phpstan-pure
|
||||
*/
|
||||
public function renderBox($entity, array $options): string;
|
||||
public function renderBox(mixed $entity, array $options): string;
|
||||
|
||||
/**
|
||||
* Return the entity as a string.
|
||||
@@ -46,7 +46,7 @@ interface ChillEntityRenderInterface
|
||||
*
|
||||
* @phpstan-pure
|
||||
*/
|
||||
public function renderString($entity, array $options): string;
|
||||
public function renderString(mixed $entity, array $options): string;
|
||||
|
||||
/**
|
||||
* Return true if the class support this object for the given options.
|
||||
|
@@ -0,0 +1,35 @@
|
||||
<?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\Entity;
|
||||
|
||||
use Chill\MainBundle\Entity\GenderIconEnum;
|
||||
|
||||
/**
|
||||
* @implements ChillEntityRenderInterface<GenderIconEnum>
|
||||
*/
|
||||
final readonly class ChillGenderIconRender implements ChillEntityRenderInterface
|
||||
{
|
||||
public function renderBox($icon, array $options): string
|
||||
{
|
||||
return '<i class="'.htmlspecialchars($icon->value, ENT_QUOTES, 'UTF-8').'"></i>';
|
||||
}
|
||||
|
||||
public function renderString($icon, array $options): string
|
||||
{
|
||||
return $icon->value;
|
||||
}
|
||||
|
||||
public function supports($icon, array $options): bool
|
||||
{
|
||||
return $icon instanceof GenderIconEnum;
|
||||
}
|
||||
}
|
@@ -0,0 +1,243 @@
|
||||
<?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\Tests\Workflow\Helper;
|
||||
|
||||
use Chill\MainBundle\Workflow\Helper\WorkflowRelatedEntityPermissionHelper;
|
||||
use Chill\MainBundle\Entity\User;
|
||||
use Chill\MainBundle\Entity\Workflow\EntityWorkflow;
|
||||
use Chill\MainBundle\Entity\Workflow\EntityWorkflowSignatureStateEnum;
|
||||
use Chill\MainBundle\Entity\Workflow\EntityWorkflowStepSignature;
|
||||
use Chill\MainBundle\Workflow\EntityWorkflowManager;
|
||||
use Chill\MainBundle\Workflow\EntityWorkflowMarkingStore;
|
||||
use Chill\MainBundle\Workflow\WorkflowTransitionContextDTO;
|
||||
use Chill\PersonBundle\Entity\Person;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Prophecy\Argument;
|
||||
use Prophecy\PhpUnit\ProphecyTrait;
|
||||
use Symfony\Component\Security\Core\Security;
|
||||
use Symfony\Component\Workflow\DefinitionBuilder;
|
||||
use Symfony\Component\Workflow\Metadata\InMemoryMetadataStore;
|
||||
use Symfony\Component\Workflow\Registry;
|
||||
use Symfony\Component\Workflow\SupportStrategy\WorkflowSupportStrategyInterface;
|
||||
use Symfony\Component\Workflow\Workflow;
|
||||
use Symfony\Component\Workflow\WorkflowInterface;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
* @coversNothing
|
||||
*/
|
||||
class WorkflowRelatedEntityPermissionHelperTest extends TestCase
|
||||
{
|
||||
use ProphecyTrait;
|
||||
|
||||
/**
|
||||
* @dataProvider provideDataNotBlockByWorkflow
|
||||
*/
|
||||
public function testNotBlockByWorkflow(EntityWorkflow $entityWorkflow, User $user, bool $expected, string $message): void
|
||||
{
|
||||
// all entities must have this workflow name, so we are ok to set it here
|
||||
$entityWorkflow->setWorkflowName('dummy');
|
||||
$object = new \stdClass();
|
||||
$helper = $this->buildHelper($object, $entityWorkflow, $user);
|
||||
|
||||
self::assertEquals($expected, $helper->notBlockedByWorkflow($entityWorkflow), $message);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider provideDataAllowedByWorkflow
|
||||
*/
|
||||
public function testAllowedByWorkflow(EntityWorkflow $entityWorkflow, User $user, bool $expected, string $message): void
|
||||
{
|
||||
// all entities must have this workflow name, so we are ok to set it here
|
||||
$entityWorkflow->setWorkflowName('dummy');
|
||||
$object = new \stdClass();
|
||||
$helper = $this->buildHelper($object, $entityWorkflow, $user);
|
||||
|
||||
self::assertEquals($expected, $helper->isAllowedByWorkflow($entityWorkflow), $message);
|
||||
}
|
||||
|
||||
public function testNoWorkflow(): void
|
||||
{
|
||||
$object = new \stdClass();
|
||||
$helper = $this->buildHelper($object, null, $user = new User());
|
||||
self::assertTrue($helper->notBlockedByWorkflow($object), "the user is not blocked by the user, as there aren't any user inside");
|
||||
}
|
||||
|
||||
private function buildHelper(object $relatedEntity, ?EntityWorkflow $entityWorkflow, User $user): WorkflowRelatedEntityPermissionHelper
|
||||
{
|
||||
$security = $this->prophesize(Security::class);
|
||||
$security->getUser()->willReturn($user);
|
||||
|
||||
$entityWorkflowManager = $this->prophesize(EntityWorkflowManager::class);
|
||||
if (null !== $entityWorkflow) {
|
||||
$entityWorkflowManager->findByRelatedEntity(Argument::type('object'))->willReturn([$entityWorkflow]);
|
||||
} else {
|
||||
$entityWorkflowManager->findByRelatedEntity(Argument::type('object'))->willReturn([]);
|
||||
}
|
||||
|
||||
return new WorkflowRelatedEntityPermissionHelper($security->reveal(), $entityWorkflowManager->reveal(), $this->buildRegistry());
|
||||
}
|
||||
|
||||
public static function provideDataAllowedByWorkflow(): iterable
|
||||
{
|
||||
$entityWorkflow = new EntityWorkflow();
|
||||
$dto = new WorkflowTransitionContextDTO($entityWorkflow);
|
||||
$entityWorkflow->setStep('test', $dto, 'to_test', new \DateTimeImmutable(), new User());
|
||||
|
||||
yield [$entityWorkflow, new User(), false, 'not allowed because the user is not present as a dest user'];
|
||||
|
||||
$entityWorkflow = new EntityWorkflow();
|
||||
$dto = new WorkflowTransitionContextDTO($entityWorkflow);
|
||||
$dto->futureDestUsers[] = $user = new User();
|
||||
$entityWorkflow->setStep('test', $dto, 'to_test', new \DateTimeImmutable(), new User());
|
||||
|
||||
yield [$entityWorkflow, $user, true, 'allowed because the user is a current user'];
|
||||
|
||||
$entityWorkflow = new EntityWorkflow();
|
||||
$dto = new WorkflowTransitionContextDTO($entityWorkflow);
|
||||
$dto->futureDestUsers[] = $user = new User();
|
||||
$entityWorkflow->setStep('test', $dto, 'to_test', new \DateTimeImmutable(), new User());
|
||||
|
||||
$dto = new WorkflowTransitionContextDTO($entityWorkflow);
|
||||
$dto->futureDestUsers[] = new User();
|
||||
$entityWorkflow->setStep('test', $dto, 'to_test', new \DateTimeImmutable(), new User());
|
||||
|
||||
yield [$entityWorkflow, $user, true, 'allowed because the user was a previous user'];
|
||||
|
||||
$entityWorkflow = new EntityWorkflow();
|
||||
$dto = new WorkflowTransitionContextDTO($entityWorkflow);
|
||||
$dto->futureDestUsers[] = $user = new User();
|
||||
$entityWorkflow->setStep('test', $dto, 'to_test', new \DateTimeImmutable(), new User());
|
||||
$dto = new WorkflowTransitionContextDTO($entityWorkflow);
|
||||
$entityWorkflow->setStep('final_positive', $dto, 'to_final_positive', new \DateTimeImmutable(), new User());
|
||||
$entityWorkflow->getCurrentStep()->setIsFinal(true);
|
||||
|
||||
yield [$entityWorkflow, $user, false, 'not allowed because: user was a previous user, but it is finalized positive'];
|
||||
|
||||
$entityWorkflow = new EntityWorkflow();
|
||||
$dto = new WorkflowTransitionContextDTO($entityWorkflow);
|
||||
$dto->futureDestUsers[] = $user = new User();
|
||||
$entityWorkflow->setStep('test', $dto, 'to_test', new \DateTimeImmutable());
|
||||
$dto = new WorkflowTransitionContextDTO($entityWorkflow);
|
||||
$entityWorkflow->setStep('final_negative', $dto, 'to_final_negative', new \DateTimeImmutable());
|
||||
$entityWorkflow->getCurrentStep()->setIsFinal(true);
|
||||
|
||||
yield [$entityWorkflow, $user, true, 'allowed: user was a previous user, it is finalized, but finalized negative'];
|
||||
|
||||
}
|
||||
|
||||
public static function provideDataNotBlockByWorkflow(): iterable
|
||||
{
|
||||
$entityWorkflow = new EntityWorkflow();
|
||||
$dto = new WorkflowTransitionContextDTO($entityWorkflow);
|
||||
$entityWorkflow->setStep('test', $dto, 'to_test', new \DateTimeImmutable());
|
||||
|
||||
yield [$entityWorkflow, new User(), false, 'blocked because the user is not present as a dest user'];
|
||||
|
||||
$entityWorkflow = new EntityWorkflow();
|
||||
$dto = new WorkflowTransitionContextDTO($entityWorkflow);
|
||||
$dto->futureDestUsers[] = $user = new User();
|
||||
$entityWorkflow->setStep('test', $dto, 'to_test', new \DateTimeImmutable(), $user);
|
||||
|
||||
yield [$entityWorkflow, $user, true, 'allowed because the user is present as a dest user'];
|
||||
|
||||
$entityWorkflow = new EntityWorkflow();
|
||||
$dto = new WorkflowTransitionContextDTO($entityWorkflow);
|
||||
$dto->futureDestUsers[] = $user = new User();
|
||||
$entityWorkflow->setStep('test', $dto, 'to_test', new \DateTimeImmutable(), $user);
|
||||
$dto = new WorkflowTransitionContextDTO($entityWorkflow);
|
||||
$dto->futureDestUsers[] = new User();
|
||||
$entityWorkflow->setStep('test', $dto, 'to_test', new \DateTimeImmutable(), $user);
|
||||
|
||||
yield [$entityWorkflow, $user, true, 'allowed because the user is present as a **previous** dest user'];
|
||||
|
||||
$entityWorkflow = new EntityWorkflow();
|
||||
$dto = new WorkflowTransitionContextDTO($entityWorkflow);
|
||||
$dto->futureDestUsers[] = $user = new User();
|
||||
$entityWorkflow->setStep('final_positive', $dto, 'to_final_positive', new \DateTimeImmutable(), $user);
|
||||
$entityWorkflow->getCurrentStep()->setIsFinal(true);
|
||||
|
||||
yield [$entityWorkflow, $user, false, 'blocked because the step is final, and final positive'];
|
||||
|
||||
$entityWorkflow = new EntityWorkflow();
|
||||
$dto = new WorkflowTransitionContextDTO($entityWorkflow);
|
||||
$dto->futureDestUsers[] = $user = new User();
|
||||
$entityWorkflow->setStep('final_negative', $dto, 'to_final_negative', new \DateTimeImmutable(), $user);
|
||||
$entityWorkflow->getCurrentStep()->setIsFinal(true);
|
||||
|
||||
yield [$entityWorkflow, $user, true, 'allowed because the step is final, and final negative'];
|
||||
|
||||
$entityWorkflow = new EntityWorkflow();
|
||||
$dto = new WorkflowTransitionContextDTO($entityWorkflow);
|
||||
$dto->futureDestUsers[] = $user = new User();
|
||||
$entityWorkflow->setStep('test', $dto, 'to_test', new \DateTimeImmutable(), $user);
|
||||
$step = $entityWorkflow->getCurrentStep();
|
||||
new EntityWorkflowStepSignature($step, new Person());
|
||||
|
||||
yield [$entityWorkflow, $user, true, 'allow, a signature is present but still pending'];
|
||||
|
||||
$entityWorkflow = new EntityWorkflow();
|
||||
$dto = new WorkflowTransitionContextDTO($entityWorkflow);
|
||||
$dto->futureDestUsers[] = $user = new User();
|
||||
$entityWorkflow->setStep('test', $dto, 'to_test', new \DateTimeImmutable(), $user);
|
||||
$step = $entityWorkflow->getCurrentStep();
|
||||
$signature = new EntityWorkflowStepSignature($step, new Person());
|
||||
$signature->setState(EntityWorkflowSignatureStateEnum::SIGNED);
|
||||
|
||||
yield [$entityWorkflow, $user, false, 'blocked, a signature is present and signed'];
|
||||
|
||||
$entityWorkflow = new EntityWorkflow();
|
||||
$dto = new WorkflowTransitionContextDTO($entityWorkflow);
|
||||
$dto->futureDestUsers[] = $user = new User();
|
||||
$entityWorkflow->setStep('final_negative', $dto, 'to_final_negative', new \DateTimeImmutable(), $user);
|
||||
$step = $entityWorkflow->getCurrentStep();
|
||||
$signature = new EntityWorkflowStepSignature($step, new Person());
|
||||
$signature->setState(EntityWorkflowSignatureStateEnum::SIGNED);
|
||||
|
||||
yield [$entityWorkflow, $user, false, 'blocked, a signature is present and signed, although the workflow is final negative'];
|
||||
|
||||
}
|
||||
|
||||
private static function buildRegistry(): Registry
|
||||
{
|
||||
$builder = new DefinitionBuilder();
|
||||
$builder
|
||||
->setInitialPlaces(['initial'])
|
||||
->addPlaces(['initial', 'test', 'final_positive', 'final_negative'])
|
||||
->setMetadataStore(
|
||||
new InMemoryMetadataStore(
|
||||
placesMetadata: [
|
||||
'final_positive' => [
|
||||
'isFinal' => true,
|
||||
'isFinalPositive' => true,
|
||||
],
|
||||
'final_negative' => [
|
||||
'isFinal' => true,
|
||||
'isFinalPositive' => false,
|
||||
],
|
||||
]
|
||||
)
|
||||
);
|
||||
|
||||
$workflow = new Workflow($builder->build(), new EntityWorkflowMarkingStore(), name: 'dummy');
|
||||
$registry = new Registry();
|
||||
$registry->addWorkflow($workflow, new class () implements WorkflowSupportStrategyInterface {
|
||||
public function supports(WorkflowInterface $workflow, object $subject): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
return $registry;
|
||||
}
|
||||
}
|
@@ -0,0 +1,115 @@
|
||||
<?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\Workflow\Helper;
|
||||
|
||||
use Chill\MainBundle\Entity\Workflow\EntityWorkflowSignatureStateEnum;
|
||||
use Chill\MainBundle\Workflow\EntityWorkflowManager;
|
||||
use Symfony\Component\Security\Core\Security;
|
||||
use Symfony\Component\Workflow\Registry;
|
||||
|
||||
/**
|
||||
* Check if an object, associated with a workflow, is blocked, or not, by this workflow.
|
||||
*/
|
||||
class WorkflowRelatedEntityPermissionHelper
|
||||
{
|
||||
public function __construct(
|
||||
private readonly Security $security,
|
||||
private readonly EntityWorkflowManager $entityWorkflowManager,
|
||||
private readonly Registry $registry,
|
||||
) {}
|
||||
|
||||
public function isAllowedByWorkflow(object $entity): bool
|
||||
{
|
||||
$entityWorkflows = $this->entityWorkflowManager->findByRelatedEntity($entity);
|
||||
$currentUser = $this->security->getUser();
|
||||
|
||||
foreach ($entityWorkflows as $entityWorkflow) {
|
||||
// if the user is finalized, we have to check if the workflow is finalPositive, or not
|
||||
if ($entityWorkflow->isFinal()) {
|
||||
$workflow = $this->registry->get($entityWorkflow, $entityWorkflow->getWorkflowName());
|
||||
$marking = $workflow->getMarkingStore()->getMarking($entityWorkflow);
|
||||
foreach ($marking->getPlaces() as $place => $int) {
|
||||
$placeMetadata = $workflow->getMetadataStore()->getPlaceMetadata($place);
|
||||
if (true === ($placeMetadata['isFinalPositive'] ?? false)) {
|
||||
// the workflow is final, and final positive, so we stop here.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($entityWorkflows as $entityWorkflow) {
|
||||
// so, the workflow is running... We return true if the current user is involved
|
||||
foreach ($entityWorkflow->getSteps() as $step) {
|
||||
if ($step->getAllDestUser()->contains($currentUser)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the user is allowed to update the given object.
|
||||
*
|
||||
* Return false if some workflow block the edition of the object.
|
||||
*/
|
||||
public function notBlockedByWorkflow(object $entity): bool
|
||||
{
|
||||
$entityWorkflows = $this->entityWorkflowManager->findByRelatedEntity($entity);
|
||||
$currentUser = $this->security->getUser();
|
||||
|
||||
$usersInvolved = [];
|
||||
$entityWorkflowsNotFinalizedPositive = [];
|
||||
foreach ($entityWorkflows as $entityWorkflow) {
|
||||
// as soon as there is one signatured applyied, we are not able to
|
||||
// edit the document any more
|
||||
foreach ($entityWorkflow->getSteps() as $step) {
|
||||
foreach ($step->getSignatures() as $signature) {
|
||||
if (EntityWorkflowSignatureStateEnum::SIGNED === $signature->getState()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($entityWorkflow->isFinal()) {
|
||||
$workflow = $this->registry->get($entityWorkflow, $entityWorkflow->getWorkflowName());
|
||||
$marking = $workflow->getMarkingStore()->getMarking($entityWorkflow);
|
||||
foreach ($marking->getPlaces() as $place => $active) {
|
||||
$metadata = $workflow->getMetadataStore()->getPlaceMetadata($place);
|
||||
if ($metadata['isFinalPositive'] ?? true) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$entityWorkflowsNotFinalizedPositive[] = $entityWorkflow;
|
||||
foreach ($entityWorkflow->getSteps() as $step) {
|
||||
foreach ($step->getAllDestUser()->toArray() as $user) {
|
||||
$usersInvolved[] = $user;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if there isn't any user, but a workflow, blocked
|
||||
if ([] !== $entityWorkflowsNotFinalizedPositive) {
|
||||
if ([] === $usersInvolved) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return in_array($currentUser, $usersInvolved, true);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
@@ -54,6 +54,8 @@ services:
|
||||
|
||||
Chill\MainBundle\Templating\Entity\NewsItemRender: ~
|
||||
|
||||
Chill\MainBundle\Templating\Entity\ChillGenderIconRender: ~
|
||||
|
||||
Chill\MainBundle\Templating\Entity\UserRender: ~
|
||||
|
||||
Chill\MainBundle\Templating\Entity\UserGroupRender: ~
|
||||
|
@@ -0,0 +1,69 @@
|
||||
<?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\Migrations\Main;
|
||||
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
final class Version20240926093955 extends AbstractMigration
|
||||
{
|
||||
public function getDescription(): string
|
||||
{
|
||||
return 'Create gender table and default entities';
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
{
|
||||
$this->addSql('CREATE SEQUENCE chill_main_gender_id_seq INCREMENT BY 1 MINVALUE 1 START 1');
|
||||
$this->addSql('CREATE TABLE chill_main_gender (id INT NOT NULL, label JSON NOT NULL, active BOOLEAN NOT NULL, genderTranslation VARCHAR(255) NOT NULL, icon VARCHAR(255) NOT NULL, ordering DOUBLE PRECISION DEFAULT \'0.0\', PRIMARY KEY(id))');
|
||||
|
||||
// Insert the four gender records into the chill_main_gender table
|
||||
$this->addSql("
|
||||
INSERT INTO chill_main_gender (id, label, active, genderTranslation, icon, ordering)
|
||||
VALUES
|
||||
(nextval('chill_main_gender_id_seq'),
|
||||
'{\"fr\": \"homme\", \"nl\": \"man\"}',
|
||||
true,
|
||||
'man',
|
||||
'bi bi-gender-male',
|
||||
1.0
|
||||
),
|
||||
(nextval('chill_main_gender_id_seq'),
|
||||
'{\"fr\": \"femme\", \"nl\": \"vrouw\"}',
|
||||
true,
|
||||
'woman',
|
||||
'bi bi-gender-female',
|
||||
1.1
|
||||
),
|
||||
(nextval('chill_main_gender_id_seq'),
|
||||
'{\"fr\": \"neutre\", \"nl\": \"neutraal\"}',
|
||||
true,
|
||||
'neutral',
|
||||
'bi bi-gender-neuter',
|
||||
1.1
|
||||
),
|
||||
(nextval('chill_main_gender_id_seq'),
|
||||
'{\"fr\": \"inconnu\", \"nl\": \"ongekend\"}',
|
||||
true,
|
||||
'unknown',
|
||||
'bi bi-question',
|
||||
1.2
|
||||
)
|
||||
");
|
||||
}
|
||||
|
||||
public function down(Schema $schema): void
|
||||
{
|
||||
$this->addSql('DROP SEQUENCE chill_main_gender_id_seq CASCADE');
|
||||
$this->addSql('DROP TABLE chill_main_gender');
|
||||
}
|
||||
}
|
@@ -43,6 +43,7 @@ lifecycleUpdate: Evenements de création et mise à jour
|
||||
address_fields: Données liées à l'adresse
|
||||
Datas: Données
|
||||
No title: Aucun titre
|
||||
icon: icône
|
||||
|
||||
user:
|
||||
profile:
|
||||
@@ -474,6 +475,12 @@ crud:
|
||||
title_delete: Supprimer une actualité
|
||||
button_delete: Supprimer
|
||||
confirm_message_delete: Êtes-vous sûr de vouloir supprimer l'actualité, "%as_string%" ?
|
||||
main_gender:
|
||||
index:
|
||||
title: Liste des genres
|
||||
add_new: Ajouter un genre
|
||||
title_new: Nouveau genre
|
||||
title_edit: Modifier un genre
|
||||
|
||||
No entities: Aucun élément
|
||||
|
||||
@@ -781,4 +788,9 @@ news:
|
||||
read_more: Lire la suite
|
||||
show_details: Voir l'actualité
|
||||
|
||||
gender:
|
||||
genderTranslation: traduction grammaticale
|
||||
not defined: Non défini
|
||||
pick gender: Choisir une genre
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user