add composer-unused, comprehensive docs, and project restructure

- Add icanhazstring/composer-unused as dev dependency for dependency hygiene checks
- Add German documentation (docs/) covering architecture, conventions, workflows, and developer checklists
- Add API layer (ApiAuth, ApiBootstrap, ApiResponse), audit, scheduler, custom fields, and SSO services
- Add Microsoft OIDC SSO, API token management, and user lifecycle features
- Add swagger-ui vendor integration and OpenAPI spec
- Add production Docker setup and bin/ scripts
- Update composer dependencies, config, templates, and frontend assets throughout

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-22 15:27:35 +01:00
parent 3eb9cc0ac4
commit 25370a1a55
389 changed files with 40506 additions and 8071 deletions

View File

@@ -104,6 +104,14 @@ class RepoQuery
}
}
public static function uuidV4(): string
{
$data = random_bytes(16);
$data[6] = chr((ord($data[6]) & 0x0f) | 0x40);
$data[8] = chr((ord($data[8]) & 0x3f) | 0x80);
return vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex($data), 4));
}
public static function addEqualsFilter(array &$where, array &$params, $value, string $sql, bool $allowEmpty = false): void
{
// Use for simple "= ?" filters; skip when empty to keep WHERE clean.
@@ -117,4 +125,27 @@ class RepoQuery
$where[] = $sql;
$params[] = $normalized;
}
public static function normalizeIdList($value): array
{
if (is_string($value)) {
$value = array_filter(array_map('trim', explode(',', $value)));
} elseif (!is_array($value)) {
return [];
}
$flat = [];
array_walk_recursive($value, static function ($item) use (&$flat): void {
$flat[] = $item;
});
$ids = [];
foreach ($flat as $item) {
$id = (int) trim((string) $item);
if ($id > 0) {
$ids[] = $id;
}
}
$ids = array_values(array_unique($ids));
sort($ids, SORT_NUMERIC);
return $ids;
}
}