mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-06-07 18:44:08 +00:00
Create event theme admin entity
This commit is contained in:
parent
3e7f03d331
commit
c1530d701f
@ -0,0 +1,44 @@
|
|||||||
|
<?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\EventBundle\Controller;
|
||||||
|
|
||||||
|
use Chill\MainBundle\CRUD\Controller\CRUDController;
|
||||||
|
use Chill\MainBundle\Pagination\PaginatorInterface;
|
||||||
|
use Doctrine\ORM\QueryBuilder;
|
||||||
|
use Symfony\Component\Form\FormInterface;
|
||||||
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
|
|
||||||
|
class EventThemeController extends CRUDController
|
||||||
|
{
|
||||||
|
protected function createFormFor(string $action, $entity, ?string $formClass = null, array $formOptions = []): FormInterface
|
||||||
|
{
|
||||||
|
if ('new' === $action) {
|
||||||
|
return parent::createFormFor($action, $entity, $formClass, ['step' => 'create']);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ('edit' === $action) {
|
||||||
|
return parent::createFormFor($action, $entity, $formClass, ['step' => 'edit']);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new \LogicException('action is not supported: '.$action);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param QueryBuilder|mixed $query
|
||||||
|
*/
|
||||||
|
protected function orderQuery(string $action, $query, Request $request, PaginatorInterface $paginator): QueryBuilder
|
||||||
|
{
|
||||||
|
/* @var QueryBuilder $query */
|
||||||
|
return $query->orderBy('e.ordering', 'ASC')
|
||||||
|
->addOrderBy('e.id', 'ASC');
|
||||||
|
}
|
||||||
|
}
|
@ -11,6 +11,9 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace Chill\EventBundle\DependencyInjection;
|
namespace Chill\EventBundle\DependencyInjection;
|
||||||
|
|
||||||
|
use Chill\EventBundle\Controller\EventThemeController;
|
||||||
|
use Chill\EventBundle\Entity\EventTheme;
|
||||||
|
use Chill\EventBundle\Form\EventThemeType;
|
||||||
use Chill\EventBundle\Security\EventVoter;
|
use Chill\EventBundle\Security\EventVoter;
|
||||||
use Chill\EventBundle\Security\ParticipationVoter;
|
use Chill\EventBundle\Security\ParticipationVoter;
|
||||||
use Symfony\Component\Config\FileLocator;
|
use Symfony\Component\Config\FileLocator;
|
||||||
@ -26,7 +29,10 @@ use Symfony\Component\HttpKernel\DependencyInjection\Extension;
|
|||||||
*/
|
*/
|
||||||
class ChillEventExtension extends Extension implements PrependExtensionInterface
|
class ChillEventExtension extends Extension implements PrependExtensionInterface
|
||||||
{
|
{
|
||||||
public function load(array $configs, ContainerBuilder $container)
|
/**
|
||||||
|
* @throws \Exception
|
||||||
|
*/
|
||||||
|
public function load(array $configs, ContainerBuilder $container): void
|
||||||
{
|
{
|
||||||
$configuration = new Configuration();
|
$configuration = new Configuration();
|
||||||
$config = $this->processConfiguration($configuration, $configs);
|
$config = $this->processConfiguration($configuration, $configs);
|
||||||
@ -45,16 +51,17 @@ class ChillEventExtension extends Extension implements PrependExtensionInterface
|
|||||||
/** (non-PHPdoc).
|
/** (non-PHPdoc).
|
||||||
* @see \Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface::prepend()
|
* @see \Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface::prepend()
|
||||||
*/
|
*/
|
||||||
public function prepend(ContainerBuilder $container)
|
public function prepend(ContainerBuilder $container): void
|
||||||
{
|
{
|
||||||
$this->prependAuthorization($container);
|
$this->prependAuthorization($container);
|
||||||
|
$this->prependCruds($container);
|
||||||
$this->prependRoute($container);
|
$this->prependRoute($container);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* add authorization hierarchy.
|
* add authorization hierarchy.
|
||||||
*/
|
*/
|
||||||
protected function prependAuthorization(ContainerBuilder $container)
|
protected function prependAuthorization(ContainerBuilder $container): void
|
||||||
{
|
{
|
||||||
$container->prependExtensionConfig('security', [
|
$container->prependExtensionConfig('security', [
|
||||||
'role_hierarchy' => [
|
'role_hierarchy' => [
|
||||||
@ -70,7 +77,7 @@ class ChillEventExtension extends Extension implements PrependExtensionInterface
|
|||||||
/**
|
/**
|
||||||
* add route to route loader for chill.
|
* add route to route loader for chill.
|
||||||
*/
|
*/
|
||||||
protected function prependRoute(ContainerBuilder $container)
|
protected function prependRoute(ContainerBuilder $container): void
|
||||||
{
|
{
|
||||||
// add routes for custom bundle
|
// add routes for custom bundle
|
||||||
$container->prependExtensionConfig('chill_main', [
|
$container->prependExtensionConfig('chill_main', [
|
||||||
@ -81,4 +88,33 @@ class ChillEventExtension extends Extension implements PrependExtensionInterface
|
|||||||
],
|
],
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function prependCruds(ContainerBuilder $container): void
|
||||||
|
{
|
||||||
|
$container->prependExtensionConfig('chill_main', [
|
||||||
|
'cruds' => [
|
||||||
|
[
|
||||||
|
'class' => EventTheme::class,
|
||||||
|
'name' => 'event_theme',
|
||||||
|
'base_path' => '/admin/event/theme',
|
||||||
|
'form_class' => EventThemeType::class,
|
||||||
|
'controller' => EventThemeController::class,
|
||||||
|
'actions' => [
|
||||||
|
'index' => [
|
||||||
|
'template' => '@ChillEvent/Admin/EventTheme/index.html.twig',
|
||||||
|
'role' => 'ROLE_ADMIN',
|
||||||
|
],
|
||||||
|
'new' => [
|
||||||
|
'role' => 'ROLE_ADMIN',
|
||||||
|
'template' => '@ChillEvent/Admin/EventTheme/new.html.twig',
|
||||||
|
],
|
||||||
|
'edit' => [
|
||||||
|
'role' => 'ROLE_ADMIN',
|
||||||
|
'template' => '@ChillEvent/Admin/EventTheme/edit.html.twig',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
183
src/Bundle/ChillEventBundle/Entity/EventTheme.php
Normal file
183
src/Bundle/ChillEventBundle/Entity/EventTheme.php
Normal file
@ -0,0 +1,183 @@
|
|||||||
|
<?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\EventBundle\Entity;
|
||||||
|
|
||||||
|
use Doctrine\Common\Collections\ArrayCollection;
|
||||||
|
use Doctrine\Common\Collections\Collection;
|
||||||
|
use Doctrine\DBAL\Types\Types;
|
||||||
|
use Doctrine\ORM\Mapping as ORM;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class EventTheme.
|
||||||
|
*/
|
||||||
|
#[ORM\Entity]
|
||||||
|
#[ORM\HasLifecycleCallbacks]
|
||||||
|
#[ORM\Table(name: 'chill_event_event_theme')]
|
||||||
|
class EventTheme
|
||||||
|
{
|
||||||
|
#[ORM\Column(type: Types::BOOLEAN, nullable: false)]
|
||||||
|
private bool $isActive = true;
|
||||||
|
|
||||||
|
#[ORM\Id]
|
||||||
|
#[ORM\Column(name: 'id', type: Types::INTEGER)]
|
||||||
|
#[ORM\GeneratedValue(strategy: 'AUTO')]
|
||||||
|
private ?int $id = null;
|
||||||
|
|
||||||
|
#[ORM\Column(type: Types::JSON)]
|
||||||
|
private array $name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var Collection<int, EventTheme>
|
||||||
|
*/
|
||||||
|
#[ORM\OneToMany(mappedBy: 'parent', targetEntity: EventTheme::class)]
|
||||||
|
private Collection $children;
|
||||||
|
|
||||||
|
#[ORM\ManyToOne(targetEntity: EventTheme::class, inversedBy: 'children')]
|
||||||
|
private ?EventTheme $parent = null;
|
||||||
|
|
||||||
|
#[ORM\Column(name: 'ordering', type: Types::FLOAT, options: ['default' => '0.0'])]
|
||||||
|
private float $ordering = 0.0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->children = new ArrayCollection();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get active.
|
||||||
|
*/
|
||||||
|
public function getIsActive(): bool
|
||||||
|
{
|
||||||
|
return $this->isActive;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get id.
|
||||||
|
*/
|
||||||
|
public function getId(): ?int
|
||||||
|
{
|
||||||
|
return $this->id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get label.
|
||||||
|
*/
|
||||||
|
public function getName(): array
|
||||||
|
{
|
||||||
|
return $this->name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set active.
|
||||||
|
*
|
||||||
|
* @param bool $active
|
||||||
|
* @return EventTheme
|
||||||
|
*/
|
||||||
|
public function setIsActive(bool $active): static
|
||||||
|
{
|
||||||
|
$this->isActive = $active;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set label.
|
||||||
|
*
|
||||||
|
* @param array $label
|
||||||
|
* @return EventTheme
|
||||||
|
*/
|
||||||
|
public function setName(array $label): static
|
||||||
|
{
|
||||||
|
$this->name = $label;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function addChild(self $child): self
|
||||||
|
{
|
||||||
|
if (!$this->children->contains($child)) {
|
||||||
|
$this->children[] = $child;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function removeChild(self $child): self
|
||||||
|
{
|
||||||
|
if ($this->children->removeElement($child)) {
|
||||||
|
// set the owning side to null (unless already changed)
|
||||||
|
if ($child->getParent() === $this) {
|
||||||
|
$child->setParent(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getChildren(): Collection
|
||||||
|
{
|
||||||
|
return $this->children;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getDescendants(): Collection
|
||||||
|
{
|
||||||
|
$descendants = new ArrayCollection();
|
||||||
|
|
||||||
|
foreach ($this->getChildren() as $child) {
|
||||||
|
if (!$descendants->contains($child)) {
|
||||||
|
$descendants->add($child);
|
||||||
|
|
||||||
|
foreach ($child->getDescendants() as $descendantsOfChild) {
|
||||||
|
if (!$descendants->contains($descendantsOfChild)) {
|
||||||
|
$descendants->add($descendantsOfChild);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $descendants;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function hasParent(): bool
|
||||||
|
{
|
||||||
|
return null !== $this->parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getOrdering(): float
|
||||||
|
{
|
||||||
|
return $this->ordering;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setOrdering(float $ordering): EventTheme
|
||||||
|
{
|
||||||
|
$this->ordering = $ordering;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getParent(): ?self
|
||||||
|
{
|
||||||
|
return $this->parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setParent(?self $parent): self
|
||||||
|
{
|
||||||
|
$this->parent = $parent;
|
||||||
|
|
||||||
|
$parent?->addChild($this);
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
}
|
67
src/Bundle/ChillEventBundle/Form/EventThemeType.php
Normal file
67
src/Bundle/ChillEventBundle/Form/EventThemeType.php
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
<?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\EventBundle\Form;
|
||||||
|
|
||||||
|
use Chill\EventBundle\Entity\EventTheme;
|
||||||
|
use Chill\MainBundle\Form\Type\TranslatableStringFormType;
|
||||||
|
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
|
||||||
|
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
|
||||||
|
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||||
|
use Symfony\Component\Form\Extension\Core\Type\NumberType;
|
||||||
|
use Symfony\Component\Form\FormBuilderInterface;
|
||||||
|
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||||
|
use Symfony\Component\Form\AbstractType;
|
||||||
|
|
||||||
|
class EventThemeType extends AbstractType
|
||||||
|
{
|
||||||
|
public function __construct(protected TranslatableStringHelperInterface $translatableStringHelper) {}
|
||||||
|
|
||||||
|
public function buildForm(FormBuilderInterface $builder, array $options): void
|
||||||
|
{
|
||||||
|
$builder
|
||||||
|
->add('name', TranslatableStringFormType::class, [
|
||||||
|
'label' => 'Nom',
|
||||||
|
]);
|
||||||
|
|
||||||
|
if ('create' === $options['step']) {
|
||||||
|
$builder
|
||||||
|
->add('parent', EntityType::class, [
|
||||||
|
'class' => EventTheme::class,
|
||||||
|
'required' => false,
|
||||||
|
'choice_label' => fn (EventTheme $theme): ?string => $this->translatableStringHelper->localize($theme->getName()),
|
||||||
|
'mapped' => 'create' === $options['step'],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$builder
|
||||||
|
->add('ordering', NumberType::class, [
|
||||||
|
'required' => true,
|
||||||
|
'scale' => 6,
|
||||||
|
])
|
||||||
|
->add('isActive', ChoiceType::class, [
|
||||||
|
'choices' => [
|
||||||
|
'Yes' => true,
|
||||||
|
'No' => false,
|
||||||
|
],
|
||||||
|
'expanded' => true,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function configureOptions(OptionsResolver $resolver): void
|
||||||
|
{
|
||||||
|
$resolver->setDefaults([
|
||||||
|
'data_class' => EventTheme::class,
|
||||||
|
]);
|
||||||
|
$resolver->setRequired('step')
|
||||||
|
->setAllowedValues('step', ['create', 'edit']);
|
||||||
|
}
|
||||||
|
}
|
@ -20,14 +20,14 @@ class AdminMenuBuilder implements LocalMenuBuilderInterface
|
|||||||
/**
|
/**
|
||||||
* @var AuthorizationCheckerInterface
|
* @var AuthorizationCheckerInterface
|
||||||
*/
|
*/
|
||||||
protected $authorizationChecker;
|
protected AuthorizationCheckerInterface $authorizationChecker;
|
||||||
|
|
||||||
public function __construct(AuthorizationCheckerInterface $authorizationChecker)
|
public function __construct(AuthorizationCheckerInterface $authorizationChecker)
|
||||||
{
|
{
|
||||||
$this->authorizationChecker = $authorizationChecker;
|
$this->authorizationChecker = $authorizationChecker;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function buildMenu($menuId, MenuItem $menu, array $parameters)
|
public function buildMenu($menuId, MenuItem $menu, array $parameters): void
|
||||||
{
|
{
|
||||||
if (!$this->authorizationChecker->isGranted('ROLE_ADMIN')) {
|
if (!$this->authorizationChecker->isGranted('ROLE_ADMIN')) {
|
||||||
return;
|
return;
|
||||||
@ -52,6 +52,10 @@ class AdminMenuBuilder implements LocalMenuBuilderInterface
|
|||||||
$menu->addChild('Role', [
|
$menu->addChild('Role', [
|
||||||
'route' => 'chill_event_admin_role',
|
'route' => 'chill_event_admin_role',
|
||||||
])->setExtras(['order' => 6530]);
|
])->setExtras(['order' => 6530]);
|
||||||
|
|
||||||
|
$menu->addChild('Theme', [
|
||||||
|
'route' => 'chill_crud_event_theme_index',
|
||||||
|
])->setExtras(['order' => 6540]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function getMenuIds(): array
|
public static function getMenuIds(): array
|
||||||
|
@ -0,0 +1,26 @@
|
|||||||
|
{% extends '@ChillMain/CRUD/Admin/index.html.twig' %}
|
||||||
|
|
||||||
|
{% block title %}
|
||||||
|
{% include('@ChillMain/CRUD/_edit_title.html.twig') %}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block admin_content %}
|
||||||
|
{% embed '@ChillMain/CRUD/_edit_content.html.twig' %}
|
||||||
|
|
||||||
|
{% block crud_content_form_rows %}
|
||||||
|
{{ form_row(form.name) }}
|
||||||
|
<div class="mb-3 row">
|
||||||
|
<label class="col-form-label col-sm-4">
|
||||||
|
{{ 'Parent'|trans }}
|
||||||
|
</label>
|
||||||
|
<div class="col-sm-8">
|
||||||
|
{{ entity.parent|chill_entity_render_box }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{ form_row(form.ordering) }}
|
||||||
|
{{ form_row(form.isActive) }}
|
||||||
|
{% endblock crud_content_form_rows %}
|
||||||
|
|
||||||
|
{% block content_form_actions_save_and_show %}{% endblock %}
|
||||||
|
{% endembed %}
|
||||||
|
{% endblock admin_content %}
|
@ -0,0 +1,45 @@
|
|||||||
|
{% extends '@ChillMain/CRUD/Admin/index.html.twig' %}
|
||||||
|
|
||||||
|
{% block admin_content %}
|
||||||
|
{% embed '@ChillMain/CRUD/_index.html.twig' %}
|
||||||
|
{% block table_entities_thead_tr %}
|
||||||
|
<th>{{ 'Id'|trans }}</th>
|
||||||
|
<th>{{ 'Title'|trans }}</th>
|
||||||
|
<th>{{ 'Ordering'|trans }}</th>
|
||||||
|
<th>{{ 'active'|trans }}</th>
|
||||||
|
<th> </th>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block table_entities_tbody %}
|
||||||
|
{% for entity in entities %}
|
||||||
|
<tr>
|
||||||
|
<td>{{ entity.id }}</td>
|
||||||
|
<td>
|
||||||
|
{{ entity|chill_entity_render_box }}
|
||||||
|
</td>
|
||||||
|
<td>{{ entity.ordering }}</td>
|
||||||
|
<td style="text-align:center;">
|
||||||
|
{%- if entity.isActive -%}
|
||||||
|
<i class="fa fa-check-square-o"></i>
|
||||||
|
{%- else -%}
|
||||||
|
<i class="fa fa-square-o"></i>
|
||||||
|
{%- endif -%}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<ul class="record_actions">
|
||||||
|
<li>
|
||||||
|
<a href="{{ chill_path_add_return_path('chill_crud_event_theme_edit', { 'id': entity.id }) }}" class="btn btn-edit"></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,11 @@
|
|||||||
|
{% extends '@ChillMain/CRUD/Admin/index.html.twig' %}
|
||||||
|
|
||||||
|
{% block title %}
|
||||||
|
{% include('@ChillMain/CRUD/_new_title.html.twig') %}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block admin_content %}
|
||||||
|
{% embed '@ChillMain/CRUD/_new_content.html.twig' %}
|
||||||
|
{% block content_form_actions_save_and_show %}{% endblock %}
|
||||||
|
{% endembed %}
|
||||||
|
{% endblock admin_content %}
|
@ -0,0 +1,13 @@
|
|||||||
|
{% set reversed_parents = parents|reverse %}
|
||||||
|
<span class="chill-entity entity-event-theme">
|
||||||
|
<span class="badge bg-chill-l-gray text-dark">
|
||||||
|
{%- for p in reversed_parents %}
|
||||||
|
<span class="parent-{{ loop.revindex0 }}">
|
||||||
|
{{ p.name|localize_translatable_string }}{{ options['default.separator'] }}
|
||||||
|
</span>
|
||||||
|
{%- endfor -%}
|
||||||
|
<span class="child">
|
||||||
|
{{ eventTheme.name|localize_translatable_string }}
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</span>
|
@ -0,0 +1,109 @@
|
|||||||
|
<?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\EventBundle\Templating\Entity;
|
||||||
|
|
||||||
|
use Chill\EventBundle\Entity\EventTheme;
|
||||||
|
use Chill\MainBundle\Templating\Entity\ChillEntityRenderInterface;
|
||||||
|
use Chill\MainBundle\Templating\TranslatableStringHelper;
|
||||||
|
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||||
|
use Twig\Error\LoaderError;
|
||||||
|
use Twig\Error\RuntimeError;
|
||||||
|
use Twig\Error\SyntaxError;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @implements ChillEntityRenderInterface<EventTheme>
|
||||||
|
*/
|
||||||
|
class EventThemeRender implements ChillEntityRenderInterface
|
||||||
|
{
|
||||||
|
public const AND_CHILDREN_MENTION = 'show_and_children_mention';
|
||||||
|
|
||||||
|
public const DEFAULT_ARGS = [
|
||||||
|
self::SEPARATOR_KEY => ' > ',
|
||||||
|
self::SHOW_AND_CHILDREN => false,
|
||||||
|
self::AND_CHILDREN_MENTION => 'event_theme.and children',
|
||||||
|
];
|
||||||
|
|
||||||
|
public const SEPARATOR_KEY = 'default.separator';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show a mention "and children" on each EventTheme, if the event theme
|
||||||
|
* has at least one child.
|
||||||
|
*/
|
||||||
|
public const SHOW_AND_CHILDREN = 'show_and_children';
|
||||||
|
|
||||||
|
public function __construct(private readonly TranslatableStringHelper $translatableStringHelper, private readonly \Twig\Environment $engine, private readonly TranslatorInterface $translator) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws RuntimeError
|
||||||
|
* @throws SyntaxError
|
||||||
|
* @throws LoaderError
|
||||||
|
*/
|
||||||
|
public function renderBox($eventTheme, array $options): string
|
||||||
|
{
|
||||||
|
$options = array_merge(self::DEFAULT_ARGS, $options);
|
||||||
|
// give some help to twig: an array of parents
|
||||||
|
$parents = $this->buildParents($eventTheme);
|
||||||
|
|
||||||
|
return $this
|
||||||
|
->engine
|
||||||
|
->render(
|
||||||
|
'@ChillEvent/Entity/event_theme.html.twig',
|
||||||
|
[
|
||||||
|
'eventTheme' => $eventTheme,
|
||||||
|
'parents' => $parents,
|
||||||
|
'options' => $options,
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function renderString($entity, array $options): string
|
||||||
|
{
|
||||||
|
/** @var EventTheme $entity */
|
||||||
|
$options = array_merge(self::DEFAULT_ARGS, $options);
|
||||||
|
|
||||||
|
$titles = [$this->translatableStringHelper->localize($entity->getName())];
|
||||||
|
|
||||||
|
// loop to parent, until root
|
||||||
|
while ($entity->hasParent()) {
|
||||||
|
$entity = $entity->getParent();
|
||||||
|
$titles[] = $this->translatableStringHelper->localize(
|
||||||
|
$entity->getTitle()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$titles = \array_reverse($titles);
|
||||||
|
|
||||||
|
$title = \implode($options[self::SEPARATOR_KEY], $titles);
|
||||||
|
|
||||||
|
if ($options[self::SHOW_AND_CHILDREN] && $entity->hasChildren()) {
|
||||||
|
$title .= ' ('.$this->translator->trans($options[self::AND_CHILDREN_MENTION]).')';
|
||||||
|
}
|
||||||
|
|
||||||
|
return $title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function supports($entity, array $options): bool
|
||||||
|
{
|
||||||
|
return $entity instanceof EventTheme;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function buildParents(EventTheme $entity): array
|
||||||
|
{
|
||||||
|
$parents = [];
|
||||||
|
|
||||||
|
while ($entity->hasParent()) {
|
||||||
|
$entity = $parents[] = $entity->getParent();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $parents;
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,7 @@
|
|||||||
services:
|
services:
|
||||||
Chill\EventBundle\Controller\:
|
Chill\EventBundle\Controller\:
|
||||||
autowire: true
|
autowire: true
|
||||||
|
autoconfigure: true
|
||||||
resource: '../Controller'
|
resource: '../Controller'
|
||||||
tags: ['controller.service_arguments']
|
tags: ['controller.service_arguments']
|
||||||
|
|
||||||
@ -9,3 +10,10 @@ services:
|
|||||||
autoconfigure: true
|
autoconfigure: true
|
||||||
resource: '../Menu/'
|
resource: '../Menu/'
|
||||||
tags: ['chill.menu_builder']
|
tags: ['chill.menu_builder']
|
||||||
|
|
||||||
|
Chill\EventBundle\Templating\Entity\:
|
||||||
|
autowire: true
|
||||||
|
autoconfigure: true
|
||||||
|
resource: '../Templating/Entity'
|
||||||
|
tags:
|
||||||
|
- 'chill.render_entity'
|
||||||
|
@ -0,0 +1,4 @@
|
|||||||
|
services:
|
||||||
|
_defaults:
|
||||||
|
autowire: true
|
||||||
|
autoconfigure: true
|
@ -31,3 +31,7 @@ services:
|
|||||||
Chill\EventBundle\Form\Type\PickEventType:
|
Chill\EventBundle\Form\Type\PickEventType:
|
||||||
tags:
|
tags:
|
||||||
- { name: form.type }
|
- { name: form.type }
|
||||||
|
|
||||||
|
Chill\EventBundle\Form\EventThemeType:
|
||||||
|
tags:
|
||||||
|
- { name: form.type }
|
||||||
|
@ -0,0 +1,40 @@
|
|||||||
|
<?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\Event;
|
||||||
|
|
||||||
|
use Doctrine\DBAL\Schema\Schema;
|
||||||
|
use Doctrine\Migrations\AbstractMigration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add event theme entity.
|
||||||
|
*/
|
||||||
|
final class Version20250428092611 extends AbstractMigration
|
||||||
|
{
|
||||||
|
public function getDescription(): string
|
||||||
|
{
|
||||||
|
return 'Add an event theme entity';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function up(Schema $schema): void
|
||||||
|
{
|
||||||
|
$this->addSql('CREATE SEQUENCE chill_event_event_theme_id_seq INCREMENT BY 1 MINVALUE 1 START 1');
|
||||||
|
$this->addSql('CREATE TABLE chill_event_event_theme (id INT NOT NULL, parent_id INT DEFAULT NULL, isActive BOOLEAN NOT NULL, name JSON NOT NULL, ordering DOUBLE PRECISION DEFAULT \'0.0\' NOT NULL, PRIMARY KEY(id))');
|
||||||
|
$this->addSql('CREATE INDEX IDX_80D7C6B0727ACA70 ON chill_event_event_theme (parent_id)');
|
||||||
|
$this->addSql('ALTER TABLE chill_event_event_theme ADD CONSTRAINT FK_80D7C6B0727ACA70 FOREIGN KEY (parent_id) REFERENCES chill_event_event_theme (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(Schema $schema): void
|
||||||
|
{
|
||||||
|
$this->addSql('ALTER TABLE chill_event_event_theme DROP CONSTRAINT FK_80D7C6B0727ACA70');
|
||||||
|
$this->addSql('DROP TABLE chill_event_event_theme');
|
||||||
|
}
|
||||||
|
}
|
@ -140,3 +140,10 @@ event:
|
|||||||
event_types: Par types d'événement
|
event_types: Par types d'événement
|
||||||
event_dates: Par date d'événement
|
event_dates: Par date d'événement
|
||||||
|
|
||||||
|
crud:
|
||||||
|
event_theme:
|
||||||
|
title_new: Créér une nouvelle thématique
|
||||||
|
title_edit: Modifier la thématique
|
||||||
|
index:
|
||||||
|
title: Liste des thématiques
|
||||||
|
add_new: Créér une nouvelle thématique
|
||||||
|
Loading…
x
Reference in New Issue
Block a user