<?php
declare(strict_types=1);
namespace VioB2BLogin\Core\Services;
use Shopware\Core\Checkout\Customer\CustomerEntity;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
use Shopware\Core\System\SalesChannel\SalesChannelContext;
use VioB2BLogin\Core\System\SalesChannel\Context\SalesChannelContextFactory;
use VioB2BLogin\Entity\Employee\EmployeeEntity;
use VioB2BLogin\Entity\Privilege\PrivilegeCollection;
use VioB2BLogin\Entity\Privilege\PrivilegeEntity;
use VioB2BLogin\Entity\Privilege\PrivilegeNamespaces;
class PrivilegeService
{
private EntityRepositoryInterface $privilegeRepository;
/**
* PrivilegeService constructor.
* @param EntityRepositoryInterface $privilegeRepository
*/
public function __construct(
EntityRepositoryInterface $privilegeRepository
)
{
$this->privilegeRepository = $privilegeRepository;
}
public function getAllPrivileges(SalesChannelContext $context): PrivilegeCollection
{
$criteria = new Criteria();
$criteria->addFilter(new EqualsFilter('active', true));
$result = $this->privilegeRepository->search($criteria, $context->getContext());
$result->sort(function (PrivilegeEntity $a, PrivilegeEntity $b) {
return $a->getNamespace() . $a->getName() <=> $b->getNamespace() . $b->getName();
});
/** @noinspection PhpIncompatibleReturnTypeInspection */
return $result->getEntities();
}
/**
* @param SalesChannelContext $context
* @return array<string,string>
*/
public function getAllGroupedPrivileges(SalesChannelContext $context): array
{
$privileges = $this->getAllPrivileges($context);
$allNamespaces = [];
$allPermissions = [];
// project to array
$projection = [];
foreach ($privileges as $privilege) {
if (!in_array($privilege->getNamespace(), $allNamespaces, true)) {
$allNamespaces[] = $privilege->getNamespace();
}
if (!in_array($privilege->getName(), $allPermissions, true)) {
$allPermissions[] = $privilege->getName();
}
if (!array_key_exists($privilege->getNamespace(), $projection)) {
$projection[$privilege->getNamespace()] = [];
}
$projection[$privilege->getNamespace()][$privilege->getName()] = $privilege;
}
foreach ( $allNamespaces as $namespace )
{
if( !array_key_exists($namespace, $projection ) ) {
$projection[$namespace] = [];
}
foreach ($allPermissions as $permission)
{
if( !array_key_exists($permission, $projection[$namespace] ) ) {
$projection[$namespace][$permission] = null;
}
}
ksort($projection[$namespace]);
}
return $projection;
}
/**
* @param SalesChannelContext $context
* @return PrivilegeCollection
*/
public function getPrivilegesOfUser(SalesChannelContext $context): PrivilegeCollection
{
$user = $context->getCustomer();
/** @var EmployeeEntity $employee */
$employee = $context->getExtensionOfType(SalesChannelContextFactory::EMPLOYEE_KEY, EmployeeEntity::class);
if(!$user instanceof CustomerEntity) {
$collection = $this->getAllActivePriveleges($context);
$collection->filterAndReduceByProperty('namespace', PrivilegeNamespaces::EMPLOYEE);
return $collection;
}
if(!$employee instanceof EmployeeEntity || $employee->getPrivileges()->count() === 0) {
// if customer is directly logged in all privileges are granted
return $this->getAllActivePriveleges($context);
}
return $employee->getPrivileges();
}
public function checkPrivilege(SalesChannelContext $context, string $namespace, string $name): bool
{
return $this->checkPrivilegeByCollection($this->getPrivilegesOfUser($context), $namespace, $name);
}
public function checkPrivilegeByCollection(PrivilegeCollection $privileges, string $namespace, string $name): bool
{
$privilege = $privileges->filter(
/**
* @param $p PrivilegeEntity
* @return bool
*/
function (PrivilegeEntity $p) use ($namespace, $name) {
return ($p->getNamespace() === $namespace && $p->getName() === $name);
})->first();
return ($privilege instanceof PrivilegeEntity);
}
/**
* @param SalesChannelContext $context
* @return PrivilegeCollection
*/
private function getAllActivePriveleges(SalesChannelContext $context): PrivilegeCollection
{
$criteria = new Criteria();
$criteria->addFilter(new EqualsFilter('active', true));
$result = $this->privilegeRepository->search($criteria, $context->getContext());
/** @noinspection PhpIncompatibleReturnTypeInspection */
return $result->getEntities();
}
}