From 7244a65c4108f64c294c086f1ce5e7d6e0f9e65f Mon Sep 17 00:00:00 2001 From: Philippe MILINK Date: Wed, 22 Aug 2018 22:13:38 +0200 Subject: [PATCH 1/2] Add compute_total parameter to create a header row with totals of defined columns --- Datatable/AbstractDatatable.php | 30 +++++++++++++++++++ Datatable/Column/AbstractColumn.php | 4 --- Datatable/Column/ColumnBuilder.php | 10 +++++++ Datatable/DatatableInterface.php | 14 +++++++++ .../views/datatable/datatable_html.html.twig | 13 ++++++++ Response/DatatableQueryBuilder.php | 23 ++++++++++++++ Twig/DatatableTwigExtension.php | 4 +++ 7 files changed, 94 insertions(+), 4 deletions(-) diff --git a/Datatable/AbstractDatatable.php b/Datatable/AbstractDatatable.php index 1acb48fd..5b6e39d2 100644 --- a/Datatable/AbstractDatatable.php +++ b/Datatable/AbstractDatatable.php @@ -14,6 +14,7 @@ use Doctrine\ORM\EntityManagerInterface; use Exception; use Sg\DatatablesBundle\Datatable\Column\ColumnBuilder; +use Sg\DatatablesBundle\Response\DatatableQueryBuilder; use Symfony\Component\PropertyAccess\PropertyAccess; use Symfony\Component\PropertyAccess\PropertyAccessor; use Symfony\Component\Routing\RouterInterface; @@ -301,6 +302,35 @@ public function getUniqueName() return $this->getName().($this->getUniqueId() > 1 ? '-'.$this->getUniqueId() : ''); } + /** + * {@inheritdoc} + */ + public function getDisplayTotals() + { + foreach ($this->getColumnBuilder()->getColumns() as $column) { + if ($column->getComputeTotal()) { + return true; + } + } + + return false; + } + + /** + * {@inheritdoc} + */ + public function computeTotals() + { + if ($this->getDisplayTotals()) { + $datatableQueryBuilder = new DatatableQueryBuilder(array(), $this); + $totals = $datatableQueryBuilder->getComputedTotals(); + + foreach ($totals as $key => $value) { + $this->getColumnBuilder()->setColumnTotal($key, $value); + } + } + } + //------------------------------------------------- // Private //------------------------------------------------- diff --git a/Datatable/Column/AbstractColumn.php b/Datatable/Column/AbstractColumn.php index f598addc..578029c5 100644 --- a/Datatable/Column/AbstractColumn.php +++ b/Datatable/Column/AbstractColumn.php @@ -365,7 +365,6 @@ public function configureOptions(OptionsResolver $resolver) 'data_source' => null, ]); - $resolver->setAllowedTypes('cell_type', ['null', 'string']); $resolver->setAllowedTypes('class_name', ['null', 'string']); $resolver->setAllowedTypes('content_padding', ['null', 'string']); $resolver->setAllowedTypes('dql', ['null', 'string']); @@ -380,15 +379,12 @@ public function configureOptions(OptionsResolver $resolver) $resolver->setAllowedTypes('visible', 'bool'); $resolver->setAllowedTypes('width', ['null', 'string']); $resolver->setAllowedTypes('add_if', ['null', 'Closure']); - $resolver->setAllowedTypes('join_type', 'string'); - $resolver->setAllowedTypes('type_of_field', ['null', 'string']); $resolver->setAllowedTypes('responsive_priority', ['null', 'int']); $resolver->setAllowedTypes('sent_in_response', ['bool']); $resolver->setAllowedTypes('compute_total', ['bool']); $resolver->setAllowedTypes('mapped', ['bool']); $resolver->setAllowedTypes('is_association', ['bool']); $resolver->setAllowedTypes('data_source', ['string', 'null']); - $resolver->setAllowedValues('cell_type', [null, 'th', 'td']); $resolver->setAllowedValues('join_type', [null, 'join', 'leftJoin', 'innerJoin']); $resolver->setAllowedValues('type_of_field', array_merge([null], array_keys(DoctrineType::getTypesMap()))); diff --git a/Datatable/Column/ColumnBuilder.php b/Datatable/Column/ColumnBuilder.php index 48c277ea..5e231c6b 100644 --- a/Datatable/Column/ColumnBuilder.php +++ b/Datatable/Column/ColumnBuilder.php @@ -185,6 +185,16 @@ public function getUniqueColumn($columnType) return \array_key_exists($columnType, $this->uniqueColumns) ? $this->uniqueColumns[$columnType] : null; } + public function setColumnTotal($dql, $total) + { + foreach ($this->columns as $column) { + if ($column->getDql() == $dql) { + $column->setTotal($total); + break; + } + } + } + //------------------------------------------------- // Helper //------------------------------------------------- diff --git a/Datatable/DatatableInterface.php b/Datatable/DatatableInterface.php index 0f3f18a7..5081deb9 100644 --- a/Datatable/DatatableInterface.php +++ b/Datatable/DatatableInterface.php @@ -132,4 +132,18 @@ public function getUniqueId(); * @return string */ public function getUniqueName(); + + /** + * Returns if a total line in the header should appear + * + * @return bool + */ + public function getDisplayTotals(); + + /** + * Compute totals before rendering the datatable HTML code + * + * @return void + */ + public function computeTotals(); } diff --git a/Resources/views/datatable/datatable_html.html.twig b/Resources/views/datatable/datatable_html.html.twig index cb377e1a..bd8568f3 100644 --- a/Resources/views/datatable/datatable_html.html.twig +++ b/Resources/views/datatable/datatable_html.html.twig @@ -45,6 +45,19 @@ {% endif %} {% endfor %} + {% if sg_datatables_view.displayTotals %} + + {% for column in sg_datatables_view.columnBuilder.columns %} + {% if column.sentInResponse %} + + {% if column.computeTotal %} + TOTAL: {{ column.total }} + {% endif %} + + {% endif %} + {% endfor %} + + {% endif %} {% if true == individual_filtering %} {% if 'foot' == sg_datatables_view.options.individualFilteringPosition or 'both' == sg_datatables_view.options.individualFilteringPosition%} diff --git a/Response/DatatableQueryBuilder.php b/Response/DatatableQueryBuilder.php index d956e00c..e68c852d 100644 --- a/Response/DatatableQueryBuilder.php +++ b/Response/DatatableQueryBuilder.php @@ -598,6 +598,29 @@ private function setLimit(QueryBuilder $qb) return $this; } + public function getComputedTotals() + { + $qb = clone $this->qb; + + $queryString = ""; + + foreach ($this->columns as $column) { + if ($column->getComputeTotal()) { + $queryString .= 'SUM(' . $this->entityShortName . '.' . $column->getDql() . ') AS ' . $column->getDql() . ' '; + } + } + + $qb->select($queryString); + $qb->resetDQLPart('orderBy'); + $this->setJoins($qb); + + $query = $qb->getQuery(); + $query->useQueryCache($this->useCountQueryCache); + call_user_func_array([$query, 'useResultCache'], $this->useCountResultCacheArgs); + + return $query->getOneOrNullResult(); + } + //------------------------------------------------- // Private - Helper //------------------------------------------------- diff --git a/Twig/DatatableTwigExtension.php b/Twig/DatatableTwigExtension.php index be96e101..a75f936d 100644 --- a/Twig/DatatableTwigExtension.php +++ b/Twig/DatatableTwigExtension.php @@ -104,6 +104,8 @@ public function getFilters() */ public function datatablesRender(Twig_Environment $twig, DatatableInterface $datatable) { + $datatable->computeTotals(); + return $twig->render( '@SgDatatables/datatable/datatable.html.twig', [ @@ -119,6 +121,8 @@ public function datatablesRender(Twig_Environment $twig, DatatableInterface $dat */ public function datatablesRenderHtml(Twig_Environment $twig, DatatableInterface $datatable) { + $datatable->computeTotals(); + return $twig->render( '@SgDatatables/datatable/datatable_html.html.twig', [ From 4d39d8b86c390ab03aa4b95286bafb5ffdb63255 Mon Sep 17 00:00:00 2001 From: Philippe MILINK Date: Tue, 23 Oct 2018 18:08:42 +0200 Subject: [PATCH 2/2] Add documentation for compute_total --- Datatable/Column/AbstractColumn.php | 2 +- Resources/doc/columns.md | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/Datatable/Column/AbstractColumn.php b/Datatable/Column/AbstractColumn.php index 578029c5..09b53f39 100644 --- a/Datatable/Column/AbstractColumn.php +++ b/Datatable/Column/AbstractColumn.php @@ -1103,7 +1103,7 @@ public function getTotal() /** * Set total. * - * @param $total + * @param mixed $total * * @return $this */ diff --git a/Resources/doc/columns.md b/Resources/doc/columns.md index 4bf30478..bc375577 100644 --- a/Resources/doc/columns.md +++ b/Resources/doc/columns.md @@ -54,6 +54,7 @@ With 'null' initialized options uses the default value of the DataTables plugin. | mapped | bool | true | | Allow to create columns not mapped in entity neither defined by DQL. | | is_association | bool | false | | Allow to force if the column is an association, usally used with `mapped` and `data_source`. | | data_source | null or string | null | | Specify the column source of the data to manipulate in the current column. Usally used with `mapped` and `data_source`. | +| compute_total | bool | false | | Compute the total of numbers of all the row selected by the query. Totals will be displayed on a header row. | ### Example @@ -761,6 +762,7 @@ public function buildDatatable(array $options = array()) } ``` + ## 10. Link column Represents a column, with a link in each cell.