diff --git a/config/services.yaml b/config/services.yaml index 82c2f9a..c86e426 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -26,8 +26,10 @@ services: - '../src/Kernel.php' - '../src/Tests/' - # controllers are imported separately to make sure services can be injected - # as action arguments even if you don't extend any base controller class + App\Core\Maker\: + resource: '../core/Maker/' + tags: ['maker.command'] + App\Core\Controller\: resource: '../core/Controller/' tags: ['controller.service_arguments'] diff --git a/core/Controller/Admin/Crud/CrudController.php b/core/Controller/Admin/Crud/CrudController.php index 6e2a5bc..8248a9d 100644 --- a/core/Controller/Admin/Crud/CrudController.php +++ b/core/Controller/Admin/Crud/CrudController.php @@ -19,6 +19,10 @@ use Symfony\Component\HttpFoundation\Session\Session; abstract class CrudController extends AdminController { protected array $filters = []; + protected array $sort = [ + 'label' => null, + 'direction' => null, + ]; abstract protected function getConfiguration(): CrudConfiguration; @@ -26,7 +30,7 @@ abstract class CrudController extends AdminController { $configuration = $this->getConfiguration(); - $this->updateFilters($request, $session); + $this->applySort('index', $query, $request); $pager = $query ->useFilters($this->filters) @@ -36,6 +40,7 @@ abstract class CrudController extends AdminController return $this->render($this->getConfiguration()->getView('index'), [ 'configuration' => $configuration, 'pager' => $pager, + 'sort' => $this->sort, 'filters' => [ 'show' => null !== $configuration->getForm('filter'), 'isEmpty' => empty($this->filters), @@ -198,4 +203,41 @@ abstract class CrudController extends AdminController } } } + + protected function applySort(string $context, RepositoryQuery $query, Request $request) + { + $configuration = $this->getConfiguration(); + + $name = $request->query->get('_sort'); + $direction = strtolower($request->query->get('_sort_direction')); + + if (!in_array($direction, ['asc', 'desc'])) { + $direction = 'asc'; + } + + foreach ($configuration->getFields($context) as $label => $field) { + $sortOption = $field['options']['sort'] ?? null; + + if (null === $sortOption) { + continue; + } + + if ($sortOption[0] !== $name) { + continue; + } + + $sorter = $sortOption[1]; + + if (is_string($sorter)) { + $query->orderBy($sorter, $direction); + } else { + call_user_func_array($sorter, [$query, $direction]); + } + + $this->sort = [ + 'label' => $label, + 'direction' => $direction, + ]; + } + } } diff --git a/core/Crud/Field/Field.php b/core/Crud/Field/Field.php index 16513e9..db5410c 100644 --- a/core/Crud/Field/Field.php +++ b/core/Crud/Field/Field.php @@ -30,6 +30,7 @@ abstract class Field 'property_builder' => null, 'view' => null, 'raw' => false, + 'sort' => null, 'attr' => [], ]); @@ -39,6 +40,20 @@ abstract class Field $resolver->setAllowedTypes('attr', 'array'); $resolver->setAllowedTypes('raw', 'boolean'); $resolver->setAllowedTypes('property_builder', ['null', 'callable']); + $resolver->setAllowedValues('sort', function($value) { + if ($value === null) { + return true; + } + + if (!is_array($value)) { + return false; + } + + $isValidParam1 = !empty($value[0]) && is_string($value[0]); + $isValidParam2 = !empty($value[1]) && (is_string($value[1]) || is_callable($value[1])); + + return $isValidParam1 && $isValidParam2; + }); return $resolver; } diff --git a/core/Resources/views/admin/crud/index.html.twig b/core/Resources/views/admin/crud/index.html.twig index 840c0c8..49bdbb5 100644 --- a/core/Resources/views/admin/crud/index.html.twig +++ b/core/Resources/views/admin/crud/index.html.twig @@ -51,12 +51,51 @@ {% for label, config in configuration.fields('index') %} {% set attr = config.options.attr is defined ? config.options.attr : [] %} + {% set isSortable = config.options.sort ?? false %} - {{ label|trans }} + {% if isSortable %} + {% if sort %} + {% if sort.label == label %} + {% if sort.direction == 'asc' %} + {% set newDirection = 'desc' %} + {% set icon = 'fa fa-sort-amount-down-alt' %} + {% else %} + {% set newDirection = 'asc' %} + {% set icon = 'fa fa-sort-amount-up-alt' %} + {% endif %} + + {% set url = path(configuration.getPageRoute('index'), { + _sort: config.options.sort[0], + _sort_direction: newDirection, + }) %} + {% else %} + {% set url = path(configuration.getPageRoute('index'), { + _sort: config.options.sort[0], + _sort_direction: 'asc', + }) %} + + {% set icon = null %} + {% endif %} + + + {% if icon is defined %} + + {% endif %} + + {{ label|trans }} + + {% else %} + {{ label|trans }} + {% endif %} + {% else %} + {{ label|trans }} + {% endif %} {% endfor %} - Actions + + {{ 'Actions'|trans }} + {% endblock %}