feat: complete jobcard client management foundation
This commit is contained in:
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Domain\User;
|
||||
|
||||
/** Canonicalizes permission names and exposes only safe permission data. */
|
||||
final class PermissionMatrix
|
||||
{
|
||||
/** @var list<string> */
|
||||
private const DISPLAY_FIELDS = ['id', 'name', 'description', 'permissions'];
|
||||
|
||||
/**
|
||||
* Trim permission names, canonicalize them, discard malformed entries, and
|
||||
* preserve first-seen order while removing duplicates.
|
||||
*
|
||||
* @param array<mixed> $permissions
|
||||
* @return list<string>
|
||||
*/
|
||||
public function normalize(array $permissions): array
|
||||
{
|
||||
$normalized = [];
|
||||
$seen = [];
|
||||
|
||||
foreach ($permissions as $permission) {
|
||||
if (!is_scalar($permission)) {
|
||||
continue;
|
||||
}
|
||||
$permission = strtolower(trim((string) $permission));
|
||||
if ($permission === '' || preg_match('/[\x00-\x20\x7F]/', $permission) === 1) {
|
||||
continue;
|
||||
}
|
||||
if (!isset($seen[$permission])) {
|
||||
$seen[$permission] = true;
|
||||
$normalized[] = $permission;
|
||||
}
|
||||
}
|
||||
|
||||
return $normalized;
|
||||
}
|
||||
|
||||
/** @param array<string, mixed> $record @return array<string, mixed> */
|
||||
public function display(array $record): array
|
||||
{
|
||||
$safe = [];
|
||||
foreach (self::DISPLAY_FIELDS as $field) {
|
||||
if (array_key_exists($field, $record)) {
|
||||
$safe[$field] = $field === 'permissions' && is_array($record[$field])
|
||||
? $this->normalize($record[$field])
|
||||
: $record[$field];
|
||||
}
|
||||
}
|
||||
return $safe;
|
||||
}
|
||||
|
||||
/** @param array<string, mixed> $record @return array<string, mixed> */
|
||||
public function toDisplay(array $record): array
|
||||
{
|
||||
return $this->display($record);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user