<?php
namespace Nellapp\Bundle\SDKBundle\Permission;
use Doctrine\ORM\EntityManagerInterface;
use Nellapp\Bundle\SDKBundle\Channel\Entity\ChannelInterface;
use Nellapp\Bundle\SDKBundle\Permission\Entity\ChannelPermissionResourceInterface;
use Nellapp\Bundle\SDKBundle\Permission\Entity\ChannelResourceInterface;
use Nellapp\Bundle\SDKBundle\Permission\Enum\ChannelUserPermissionEnumInterface;
use Nellapp\Bundle\SDKBundle\Permission\Enum\ChannelUserPermissionEnumManager;
use Nellapp\Bundle\SDKBundle\Permission\Enum\ChannelUserPermissionForFormEnumInterface;
use Nellapp\Bundle\SDKBundle\Permission\Repository\ChannelResourceRepositoryInterface;
use Nellapp\Bundle\SDKBundle\Permission\Repository\ChannelUserPermissionRepositoryInterface;
use Nellapp\Bundle\SDKBundle\Permission\Security\Hierarchy\ChannelUserPermissionHierarchyManager;
use Symfony\Contracts\Cache\CacheInterface;
class ChannelUserPermissionManager
{
public function __construct(
private EntityManagerInterface $entityManager,
private ChannelUserPermissionHierarchyManager $channelUserPermissionHierarchyManager,
private ChannelUserPermissionEnumManager $channelUserPermissionEnumManager,
private CacheInterface $sdkCache,
private bool $debug = false,
)
{
}
/**
* @return string[]
*
* Return list of classname for channel permission resources
*/
public function getChannelPermissionResourceClasses(): array
{
return array_map(function (array $info) {
return $info['resource_class'];
}, $this->getResourcesInfo());
}
private function getResourcesInfo(): array
{
if ($this->debug) {
return $this->loadChannelPermissionResourceClasses();
}
return $this->sdkCache->get('channel_permission_resources', function () {
return $this->loadChannelPermissionResourceClasses();
});
}
private function loadChannelPermissionResourceClasses(): array
{
$classes = [];
foreach ($this->entityManager->getMetadataFactory()->getAllMetadata() as $metadata) {
$ref = $metadata->getReflectionClass();
if ($ref->implementsInterface(ChannelPermissionResourceInterface::class) && !$ref->isAbstract()) {
$channelResourceClass = $metadata->getAssociationTargetClass('resource');
$channelPermissionResourceRepository = $this->entityManager->getRepository($metadata->getName());
$channelResourceRepository = $this->entityManager->getRepository($channelResourceClass);
if (!is_subclass_of($channelPermissionResourceRepository, ChannelUserPermissionRepositoryInterface::class)) {
throw new \LogicException(sprintf(
'The repository for "%s" must implements "%s"',
$metadata->getName(),
ChannelUserPermissionRepositoryInterface::class
));
}
if (!is_subclass_of($channelResourceRepository, ChannelResourceRepositoryInterface::class)) {
throw new \LogicException(sprintf(
'The repository for "%s" must implements "%s"',
$channelResourceClass,
ChannelResourceRepositoryInterface::class
));
}
$classes[$channelResourceClass] = [
'resource_class' => $metadata->getName(),
];
}
}
return $classes;
}
public function getChannelResourceRepository(string $channelUserResourcePermissionClass): ChannelResourceRepositoryInterface
{
foreach ($this->getChannelPermissionResourceClasses() as $channelResourceClass => $channelResourcePermissionClass) {
if ($channelUserResourcePermissionClass === $channelResourcePermissionClass) {
return $this->entityManager->getRepository($channelResourceClass);
}
}
throw new \LogicException(sprintf(
'Cannot find any channel resource repository for user resource permission class "%s".',
$channelUserResourcePermissionClass,
));
}
public function getChannelPermissionResourceRepository(?string $channelUserPermissionResourceClass): ?ChannelUserPermissionRepositoryInterface
{
if ($channelUserPermissionResourceClass === null) {
return null;
}
foreach ($this->getChannelPermissionResourceClasses() as $channelResourcePermissionClass) {
if ($channelUserPermissionResourceClass === $channelResourcePermissionClass) {
return $this->entityManager->getRepository($channelResourcePermissionClass);
}
}
return null;
}
public function getChannelUserPermissionHierarchies(ChannelInterface|ChannelResourceInterface|null $subject): array
{
return $this->channelUserPermissionHierarchyManager->getChannelUserPermissionHierarchies($subject::class);
}
/**
* @param ChannelInterface|ChannelResourceInterface|null $subject
* @return ChannelUserPermissionEnumInterface[]
*/
public function getChannelUserPermissionEnums(ChannelInterface|ChannelResourceInterface|null $subject): array
{
return $this->channelUserPermissionEnumManager->getChannelUserPermissionEnums($subject);
}
}