Skip to content
This repository was archived by the owner on Feb 4, 2023. It is now read-only.

Commit 403577a

Browse files
Add compute_total parameter to create a header row with totals of defined columns
1 parent 4bb03c8 commit 403577a

7 files changed

+218
-11
lines changed

Datatable/AbstractDatatable.php

+30
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
namespace Sg\DatatablesBundle\Datatable;
1313

1414
use Sg\DatatablesBundle\Datatable\Column\ColumnBuilder;
15+
use Sg\DatatablesBundle\Response\DatatableQueryBuilder;
1516

1617
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
1718
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
@@ -320,6 +321,35 @@ public function getUniqueName()
320321
return $this->getName().($this->getUniqueId() > 1 ? '-'.$this->getUniqueId() : '');
321322
}
322323

324+
/**
325+
* {@inheritdoc}
326+
*/
327+
public function getDisplayTotals()
328+
{
329+
foreach ($this->getColumnBuilder()->getColumns() as $column) {
330+
if ($column->getComputeTotal()) {
331+
return true;
332+
}
333+
}
334+
335+
return false;
336+
}
337+
338+
/**
339+
* {@inheritdoc}
340+
*/
341+
public function computeTotals()
342+
{
343+
if ($this->getDisplayTotals()) {
344+
$datatableQueryBuilder = new DatatableQueryBuilder(array(), $this);
345+
$totals = $datatableQueryBuilder->getComputedTotals();
346+
347+
foreach ($totals as $key => $value) {
348+
$this->getColumnBuilder()->setColumnTotal($key, $value);
349+
}
350+
}
351+
}
352+
323353
//-------------------------------------------------
324354
// Private
325355
//-------------------------------------------------

Datatable/Column/AbstractColumn.php

+100
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,30 @@ abstract class AbstractColumn implements ColumnInterface
290290
*/
291291
protected $originalTypeOfField;
292292

293+
/**
294+
* If the field is sent in the response, to show in the webpage
295+
* Is set in the ColumnBuilder.
296+
* Default: true
297+
*
298+
* @var bool
299+
*/
300+
protected $sentInResponse;
301+
302+
/**
303+
* If this column displays the total of its cells in its head
304+
* Default: false
305+
*
306+
* @var bool
307+
*/
308+
protected $computeTotal;
309+
310+
/**
311+
* Contains the eventually computed total of the column
312+
*
313+
* @var mixed
314+
*/
315+
protected $total;
316+
293317
//-------------------------------------------------
294318
// Options
295319
//-------------------------------------------------
@@ -323,6 +347,8 @@ public function configureOptions(OptionsResolver $resolver)
323347
'join_type' => 'leftJoin',
324348
'type_of_field' => null,
325349
'responsive_priority' => null,
350+
'sent_in_response' => true,
351+
'compute_total' => false
326352
));
327353

328354
$resolver->setAllowedTypes('cell_type', array('null', 'string'));
@@ -343,6 +369,8 @@ public function configureOptions(OptionsResolver $resolver)
343369
$resolver->setAllowedTypes('join_type', 'string');
344370
$resolver->setAllowedTypes('type_of_field', array('null', 'string'));
345371
$resolver->setAllowedTypes('responsive_priority', array('null', 'int'));
372+
$resolver->setAllowedTypes('sent_in_response', array('bool'));
373+
$resolver->setAllowedTypes('compute_total', array('bool'));
346374

347375
$resolver->setAllowedValues('cell_type', array(null, 'th', 'td'));
348376
$resolver->setAllowedValues('join_type', array(null, 'join', 'leftJoin', 'innerJoin'));
@@ -1075,4 +1103,76 @@ public function setOriginalTypeOfField($originalTypeOfField)
10751103

10761104
return $this;
10771105
}
1106+
1107+
/**
1108+
* Get sentInResponse.
1109+
*
1110+
* @return bool
1111+
*/
1112+
public function getSentInResponse()
1113+
{
1114+
return $this->sentInResponse;
1115+
}
1116+
1117+
/**
1118+
* Set sentIntResponse.
1119+
*
1120+
* @param bool $sentInResponse
1121+
*
1122+
* @return $this
1123+
*/
1124+
public function setSentInResponse($sentInResponse)
1125+
{
1126+
$this->sentInResponse = $sentInResponse;
1127+
1128+
return $this;
1129+
}
1130+
1131+
/**
1132+
* Get computeTotal.
1133+
*
1134+
* @return bool
1135+
*/
1136+
public function getComputeTotal()
1137+
{
1138+
return $this->computeTotal;
1139+
}
1140+
1141+
/**
1142+
* Set sentIntResponse.
1143+
*
1144+
* @param bool $computeTotal
1145+
*
1146+
* @return $this
1147+
*/
1148+
public function setComputeTotal($computeTotal)
1149+
{
1150+
$this->computeTotal = $computeTotal;
1151+
1152+
return $this;
1153+
}
1154+
1155+
/**
1156+
* Get total
1157+
*
1158+
* @return mixed
1159+
*/
1160+
public function getTotal()
1161+
{
1162+
return $this->total;
1163+
}
1164+
1165+
/**
1166+
* Set total
1167+
*
1168+
* @param $total
1169+
*
1170+
* @return $this
1171+
*/
1172+
public function setTotal($total)
1173+
{
1174+
$this->total = $total;
1175+
1176+
return $this;
1177+
}
10781178
}

Datatable/Column/ColumnBuilder.php

+10
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,16 @@ public function getUniqueColumn($columnType)
194194
return array_key_exists($columnType, $this->uniqueColumns) ? $this->uniqueColumns[$columnType] : null;
195195
}
196196

197+
public function setColumnTotal($dql, $total)
198+
{
199+
foreach ($this->columns as $column) {
200+
if ($column->getDql() == $dql) {
201+
$column->setTotal($total);
202+
break;
203+
}
204+
}
205+
}
206+
197207
//-------------------------------------------------
198208
// Helper
199209
//-------------------------------------------------

Datatable/DatatableInterface.php

+14
Original file line numberDiff line numberDiff line change
@@ -139,4 +139,18 @@ public function getUniqueId();
139139
* @return string
140140
*/
141141
public function getUniqueName();
142+
143+
/**
144+
* Returns if a total line in the header should appear
145+
*
146+
* @return bool
147+
*/
148+
public function getDisplayTotals();
149+
150+
/**
151+
* Compute totals before rendering the datatable HTML code
152+
*
153+
* @return void
154+
*/
155+
public function computeTotals();
142156
}

Resources/views/datatable/datatable_html.html.twig

+37-11
Original file line numberDiff line numberDiff line change
@@ -20,31 +20,57 @@
2020
{% if 'head' == sg_datatables_view.options.individualFilteringPosition or 'both' == sg_datatables_view.options.individualFilteringPosition%}
2121
<tr>
2222
{% for column in sg_datatables_view.columnBuilder.columns %}
23-
<th>{{ column.title }}</th>
23+
{% if column.sentInResponse %}
24+
<th>{{ column.title }}</th>
25+
{% endif %}
2426
{% endfor %}
2527
</tr>
2628
<tr id="sg-datatables-{{ sg_datatables_view.uniqueName }}-filterrow">
2729
{% for column in sg_datatables_view.columnBuilder.columns %}
28-
<th>
29-
{% if column.searchable %}
30-
{{ sg_datatables_render_filter(sg_datatables_view, column, 'head') }}
31-
{% endif %}
32-
</th>
30+
{% if column.sentInResponse %}
31+
<th>
32+
{% if column.searchable %}
33+
{{ sg_datatables_render_filter(sg_datatables_view, column, 'head') }}
34+
{% endif %}
35+
</th>
36+
{% endif %}
3337
{% endfor %}
3438
</tr>
3539
{% endif %}
3640
{% endif %}
41+
<tr>
42+
{% for column in sg_datatables_view.columnBuilder.columns %}
43+
{% if column.sentInResponse %}
44+
<th>{{ column.title }}</th>
45+
{% endif %}
46+
{% endfor %}
47+
</tr>
48+
{% if sg_datatables_view.displayTotals %}
49+
<tr>
50+
{% for column in sg_datatables_view.columnBuilder.columns %}
51+
{% if column.sentInResponse %}
52+
<th>
53+
{% if column.computeTotal %}
54+
TOTAL: {{ column.total }}
55+
{% endif %}
56+
</th>
57+
{% endif %}
58+
{% endfor %}
59+
</tr>
60+
{% endif %}
3761
</thead>
3862
{% if true == individual_filtering %}
3963
{% if 'foot' == sg_datatables_view.options.individualFilteringPosition or 'both' == sg_datatables_view.options.individualFilteringPosition%}
4064
<tfoot>
4165
<tr>
4266
{% for column in sg_datatables_view.columnBuilder.columns %}
43-
<td>
44-
{% if column.searchable %}
45-
{{ sg_datatables_render_filter(sg_datatables_view, column, 'foot') }}
46-
{% endif %}
47-
</td>
67+
{% if column.sentInResponse %}
68+
<td>
69+
{% if column.searchable %}
70+
{{ sg_datatables_render_filter(sg_datatables_view, column, 'foot') }}
71+
{% endif %}
72+
</td>
73+
{% endif %}
4874
{% endfor %}
4975
</tr>
5076
</tfoot>

Response/DatatableQueryBuilder.php

+23
Original file line numberDiff line numberDiff line change
@@ -556,6 +556,29 @@ public function getCountAllResults()
556556
: count($query->getResult());
557557
}
558558

559+
public function getComputedTotals()
560+
{
561+
$qb = clone $this->qb;
562+
563+
$queryString = "";
564+
565+
foreach ($this->columns as $column) {
566+
if ($column->getComputeTotal()) {
567+
$queryString .= 'SUM(' . $this->entityShortName . '.' . $column->getDql() . ') AS ' . $column->getDql() . ' ';
568+
}
569+
}
570+
571+
$qb->select($queryString);
572+
$qb->resetDQLPart('orderBy');
573+
$this->setJoins($qb);
574+
575+
$query = $qb->getQuery();
576+
$query->useQueryCache($this->useCountQueryCache);
577+
call_user_func_array([$query, 'useResultCache'], $this->useCountResultCacheArgs);
578+
579+
return $query->getOneOrNullResult();
580+
}
581+
559582
/**
560583
* Defines whether query used for records retrieval should use query cache if available.
561584
*

Twig/DatatableTwigExtension.php

+4
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,8 @@ public function getFilters()
120120
*/
121121
public function datatablesRender(Twig_Environment $twig, DatatableInterface $datatable)
122122
{
123+
$datatable->computeTotals();
124+
123125
return $twig->render(
124126
'@SgDatatables/datatable/datatable.html.twig',
125127
array(
@@ -138,6 +140,8 @@ public function datatablesRender(Twig_Environment $twig, DatatableInterface $dat
138140
*/
139141
public function datatablesRenderHtml(Twig_Environment $twig, DatatableInterface $datatable)
140142
{
143+
$datatable->computeTotals();
144+
141145
return $twig->render(
142146
'@SgDatatables/datatable/datatable_html.html.twig',
143147
array(

0 commit comments

Comments
 (0)