[Beeframework-svn] SF.net SVN: beeframework:[299] trunk/framework/Bee
Brought to you by:
b_hartmann,
m_plomer
|
From: <m_p...@us...> - 2015-03-07 00:52:15
|
Revision: 299
http://sourceforge.net/p/beeframework/code/299
Author: m_plomer
Date: 2015-03-07 00:52:12 +0000 (Sat, 07 Mar 2015)
Log Message:
-----------
Persistence:
- DaoBase: rework
Modified Paths:
--------------
trunk/framework/Bee/Context/AbstractContext.php
trunk/framework/Bee/Context/Config/Scope/SessionScope.php
trunk/framework/Bee/MVC/HttpRequest.php
trunk/framework/Bee/MVC/IHttpRequest.php
trunk/framework/Bee/Persistence/Doctrine2/GenericDaoBase.php
trunk/framework/Bee/Persistence/PaginationBase.php
Added Paths:
-----------
trunk/framework/Bee/Persistence/Doctrine2/PaginatingDao.php
Removed Paths:
-------------
trunk/framework/Bee/Persistence/Doctrine/
trunk/framework/Bee/Persistence/Doctrine2/AbstractGenericDao.php
trunk/framework/Bee/Persistence/Doctrine2/DaoBase.php
Modified: trunk/framework/Bee/Context/AbstractContext.php
===================================================================
--- trunk/framework/Bee/Context/AbstractContext.php 2015-03-05 17:00:03 UTC (rev 298)
+++ trunk/framework/Bee/Context/AbstractContext.php 2015-03-07 00:52:12 UTC (rev 299)
@@ -649,7 +649,7 @@
* @throws BeanNotOfRequiredTypeException
* @throws Exception
*/
- public function getBean($name, $requiredType = null) {
+ public function &getBean($name, $requiredType = null) {
$beanName = $this->transformedBeanName($name);
@@ -684,7 +684,7 @@
// @todo: catch IllegalStateException in case scope is not active (e.g. no session started...)
// not needed for session, request, prototype scopes but maybe for fancy new scope implementations...
- $scopedInstance = $scope->get($beanName, new AbstractContext_ObjectFactoryImpl($beanName, $localBeanDefinition, $this));
+ $scopedInstance =& $scope->get($beanName, new AbstractContext_ObjectFactoryImpl($beanName, $localBeanDefinition, $this));
$bean = $this->getObjectForBeanInstance($scopedInstance, $name, $beanName, $localBeanDefinition);
@@ -706,8 +706,8 @@
* @throws BeanIsNotAFactoryException
* @return object the object to expose for the bean
*/
- protected function getObjectForBeanInstance(
- $beanInstance, $name, $beanName, IBeanDefinition $mbd) {
+ protected function &getObjectForBeanInstance(
+ &$beanInstance, $name, $beanName, IBeanDefinition $mbd) {
// Don't let calling code try to dereference the factory if the bean isn't a factory.
if (ContextUtils::isFactoryDereference($name) && !($beanInstance instanceof IFactoryBean)) {
Modified: trunk/framework/Bee/Context/Config/Scope/SessionScope.php
===================================================================
--- trunk/framework/Bee/Context/Config/Scope/SessionScope.php 2015-03-05 17:00:03 UTC (rev 298)
+++ trunk/framework/Bee/Context/Config/Scope/SessionScope.php 2015-03-07 00:52:12 UTC (rev 299)
@@ -45,7 +45,7 @@
* @param IObjectFactory $objectFactory
* @return mixed|Object
*/
- public function get($beanName, IObjectFactory $objectFactory) {
+ public function &get($beanName, IObjectFactory $objectFactory) {
$beans =& $_SESSION[$this->id.self::SESSION_SCOPE_PREFIX];
$scopedObject =& $beans[$beanName];
if(is_null($scopedObject)) {
Modified: trunk/framework/Bee/MVC/HttpRequest.php
===================================================================
--- trunk/framework/Bee/MVC/HttpRequest.php 2015-03-05 17:00:03 UTC (rev 298)
+++ trunk/framework/Bee/MVC/HttpRequest.php 2015-03-07 00:52:12 UTC (rev 299)
@@ -223,4 +223,8 @@
public function getAjax() {
return $this->ajax;
}
+
+ function __toString() {
+ return 'HttpRequest{' . $this->getMethod() . '|' . $this->getPathInfo() . '|ajax:' . $this->getAjax() . '}';
+ }
}
Modified: trunk/framework/Bee/MVC/IHttpRequest.php
===================================================================
--- trunk/framework/Bee/MVC/IHttpRequest.php 2015-03-05 17:00:03 UTC (rev 298)
+++ trunk/framework/Bee/MVC/IHttpRequest.php 2015-03-07 00:52:12 UTC (rev 299)
@@ -107,4 +107,9 @@
* @return bool
*/
public function getAjax();
+
+ /**
+ * @return string
+ */
+ public function __toString();
}
\ No newline at end of file
Deleted: trunk/framework/Bee/Persistence/Doctrine2/AbstractGenericDao.php
===================================================================
--- trunk/framework/Bee/Persistence/Doctrine2/AbstractGenericDao.php 2015-03-05 17:00:03 UTC (rev 298)
+++ trunk/framework/Bee/Persistence/Doctrine2/AbstractGenericDao.php 2015-03-07 00:52:12 UTC (rev 299)
@@ -1,130 +0,0 @@
-<?php
-namespace Bee\Persistence\Doctrine2;
-/*
- * Copyright 2008-2014 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-use Doctrine\ORM\Query;
-use Doctrine\ORM\QueryBuilder;
-use UnexpectedValueException;
-
-/**
- * User: mp
- * Date: 02.09.13
- * Time: 20:35
- */
-
-abstract class AbstractGenericDao extends DaoBase {
-
- /**
- * @param mixed $id
- * @throws UnexpectedValueException
- * @return mixed
- */
- public function getById($id) {
- $qb = $this->getBaseQuery();
- $this->applyWhereId($id, $qb);
- return $this->getSingleResult($qb);
- }
-
- /**
- * @param QueryBuilder $qb
- * @return mixed
- */
- protected function getSingleResult(QueryBuilder $qb) {
- $q = $qb->getQuery();
- $this->decorateQuery($q);
- return $q->getSingleResult($this->getHydrationMode());
- }
-
- /**
- * @param Query $q
- */
- protected function decorateQuery(Query $q) {
- }
-
- /**
- * @return QueryBuilder
- */
- protected function getBaseQuery() {
- $baseEntityAlias = $this->getEntityAlias();
- $indexBy = count($this->getIdFieldName()) > 1 ? null : $baseEntityAlias . '.' . $this->getIdFieldName();
- return $this->getEntityManager()->createQueryBuilder()->select($baseEntityAlias)
- ->from($this->getEntity(), $baseEntityAlias, $indexBy);
- }
-
- /**
- * @return string
- */
- protected function getEntityAlias() {
- return 'e';
- }
-
- /**
- * @return null
- */
- protected function getHydrationMode() {
- return null;
- }
-
- /**
- * @return string
- */
- public abstract function getEntity();
-
- /**
- * @return string|array
- */
- protected function getIdFieldName() {
- $classMetadata = $this->getEntityManager()->getClassMetadata($this->getEntity());
- $idFields = $classMetadata->getIdentifierFieldNames();
- return count($idFields) > 1 ? $idFields : $idFields[0];
- }
-
- /**
- * @param mixed $id
- * @param QueryBuilder $qb
- * @throws \UnexpectedValueException
- */
- protected function applyWhereId($id, QueryBuilder $qb) {
- $idFields = $this->getIdFieldName();
-
- $expectedDim = count($idFields);
- $actualDim = count($id);
-
- // unpack single-valued id if necessary
- if (is_array($id) && $actualDim === 1) {
- $id = $id[0];
- }
-
- $baseEntityAlias = $this->getEntityAlias();
- if ($expectedDim > 1) {
- // composite key
- if ($actualDim === 1) {
- $id = DaoUtils::explodeScalarId($id, $idFields);
- } else if ($actualDim !== $expectedDim) {
- throw new UnexpectedValueException('Dimension of given ID (' . count($id) . ') does not match expected dimension (' . count($idFields) . ').');
- }
-
- // here we can be sure that the dimensions match - both branches above would have thrown otherwise
- $whereParts = array();
- array_walk($id, function ($value, $key) use ($baseEntityAlias, &$whereParts) {
- $whereParts[] = $baseEntityAlias . '.' . $key . ' = ' . ':' . $key;
- });
- $qb->where(implode(' AND ', $whereParts))->setParameters($id);
- } else {
- $qb->where($baseEntityAlias . '.' . $idFields . ' = :id')->setParameter('id', $id);
- }
- }
-}
Deleted: trunk/framework/Bee/Persistence/Doctrine2/DaoBase.php
===================================================================
--- trunk/framework/Bee/Persistence/Doctrine2/DaoBase.php 2015-03-05 17:00:03 UTC (rev 298)
+++ trunk/framework/Bee/Persistence/Doctrine2/DaoBase.php 2015-03-07 00:52:12 UTC (rev 299)
@@ -1,171 +0,0 @@
-<?php
-namespace Bee\Persistence\Doctrine2;
-
-/*
- * Copyright 2008-2015 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-use Bee\Persistence\IOrderAndLimitHolder;
-use Bee\Persistence\IRestrictionHolder;
-use Bee\Utils\Strings;
-use Doctrine\ORM\Query;
-use Doctrine\ORM\QueryBuilder;
-use Doctrine\ORM\Tools\Pagination\Paginator;
-use Exception;
-
-/**
- * User: mp
- * Date: 05.05.13
- * Time: 17:26
- */
-class DaoBase extends EntityManagerHolder {
-
- /**
- * @param QueryBuilder $queryBuilder
- * @param IRestrictionHolder $restrictionHolder
- * @param IOrderAndLimitHolder $orderAndLimitHolder
- * @param array $defaultOrderMapping
- * @param null $hydrationMode
- * @return array
- */
- public function executeListQuery(QueryBuilder $queryBuilder, IRestrictionHolder $restrictionHolder = null, IOrderAndLimitHolder $orderAndLimitHolder = null, array $defaultOrderMapping = null, $hydrationMode = null) {
- $this->applyFilterRestrictions($queryBuilder, $restrictionHolder);
- $this->applyOrderMapping($queryBuilder, $orderAndLimitHolder, $defaultOrderMapping);
- $q = $this->getQueryFromBuilder($queryBuilder);
- if(!is_null($hydrationMode)) {
- $q->setHydrationMode($hydrationMode);
- }
- return $this->getPaginatedOrderedResultFromQuery($q, $orderAndLimitHolder);
- }
-
- /**
- * @param QueryBuilder $qb
- * @return Query
- */
- protected function getQueryFromBuilder(QueryBuilder $qb) {
- return $qb->getQuery();
- }
-
- /**
- * todo: give this a proper name. This method ONLY applies the text filter (and is only ever intended to do so). All
- * todo: other filters are use-case- (or at least entity-) specific.
- * @param QueryBuilder $queryBuilder
- * @param IRestrictionHolder $restrictionHolder
- */
- protected final function applyFilterRestrictions(QueryBuilder &$queryBuilder, IRestrictionHolder $restrictionHolder = null) {
- if (is_null($restrictionHolder)) {
- return;
- }
-
- if (!Strings::hasText($restrictionHolder->getFilterString())) {
- return;
- }
-
- $filterTokens = Strings::tokenizeToArray($restrictionHolder->getFilterString(), ' ');
- foreach ($filterTokens as $no => $token) {
- $andWhereString = '';
- $params = array();
-
- $tokenName = 'filtertoken' . $no;
- $params[$tokenName] = '%' . $token . '%';
- foreach ($restrictionHolder->getFilterableFields() as $fieldName) {
- // $fieldName MUST BE A DOCTRINE NAME
- if (Strings::hasText($andWhereString)) {
- $andWhereString .= ' OR ';
- }
-
- $andWhereString .= $fieldName . ' LIKE :' . $tokenName;
- }
- if (Strings::hasText($andWhereString)) {
- $queryBuilder->andWhere($andWhereString);
-
- foreach ($params as $key => $value) {
- $queryBuilder->setParameter($key, $value);
- }
- }
- }
- }
-
- /**
- * @param QueryBuilder $queryBuilder
- * @param IOrderAndLimitHolder $orderAndLimitHolder
- * @param array $defaultOrderMapping
- */
- protected final function applyOrderMapping(QueryBuilder &$queryBuilder, IOrderAndLimitHolder $orderAndLimitHolder = null, array $defaultOrderMapping = null) {
- if (is_null($defaultOrderMapping)) {
- $defaultOrderMapping = array();
- }
- if (is_null($orderAndLimitHolder)) {
- $orderMapping = $defaultOrderMapping;
- } else {
- $orderMapping = count($orderAndLimitHolder->getOrderMapping()) > 0 ? $orderAndLimitHolder->getOrderMapping() : $defaultOrderMapping;
- }
-
- foreach ($orderMapping as $orderField => $orderDir) {
- $queryBuilder->addOrderBy($orderField, $orderDir);
- }
- }
-
- /**
- * @param callback $func
- * @throws Exception
- * @return mixed
- *
- * @deprecated use EntityManagerHolder::transactional() instead
- */
- public function doInTransaction($func) {
- $this->getLog()->info('Begin transaction.');
- $this->getEntityManager()->beginTransaction();
- try {
- $result = $func($this, $this->getLog());
-
- $this->getLog()->info('Transaction committing...');
-
- $this->getEntityManager()->commit();
- $this->getEntityManager()->flush();
-
- $this->getLog()->info('Transaction committed!');
- return $result;
- } catch (Exception $e) {
- $this->getLog()->warn('Exception caught, rolling back!', $e);
- $this->getEntityManager()->rollBack();
- throw $e;
- }
- }
-
- /**
- * @param Query $q
- * @param IOrderAndLimitHolder $orderAndLimitHolder
- * @return array|Paginator
- */
- protected function getPaginatedOrderedResultFromQuery(Query $q, IOrderAndLimitHolder $orderAndLimitHolder = null) {
- if (!is_null($orderAndLimitHolder) && $orderAndLimitHolder->getPageSize() > 0) {
- $q->setFirstResult($orderAndLimitHolder->getCurrentPage() * $orderAndLimitHolder->getPageSize());
- $q->setMaxResults($orderAndLimitHolder->getPageSize());
- $paginator = new JsonSerializablePaginator($q, $this->useWhereInPagination());
- $paginator->setUseOutputWalkers(false);
- $orderAndLimitHolder->setResultCount(count($paginator));
- return $paginator;
- } else {
- return $q->getResult($q->getHydrationMode());
- }
- }
-
- /**
- * @return bool
- */
- protected function useWhereInPagination() {
- return true;
- }
-}
Modified: trunk/framework/Bee/Persistence/Doctrine2/GenericDaoBase.php
===================================================================
--- trunk/framework/Bee/Persistence/Doctrine2/GenericDaoBase.php 2015-03-05 17:00:03 UTC (rev 298)
+++ trunk/framework/Bee/Persistence/Doctrine2/GenericDaoBase.php 2015-03-07 00:52:12 UTC (rev 299)
@@ -2,7 +2,6 @@
namespace Bee\Persistence\Doctrine2;
use Bee\Persistence\IOrderAndLimitHolder;
-use Bee\Persistence\IRestrictionHolder;
use Bee\Utils\Assert;
use Bee\Utils\Strings;
use Doctrine\ORM\QueryBuilder;
@@ -12,8 +11,11 @@
* Class GenericDaoBase
* @package Bee\Persistence\Doctrine2
*/
-abstract class GenericDaoBase extends DaoBase {
+abstract class GenericDaoBase extends PaginatingDao {
+ const FILTER_STRING = 'filterString';
+ const FILTER_STRING_FIELDS = 'filterStringFields';
+
/**
* @var callable
*/
@@ -121,71 +123,132 @@
}
/**
- * @param IRestrictionHolder $restrictionHolder
+ * @param mixed $filters
* @param IOrderAndLimitHolder $orderAndLimitHolder
* @param array $defaultOrderMapping
* @return array
*/
- public function getList(IRestrictionHolder $restrictionHolder = null, IOrderAndLimitHolder $orderAndLimitHolder = null, array $defaultOrderMapping = null) {
- return $this->executeListQuery($this->getBaseQuery(), $restrictionHolder, $orderAndLimitHolder, $defaultOrderMapping, null);
+ public function getList($filters = null, IOrderAndLimitHolder $orderAndLimitHolder = null, array $defaultOrderMapping = null, $hydrationMode = null) {
+ $qb = $this->getBaseQuery();
+ $this->applyFilterRestrictions($qb, $filters);
+ return $this->executeListQuery($qb, $orderAndLimitHolder, $defaultOrderMapping ?: $this->getDefaultOrderMapping(), $hydrationMode ?: $this->getHydrationMode());
}
/**
- * @param QueryBuilder $queryBuilder
- * @param IRestrictionHolder $restrictionHolder
- * @param IOrderAndLimitHolder $orderAndLimitHolder
- * @param array $defaultOrderMapping
- * @param null $hydrationMode
- * @return array
+ * @param null $entity
+ * @return QueryBuilder
*/
- public function executeListQuery(QueryBuilder $queryBuilder, IRestrictionHolder $restrictionHolder = null, IOrderAndLimitHolder $orderAndLimitHolder = null, array $defaultOrderMapping = null, $hydrationMode = null) {
- if (!is_null($restrictionHolder)) {
- $internalFilterableFields = array();
- if (Strings::hasText($restrictionHolder->getFilterString())) {
- $this->disaggregateAndInternalizeFieldList($restrictionHolder->getFilterableFields(), $internalFilterableFields, $queryBuilder);
- }
-// $internalFilters = array();
-// if (count($restrictionHolder->getFilters()) > 0) {
-// $this->internalizeFieldValueMapping($restrictionHolder->getFilters(), $internalFilters, $queryBuilder);
-// }
- $restrictionHolder = new GenericDaoBase_RestrictionWrapper($restrictionHolder, $internalFilterableFields);
+ protected function getBaseQuery($entity = null) {
+ $baseEntityAlias = $this->getEntityAlias();
+ $entity = $entity ?: $this->getEntity();
+// $indexBy = count($this->getIdFieldName()) > 1 ? null : $baseEntityAlias . '.' . $this->getIdFieldName();
+// return $this->getEntityManager()->createQueryBuilder()->select($baseEntityAlias)
+// ->from($this->getEntity(), $baseEntityAlias, $indexBy);
+ $qb = $this->getEntityManager()->createQueryBuilder()->select($baseEntityAlias)->from($entity, $baseEntityAlias, $this->getIndexBy());
+ $this->addJoinsToBaseQuery($qb);
+ $this->addRestrictionsToBaseQuery($qb);
+ return $qb;
+ }
+
+ /**
+ * @param QueryBuilder $q
+ */
+ protected function addJoinsToBaseQuery(QueryBuilder $q) {
+ foreach ($this->joins as $join) {
+ $this->internalizePathExpression($join, $q, true);
}
+ }
- if (!is_null($orderAndLimitHolder)) {
- if (count($orderAndLimitHolder->getOrderMapping()) > 0) {
- $internalMapping = array();
- $this->disaggregateAndInternalizeFieldValueMapping($orderAndLimitHolder->getOrderMapping(), $internalMapping, $queryBuilder);
- $orderAndLimitHolder = new GenericDaoBase_OrderAndLimitWrapper($orderAndLimitHolder, $internalMapping);
- }
+ /**
+ * @param QueryBuilder $q
+ */
+ protected function addRestrictionsToBaseQuery(QueryBuilder $q) {
+ foreach ($this->restrictions as $restriction) {
+ $q->andWhere($restriction);
}
+ }
- return parent::executeListQuery($queryBuilder, $restrictionHolder, $orderAndLimitHolder, $defaultOrderMapping ?: $this->getDefaultOrderMapping(), $hydrationMode ?: $this->getHydrationMode());
+ /**
+ * @param QueryBuilder $qb
+ * @return mixed
+ */
+ protected function getSingleResult(QueryBuilder $qb) {
+ $q = $this->getQueryFromBuilder($qb);
+ return $q->getSingleResult($this->getHydrationMode());
}
/**
+ * @return null|string
+ */
+ protected function getHydrationMode() {
+ return null;
+ }
+
+ /**
+ * @return string
+ */
+ protected function getEntityAlias() {
+ return 'e';
+ }
+
+ /**
+ * @return mixed
+ */
+ abstract protected function getIdFieldName();
+
+ /**
+ * @return string
+ */
+ public abstract function getEntity();
+
+ /**
+ * @return null
+ */
+ protected function getIndexBy() {
+ return null;
+ }
+
+ // =================================================================================================================
+ // == Field disaggregation and canonicalization ====================================================================
+ // =================================================================================================================
+
+ /**
+ * @param QueryBuilder $queryBuilder
+ * @param array $orderMapping
+ * @return QueryBuilder
+ */
+ protected function applyOrderMapping(QueryBuilder $queryBuilder, array $orderMapping = array()) {
+ return parent::applyOrderMapping($queryBuilder, $this->disaggregateAndInternalizeFieldValueMapping($orderMapping, $queryBuilder));
+ }
+
+ /**
* @param array $externalFieldValueMapping
* @param array $internalFieldValueMapping
* @param QueryBuilder $queryBuilder
+ * @return array
*/
- protected final function disaggregateAndInternalizeFieldValueMapping(array $externalFieldValueMapping, array &$internalFieldValueMapping, QueryBuilder $queryBuilder) {
+ protected final function disaggregateAndInternalizeFieldValueMapping(array $externalFieldValueMapping, QueryBuilder $queryBuilder, array &$internalFieldValueMapping = array()) {
foreach ($externalFieldValueMapping as $field => $value) {
array_walk($this->getFieldDisaggregation($field), function ($field) use (&$internalFieldValueMapping, $queryBuilder, $value) {
$internalFieldValueMapping[$this->internalizeFieldExpression($field, $queryBuilder)] = $value;
});
}
+ return $internalFieldValueMapping;
}
/**
* @param array $externalFieldList
+ * @param QueryBuilder $queryBuilder
* @param array $internalFieldList
- * @param QueryBuilder $queryBuilder
+ * @return array
*/
- protected final function disaggregateAndInternalizeFieldList(array $externalFieldList, array &$internalFieldList, QueryBuilder $queryBuilder) {
+ protected final function disaggregateAndInternalizeFieldList(array $externalFieldList, QueryBuilder $queryBuilder, array &$internalFieldList = array()) {
foreach ($externalFieldList as $field) {
$internalFieldList = array_merge($internalFieldList, array_map(function ($field) use (&$queryBuilder) {
return $this->internalizeFieldExpression($field, $queryBuilder);
}, $this->getFieldDisaggregation($field)));
}
+ return $internalFieldList;
}
/**
@@ -268,86 +331,72 @@
return $pathExpr;
}
- /**
- * @param null $entity
- * @return QueryBuilder
- */
- protected function getBaseQuery($entity = null) {
- $baseEntityAlias = $this->getEntityAlias();
- $entity = $entity ?: $this->getEntity();
-// $indexBy = count($this->getIdFieldName()) > 1 ? null : $baseEntityAlias . '.' . $this->getIdFieldName();
-// return $this->getEntityManager()->createQueryBuilder()->select($baseEntityAlias)
-// ->from($this->getEntity(), $baseEntityAlias, $indexBy);
- $qb = $this->getEntityManager()->createQueryBuilder()->select($baseEntityAlias)->from($entity, $baseEntityAlias, $this->getIndexBy());
- $this->addJoinsToBaseQuery($qb);
- $this->addRestrictionsToBaseQuery($qb);
- return $qb;
- }
+ // =================================================================================================================
+ // == Filtering helpers ============================================================================================
+ // =================================================================================================================
/**
- * @param QueryBuilder $q
+ * Apply the filter restrictions defined by the filters array to the given QueryBuilder.
+ *
+ * Intended to be overridden by subclasses. The default implementation only applies a string filter if defined.
+ *
+ * @param QueryBuilder $queryBuilder
+ * @param mixed $filters
+ * @return QueryBuilder for chaining
*/
- protected function addJoinsToBaseQuery(QueryBuilder $q) {
- foreach ($this->joins as $join) {
- $this->internalizePathExpression($join, $q, true);
+ protected function applyFilterRestrictions(QueryBuilder &$queryBuilder, $filters = null) {
+ if (!is_null($filters)) {
+ if(array_key_exists(self::FILTER_STRING, $filters) && Strings::hasText($filterString = $filters[self::FILTER_STRING])) {
+ $this->addStringFilterRestrictions($queryBuilder, $filterString, $filters[self::FILTER_STRING_FIELDS]);
+ }
}
+ return $queryBuilder;
}
/**
- * @param QueryBuilder $q
+ * @param QueryBuilder $queryBuilder
+ * @param string $filterString
+ * @param array $filterableFields
+ * @return QueryBuilder
*/
- protected function addRestrictionsToBaseQuery(QueryBuilder $q) {
- foreach ($this->restrictions as $restriction) {
- $q->andWhere($restriction);
- }
- }
+ protected function addStringFilterRestrictions(QueryBuilder $queryBuilder, $filterString, array $filterableFields = array()) {
+ if (Strings::hasText($filterString)) {
+ $filterableFields = $this->disaggregateAndInternalizeFieldList($filterableFields, $queryBuilder);
- /**
- * @param QueryBuilder $qb
- * @return mixed
- */
- protected function getSingleResult(QueryBuilder $qb) {
- $q = $this->getQueryFromBuilder($qb);
- return $q->getSingleResult($this->getHydrationMode());
- }
+ $filterTokens = Strings::tokenizeToArray($filterString, ' ');
+ foreach ($filterTokens as $no => $token) {
+ $andWhereString = '';
+ $params = array();
- /**
- * @return null|string
- */
- protected function getHydrationMode() {
- return null;
- }
+ $tokenName = 'filtertoken' . $no;
+ $params[$tokenName] = '%' . $token . '%';
+ foreach ($filterableFields as $fieldName) {
+ // $fieldName MUST BE A DOCTRINE NAME
+ if (Strings::hasText($andWhereString)) {
+ $andWhereString .= ' OR ';
+ }
- /**
- * @return string
- */
- protected function getEntityAlias() {
- return 'e';
- }
+ $andWhereString .= $fieldName . ' LIKE :' . $tokenName;
+ }
+ if (Strings::hasText($andWhereString)) {
+ $queryBuilder->andWhere($andWhereString);
- /**
- * @return mixed
- */
- abstract protected function getIdFieldName();
-
- /**
- * @return string
- */
- public abstract function getEntity();
-
- /**
- * @return null
- */
- protected function getIndexBy() {
- return null;
+ foreach ($params as $key => $value) {
+ $queryBuilder->setParameter($key, $value);
+ }
+ }
+ }
+ }
+ return $queryBuilder;
}
/**
* @param QueryBuilder $queryBuilder
* @param $filters
* @param string $fieldPath
+ * @return QueryBuilder for chaining
*/
- protected function addCategoryRestrictions(QueryBuilder $queryBuilder, $filters, $fieldPath) {
+ protected final function addCategoryRestrictions(QueryBuilder $queryBuilder, $filters, $fieldPath) {
if (array_key_exists($fieldPath, $filters)) {
if (!is_array($catIds = $filters[$fieldPath])) {
$catIds = array_filter(explode(',', $catIds));
@@ -356,6 +405,7 @@
$queryBuilder->andWhere($queryBuilder->expr()->in('IDENTITY(' . $this->internalizeFieldExpression($fieldPath, $queryBuilder) . ')', $catIds));
}
}
+ return $queryBuilder;
}
/**
@@ -363,12 +413,14 @@
* @param array $filters
* @param string $fieldExpr
* @param string $filterKey
+ * @return QueryBuilder for chaining
*/
- protected function addValueRestriction(QueryBuilder $queryBuilder, $filters, $fieldExpr, $filterKey = '') {
+ protected final function addValueRestriction(QueryBuilder $queryBuilder, $filters, $fieldExpr, $filterKey = '') {
$filterKey = $filterKey ?: $fieldExpr;
if (array_key_exists($filterKey, $filters) && $value = $filters[$filterKey]) {
$queryBuilder->andWhere($this->internalizeFieldExpression($fieldExpr, $queryBuilder) . ' = :val')->setParameter('val', $value);
}
+ return $queryBuilder;
}
// =================================================================================================================
@@ -456,107 +508,4 @@
}
return array($aggregateFieldName);
}
-}
-
-class GenericDaoBase_OrderAndLimitWrapper implements IOrderAndLimitHolder {
-
- /**
- * @var IOrderAndLimitHolder
- */
- private $wrappedOrderAndLimitHolder;
-
- /**
- * @var array
- */
- private $internalOrderMapping;
-
- function __construct(IOrderAndLimitHolder $wrappedOrderAndLimitHolder, $internalOrderMapping) {
- $this->wrappedOrderAndLimitHolder = $wrappedOrderAndLimitHolder;
- $this->internalOrderMapping = $internalOrderMapping;
- }
-
- /**
- * @return array
- */
- public function getOrderMapping() {
- return $this->internalOrderMapping;
- }
-
- /**
- * @return int
- */
- public function getPageSize() {
- return $this->wrappedOrderAndLimitHolder->getPageSize();
- }
-
- /**
- * @return int
- */
- public function getPageCount() {
- return $this->wrappedOrderAndLimitHolder->getPageCount();
- }
-
- /**
- * @return int
- */
- public function getCurrentPage() {
- return $this->wrappedOrderAndLimitHolder->getCurrentPage();
- }
-
- /**
- * @param $currentPage
- */
- public function setCurrentPage($currentPage) {
- $this->wrappedOrderAndLimitHolder->setCurrentPage($currentPage);
- }
-
- /**
- * @param int $resultCount
- */
- public function setResultCount($resultCount) {
- $this->wrappedOrderAndLimitHolder->setResultCount($resultCount);
- }
-}
-
-class GenericDaoBase_RestrictionWrapper implements IRestrictionHolder {
-
- /**
- * @var IRestrictionHolder
- */
- private $wrappedRestrictionHolder;
-
- /**
- * @var array
- */
- private $internalFilterableFields;
-
- /**
- * @param $wrappedRestrictionHolder
- * @param $internalFilterableFields
- */
- function __construct(IRestrictionHolder $wrappedRestrictionHolder, array $internalFilterableFields/*, array $internalFilters*/) {
- $this->wrappedRestrictionHolder = $wrappedRestrictionHolder;
- $this->internalFilterableFields = $internalFilterableFields;
- }
-
- /**
- * @return array
- */
- public function getFilterableFields() {
- return $this->internalFilterableFields;
- }
-
- /**
- * @return array
- */
- public function getFilterString() {
- return $this->wrappedRestrictionHolder->getFilterString();
- }
-
- /**
- * @return array
- */
- public function getFilters() {
- return $this->wrappedRestrictionHolder->getFilters();
- }
}
\ No newline at end of file
Added: trunk/framework/Bee/Persistence/Doctrine2/PaginatingDao.php
===================================================================
--- trunk/framework/Bee/Persistence/Doctrine2/PaginatingDao.php (rev 0)
+++ trunk/framework/Bee/Persistence/Doctrine2/PaginatingDao.php 2015-03-07 00:52:12 UTC (rev 299)
@@ -0,0 +1,124 @@
+<?php
+namespace Bee\Persistence\Doctrine2;
+
+/*
+ * Copyright 2008-2015 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+use Bee\Persistence\IOrderAndLimitHolder;
+use Doctrine\ORM\Query;
+use Doctrine\ORM\QueryBuilder;
+use Doctrine\ORM\Tools\Pagination\Paginator;
+use Exception;
+
+/**
+ * User: mp
+ * Date: 05.05.13
+ * Time: 17:26
+ */
+class PaginatingDao extends EntityManagerHolder {
+
+ /**
+ * @param QueryBuilder $queryBuilder
+ * @param IOrderAndLimitHolder $orderAndLimitHolder
+ * @param array $defaultOrderMapping
+ * @param null $hydrationMode
+ * @return array
+ */
+ protected final function executeListQuery(QueryBuilder $queryBuilder, IOrderAndLimitHolder $orderAndLimitHolder = null, array $defaultOrderMapping = array(), $hydrationMode = null) {
+ if (is_null($orderAndLimitHolder)) {
+ $orderMapping = $defaultOrderMapping;
+ } else {
+ $orderMapping = count($orderAndLimitHolder->getOrderMapping()) > 0 ? $orderAndLimitHolder->getOrderMapping() : $defaultOrderMapping;
+ }
+ $this->applyOrderMapping($queryBuilder, $orderMapping);
+ $q = $this->getQueryFromBuilder($queryBuilder);
+ if(!is_null($hydrationMode)) {
+ $q->setHydrationMode($hydrationMode);
+ }
+ return $this->getPaginatedOrderedResultFromQuery($q, $orderAndLimitHolder);
+ }
+
+ /**
+ * @param QueryBuilder $qb
+ * @return Query
+ */
+ protected function getQueryFromBuilder(QueryBuilder $qb) {
+ return $qb->getQuery();
+ }
+
+ /**
+ * @param QueryBuilder $queryBuilder
+ * @param array $orderMapping
+ * @return QueryBuilder
+ */
+ protected function applyOrderMapping(QueryBuilder $queryBuilder, array $orderMapping = array()) {
+ foreach ($orderMapping as $orderField => $orderDir) {
+ $queryBuilder->addOrderBy($orderField, $orderDir);
+ }
+ return $queryBuilder;
+ }
+
+ /**
+ * @param callback $func
+ * @throws Exception
+ * @return mixed
+ *
+ * @deprecated use EntityManagerHolder::transactional() instead
+ */
+ public function doInTransaction($func) {
+ $this->getLog()->info('Begin transaction.');
+ $this->getEntityManager()->beginTransaction();
+ try {
+ $result = $func($this, $this->getLog());
+
+ $this->getLog()->info('Transaction committing...');
+
+ $this->getEntityManager()->commit();
+ $this->getEntityManager()->flush();
+
+ $this->getLog()->info('Transaction committed!');
+ return $result;
+ } catch (Exception $e) {
+ $this->getLog()->warn('Exception caught, rolling back!', $e);
+ $this->getEntityManager()->rollBack();
+ throw $e;
+ }
+ }
+
+ /**
+ * @param Query $q
+ * @param IOrderAndLimitHolder $orderAndLimitHolder
+ * @return array|Paginator
+ */
+ protected function getPaginatedOrderedResultFromQuery(Query $q, IOrderAndLimitHolder $orderAndLimitHolder = null) {
+ if (!is_null($orderAndLimitHolder) && $orderAndLimitHolder->getPageSize() > 0) {
+ $q->setFirstResult($orderAndLimitHolder->getCurrentPage() * $orderAndLimitHolder->getPageSize());
+ $q->setMaxResults($orderAndLimitHolder->getPageSize());
+ $paginator = new JsonSerializablePaginator($q, $this->useWhereInPagination());
+ $paginator->setUseOutputWalkers(false);
+ $orderAndLimitHolder->setResultCount(count($paginator));
+ return $paginator;
+ } else {
+ return $q->getResult($q->getHydrationMode());
+ }
+ }
+
+ /**
+ * @return bool
+ */
+ protected function useWhereInPagination() {
+ return true;
+ }
+}
Modified: trunk/framework/Bee/Persistence/PaginationBase.php
===================================================================
--- trunk/framework/Bee/Persistence/PaginationBase.php 2015-03-05 17:00:03 UTC (rev 298)
+++ trunk/framework/Bee/Persistence/PaginationBase.php 2015-03-07 00:52:12 UTC (rev 299)
@@ -15,6 +15,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+use ArrayAccess;
use JsonSerializable;
/**
@@ -25,33 +26,23 @@
*/
abstract class PaginationBase implements IOrderAndLimitHolder, JsonSerializable {
- /**
- * @var int
- */
- private $pageSize = 50;
+ /**
+ * @var ArrayAccess | array
+ */
+ private $state = array();
/**
- * @var int
- */
- private $currentPage = 0;
-
- /**
- * @var int
- */
- private $resultCount;
-
- /**
* @return int
*/
public function getPageSize() {
- return $this->pageSize;
+ return $this->state['pageSize'];
}
/**
* @param int $pageSize
*/
public function setPageSize($pageSize) {
- $this->pageSize = intval($pageSize);
+ $this->state['pageSize'] = intval($pageSize);
}
/**
@@ -65,7 +56,7 @@
* @return int
*/
public function getCurrentPage() {
- return $this->currentPage;
+ return $this->state['currentPage'];
}
/**
@@ -73,14 +64,14 @@
*/
public function setCurrentPage($currentPage) {
$currentPage = intval($currentPage);
- $this->currentPage = $currentPage < 0 ? 0 : $currentPage;
+ $this->state['currentPage'] = $currentPage < 0 ? 0 : $currentPage;
}
/**
* @param int $resultCount
*/
public function setResultCount($resultCount) {
- $this->resultCount = intval($resultCount);
+ $this->state['resultCount'] = intval($resultCount);
if($this->getCurrentPage() >= $this->getPageCount()) {
$this->adjustCurrentPageOnOverflow();
}
@@ -90,7 +81,7 @@
* @return int
*/
public function getResultCount() {
- return $this->resultCount;
+ return $this->state['resultCount'];
}
/**
@@ -102,6 +93,20 @@
}
/**
+ * @return array|ArrayAccess
+ */
+ public function getState() {
+ return $this->state;
+ }
+
+ /**
+ * @param array|ArrayAccess $state
+ */
+ public function setState($state) {
+ $this->state = $state;
+ }
+
+ /**
* @return array
*/
function jsonSerialize() {
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|