Feature: Creating Privacy Basics

This commit is contained in:
2026-08-24 21:06:11 +03:00
parent e31de1b4e3
commit 9f540cbaa4
38 changed files with 1969 additions and 3 deletions
+21
View File
@@ -0,0 +1,21 @@
<?php
namespace Modules\Core\Export;
/**
* One column in a CsvWriter schema: a header label plus a closure that pulls this
* column's value out of one record. The closure doesn't care what shape a record
* is — an array, an Eloquent model, a DTO — so the same CsvWriter serves any
* domain (GDPR export, an admin catalog export, an accounting export) by simply
* being handed a different column schema and a different row source.
*/
final class CsvColumn
{
/**
* @param \Closure(mixed): (string|int|float|null) $value
*/
public function __construct(
public readonly string $header,
public readonly \Closure $value,
) {}
}
+45
View File
@@ -0,0 +1,45 @@
<?php
namespace Modules\Core\Export;
/**
* A generic columns + rows -> CSV file writer. No knowledge of any domain (GDPR,
* catalog, accounting, ...) — a caller supplies the schema (CsvColumn[]) and the
* data source (any iterable of records), and this writes one CSV. Reusable for
* any future bulk-export need without modification.
*/
class CsvWriter
{
/**
* @param array<int, CsvColumn> $columns
* @param iterable<mixed> $rows
*/
public function write(array $columns, iterable $rows, string $path): void
{
$handle = fopen($path, 'w');
fputcsv($handle, array_map(fn (CsvColumn $column) => $column->header, $columns));
foreach ($rows as $row) {
fputcsv($handle, array_map(
fn (CsvColumn $column) => $this->stringify(($column->value)($row)),
$columns
));
}
fclose($handle);
}
private function stringify(mixed $value): string
{
if ($value === null) {
return '';
}
if (is_array($value)) {
return json_encode($value);
}
return (string) $value;
}
}