diff --git a/src/DataTables/Adapters/TwoStepORMAdapter.php b/src/DataTables/Adapters/TwoStepORMAdapter.php index 551c1769..53408f91 100644 --- a/src/DataTables/Adapters/TwoStepORMAdapter.php +++ b/src/DataTables/Adapters/TwoStepORMAdapter.php @@ -55,6 +55,8 @@ class TwoStepORMAdapter extends ORMAdapter private bool $use_simple_total = false; + private \Closure|null $query_modifier; + public function __construct(ManagerRegistry $registry = null) { parent::__construct($registry); @@ -81,6 +83,10 @@ class TwoStepORMAdapter extends ORMAdapter */ $resolver->setDefault('simple_total_query', false); + //Add the possibility of a closure to modify the query builder before the query is executed + $resolver->setDefault('query_modifier', null); + $resolver->setAllowedTypes('query_modifier', ['null', \Closure::class]); + } protected function afterConfiguration(array $options): void @@ -88,6 +94,7 @@ class TwoStepORMAdapter extends ORMAdapter parent::afterConfiguration($options); $this->detailQueryCallable = $options['detail_query']; $this->use_simple_total = $options['simple_total_query']; + $this->query_modifier = $options['query_modifier']; } protected function prepareQuery(AdapterQuery $query): void @@ -159,6 +166,11 @@ class TwoStepORMAdapter extends ORMAdapter ; } + //Apply the query modifier, if set + if ($this->query_modifier !== null) { + $builder = $this->query_modifier->__invoke($builder); + } + $id_query = $builder->getQuery(); $event = new ORMAdapterQueryEvent($id_query); $state->getDataTable()->getEventDispatcher()->dispatch($event, ORMAdapterEvents::PRE_QUERY); diff --git a/src/DataTables/PartsDataTable.php b/src/DataTables/PartsDataTable.php index 98bfb809..b356d1c0 100644 --- a/src/DataTables/PartsDataTable.php +++ b/src/DataTables/PartsDataTable.php @@ -127,18 +127,21 @@ final class PartsDataTable implements DataTableTypeInterface ->add('category', EntityColumn::class, [ 'label' => $this->translator->trans('part.table.category'), 'property' => 'category', + 'orderField' => '_category.name' ]) ->add('footprint', EntityColumn::class, [ 'property' => 'footprint', 'label' => $this->translator->trans('part.table.footprint'), + 'orderField' => '_footprint.name' ]) ->add('manufacturer', EntityColumn::class, [ 'property' => 'manufacturer', 'label' => $this->translator->trans('part.table.manufacturer'), + 'orderField' => '_manufacturer.name' ]) ->add('storelocation', TextColumn::class, [ 'label' => $this->translator->trans('part.table.storeLocations'), - 'orderField' => 'storelocations.name', + 'orderField' => '_storelocations.name', 'render' => fn ($value, Part $context) => $this->partDataTableHelper->renderStorageLocations($context), ], alias: 'storage_location') ->add('amount', TextColumn::class, [ @@ -154,6 +157,7 @@ final class PartsDataTable implements DataTableTypeInterface ->add('partUnit', TextColumn::class, [ 'field' => 'partUnit.name', 'label' => $this->translator->trans('part.table.partUnit'), + 'orderField' => '_partUnit.name' ]) ->add('addedDate', LocaleDateTimeColumn::class, [ 'label' => $this->translator->trans('part.table.addedDate'), @@ -217,6 +221,7 @@ final class PartsDataTable implements DataTableTypeInterface }, new SearchCriteriaProvider(), ], + 'query_modifier' => $this->addJoins(...), ]); } @@ -241,18 +246,6 @@ final class PartsDataTable implements DataTableTypeInterface ) AS HIDDEN amountSum' ) ->from(Part::class, 'part') - /*->leftJoin('part.category', 'category') - ->leftJoin('part.master_picture_attachment', 'master_picture_attachment') - ->leftJoin('part.partLots', 'partLots') - ->leftJoin('partLots.storage_location', 'storelocations') - ->leftJoin('part.footprint', 'footprint') - ->leftJoin('footprint.master_picture_attachment', 'footprint_attachment') - ->leftJoin('part.manufacturer', 'manufacturer') - ->leftJoin('part.orderdetails', 'orderdetails') - ->leftJoin('orderdetails.supplier', 'suppliers') - ->leftJoin('part.attachments', 'attachments') - ->leftJoin('part.partUnit', 'partUnit') - ->leftJoin('part.parameters', 'parameters')*/ //This must be the only group by, or the paginator will not work correctly ->addGroupBy('part.id'); @@ -318,20 +311,14 @@ final class PartsDataTable implements DataTableTypeInterface FieldHelper::addOrderByFieldParam($builder, 'part.id', 'ids'); } - private function buildCriteria(QueryBuilder $builder, array $options): void + /** + * This function is called right before the filter query is executed. + * We use it to dynamically add joins to the query, if the fields are used in the query. + * @param QueryBuilder $builder + * @return QueryBuilder + */ + private function addJoins(QueryBuilder $builder): QueryBuilder { - //Apply the search criterias first - if ($options['search'] instanceof PartSearchFilter) { - $search = $options['search']; - $search->apply($builder); - } - - //We do the most stuff here in the filter class - if ($options['filter'] instanceof PartFilter) { - $filter = $options['filter']; - $filter->apply($builder); - } - //Check if the query contains certain conditions, for which we need to add additional joins //The join fields get prefixed with an underscore, so we can check if they are used in the query easy without confusing them for a part subfield $dql = $builder->getDQL(); @@ -366,5 +353,21 @@ final class PartsDataTable implements DataTableTypeInterface $builder->leftJoin('part.parameters', '_parameters'); } + return $builder; + } + + private function buildCriteria(QueryBuilder $builder, array $options): void + { + //Apply the search criterias first + if ($options['search'] instanceof PartSearchFilter) { + $search = $options['search']; + $search->apply($builder); + } + + //We do the most stuff here in the filter class + if ($options['filter'] instanceof PartFilter) { + $filter = $options['filter']; + $filter->apply($builder); + } } }