Repository: symfony/symfony
File: src/Symfony/Component/Security/Core/Dumper/MermaidDumper.php (PHP)

Code before:

        $output = ["graph {$direction->value}"];
        $allRoles = $this->getAllRoles($hierarchy);

        foreach ($allRoles as $role) {
            $output[] = $this->formatRoleNode($role);
        }

        foreach ($hierarchy as $parentRole => $childRoles) {
            foreach ($childRoles as $childRole) {
                $output[] = "    {$this->normalizeRoleName($parentRole)} --> {$this->normalizeRoleName($childRole)}";
            }
        }

        return implode("\n", array_filter($output));
    }

    private function extractHierarchy(RoleHierarchyInterface $roleHierarchy): array
    {
        if (!$roleHierarchy instanceof RoleHierarchy) {
            return [];
        }

        $reflection = new \ReflectionClass(RoleHierarchy::class);

        if ($reflection->hasProperty('hierarchy')) {
            $hierarchyProperty = $reflection->getProperty('hierarchy');

            return $hierarchyProperty->getValue($roleHierarchy);
        }

        return [];
    }

    private function getAllRoles(array $hierarchy): array
    {
        $allRoles = [];

        foreach ($hierarchy as $parentRole => $childRoles) {
            $allRoles[] = $parentRole;
            foreach ($childRoles as $childRole) {
                $allRoles[] = $childRole;
            }
        }

        return array_unique($allRoles);
    }

    private function formatRoleNode(string $role): string
    {
        $escapedRole = $this->normalizeRoleName($role);

Review comment (suggestion):
`RoleHierarchy` is in the same component, so we don't need this `$reflection->hasProperty('hierarchy')` check. We know it has this property (even if private).

Code after:

        $output = ["graph {$direction->value}"];
        $allRoles = $this->getAllRoles($hierarchy);

        foreach ($allRoles as $role) {
            $output[] = $this->formatRoleNode($role);
        }

        foreach ($hierarchy as $parentRole => $childRoles) {
            foreach ($childRoles as $childRole) {
                $output[] = "    {$this->normalizeRoleName($parentRole)} --> {$this->normalizeRoleName($childRole)}";
            }
        }

        return implode("\n", array_filter($output));
    }

    private function extractHierarchy(RoleHierarchyInterface $roleHierarchy): array
    {
        if (!$roleHierarchy instanceof RoleHierarchy) {
            return [];
        }

        $reflection = new \ReflectionClass(RoleHierarchy::class);

        $hierarchyProperty = $reflection->getProperty('hierarchy');

        return $hierarchyProperty->getValue($roleHierarchy);
    }

    private function getAllRoles(array $hierarchy): array
    {
        $allRoles = [];

        foreach ($hierarchy as $parentRole => $childRoles) {
            $allRoles[] = $parentRole;
            foreach ($childRoles as $childRole) {
                $allRoles[] = $childRole;
            }
        }

        return array_unique($allRoles);
    }

    private function formatRoleNode(string $role): string
    {
        $escapedRole = $this->normalizeRoleName($role);

        return "    {$escapedRole}";
    }