mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-09-18 12:44:59 +00:00
87 lines
3.0 KiB
PHP
87 lines
3.0 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
/*
|
|
* Chill is a software for social workers
|
|
*
|
|
* For the full copyright and license information, please view
|
|
* the LICENSE file that was distributed with this source code.
|
|
*/
|
|
|
|
namespace Chill\MainBundle\Security;
|
|
|
|
use Symfony\Component\Security\Core\Role\RoleHierarchyInterface;
|
|
use Symfony\Contracts\Translation\TranslatorInterface;
|
|
|
|
final readonly class RoleDumper
|
|
{
|
|
public function __construct(
|
|
private RoleProvider $roleProvider,
|
|
private RoleHierarchyInterface $roleHierarchy,
|
|
private TranslatorInterface $translator,
|
|
) {}
|
|
|
|
public function dumpAsMarkdown(): string
|
|
{
|
|
$roles = $this->roleProvider->getRoles();
|
|
$rolesWithoutScopes = $this->roleProvider->getRolesWithoutScopes();
|
|
|
|
// Group roles by title
|
|
$groups = [];
|
|
foreach ($roles as $role) {
|
|
$title = $this->roleProvider->getRoleTitle($role);
|
|
$title ??= 'Other';
|
|
$groups[$title][] = $role;
|
|
}
|
|
|
|
// Sort groups by title
|
|
ksort($groups, SORT_NATURAL | SORT_FLAG_CASE);
|
|
|
|
$lines = [];
|
|
foreach ($groups as $title => $roleList) {
|
|
// Sort roles by translated label for deterministic output
|
|
usort($roleList, function (string $a, string $b): int {
|
|
$ta = $this->translator->trans($a);
|
|
$tb = $this->translator->trans($b);
|
|
|
|
return strcasecmp($ta, $tb);
|
|
});
|
|
|
|
$translatedTitle = $this->translator->trans($title);
|
|
$lines[] = '## '.$translatedTitle;
|
|
|
|
foreach ($roleList as $role) {
|
|
// Translate primary role
|
|
$translatedRole = $this->translator->trans($role);
|
|
|
|
// Scope marker: (S) if needs scope, (~~S~~) if no scope required
|
|
$needsScope = !in_array($role, $rolesWithoutScopes, true);
|
|
$scopeMarker = $needsScope ? '(S)' : '(~~S~~)';
|
|
|
|
// Compute dependent roles from hierarchy (exclude itself)
|
|
$reachable = $this->roleHierarchy->getReachableRoleNames([$role]);
|
|
$dependents = array_values(array_filter($reachable, static fn (string $r): bool => $r !== $role));
|
|
|
|
// Translate dependents and sort deterministically
|
|
$translatedDependents = array_map(fn (string $r) => $this->translator->trans($r), $dependents);
|
|
sort($translatedDependents, SORT_NATURAL | SORT_FLAG_CASE);
|
|
|
|
if (count($translatedDependents) > 0) {
|
|
$lines[] = sprintf('- **%s** %s: %s', $translatedRole, $scopeMarker, implode(', ', $translatedDependents));
|
|
} else {
|
|
$lines[] = sprintf('- **%s** %s', $translatedRole, $scopeMarker);
|
|
}
|
|
}
|
|
|
|
// Add a blank line between groups
|
|
$lines[] = '';
|
|
}
|
|
|
|
// Trim possible trailing blank line
|
|
$markdown = rtrim(implode("\n", $lines));
|
|
|
|
return $markdown."\n"; // End with newline for POSIX friendliness
|
|
}
|
|
}
|