私はそれを理解したと思います。
まず、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 が見つかった場合は を返します。
しかし、まだ気に入らない点がいくつかあり、改善される可能性があると思います。
実装する Entity クラスで、次のAclChildEntityInterface
ようなことをしたい:
public function getAclChildren(){
return array(
'mediacategories' => $this->mediacategories,
'medialanguages' => $this->medialanguages,
);
}
または get メソッドに関するものです。
しかし、投票者のそれらにアクセスしたい場合、私は常にメイン エンティティ メディアを所有者として PersistentCollection を取得するため、それらに直接アクセスすることはできません。それが私が使用する理由call_user_funk
です。
改善に感謝します!