From 3524cd8a6b77b292b57e23772afc7747f7df7d04 Mon Sep 17 00:00:00 2001 From: Toni Uebernickel Date: Fri, 20 Jan 2012 13:17:48 +0100 Subject: [PATCH] add handling of parent ACL * fix ObjectIdentityQuery::findGrandChildren --- Model/Acl/ObjectIdentity.php | 92 +++++++++++++++++++++++++++++ Model/Acl/ObjectIdentityQuery.php | 37 ++++++++++++ Security/Acl/AclProvider.php | 12 +--- Security/Acl/Domain/MutableAcl.php | 4 +- Security/Acl/MutableAclProvider.php | 15 ++++- 5 files changed, 145 insertions(+), 15 deletions(-) diff --git a/Model/Acl/ObjectIdentity.php b/Model/Acl/ObjectIdentity.php index 51648fc..1f7e2b6 100644 --- a/Model/Acl/ObjectIdentity.php +++ b/Model/Acl/ObjectIdentity.php @@ -10,12 +10,33 @@ namespace Propel\PropelBundle\Model\Acl; +use Criteria; use PropelPDO; use Propel\PropelBundle\Model\Acl\om\BaseObjectIdentity; class ObjectIdentity extends BaseObjectIdentity { + /** + * The parent id that has been unset. + * + * @var int + */ + protected $previousParentId = null; + + public function setParentObjectIdentityId($v) + { + $prev = $this->getParentObjectIdentityId(); + + parent::setParentObjectIdentityId($v); + + if ($this->isColumnModified(ObjectIdentityPeer::PARENT_OBJECT_IDENTITY_ID)) { + $this->previousParentId = $prev; + } + + return $this; + } + public function preInsert(PropelPDO $con = null) { // Compatibility with default implementation. @@ -25,6 +46,77 @@ class ObjectIdentity extends BaseObjectIdentity $this->addObjectIdentityAncestorRelatedByAncestorId($ancestor); + $this->updateAncestorsTree($con); + return true; } + + public function preUpdate(PropelPDO $con = null) + { + if ($this->isColumnModified(ObjectIdentityPeer::PARENT_OBJECT_IDENTITY_ID)) { + $this->updateAncestorsTree($con); + } + + return true; + } + + public function preDelete(PropelPDO $con = null) + { + $this->previousParentId = $this->getParentObjectIdentityId(); + + return true; + } + + public function postDelete(PropelPDO $con = null) + { + $this->updateAncestorsTree($con); + + return true; + } + + /** + * Update all ancestor entries to reflect changes on this instance. + * + * @param PropelPDO $con + * + * @return ObjectIdentity $this + */ + protected function updateAncestorsTree(PropelPDO $con = null) + { + if (null !== $this->previousParentId) { + $childrenIds = array(); + $children = ObjectIdentityQuery::create()->findGrandChildren($this, $con); + foreach ($children as $eachChild) { + $childrenIds[] = $eachChild->getId(); + } + + ObjectIdentityAncestorQuery::create() + ->filterByObjectIdentityId($childrenIds) + ->filterByAncestorId($this->previousParentId) + ->delete($con) + ; + } else { + $parent = $this->getObjectIdentityRelatedByParentObjectIdentityId($con); + + $children = ObjectIdentityQuery::create()->findGrandChildren($this, $con); + foreach ($children as $eachChild) { + $ancestor = ObjectIdentityAncestorQuery::create() + ->filterByObjectIdentityId($eachChild->getId()) + ->filterByAncestorId($parent->getId()) + ->findOneOrCreate($con) + ; + + if (!$ancestor->isNew()) { + continue; + } + + $eachChild + ->addObjectIdentityAncestorRelatedByObjectIdentityId($ancestor) + ->save($con) + ; + } + } + + return $this; + } } diff --git a/Model/Acl/ObjectIdentityQuery.php b/Model/Acl/ObjectIdentityQuery.php index 60b01f1..223eb97 100644 --- a/Model/Acl/ObjectIdentityQuery.php +++ b/Model/Acl/ObjectIdentityQuery.php @@ -10,7 +10,9 @@ namespace Propel\PropelBundle\Model\Acl; +use Criteria; use PropelPDO; +use PropelCollection; use Propel\PropelBundle\Model\Acl\ObjectIdentity; use Propel\PropelBundle\Model\Acl\om\BaseObjectIdentityQuery; @@ -56,4 +58,39 @@ class ObjectIdentityQuery extends BaseObjectIdentityQuery ->findOne($con) ; } + + /** + * Return all children of the given object identity. + * + * @param ObjectIdentity $objectIdentity + * @param PropelPDO $con + * + * @return PropelCollection + */ + public function findChildren(ObjectIdentity $objectIdentity, PropelPDO $con = null) + { + return $this + ->filterByObjectIdentityRelatedByParentObjectIdentityId($objectIdentity) + ->find($con) + ; + } + + /** + * Return all children and grand-children of the given object identity. + * + * @param ObjectIdentity $objectIdentity + * @param PropelPDO $con + * + * @return PropelCollection + */ + public function findGrandChildren(ObjectIdentity $objectIdentity, PropelPDO $con = null) + { + return $this + ->useObjectIdentityAncestorRelatedByObjectIdentityIdQuery() + ->filterByObjectIdentityRelatedByAncestorId($objectIdentity) + ->filterByObjectIdentityRelatedByObjectIdentityId($objectIdentity, Criteria::NOT_EQUAL) + ->endUse() + ->find($con) + ; + } } diff --git a/Security/Acl/AclProvider.php b/Security/Acl/AclProvider.php index 7b07d22..7b0ec47 100644 --- a/Security/Acl/AclProvider.php +++ b/Security/Acl/AclProvider.php @@ -76,17 +76,9 @@ class AclProvider implements AclProviderInterface } if ($directChildrenOnly) { - $collection = ObjectIdentityQuery::create() - ->filterByObjectIdentityRelatedByParentObjectIdentityId($modelIdentity) - ->find($this->connection) - ; + $collection = ObjectIdentityQuery::create()->findChildren($modelIdentity, $this->connection); } else { - $collection = ObjectIdentityQuery::create() - ->useObjectIdentityAncestorRelatedByAncestorIdQuery() - ->filterByObjectIdentityRelatedByAncestorId($modelIdentity) - ->endUse() - ->find($this->connection) - ; + $collection = ObjectIdentityQuery::create()->findGrandChildren($modelIdentity, $this->connection); } $children = array(); diff --git a/Security/Acl/Domain/MutableAcl.php b/Security/Acl/Domain/MutableAcl.php index df93acd..e1bf97d 100644 --- a/Security/Acl/Domain/MutableAcl.php +++ b/Security/Acl/Domain/MutableAcl.php @@ -120,9 +120,9 @@ class MutableAcl extends Acl implements MutableAclInterface /** * Sets the parent ACL * - * @param AclInterface $acl + * @param AclInterface|null $acl */ - public function setParentAcl(AclInterface $acl) + public function setParentAcl(AclInterface $acl = null) { $this->parentAcl = $acl; } diff --git a/Security/Acl/MutableAclProvider.php b/Security/Acl/MutableAclProvider.php index 857f862..9b25d90 100644 --- a/Security/Acl/MutableAclProvider.php +++ b/Security/Acl/MutableAclProvider.php @@ -129,8 +129,6 @@ class MutableAclProvider extends AclProvider implements MutableAclProviderInterf * * Changes to parent ACLs are not persisted. * - * @todo Add handling of parent ACL changes (tree changes). - * * @throws AclException * * @param MutableAclInterface $acl @@ -167,6 +165,18 @@ class MutableAclProvider extends AclProvider implements MutableAclProviderInterf } } + if (null === $acl->getParentAcl()) { + $objectIdentity + ->setParentObjectIdentityId(null) + ->save($this->connection) + ; + } else { + $objectIdentity + ->setParentObjectIdentityId($acl->getParentAcl()->getId()) + ->save($this->connection) + ; + } + $this->connection->commit(); return true; @@ -247,7 +257,6 @@ class MutableAclProvider extends AclProvider implements MutableAclProviderInterf return $entry; } - /** * Get an ACL for this provider. *