我想我想通了。
首先,我创建了一个名为AclChildEntityInterface的新接口。很简单:
interface AclChildEntityInterface{
public function getAclChildren();
}
我要检查子 ACL / ACE 的每个实体都实现它并返回一个函数数组以获取子实体。
class Gallery implements AclChildEntityInterface
{
public function getAclChildren(){
return array(
'mediacategories' => 'getMediacategories',
'medialanguages' => 'getMedialanguages',
);
}
}
注意:数组值必须作为函数存在于当前实体类中。
之后,我创建了一个新的 AclVoter 来扩展Symfony\Component\Security\Acl\Voter\AclVoter
:
类几乎相同,我只是改变了投票功能中的行为
catch (AclNotFoundException $noAcl)
use Symfony\Component\Security\Acl\Voter\AclVoter as BaseVoter;
...
use Develth\Prodcut\GalleryBundle\Entity\AclChildEntityInterface;
class MediaAclVoter extends BaseVoter
{
...
public function vote(TokenInterface $token, $object, array $attributes)
{
...
} catch (AclNotFoundException $noAcl) {
if (null !== $this->logger) {
$this->logger->debug('No ACL found for the object identity. Voting to deny access.');
}
// Check if entity has childs to check
if($object instanceof AclChildEntityInterface){
$entityChilds = $object->getAclChildren();
foreach ($entityChilds as $child) {
$childEntites = call_user_func( array($object,$child) );
foreach ($childEntites as $childEntity) {
$mapping = $childEntity->getName();
$oid = $this->objectIdentityRetrievalStrategy->getObjectIdentity($childEntity);
try{
$acl = $this->aclProvider->findAcl($oid, $sids);
if($acl->isGranted($masks, $sids, false)){
// Has permission to view. show it.
return self::ACCESS_GRANTED;
}
}catch(AclNotFoundException $noAcl){
// No ACL for this entity. Ignore
}catch(NoAceFoundException $noAce){
// No ACE for this entity. Ignore because other could have.
}
}
}
}
return self::ACCESS_DENIED;
} catch (NoAceFoundException $noAce) {
...
}
这里会发生什么?
如果没有为当前实体找到 ACL,它会检查它是否是先前创建的 AclChildEntityInterface 的实例。它让每个 childAcl 检查并返回一个ACCESS_GRANTED
是否找到 ACE。
但仍有一些我不喜欢的东西,我认为它可以改进。
在实现的实体类中,AclChildEntityInterface
我想做这样的事情:
public function getAclChildren(){
return array(
'mediacategories' => $this->mediacategories,
'medialanguages' => $this->medialanguages,
);
}
或关于获取方法。
但是,如果我想访问 Voter 中的那些,我总是以主实体媒体作为所有者获得 PersistentCollection,因此我无法直接访问这些。这就是我使用call_user_funk
.
我感谢改进!