Skip to content

Commit

Permalink
Move initialization logic out from the builder, extract array util he…
Browse files Browse the repository at this point in the history
…lper class
  • Loading branch information
Kreyu committed Nov 6, 2024
1 parent 677bbab commit 1667587
Show file tree
Hide file tree
Showing 5 changed files with 122 additions and 53 deletions.
61 changes: 17 additions & 44 deletions src/DataCollector/DataTableDataCollector.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
use Kreyu\Bundle\DataTableBundle\Filter\FiltrationData;
use Kreyu\Bundle\DataTableBundle\Pagination\PaginationData;
use Kreyu\Bundle\DataTableBundle\Sorting\SortingData;
use Kreyu\Bundle\DataTableBundle\Util\ArrayUtil;
use Symfony\Bundle\FrameworkBundle\DataCollector\AbstractDataCollector;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
Expand All @@ -42,34 +43,39 @@ public function __sleep(): array
return parent::__sleep();
}

public static function getTemplate(): ?string
{
return '@KreyuDataTable/data_collector/template.html.twig';
}

public function collect(Request $request, Response $response, ?\Throwable $exception = null): void
{
}

public function collectDataTable(DataTableInterface $dataTable): void
{
$data = [
'columns' => $this->mapWithKeys(
'columns' => ArrayUtil::mapWithKeys(
fn (ColumnInterface $column) => [$column->getName() => $this->dataExtractor->extractColumnConfiguration($column)],
$dataTable->getColumns(),
),
'filters' => $this->mapWithKeys(
'filters' => ArrayUtil::mapWithKeys(
fn (FilterInterface $filter) => [$filter->getName() => $this->dataExtractor->extractFilterConfiguration($filter)],
$dataTable->getFilters(),
),
'actions' => $this->mapWithKeys(
'actions' => ArrayUtil::mapWithKeys(
fn (ActionInterface $action) => [$action->getName() => $this->dataExtractor->extractActionConfiguration($action)],
$dataTable->getActions(),
),
'row_actions' => $this->mapWithKeys(
'row_actions' => ArrayUtil::mapWithKeys(
fn (ActionInterface $action) => [$action->getName() => $this->dataExtractor->extractActionConfiguration($action)],
$dataTable->getRowActions(),
),
'batch_actions' => $this->mapWithKeys(
'batch_actions' => ArrayUtil::mapWithKeys(
fn (ActionInterface $action) => [$action->getName() => $this->dataExtractor->extractActionConfiguration($action)],
$dataTable->getBatchActions(),
),
'exporters' => $this->mapWithKeys(
'exporters' => ArrayUtil::mapWithKeys(
fn (ExporterInterface $exporter) => [$exporter->getName() => $this->dataExtractor->extractExporterConfiguration($exporter)],
$dataTable->getExporters(),
),
Expand All @@ -83,14 +89,14 @@ public function collectDataTable(DataTableInterface $dataTable): void
public function collectDataTableView(DataTableInterface $dataTable, DataTableView $view): void
{
$this->data[$dataTable->getName()] += [
'view_vars' => $this->ksort($view->vars),
'view_vars' => ArrayUtil::ksort($view->vars),
'value_rows' => $this->dataExtractor->extractValueRows($view),
];
}

public function collectColumnHeaderView(ColumnInterface $column, ColumnHeaderView $view): void
{
$this->data[$column->getDataTable()->getName()]['columns'][$column->getName()]['header_view_vars'] = $this->ksort($view->vars);
$this->data[$column->getDataTable()->getName()]['columns'][$column->getName()]['header_view_vars'] = ArrayUtil::ksort($view->vars);
}

public function collectColumnValueView(ColumnInterface $column, ColumnValueView $view): void
Expand All @@ -100,7 +106,7 @@ public function collectColumnValueView(ColumnInterface $column, ColumnValueView
return;
}

$this->data[$column->getDataTable()->getName()]['columns'][$column->getName()]['value_view_vars'] = $this->ksort($view->vars);
$this->data[$column->getDataTable()->getName()]['columns'][$column->getName()]['value_view_vars'] = ArrayUtil::ksort($view->vars);
}

public function collectSortingData(DataTableInterface $dataTable, SortingData $data): void
Expand Down Expand Up @@ -128,7 +134,7 @@ public function collectPaginationData(DataTableInterface $dataTable, PaginationD

public function collectFilterView(FilterInterface $filter, FilterView $view): void
{
$this->data[$filter->getDataTable()->getName()]['filters'][$filter->getName()]['view_vars'] = $this->ksort($view->vars);
$this->data[$filter->getDataTable()->getName()]['filters'][$filter->getName()]['view_vars'] = ArrayUtil::ksort($view->vars);
}

public function collectFiltrationData(DataTableInterface $dataTable, FiltrationData $data): void
Expand Down Expand Up @@ -156,44 +162,11 @@ public function collectActionView(ActionInterface $action, ActionView $view): vo
ActionContext::Batch => 'batch_actions',
};

$this->data[$action->getDataTable()->getName()][$actionsKey][$action->getName()]['view_vars'] = $this->ksort($view->vars);
}

public static function getTemplate(): ?string
{
return '@KreyuDataTable/data_collector/template.html.twig';
$this->data[$action->getDataTable()->getName()][$actionsKey][$action->getName()]['view_vars'] = ArrayUtil::ksort($view->vars);
}

public function getData(): array|Data
{
return $this->data;
}

/**
* @internal
*/
private function mapWithKeys(callable $callback, array $array): array
{
$data = [];

foreach ($array as $value) {
foreach ($callback($value) as $mapKey => $mapValue) {
$data[$mapKey] = $mapValue;
}
}

return $data;
}

/**
* @internal
*/
private function ksort(array $array): array
{
$copy = $array;

ksort($copy);

return $copy;
}
}
18 changes: 13 additions & 5 deletions src/DataTable.php
Original file line number Diff line number Diff line change
Expand Up @@ -134,19 +134,19 @@ public function initialize(): void

$this->dispatch(DataTableEvents::PRE_INITIALIZE, new DataTableEvent($this));

if ($paginationData = $this->getInitialPaginationData()) {
if (null === $this->paginationData && $paginationData = $this->getInitialPaginationData()) {
$this->paginate($paginationData, false);
}

if ($sortingData = $this->getInitialSortingData()) {
if (null === $this->sortingData && $sortingData = $this->getInitialSortingData()) {
$this->sort($sortingData, false);
}

if ($filtrationData = $this->getInitialFiltrationData()) {
if (null === $this->filtrationData && $filtrationData = $this->getInitialFiltrationData()) {
$this->filter($filtrationData, false);
}

if ($personalizationData = $this->getInitialPersonalizationData()) {
if (null === $this->personalizationData && $personalizationData = $this->getInitialPersonalizationData()) {
$this->personalize($personalizationData, false);
}

Expand Down Expand Up @@ -584,7 +584,7 @@ public function export(?ExportData $data = null): ExportFile
$data = $event->getExportData();

if (ExportStrategy::IncludeAll === $data->strategy) {
$dataTable->getQuery()->paginate(new PaginationData(perPage: null));
$this->paginate(new PaginationData(page: 1, perPage: null), persistence: false);
}

if (!$data->includePersonalization) {
Expand Down Expand Up @@ -784,6 +784,10 @@ public function handleRequest(mixed $request): void

public function createView(): DataTableView
{
if (!$this->initialized) {
$this->initialize();
}

$type = $this->config->getType();
$options = $this->config->getOptions();

Expand All @@ -796,6 +800,10 @@ public function createView(): DataTableView

public function createExportView(): DataTableView
{
if (!$this->initialized) {
$this->initialize();
}

$type = $this->config->getType();
$options = $this->config->getOptions();

Expand Down
4 changes: 0 additions & 4 deletions src/DataTableBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -775,10 +775,6 @@ public function getDataTable(): DataTableInterface
$dataTable->addExporter($exporter->getExporter());
}

// TODO: Remove initialization logic from builder.
// Instead, add "initialized" flag to the data table itself to allow lazy initialization.
$dataTable->initialize();

return $dataTable;
}

Expand Down
53 changes: 53 additions & 0 deletions src/Util/ArrayUtil.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<?php

declare(strict_types=1);

namespace Kreyu\Bundle\DataTableBundle\Util;

/**
* @internal
*/
class ArrayUtil
{
/**
* Maps an array with callable that returns an array of key-value pairs.
*
* <code>
* $map = ArrayUtil::mapWithKeys(
* callback: fn (array $array) => [$array['id'] => $array['name']],
* array: [
* ['id' => 1, 'name' => 'John'],
* ['id' => 2, 'name' => 'Jane'],
* ]
* );
*
* var_dump($map); // array(2) { [1] => string(4) "John" [2] => string(4) "Jane" }
* </code>
*
* @param callable(mixed): array<int|string, mixed> $callback
*/
public static function mapWithKeys(callable $callback, array $array): array
{
$data = [];

foreach ($array as $value) {
foreach ($callback($value) as $mapKey => $mapValue) {
$data[$mapKey] = $mapValue;
}
}

return $data;
}

/**
* Performs a `ksort` on a copy of given array instead of modifying it by reference.
*/
public static function ksort(array $array, int $flags = SORT_REGULAR): array
{
$copy = $array;

ksort($copy, $flags);

return $copy;
}
}
39 changes: 39 additions & 0 deletions tests/Unit/Util/ArrayUtilTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?php

declare(strict_types=1);

namespace Kreyu\Bundle\DataTableBundle\Tests\Unit\Util;

use Kreyu\Bundle\DataTableBundle\Util\ArrayUtil;
use PHPUnit\Framework\TestCase;

class ArrayUtilTest extends TestCase
{
public function testKsort()
{
$input = ['c' => 3, 'b' => 2, 'a' => 1];
$output = ArrayUtil::ksort($input);

$this->assertSame(['a' => 1, 'b' => 2, 'c' => 3], $output);
$this->assertSame(['c' => 3, 'b' => 2, 'a' => 1], $input);
}

public function testMapWithKeys()
{
$input = [
['id' => 1, 'name' => 'John'],
['id' => 2, 'name' => 'Jane'],
];

$output = ArrayUtil::mapWithKeys(
callback: fn (array $array) => [$array['id'] => $array['name']],
array: $input,
);

$this->assertSame([1 => 'John', 2 => 'Jane'], $output);
$this->assertSame([
['id' => 1, 'name' => 'John'],
['id' => 2, 'name' => 'Jane'],
], $input);
}
}

0 comments on commit 1667587

Please sign in to comment.