Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FIX] summarizeFormat() - Format leaking across columns #1530

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 30 additions & 13 deletions src/ProcessDataSource.php
Original file line number Diff line number Diff line change
Expand Up @@ -342,41 +342,58 @@ private function applySummaries(MorphToMany|EloquentBuilder|BaseCollection|Query
return;
}

$format = function ($summarize, $column, $field, $value) {
$applySummaryFormat = function ($summarizeMethod, $column, $field, $value) {
if (method_exists($this->component, 'summarizeFormat')) {
$summarizeFormat = $this->component->summarizeFormat();
$summarizeFormatTasks = $this->component->summarizeFormat();

if (count($summarizeFormat) === 0) {
data_set($column, 'summarize.' . $summarize, $value);
if (count($summarizeFormatTasks) === 0) {
data_set($column, 'summarize.' . $summarizeMethod, $value);

return;
}

foreach ($summarizeFormat as $field => $format) {
$parts = explode('.', $field);
foreach ($summarizeFormatTasks as $field => $applySummaryFormat) {
$fieldAndSummarizeMethods = explode('.', $field);

if (isset($parts[1])) {
$formats = str($parts[1])->replace(['{', '}'], '');
$allowedSummarizeFormats = explode(',', $formats);
if (count($fieldAndSummarizeMethods) != 2) {
throw new \InvalidArgumentException('Summary Formatter expects key "column_name.{summarize_method}", [' . $field . '] given instead.');
}

$fieldName = $fieldAndSummarizeMethods[0];
$sumarizeMethods = $fieldAndSummarizeMethods[1];

$applyFormatToSummarizeMethods = str($sumarizeMethods)->replaceMatches('/\s+/', '')
->replace(['{', '}'], '')
->explode(',')
->toArray();

if (in_array($summarizeMethod, $applyFormatToSummarizeMethods)) {
$formattingClosure = $this->component->summarizeFormat()[$field];

if (in_array($summarize, $allowedSummarizeFormats)) {
data_set($column, 'summarize.' . $summarize, $this->component->summarizeFormat()[$field]($value));
if (!is_callable($formattingClosure)) {
throw new \InvalidArgumentException('Summary Formatter expects a callable function, ' . gettype($formattingClosure) . ' given instead.');
}

if (in_array($fieldName, [$column->field, $column->dataField])) {
$value = $formattingClosure($value);
}

data_set($column, 'summarize.' . $summarizeMethod, $value);
}
}
}
};

$this->component->columns = collect($this->component->columns)
->map(function (array|\stdClass|Column $column) use ($results, $format) {
->map(function (array|\stdClass|Column $column) use ($results, $applySummaryFormat) {
$field = strval(data_get($column, 'dataField')) ?: strval(data_get($column, 'field'));

$summaries = ['sum', 'count', 'avg', 'min', 'max'];

foreach ($summaries as $summary) {
if (data_get($column, $summary . '.header') || data_get($column, $summary . '.footer')) {
$value = $results->{$summary}($field);
$format($summary, $column, $field, $value);
$applySummaryFormat($summary, $column, $field, $value);
}
}

Expand Down
11 changes: 10 additions & 1 deletion tests/Concerns/Components/DishesCalculationsTable.php
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ public function fields(): PowerGridFields
return PowerGrid::fields()
->add('id')
->add('name')
->add('calories', fn ($dish) => $dish->calories . ' kcal')
->add('price');
}

Expand All @@ -84,6 +85,10 @@ public function columns(): array
->searchable()
->field('name'),

Column::make('Calories', 'calories', 'calories')
->withAvg('Average', header: true, footer: false)
->sortable(),

Column::add()
->title(__('Price'))
->field('price')
Expand All @@ -99,12 +104,16 @@ public function columns(): array

public function summarizeFormat(): array
{
$fmt = (new \NumberFormatter('pt-PT', \NumberFormatter::DEFAULT_STYLE));

return [
'price.{sum,avg,min,max}' => function ($value) {
return (new \NumberFormatter('en_US', \NumberFormatter::CURRENCY))
->formatCurrency($value, 'USD');
},
'price.{count}' => fn ($value) => $value,
'price.{count}' => fn ($value) => $fmt->format($value) . ' item(s)',
'calories.{avg}' => fn ($value) => $fmt->format($value) . ' kcal',

];
}

Expand Down
21 changes: 11 additions & 10 deletions tests/Feature/CalculationsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,15 @@ function () {
}
);

it('calculate "count" on id field', function (string $component, object $params) {
it('calculates "count" on id field', function (string $component, object $params) {
livewire($component)
->call($params->theme)
->assertSee('Count ID: 12')
->set('search', 'Dish C')
->assertSee('Count ID: 1');
})->with('calculations');

it('calculate "sum" on price field', function (string $component, object $params) {
it('calculates "sum" on price field', function (string $component, object $params) {
livewire($component)
->call($params->theme)
->assertSeeHtml('<span>Sum Price: $15,000.60</span>')
Expand All @@ -29,29 +29,30 @@ function () {
->assertSeeHtml('<span>Sum Price: $600.00</span>');
})->with('calculations')->skip('Refactoring');

it('calculate "count" on price field', function (string $component, object $params) {
it('calculates "count" and formats on price field', function (string $component, object $params) {
livewire($component)
->call($params->theme)
->assertSeeHtml('Count Price: 12')
->assertSeeHtml('Count Price: 12 item(s)')
->set('search', 'Dish C')
->assertSeeHtml('Count Price: 1')
->assertSeeHtml('Count Price: 1 item(s)')
->set('search', 'Dish F')
->assertSeeHtml('Count Price: 1');
->assertSeeHtml('Count Price: 1 item(s)');
})->with('calculations');

it('calculate "avg" on price field', function (string $component, object $params) {
it('calculates and formats "avg" on price field and calorie fields', function (string $component, object $params) {
livewire($component)
->call($params->theme)
->assertSeeHtml('<span>Avg Price: $1,250.05</span>');
->assertSeeHtml('<span>Avg Price: $1,250.05</span>')
->assertSeeHtml('<span>Average: 224 kcal</span>');
})->with('calculations');

it('calculate "min" on price field', function (string $component, object $params) {
it('calculates "min" on price field', function (string $component, object $params) {
livewire($component)
->call($params->theme)
->assertSeeHtml('<span>Min Price: $100.00</span>');
})->with('calculations');

it('calculate "max" on price field', function (string $component, object $params) {
it('calculates "max" on price field', function (string $component, object $params) {
livewire($component)
->call($params->theme)
->assertSeeHtml('<span>Max Price: $7,500.00</span>');
Expand Down
Loading