我想我想通了。
首先,我創建了一個新的接口,稱爲AclChildEntityInterface。 很簡單:
interface AclChildEntityInterface{
public function getAclChildren();
}
我要檢查孩子ACL/ACE每個實體實現它,並返回的功能的陣列來獲得孩子的entites。
class Gallery implements AclChildEntityInterface
{
public function getAclChildren(){
return array(
'mediacategories' => 'getMediacategories',
'medialanguages' => 'getMedialanguages',
);
}
}
注:數組值必須存在作爲當前實體類功能。
之後我創建的擴展Symfony\Component\Security\Acl\Voter\AclVoter
新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的實例。如果找到ACE,它會讓每個childAcl檢查並返回一個ACCESS_GRANTED
。
但還是有些事情我不喜歡,我認爲它可以改進。
在實現AclChildEntityInterface
實體類我想要做這樣的事情:
public function getAclChildren(){
return array(
'mediacategories' => $this->mediacategories,
'medialanguages' => $this->medialanguages,
);
}
或有關Get方法。
但是,如果我想訪問選民中的那些,我總是得到與主實體媒體作爲所有者的PersistentCollection,所以我不能直接訪問這些。這就是爲什麼我使用call_user_funk
。
我很感謝改進!