57 lines
1.9 KiB
PHP
57 lines
1.9 KiB
PHP
<?php
|
|
|
|
namespace App\Services\Analytics;
|
|
|
|
use Closure;
|
|
|
|
/**
|
|
* Измерение (группировка) отчёта: по чему группируем строки таблицы.
|
|
* Несёт SQL-выражение для SELECT/GROUP BY и опциональные join + резолвер подписей.
|
|
*/
|
|
readonly class Dimension
|
|
{
|
|
/**
|
|
* @param 'string'|'date' $type
|
|
* @param string $select raw SQL-выражение, дающее сырое значение измерения
|
|
* @param ?string $groupBy выражение для GROUP BY (по умолчанию = $select)
|
|
* @param ?Closure $applyJoin fn(\Illuminate\Database\Query\Builder $q): void — добавить нужный JOIN
|
|
* @param ?Closure $labels fn(array $rawValues): array<int|string,string> — карта «сырое значение => подпись»
|
|
*/
|
|
public function __construct(
|
|
public string $key,
|
|
public string $label,
|
|
public string $type,
|
|
public string $select,
|
|
public ?string $groupBy = null,
|
|
public ?Closure $applyJoin = null,
|
|
public ?Closure $labels = null,
|
|
) {}
|
|
|
|
public function groupByExpr(): string
|
|
{
|
|
return $this->groupBy ?? $this->select;
|
|
}
|
|
|
|
/**
|
|
* Подпись сырого значения для вывода в таблице.
|
|
*
|
|
* @param array<int|string,string>|null $labelMap
|
|
*/
|
|
public function display(mixed $raw, ?array $labelMap = null): string
|
|
{
|
|
if ($raw === null || $raw === '') {
|
|
return '—';
|
|
}
|
|
|
|
if ($labelMap !== null && array_key_exists($raw, $labelMap)) {
|
|
return $labelMap[$raw];
|
|
}
|
|
|
|
if ($this->type === 'date') {
|
|
return \Illuminate\Support\Carbon::parse((string) $raw)->format('d.m.Y');
|
|
}
|
|
|
|
return (string) $raw;
|
|
}
|
|
}
|