121 lines
3.8 KiB
PHP
121 lines
3.8 KiB
PHP
<?php
|
||
|
||
namespace App\Business;
|
||
|
||
use Illuminate\Http\Request;
|
||
use Illuminate\Support\Collection;
|
||
|
||
class CourierPayableSummaryFilter
|
||
{
|
||
/** @return array{date:string,person:string,courier:string,keyword:string} */
|
||
public function fromRequest(Request $request): array
|
||
{
|
||
$clean = static function (string $key, int $maxLength) use ($request): string {
|
||
$value = $request->query($key, '');
|
||
|
||
if (! is_scalar($value)) {
|
||
return '';
|
||
}
|
||
|
||
return mb_substr(trim((string) $value), 0, $maxLength);
|
||
};
|
||
|
||
return [
|
||
'date' => $clean('date', 50),
|
||
'person' => $clean('person', 100),
|
||
'courier' => $clean('courier', 100),
|
||
'keyword' => $clean('keyword', 191),
|
||
];
|
||
}
|
||
|
||
/** @param array{date:string,person:string,courier:string,keyword:string} $filters */
|
||
public function hasFilters(array $filters): bool
|
||
{
|
||
return collect($filters)->contains(static fn (string $value): bool => $value !== '');
|
||
}
|
||
|
||
/**
|
||
* @param Collection<int, mixed> $rows
|
||
* @param list<string> $headers
|
||
* @param array{date:string,person:string,courier:string,keyword:string} $filters
|
||
* @return Collection<int, mixed>
|
||
*/
|
||
public function apply(Collection $rows, array $headers, array $filters): Collection
|
||
{
|
||
if (! $this->hasFilters($filters)) {
|
||
return $rows;
|
||
}
|
||
|
||
$dateColumn = $this->columnIndex($headers, ['日期', '结算月份', '结算月', '月份']);
|
||
$personColumn = $this->columnIndex($headers, ['负责人', '责任人']);
|
||
$courierColumn = $this->columnIndex($headers, ['快递公司', '快递名称', '快递名', '快递']);
|
||
|
||
return $rows->filter(function (mixed $row) use ($filters, $dateColumn, $personColumn, $courierColumn): bool {
|
||
if (! is_array($row)) {
|
||
return false;
|
||
}
|
||
|
||
if (! $this->columnMatches($row, $dateColumn, $filters['date'])
|
||
|| ! $this->columnMatches($row, $personColumn, $filters['person'])
|
||
|| ! $this->columnMatches($row, $courierColumn, $filters['courier'])) {
|
||
return false;
|
||
}
|
||
|
||
if ($filters['keyword'] === '') {
|
||
return true;
|
||
}
|
||
|
||
foreach ($row as $value) {
|
||
if ($this->contains($value, $filters['keyword'])) {
|
||
return true;
|
||
}
|
||
}
|
||
|
||
return false;
|
||
});
|
||
}
|
||
|
||
/** @param list<string> $headers */
|
||
public function dateColumnIndex(array $headers): ?int
|
||
{
|
||
return $this->columnIndex($headers, ['日期', '结算月份', '结算月', '月份']);
|
||
}
|
||
|
||
/** @param list<string> $headers */
|
||
private function columnIndex(array $headers, array $aliases): ?int
|
||
{
|
||
$normalizedAliases = array_map(
|
||
static fn (string $alias): string => mb_strtolower(preg_replace('/[\\s ]+/u', '', $alias) ?? $alias),
|
||
$aliases,
|
||
);
|
||
|
||
foreach ($headers as $index => $header) {
|
||
$normalizedHeader = mb_strtolower(preg_replace('/[\\s ]+/u', '', trim((string) $header)) ?? trim((string) $header));
|
||
|
||
if (in_array($normalizedHeader, $normalizedAliases, true)) {
|
||
return (int) $index;
|
||
}
|
||
}
|
||
|
||
return null;
|
||
}
|
||
|
||
private function columnMatches(array $row, ?int $column, string $needle): bool
|
||
{
|
||
if ($needle === '') {
|
||
return true;
|
||
}
|
||
|
||
return $column !== null && $this->contains($row[$column] ?? '', $needle);
|
||
}
|
||
|
||
private function contains(mixed $value, string $needle): bool
|
||
{
|
||
if (! is_scalar($value) && ! $value instanceof \Stringable) {
|
||
return false;
|
||
}
|
||
|
||
return mb_stripos((string) $value, $needle, 0, 'UTF-8') !== false;
|
||
}
|
||
}
|