From 078a8a1080dd843b70dd3ea58f47bb6dfdc5fd87 Mon Sep 17 00:00:00 2001 From: prophet777 Date: Fri, 12 Dec 2014 18:13:35 +0100 Subject: [PATCH] Allow extra queries to bypass acl filter --- ORM/AclFilter.php | 34 ++++++++++++++++++++++++++----- ORM/AclWalker.php | 23 +++++++++++++++++++-- ORM/ExtraCriteria.php | 47 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 97 insertions(+), 7 deletions(-) create mode 100644 ORM/ExtraCriteria.php diff --git a/ORM/AclFilter.php b/ORM/AclFilter.php index abe565b..e1bf6a4 100644 --- a/ORM/AclFilter.php +++ b/ORM/AclFilter.php @@ -13,6 +13,8 @@ class AclFilter { + const HINT_ACL_EXTRA_CRITERIA = 'acl_extra_criteria'; + /** * Construct AclFilter * @@ -44,13 +46,32 @@ public function apply( $query, array $permissions = array('VIEW'), $identity = null, - $alias = null + $alias = null, + $extraCriteria = false ) { if (null === $identity) { $token = $this->securityContext->getToken(); $identity = $token->getUser(); } + if(!is_array($extraCriteria)){ + $extraCriteria = array($extraCriteria); + } + + $sqlQueries = []; + foreach($extraCriteria as $criteria){ + if($criteria instanceof QueryBuilder) { + $sqlQueries[] = $criteria->getQuery()->getSQL(); + } elseif($criteria instanceof Query){ + $sqlQueries[] = $criteria->getSQL(); + } else{ + $sqlQueries[] = $criteria; + } + } + + + $query->setHint(static::HINT_ACL_EXTRA_CRITERIA, $sqlQueries); + if ($query instanceof QueryBuilder) { $query = $this->cloneQuery($query->getQuery()); } elseif ($query instanceof Query) { @@ -69,14 +90,18 @@ public function apply( $metadata = $entity['metadata']; $alias = $entity['alias']; $table = $metadata->getQuotedTableName($this->em->getConnection()->getDatabasePlatform()); + $aclQuery = $this->getExtraQuery( $this->getClasses($metadata), $this->getIdentifiers($identity), $maskBuilder->get() ); - $hintAclMetadata = - (false !== $query->getHint('acl.metadata')) ? $query->getHint('acl.metadata') : array(); + $hintAclMetadata = (false !== $query->getHint('acl.metadata')) + ? $query->getHint('acl.metadata') + : array() + ; + $hintAclMetadata[] = array('query' => $aclQuery, 'table' => $table, 'alias' => $alias); $query->setHint('acl.metadata', $hintAclMetadata); @@ -91,6 +116,7 @@ public function apply( * @param array $classes * @param array $identifiers * @param integer $mask + * @param array $extraCriteria * @return string */ private function getExtraQuery(Array $classes, Array $identifiers, $mask) @@ -148,8 +174,6 @@ protected function getEntityFromAlias(AbstractQuery $query, $alias = null) } } } - - return; } /** diff --git a/ORM/AclWalker.php b/ORM/AclWalker.php index 6d92359..92fc3fb 100644 --- a/ORM/AclWalker.php +++ b/ORM/AclWalker.php @@ -9,12 +9,13 @@ class AclWalker extends SqlWalker /** * @param $fromClause * - * @return string + * @return string */ public function walkFromClause($fromClause) { $sql = parent::walkFromClause($fromClause); $aclMetadata = $this->getQuery()->getHint('acl.metadata'); + $extraQueries = $this->getQuery()->getHint(AclFilter::HINT_ACL_EXTRA_CRITERIA); if ($aclMetadata) { foreach ($aclMetadata as $key => $metadata) { @@ -22,10 +23,11 @@ public function walkFromClause($fromClause) $query = $metadata['query']; $table = $metadata['table']; $tableAlias = $this->getSQLTableAlias($table, $alias); + $this->parseExtraQueries($extraQueries, $tableAlias); $aclAlias = 'ta' . $key . '_'; $aclSql = <<parseExtraQueries($extraQueries, $tableAlias)})) ACL_SQL; $sql .= ' ' . $aclSql; } @@ -33,4 +35,21 @@ public function walkFromClause($fromClause) return $sql; } + + /** + * @param array $extraQueries + * @param string $tableAlias + * + * @return array + */ + protected function parseExtraQueries(Array $extraQueries, $tableAlias) + { + $clause = array(); + + foreach($extraQueries as $query){ + $clause[] = $tableAlias.'.id IN(('.$query.'))'; + } + + return implode(' OR ', $clause); + } } diff --git a/ORM/ExtraCriteria.php b/ORM/ExtraCriteria.php new file mode 100644 index 0000000..876927c --- /dev/null +++ b/ORM/ExtraCriteria.php @@ -0,0 +1,47 @@ +operator = $operator; + $this->expression = $expression; + } + + /** + * @return string + */ + public function getOperator() + { + return $this->operator; + } + + /** + * @return string + */ + public function getExpression() + { + return $this->expression; + } +} \ No newline at end of file