From b9ff877f149dc7c4d3339c773252be4c5d3fcb9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Steve=20M=C3=BCller?= Date: Wed, 15 Jan 2014 22:16:21 +0100 Subject: [PATCH 01/13] fix SQL generation on table lock hint capable platforms --- .../ORM/Persisters/BasicEntityPersister.php | 29 +++++++------ .../ORM/Persisters/EntityPersister.php | 4 +- .../Persisters/JoinedSubclassPersister.php | 23 +++++----- lib/Doctrine/ORM/Query/SqlWalker.php | 43 +++++++++---------- .../ORM/Query/SelectSqlGenerationTest.php | 4 +- 5 files changed, 51 insertions(+), 52 deletions(-) diff --git a/lib/Doctrine/ORM/Persisters/BasicEntityPersister.php b/lib/Doctrine/ORM/Persisters/BasicEntityPersister.php index 32488aa09..01d1bdd44 100644 --- a/lib/Doctrine/ORM/Persisters/BasicEntityPersister.php +++ b/lib/Doctrine/ORM/Persisters/BasicEntityPersister.php @@ -408,7 +408,7 @@ class BasicEntityPersister implements EntityPersister break; } - + $params[] = $value; $set[] = $column . ' = ' . $placeholder; $types[] = $this->columnTypes[$columnName]; @@ -805,7 +805,7 @@ class BasicEntityPersister implements EntityPersister $sql = $this->getSelectSQL($id, null, $lockMode); list($params, $types) = $this->expandParameters($id); $stmt = $this->conn->executeQuery($sql, $params, $types); - + $hydrator = $this->em->newHydrator(Query::HYDRATE_OBJECT); $hydrator->hydrateAll($stmt, $this->rsm, array(Query::HINT_REFRESH => true)); } @@ -1052,7 +1052,7 @@ class BasicEntityPersister implements EntityPersister $tableName = $this->quoteStrategy->getTableName($this->class, $this->platform); if ('' !== $filterSql) { - $conditionSql = $conditionSql + $conditionSql = $conditionSql ? $conditionSql . ' AND ' . $filterSql : $filterSql; } @@ -1205,7 +1205,7 @@ class BasicEntityPersister implements EntityPersister if ($assoc['isOwningSide']) { $tableAlias = $this->getSQLTableAlias($association['targetEntity'], $assocAlias); $this->selectJoinSql .= ' ' . $this->getJoinSQLForJoinColumns($association['joinColumns']); - + foreach ($association['joinColumns'] as $joinColumn) { $sourceCol = $this->quoteStrategy->getJoinColumnName($joinColumn, $this->class, $this->platform); $targetCol = $this->quoteStrategy->getReferencedJoinColumnName($joinColumn, $this->class, $this->platform); @@ -1335,7 +1335,7 @@ class BasicEntityPersister implements EntityPersister foreach ($columns as $column) { $placeholder = '?'; - if (isset($this->class->fieldNames[$column]) + if (isset($this->class->fieldNames[$column]) && isset($this->columnTypes[$this->class->fieldNames[$column]]) && isset($this->class->fieldMappings[$this->class->fieldNames[$column]]['requireSQLConversion'])) { @@ -1408,7 +1408,7 @@ class BasicEntityPersister implements EntityPersister $columnName = $this->quoteStrategy->getColumnName($field, $class, $this->platform); $sql = $tableAlias . '.' . $columnName; $columnAlias = $this->getSQLColumnAlias($class->columnNames[$field]); - + $this->rsm->addFieldResult($alias, $columnAlias, $field); if (isset($class->fieldMappings[$field]['requireSQLConversion'])) { @@ -1465,7 +1465,7 @@ class BasicEntityPersister implements EntityPersister break; } - $lock = $this->platform->appendLockHint($this->getLockTablesSql(), $lockMode); + $lock = $this->getLockTablesSql($lockMode); $where = ($conditionSql ? ' WHERE ' . $conditionSql : '') . ' '; $sql = 'SELECT 1 ' . $lock @@ -1480,13 +1480,18 @@ class BasicEntityPersister implements EntityPersister /** * Gets the FROM and optionally JOIN conditions to lock the entity managed by this persister. * + * @param integer $lockMode One of the Doctrine\DBAL\LockMode::* constants. + * * @return string */ - protected function getLockTablesSql() + protected function getLockTablesSql($lockMode) { - return 'FROM ' - . $this->quoteStrategy->getTableName($this->class, $this->platform) . ' ' - . $this->getSQLTableAlias($this->class->name); + return $this->platform->appendLockHint( + 'FROM ' + . $this->quoteStrategy->getTableName($this->class, $this->platform) . ' ' + . $this->getSQLTableAlias($this->class->name), + $lockMode + ); } /** @@ -1796,7 +1801,7 @@ class BasicEntityPersister implements EntityPersister $alias = $this->getSQLTableAlias($this->class->name); $sql = 'SELECT 1 ' - . $this->getLockTablesSql() + . $this->getLockTablesSql(null) . ' WHERE ' . $this->getSelectConditionSQL($criteria); if ($filterSql = $this->generateFilterConditionSQL($this->class, $alias)) { diff --git a/lib/Doctrine/ORM/Persisters/EntityPersister.php b/lib/Doctrine/ORM/Persisters/EntityPersister.php index fde9d5540..198f2bae0 100644 --- a/lib/Doctrine/ORM/Persisters/EntityPersister.php +++ b/lib/Doctrine/ORM/Persisters/EntityPersister.php @@ -74,7 +74,7 @@ interface EntityPersister */ public function getSelectSQL($criteria, $assoc = null, $lockMode = 0, $limit = null, $offset = null, array $orderBy = null); - /** + /** * Expands the parameters from the given criteria and use the correct binding types if found. * * @param $criteria @@ -269,7 +269,7 @@ interface EntityPersister * Locks all rows of this entity matching the given criteria with the specified pessimistic lock mode. * * @param array $criteria - * @param int $lockMode + * @param int $lockMode One of the Doctrine\DBAL\LockMode::* constants. * * @return void */ diff --git a/lib/Doctrine/ORM/Persisters/JoinedSubclassPersister.php b/lib/Doctrine/ORM/Persisters/JoinedSubclassPersister.php index 00d03b51c..a5666bf8d 100644 --- a/lib/Doctrine/ORM/Persisters/JoinedSubclassPersister.php +++ b/lib/Doctrine/ORM/Persisters/JoinedSubclassPersister.php @@ -288,7 +288,7 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister foreach ($this->class->parentClasses as $parentClass) { $parentMetadata = $this->em->getClassMetadata($parentClass); $parentTable = $this->quoteStrategy->getTableName($parentMetadata, $this->platform); - + $this->conn->delete($parentTable, $id); } } @@ -342,7 +342,7 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister // If the current class in the root entity, add the filters if ($filterSql = $this->generateFilterConditionSQL($this->em->getClassMetadata($this->class->rootEntityName), $this->getSQLTableAlias($this->class->rootEntityName))) { - $conditionSql .= $conditionSql + $conditionSql .= $conditionSql ? ' AND ' . $filterSql : $filterSql; } @@ -387,16 +387,13 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister } /** - * Get the FROM and optionally JOIN conditions to lock the entity managed by this persister. - * - * @return string + * {@inheritdoc} */ - public function getLockTablesSql() + protected function getLockTablesSql($lockMode) { $joinSql = ''; $identifierColumns = $this->class->getIdentifierColumnNames(); $baseTableAlias = $this->getSQLTableAlias($this->class->name); - $quotedTableName = $this->quoteStrategy->getTableName($this->class, $this->platform); // INNER JOIN parent tables foreach ($this->class->parentClasses as $parentClassName) { @@ -412,7 +409,7 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister $joinSql .= implode(' AND ', $conditions); } - return 'FROM ' . $quotedTableName . ' ' . $baseTableAlias . $joinSql; + return parent::getLockTablesSql($lockMode) . $joinSql; } /** @@ -488,8 +485,8 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister // Add join columns (foreign keys) foreach ($subClass->associationMappings as $mapping) { - if ( ! $mapping['isOwningSide'] - || ! ($mapping['type'] & ClassMetadata::TO_ONE) + if ( ! $mapping['isOwningSide'] + || ! ($mapping['type'] & ClassMetadata::TO_ONE) || isset($mapping['inherited'])) { continue; } @@ -505,17 +502,17 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister } $this->selectColumnListSql = implode(', ', $columnList); - + return $this->selectColumnListSql; } /** - * {@inheritdoc} + * {@inheritdoc} */ protected function getInsertColumnList() { // Identifier columns must always come first in the column list of subclasses. - $columns = $this->class->parentClasses + $columns = $this->class->parentClasses ? $this->class->getIdentifierColumnNames() : array(); diff --git a/lib/Doctrine/ORM/Query/SqlWalker.php b/lib/Doctrine/ORM/Query/SqlWalker.php index cdb1bb24f..42706d650 100644 --- a/lib/Doctrine/ORM/Query/SqlWalker.php +++ b/lib/Doctrine/ORM/Query/SqlWalker.php @@ -457,7 +457,7 @@ class SqlWalker implements TreeWalker } $sqlParts[] = (($this->useSqlTableAliases) ? $this->getSQLTableAlias($class->getTableName(), $dqlAlias) . '.' : '') - . $class->discriminatorColumn['name'] . ' IN (' . implode(', ', $values) . ')'; + . $class->discriminatorColumn['name'] . ' IN (' . implode(', ', $values) . ')'; } $sql = implode(' AND ', $sqlParts); @@ -497,7 +497,7 @@ class SqlWalker implements TreeWalker default: //@todo: throw exception? return ''; - break; + break; } $filterClauses = array(); @@ -576,7 +576,7 @@ class SqlWalker implements TreeWalker $this->rsm->isSelect = false; return $this->walkUpdateClause($AST->updateClause) - . $this->walkWhereClause($AST->whereClause); + . $this->walkWhereClause($AST->whereClause); } /** @@ -588,7 +588,7 @@ class SqlWalker implements TreeWalker $this->rsm->isSelect = false; return $this->walkDeleteClause($AST->deleteClause) - . $this->walkWhereClause($AST->whereClause); + . $this->walkWhereClause($AST->whereClause); } /** @@ -703,10 +703,10 @@ class SqlWalker implements TreeWalker } $addMetaColumns = ! $this->query->getHint(Query::HINT_FORCE_PARTIAL_LOAD) && - $this->query->getHydrationMode() == Query::HYDRATE_OBJECT - || - $this->query->getHydrationMode() != Query::HYDRATE_OBJECT && - $this->query->getHint(Query::HINT_INCLUDE_META_COLUMNS); + $this->query->getHydrationMode() == Query::HYDRATE_OBJECT + || + $this->query->getHydrationMode() != Query::HYDRATE_OBJECT && + $this->query->getHint(Query::HINT_INCLUDE_META_COLUMNS); foreach ($this->selectedClasses as $selectedClass) { $class = $selectedClass['class']; @@ -804,10 +804,7 @@ class SqlWalker implements TreeWalker $sqlParts = array(); foreach ($identificationVarDecls as $identificationVariableDecl) { - $sql = $this->platform->appendLockHint( - $this->walkRangeVariableDeclaration($identificationVariableDecl->rangeVariableDeclaration), - $this->query->getHint(Query::HINT_LOCK_MODE) - ); + $sql = $this->walkRangeVariableDeclaration($identificationVariableDecl->rangeVariableDeclaration); foreach ($identificationVariableDecl->joins as $join) { $sql .= $this->walkJoin($join); @@ -849,8 +846,11 @@ class SqlWalker implements TreeWalker $this->rootAliases[] = $dqlAlias; } - $sql = $this->quoteStrategy->getTableName($class,$this->platform) . ' ' - . $this->getSQLTableAlias($class->getTableName(), $dqlAlias); + $sql = $this->platform->appendLockHint( + $this->quoteStrategy->getTableName($class, $this->platform) . ' ' . + $this->getSQLTableAlias($class->getTableName(), $dqlAlias), + $this->query->getHint(Query::HINT_LOCK_MODE) + ); if ($class->isInheritanceTypeJoined()) { $sql .= $this->_generateClassTableInheritanceJoins($class, $dqlAlias); @@ -902,7 +902,7 @@ class SqlWalker implements TreeWalker case ($assoc['type'] & ClassMetadata::TO_ONE): $conditions = array(); - foreach ($assoc['joinColumns'] as $joinColumn) { + foreach ($assoc['joinColumns'] as $joinColumn) { $quotedSourceColumn = $this->quoteStrategy->getJoinColumnName($joinColumn, $targetClass, $this->platform); $quotedTargetColumn = $this->quoteStrategy->getReferencedJoinColumnName($joinColumn, $targetClass, $this->platform); @@ -1442,10 +1442,7 @@ class SqlWalker implements TreeWalker $sqlParts = array (); foreach ($identificationVarDecls as $subselectIdVarDecl) { - $sql = $this->platform->appendLockHint( - $this->walkRangeVariableDeclaration($subselectIdVarDecl->rangeVariableDeclaration), - $this->query->getHint(Query::HINT_LOCK_MODE) - ); + $sql = $this->walkRangeVariableDeclaration($subselectIdVarDecl->rangeVariableDeclaration); foreach ($subselectIdVarDecl->joins as $join) { $sql .= $this->walkJoin($join); @@ -1463,7 +1460,7 @@ class SqlWalker implements TreeWalker public function walkSimpleSelectClause($simpleSelectClause) { return 'SELECT' . ($simpleSelectClause->isDistinct ? ' DISTINCT' : '') - . $this->walkSimpleSelectExpression($simpleSelectClause->simpleSelectExpression); + . $this->walkSimpleSelectExpression($simpleSelectClause->simpleSelectExpression); } /** @@ -1602,7 +1599,7 @@ class SqlWalker implements TreeWalker public function walkAggregateExpression($aggExpression) { return $aggExpression->functionName . '(' . ($aggExpression->isDistinct ? 'DISTINCT ' : '') - . $this->walkSimpleArithmeticExpression($aggExpression->pathExpression) . ')'; + . $this->walkSimpleArithmeticExpression($aggExpression->pathExpression) . ')'; } /** @@ -1907,7 +1904,7 @@ class SqlWalker implements TreeWalker // join to target table $sql .= $this->quoteStrategy->getJoinTableName($owningAssoc, $targetClass, $this->platform) . ' ' . $joinTableAlias - . ' INNER JOIN ' . $this->quoteStrategy->getTableName($targetClass, $this->platform) . ' ' . $targetTableAlias . ' ON '; + . ' INNER JOIN ' . $this->quoteStrategy->getTableName($targetClass, $this->platform) . ' ' . $targetTableAlias . ' ON '; // join conditions $joinColumns = $assoc['isOwningSide'] ? $joinTable['inverseJoinColumns'] : $joinTable['joinColumns']; @@ -2091,7 +2088,7 @@ class SqlWalker implements TreeWalker } $sql .= ' BETWEEN ' . $this->walkArithmeticExpression($betweenExpr->leftBetweenExpression) - . ' AND ' . $this->walkArithmeticExpression($betweenExpr->rightBetweenExpression); + . ' AND ' . $this->walkArithmeticExpression($betweenExpr->rightBetweenExpression); return $sql; } diff --git a/tests/Doctrine/Tests/ORM/Query/SelectSqlGenerationTest.php b/tests/Doctrine/Tests/ORM/Query/SelectSqlGenerationTest.php index f0afcc798..9ab441627 100644 --- a/tests/Doctrine/Tests/ORM/Query/SelectSqlGenerationTest.php +++ b/tests/Doctrine/Tests/ORM/Query/SelectSqlGenerationTest.php @@ -2000,11 +2000,11 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase $connMock->setDatabasePlatform(new \Doctrine\DBAL\Platforms\SQLServerPlatform()); $this->assertSqlGeneration( "SELECT u.id FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE CONCAT(u.name, u.status, 's') = ?1", - "SELECT c0_.id AS id0 FROM cms_users c0_ WITH (NOLOCK) WHERE (c0_.name + c0_.status + 's') = ?" + "SELECT c0_.id AS id0 FROM cms_users c0_ WHERE (c0_.name + c0_.status + 's') = ?" ); $this->assertSqlGeneration( "SELECT CONCAT(u.id, u.name, u.status) FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE u.id = ?1", - "SELECT (c0_.id + c0_.name + c0_.status) AS sclr0 FROM cms_users c0_ WITH (NOLOCK) WHERE c0_.id = ?" + "SELECT (c0_.id + c0_.name + c0_.status) AS sclr0 FROM cms_users c0_ WHERE c0_.id = ?" ); $connMock->setDatabasePlatform($orgPlatform); From 996499e6fc969d0a028859bbf11b6a978514c585 Mon Sep 17 00:00:00 2001 From: Wouter J Date: Sat, 18 Jan 2014 11:09:22 +0100 Subject: [PATCH 02/13] Added exception class names --- docs/en/reference/dql-doctrine-query-language.rst | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/en/reference/dql-doctrine-query-language.rst b/docs/en/reference/dql-doctrine-query-language.rst index 84936ea67..6d78482dc 100644 --- a/docs/en/reference/dql-doctrine-query-language.rst +++ b/docs/en/reference/dql-doctrine-query-language.rst @@ -929,8 +929,9 @@ the Query class. Here they are: result is either a plain collection of objects (pure) or an array where the objects are nested in the result rows (mixed). - ``Query#getSingleResult()``: Retrieves a single object. If the - result contains more than one or no object, an exception is thrown. The - pure/mixed distinction does not apply. + result contains more than one object, an ``NonUniqueResultException`` + is thrown. If the result contains no objects, an ``NoResultException`` + is thrown. The pure/mixed distinction does not apply. - ``Query#getOneOrNullResult()``: Retrieve a single object. If no object is found null will be returned. - ``Query#getArrayResult()``: Retrieves an array graph (a nested From 65f002d62caec995c3efdc20ced0277388930184 Mon Sep 17 00:00:00 2001 From: Giulio De Donato Date: Sat, 18 Jan 2014 23:44:44 +0100 Subject: [PATCH 03/13] added license badge --- README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.markdown b/README.markdown index bf337b12f..9d22aeb72 100644 --- a/README.markdown +++ b/README.markdown @@ -9,7 +9,7 @@ Master: [![Build Status](https://secure.travis-ci.org/doctrine/doctrine2.png?bra Master: [![Coverage Status](https://coveralls.io/repos/doctrine/doctrine2/badge.png?branch=master)](https://coveralls.io/r/doctrine/doctrine2?branch=master) [![Latest Stable Version](https://poser.pugx.org/doctrine/orm/v/stable.png)](https://packagist.org/packages/doctrine/orm) [![Total Downloads](https://poser.pugx.org/doctrine/orm/downloads.png)](https://packagist.org/packages/doctrine/orm) - +[![License](https://poser.pugx.org/doctrine/orm/license.png)](https://packagist.org/packages/doctrine/orm) Doctrine 2 is an object-relational mapper (ORM) for PHP 5.3.2+ that provides transparent persistence for PHP objects. It sits on top of a powerful database abstraction layer (DBAL). One of its key features From bba5ec27fbbe35224be48878a0c92827ef2f9733 Mon Sep 17 00:00:00 2001 From: Benjamin Eberlei Date: Mon, 20 Jan 2014 09:36:15 +0100 Subject: [PATCH 04/13] Remove badges --- README.markdown | 3 --- 1 file changed, 3 deletions(-) diff --git a/README.markdown b/README.markdown index 9d22aeb72..502d8bac2 100644 --- a/README.markdown +++ b/README.markdown @@ -8,9 +8,6 @@ Master: [![Build Status](https://secure.travis-ci.org/doctrine/doctrine2.png?bra Master: [![Coverage Status](https://coveralls.io/repos/doctrine/doctrine2/badge.png?branch=master)](https://coveralls.io/r/doctrine/doctrine2?branch=master) -[![Latest Stable Version](https://poser.pugx.org/doctrine/orm/v/stable.png)](https://packagist.org/packages/doctrine/orm) [![Total Downloads](https://poser.pugx.org/doctrine/orm/downloads.png)](https://packagist.org/packages/doctrine/orm) -[![License](https://poser.pugx.org/doctrine/orm/license.png)](https://packagist.org/packages/doctrine/orm) - Doctrine 2 is an object-relational mapper (ORM) for PHP 5.3.2+ that provides transparent persistence for PHP objects. It sits on top of a powerful database abstraction layer (DBAL). One of its key features is the option to write database queries in a proprietary object oriented SQL dialect called Doctrine Query Language (DQL), From 330c66559cdf1f1d03695811bb8e56d8219442ee Mon Sep 17 00:00:00 2001 From: Matthieu Napoli Date: Tue, 21 Jan 2014 10:54:13 +0100 Subject: [PATCH 05/13] Improved DQL's "new" operator documentation I had to dig through the pull requests and issues to figure that out, so I believe it's best documented explicitly. --- docs/en/reference/dql-doctrine-query-language.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/en/reference/dql-doctrine-query-language.rst b/docs/en/reference/dql-doctrine-query-language.rst index 6d78482dc..44094e255 100644 --- a/docs/en/reference/dql-doctrine-query-language.rst +++ b/docs/en/reference/dql-doctrine-query-language.rst @@ -509,6 +509,8 @@ And then use the ``NEW`` DQL keyword : $query = $em->createQuery('SELECT NEW CustomerDTO(c.name, e.email, a.city, SUM(o.value)) FROM Customer c JOIN c.email e JOIN c.address a JOIN c.orders o GROUP BY c'); $users = $query->getResult(); // array of CustomerDTO +Note that you cannot pass entities as constructor parameters for now. + Using INDEX BY ~~~~~~~~~~~~~~ From 30c3eb0465ff7fe3c1d60415b41b2df632ec1426 Mon Sep 17 00:00:00 2001 From: Matthieu Napoli Date: Tue, 21 Jan 2014 17:34:54 +0100 Subject: [PATCH 06/13] Improved DQL's "new" operator documentation --- docs/en/reference/dql-doctrine-query-language.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/en/reference/dql-doctrine-query-language.rst b/docs/en/reference/dql-doctrine-query-language.rst index 44094e255..06aaa58ab 100644 --- a/docs/en/reference/dql-doctrine-query-language.rst +++ b/docs/en/reference/dql-doctrine-query-language.rst @@ -509,7 +509,7 @@ And then use the ``NEW`` DQL keyword : $query = $em->createQuery('SELECT NEW CustomerDTO(c.name, e.email, a.city, SUM(o.value)) FROM Customer c JOIN c.email e JOIN c.address a JOIN c.orders o GROUP BY c'); $users = $query->getResult(); // array of CustomerDTO -Note that you cannot pass entities as constructor parameters for now. +Note that you can only pass scalar expressions to the constructor. Using INDEX BY ~~~~~~~~~~~~~~ From 9653213914db5742ef73951013df1c1f0a0059cb Mon Sep 17 00:00:00 2001 From: Benjamin Eberlei Date: Tue, 4 Feb 2014 00:02:09 +0100 Subject: [PATCH 07/13] Add warning about non scalar use in Criteria. --- docs/en/reference/working-with-associations.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/en/reference/working-with-associations.rst b/docs/en/reference/working-with-associations.rst index f79da752d..a762ee9ac 100644 --- a/docs/en/reference/working-with-associations.rst +++ b/docs/en/reference/working-with-associations.rst @@ -702,3 +702,8 @@ methods: * ``notIn($field, array $values)`` +.. note:: + + There is a limitation on the compatibility of Criteria comparisons. + You have to use scalar values only as the value in a comparison or + the behaviour between different backends is not the same. From 626efdafd48a01cd9f54b6b94b158a5dfb4f8261 Mon Sep 17 00:00:00 2001 From: Benjamin Eberlei Date: Tue, 4 Feb 2014 08:49:08 +0100 Subject: [PATCH 08/13] Delete old phing build leftover. --- tests/NativePhpunitTask.php | 249 ------------------------------------ 1 file changed, 249 deletions(-) delete mode 100644 tests/NativePhpunitTask.php diff --git a/tests/NativePhpunitTask.php b/tests/NativePhpunitTask.php deleted file mode 100644 index e76402e30..000000000 --- a/tests/NativePhpunitTask.php +++ /dev/null @@ -1,249 +0,0 @@ - - */ -class NativePhpunitTask extends Task -{ - private $test; - private $testfile; - private $testdirectory; - private $configuration = null; - private $coverageClover = null; - private $junitlogfile = null; - private $haltonfailure = true; - private $haltonerror = true; - - public function setTestdirectory($directory) { - $this->testdirectory = $directory; - } - - public function setTest($test) { - $this->test = $test; - } - - public function setTestfile($testfile) { - $this->testfile = $testfile; - } - - public function setJunitlogfile($junitlogfile) { - if (strlen($junitlogfile) == 0) { - $junitlogfile = NULL; - } - - $this->junitlogfile = $junitlogfile; - } - - public function setConfiguration($configuration) { - if (strlen($configuration) == 0) { - $configuration = NULL; - } - - $this->configuration = $configuration; - } - - public function setCoverageClover($coverageClover) { - if (strlen($coverageClover) == 0) { - $coverageClover = NULL; - } - - $this->coverageClover = $coverageClover; - } - - public function setHaltonfailure($haltonfailures) { - $this->haltonfailure = $haltonfailures; - } - - public function setHaltonerror($haltonerrors) { - $this->haltonerror = $haltonerrors; - } - - public function init() - { - require_once "PHPUnit/Runner/Version.php"; - $version = PHPUnit_Runner_Version::id(); - - if (version_compare($version, '3.4.0') < 0) - { - throw new BuildException("NativePHPUnitTask requires PHPUnit version >= 3.2.0", $this->getLocation()); - } - - require_once 'PHPUnit/Util/Filter.php'; - - // point PHPUnit_MAIN_METHOD define to non-existing method - if (!defined('PHPUnit_MAIN_METHOD')) - { - define('PHPUnit_MAIN_METHOD', 'PHPUnitTask::undefined'); - } - } - - public function main() - { - if (!is_dir(realpath($this->testdirectory))) { - throw new BuildException("NativePHPUnitTask requires a Test Directory path given, '".$this->testdirectory."' given."); - } - set_include_path(realpath($this->testdirectory) . PATH_SEPARATOR . get_include_path()); - - $printer = new NativePhpunitPrinter(); - - $arguments = array( - 'configuration' => $this->configuration, - 'coverageClover' => $this->coverageClover, - 'junitLogfile' => $this->junitlogfile, - 'printer' => $printer, - ); - - require_once "PHPUnit/TextUI/TestRunner.php"; - $runner = new PHPUnit_TextUI_TestRunner(); - $suite = $runner->getTest($this->test, $this->testfile, true); - - try { - $result = $runner->doRun($suite, $arguments); - /* @var $result PHPUnit_Framework_TestResult */ - - if ( ($this->haltonfailure && $result->failureCount() > 0) || ($this->haltonerror && $result->errorCount() > 0) ) { - throw new BuildException("PHPUnit: ".$result->failureCount()." Failures and ".$result->errorCount()." Errors, ". - "last failure message: ".$printer->getMessages()); - } - - $this->log("PHPUnit Success: ".count($result->passed())." tests passed, no ". - "failures (".$result->skippedCount()." skipped, ".$result->notImplementedCount()." not implemented)"); - - // Hudson for example doesn't like the backslash in class names - if (file_exists($this->coverageClover)) { - $this->log("Generated Clover Coverage XML to: ".$this->coverageClover); - $content = file_get_contents($this->coverageClover); - $content = str_replace("\\", ".", $content); - file_put_contents($this->coverageClover, $content); - unset($content); - } - - } catch(\Exception $e) { - throw new BuildException("NativePhpunitTask failed: ".$e->getMessage()); - } - } -} - -class NativePhpunitPrinter extends PHPUnit_Util_Printer implements PHPUnit_Framework_TestListener -{ - private $_messages = array(); - - public function write($buffer) - { - // do nothing - } - - public function getMessages() - { - return $this->_messages; - } - - /** - * An error occurred. - * - * @param PHPUnit_Framework_Test $test - * @param Exception $e - * @param float $time - */ - public function addError(PHPUnit_Framework_Test $test, Exception $e, $time) - { - $this->_messages[] = "Test ERROR: ".$test->getName().": ".$e->getMessage(); - } - - /** - * A failure occurred. - * - * @param PHPUnit_Framework_Test $test - * @param PHPUnit_Framework_AssertionFailedError $e - * @param float $time - */ - public function addFailure(PHPUnit_Framework_Test $test, PHPUnit_Framework_AssertionFailedError $e, $time) - { - $this->_messages[] = "Test FAILED: ".$test->getName().": ".$e->getMessage(); - } - - /** - * Incomplete test. - * - * @param PHPUnit_Framework_Test $test - * @param Exception $e - * @param float $time - */ - public function addIncompleteTest(PHPUnit_Framework_Test $test, Exception $e, $time) - { - - } - - /** - * Skipped test. - * - * @param PHPUnit_Framework_Test $test - * @param Exception $e - * @param float $time - * @since Method available since Release 3.0.0 - */ - public function addSkippedTest(PHPUnit_Framework_Test $test, Exception $e, $time) - { - - } - - /** - * A test suite started. - * - * @param PHPUnit_Framework_TestSuite $suite - * @since Method available since Release 2.2.0 - */ - public function startTestSuite(PHPUnit_Framework_TestSuite $suite) - { - - } - - /** - * A test suite ended. - * - * @param PHPUnit_Framework_TestSuite $suite - * @since Method available since Release 2.2.0 - */ - public function endTestSuite(PHPUnit_Framework_TestSuite $suite) - { - - } - - /** - * A test started. - * - * @param PHPUnit_Framework_Test $test - */ - public function startTest(PHPUnit_Framework_Test $test) - { - - } - - /** - * A test ended. - * - * @param PHPUnit_Framework_Test $test - * @param float $time - */ - public function endTest(PHPUnit_Framework_Test $test, $time) - { - - } -} \ No newline at end of file From 7107a85041a38f2be8afce4e372a67e586315f98 Mon Sep 17 00:00:00 2001 From: shustrik Date: Thu, 6 Feb 2014 01:27:17 +0300 Subject: [PATCH 09/13] faild test with multiple HINT_CUSTOM_TREE_WALKERS failed test when we have more than 1 walker HINT_CUSTOM_TREE_WALKERS , because walkSelectStatement in TreeWalkerChain saves the last hint _queryComponents result. --- .../Tests/ORM/Query/CustomTreeWalkersTest.php | 51 ++++++++++++++++++- 1 file changed, 50 insertions(+), 1 deletion(-) diff --git a/tests/Doctrine/Tests/ORM/Query/CustomTreeWalkersTest.php b/tests/Doctrine/Tests/ORM/Query/CustomTreeWalkersTest.php index b00d43223..bd6bf43f3 100644 --- a/tests/Doctrine/Tests/ORM/Query/CustomTreeWalkersTest.php +++ b/tests/Doctrine/Tests/ORM/Query/CustomTreeWalkersTest.php @@ -42,7 +42,7 @@ class CustomTreeWalkersTest extends \Doctrine\Tests\OrmTestCase { $query = $this->_em->createQuery($dqlToBeTested); $query->setHint(Query::HINT_CUSTOM_TREE_WALKERS, $treeWalkers) - ->useQueryCache(false); + ->useQueryCache(false); if ($outputWalker) { $query->setHint(Query::HINT_CUSTOM_OUTPUT_WALKER, $outputWalker); @@ -96,6 +96,15 @@ class CustomTreeWalkersTest extends \Doctrine\Tests\OrmTestCase __NAMESPACE__ . '\\AddUnknownQueryComponentWalker' ); } + + public function testSupportsSeveralHintsQueriesWithoutWhere() + { + $this->assertSqlGeneration( + 'select u from Doctrine\Tests\Models\CMS\CmsUser u', + "SELECT c0_.id AS id0, c0_.status AS status1, c0_.username AS username2, c0_.name AS name3, c1_.id AS id4, c1_.country AS country5, c1_.zip AS zip6, c1_.city AS city7, c0_.email_id AS email_id8, c1_.user_id AS user_id9 FROM cms_users c0_ LEFT JOIN cms_addresses c1_ ON c0_.id = c1_.user_id WHERE c0_.id = 1", + array('Doctrine\Tests\ORM\Functional\CustomTreeWalkerJoin', 'Doctrine\Tests\ORM\Functional\CustomTreeWalker') + ); + } } class AddUnknownQueryComponentWalker extends Query\SqlWalker @@ -183,3 +192,43 @@ class CustomTreeWalker extends Query\TreeWalkerAdapter } } } + +class CustomTreeWalkerJoin extends Query\TreeWalkerAdapter +{ + public function walkSelectStatement(Query\AST\SelectStatement $selectStatement) + { + foreach ($selectStatement->fromClause->identificationVariableDeclarations as $identificationVariableDeclaration) { + if ($identificationVariableDeclaration->rangeVariableDeclaration->abstractSchemaName == 'Doctrine\Tests\Models\CMS\CmsUser') { + $identificationVariableDeclaration->joins[] = new Query\AST\Join( + Query\AST\Join::JOIN_TYPE_LEFT, + new Query\AST\JoinAssociationDeclaration( + new Query\AST\JoinAssociationPathExpression( + $identificationVariableDeclaration->rangeVariableDeclaration->aliasIdentificationVariable, + 'address' + ), + $identificationVariableDeclaration->rangeVariableDeclaration->aliasIdentificationVariable . 'a', + null + ) + ); + $selectStatement->selectClause->selectExpressions[] = + new Query\AST\SelectExpression( + $identificationVariableDeclaration->rangeVariableDeclaration->aliasIdentificationVariable . 'a', + null, + false + ); + $meta1 = $this->_getQuery()->getEntityManager()->getClassMetadata('Doctrine\Tests\Models\CMS\CmsUser'); + $meta = $this->_getQuery()->getEntityManager()->getClassMetadata('Doctrine\Tests\Models\CMS\CmsAddress'); + $this->setQueryComponent($identificationVariableDeclaration->rangeVariableDeclaration->aliasIdentificationVariable . 'a', + array( + 'metadata' => $meta, + 'parent' => $identificationVariableDeclaration->rangeVariableDeclaration->aliasIdentificationVariable, + 'relation' => $meta1->getAssociationMapping('address'), + 'map' => null, + 'nestingLevel' => 0, + 'token' => null + ) + ); + } + } + } +} From 543ab500da014fa8afef0eb2b4d540908e9e65a1 Mon Sep 17 00:00:00 2001 From: shustrik Date: Thu, 6 Feb 2014 10:53:34 +0300 Subject: [PATCH 10/13] rename test --- tests/Doctrine/Tests/ORM/Query/CustomTreeWalkersTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Doctrine/Tests/ORM/Query/CustomTreeWalkersTest.php b/tests/Doctrine/Tests/ORM/Query/CustomTreeWalkersTest.php index bd6bf43f3..c603db6fa 100644 --- a/tests/Doctrine/Tests/ORM/Query/CustomTreeWalkersTest.php +++ b/tests/Doctrine/Tests/ORM/Query/CustomTreeWalkersTest.php @@ -97,7 +97,7 @@ class CustomTreeWalkersTest extends \Doctrine\Tests\OrmTestCase ); } - public function testSupportsSeveralHintsQueriesWithoutWhere() + public function testSupportsSeveralHintsQueries() { $this->assertSqlGeneration( 'select u from Doctrine\Tests\Models\CMS\CmsUser u', From a6b43b93ace3a04af9ca41d3afc9670df155e266 Mon Sep 17 00:00:00 2001 From: shustrik Date: Thu, 6 Feb 2014 16:06:00 +0300 Subject: [PATCH 11/13] fix TreeWalkerChain. Create walker object in foreach. --- lib/Doctrine/ORM/Query/TreeWalkerChain.php | 166 +++++++++++++++------ 1 file changed, 117 insertions(+), 49 deletions(-) diff --git a/lib/Doctrine/ORM/Query/TreeWalkerChain.php b/lib/Doctrine/ORM/Query/TreeWalkerChain.php index 4ce356d84..72027ce14 100644 --- a/lib/Doctrine/ORM/Query/TreeWalkerChain.php +++ b/lib/Doctrine/ORM/Query/TreeWalkerChain.php @@ -25,10 +25,17 @@ namespace Doctrine\ORM\Query; * the AST to influence the final output produced by the last walker. * * @author Roman Borschel - * @since 2.0 + * @since 2.0 */ class TreeWalkerChain implements TreeWalker { + /** + * The tree walkers. + * + * @var string[] + */ + private $_walkersClasses = array(); + /** * The tree walkers. * @@ -100,7 +107,7 @@ class TreeWalkerChain implements TreeWalker */ public function addTreeWalker($walkerClass) { - $this->_walkers[] = new $walkerClass($this->_query, $this->_parserResult, $this->_queryComponents); + $this->_walkersClasses[] = $walkerClass; } /** @@ -108,7 +115,8 @@ class TreeWalkerChain implements TreeWalker */ public function walkSelectStatement(AST\SelectStatement $AST) { - foreach ($this->_walkers as $walker) { + foreach ($this->_walkersClasses as $walkerClass) { + $walker = $this->getWalker($walkerClass); $walker->walkSelectStatement($AST); $this->_queryComponents = $walker->getQueryComponents(); @@ -120,7 +128,8 @@ class TreeWalkerChain implements TreeWalker */ public function walkSelectClause($selectClause) { - foreach ($this->_walkers as $walker) { + foreach ($this->_walkersClasses as $walkerClass) { + $walker = $this->getWalker($walkerClass); $walker->walkSelectClause($selectClause); } } @@ -130,7 +139,8 @@ class TreeWalkerChain implements TreeWalker */ public function walkFromClause($fromClause) { - foreach ($this->_walkers as $walker) { + foreach ($this->_walkersClasses as $walkerClass) { + $walker = $this->getWalker($walkerClass); $walker->walkFromClause($fromClause); } } @@ -140,7 +150,8 @@ class TreeWalkerChain implements TreeWalker */ public function walkFunction($function) { - foreach ($this->_walkers as $walker) { + foreach ($this->_walkersClasses as $walkerClass) { + $walker = $this->getWalker($walkerClass); $walker->walkFunction($function); } } @@ -150,7 +161,8 @@ class TreeWalkerChain implements TreeWalker */ public function walkOrderByClause($orderByClause) { - foreach ($this->_walkers as $walker) { + foreach ($this->_walkersClasses as $walkerClass) { + $walker = $this->getWalker($walkerClass); $walker->walkOrderByClause($orderByClause); } } @@ -160,7 +172,8 @@ class TreeWalkerChain implements TreeWalker */ public function walkOrderByItem($orderByItem) { - foreach ($this->_walkers as $walker) { + foreach ($this->_walkersClasses as $walkerClass) { + $walker = $this->getWalker($walkerClass); $walker->walkOrderByItem($orderByItem); } } @@ -170,7 +183,8 @@ class TreeWalkerChain implements TreeWalker */ public function walkHavingClause($havingClause) { - foreach ($this->_walkers as $walker) { + foreach ($this->_walkersClasses as $walkerClass) { + $walker = $this->getWalker($walkerClass); $walker->walkHavingClause($havingClause); } } @@ -180,7 +194,8 @@ class TreeWalkerChain implements TreeWalker */ public function walkJoin($join) { - foreach ($this->_walkers as $walker) { + foreach ($this->_walkersClasses as $walkerClass) { + $walker = $this->getWalker($walkerClass); $walker->walkJoin($join); } } @@ -190,7 +205,8 @@ class TreeWalkerChain implements TreeWalker */ public function walkSelectExpression($selectExpression) { - foreach ($this->_walkers as $walker) { + foreach ($this->_walkersClasses as $walkerClass) { + $walker = $this->getWalker($walkerClass); $walker->walkSelectExpression($selectExpression); } } @@ -200,7 +216,8 @@ class TreeWalkerChain implements TreeWalker */ public function walkQuantifiedExpression($qExpr) { - foreach ($this->_walkers as $walker) { + foreach ($this->_walkersClasses as $walkerClass) { + $walker = $this->getWalker($walkerClass); $walker->walkQuantifiedExpression($qExpr); } } @@ -210,7 +227,8 @@ class TreeWalkerChain implements TreeWalker */ public function walkSubselect($subselect) { - foreach ($this->_walkers as $walker) { + foreach ($this->_walkersClasses as $walkerClass) { + $walker = $this->getWalker($walkerClass); $walker->walkSubselect($subselect); } } @@ -220,7 +238,8 @@ class TreeWalkerChain implements TreeWalker */ public function walkSubselectFromClause($subselectFromClause) { - foreach ($this->_walkers as $walker) { + foreach ($this->_walkersClasses as $walkerClass) { + $walker = $this->getWalker($walkerClass); $walker->walkSubselectFromClause($subselectFromClause); } } @@ -230,7 +249,8 @@ class TreeWalkerChain implements TreeWalker */ public function walkSimpleSelectClause($simpleSelectClause) { - foreach ($this->_walkers as $walker) { + foreach ($this->_walkersClasses as $walkerClass) { + $walker = $this->getWalker($walkerClass); $walker->walkSimpleSelectClause($simpleSelectClause); } } @@ -240,7 +260,8 @@ class TreeWalkerChain implements TreeWalker */ public function walkSimpleSelectExpression($simpleSelectExpression) { - foreach ($this->_walkers as $walker) { + foreach ($this->_walkersClasses as $walkerClass) { + $walker = $this->getWalker($walkerClass); $walker->walkSimpleSelectExpression($simpleSelectExpression); } } @@ -250,7 +271,8 @@ class TreeWalkerChain implements TreeWalker */ public function walkAggregateExpression($aggExpression) { - foreach ($this->_walkers as $walker) { + foreach ($this->_walkersClasses as $walkerClass) { + $walker = $this->getWalker($walkerClass); $walker->walkAggregateExpression($aggExpression); } } @@ -260,7 +282,8 @@ class TreeWalkerChain implements TreeWalker */ public function walkGroupByClause($groupByClause) { - foreach ($this->_walkers as $walker) { + foreach ($this->_walkersClasses as $walkerClass) { + $walker = $this->getWalker($walkerClass); $walker->walkGroupByClause($groupByClause); } } @@ -270,7 +293,8 @@ class TreeWalkerChain implements TreeWalker */ public function walkGroupByItem($groupByItem) { - foreach ($this->_walkers as $walker) { + foreach ($this->_walkersClasses as $walkerClass) { + $walker = $this->getWalker($walkerClass); $walker->walkGroupByItem($groupByItem); } } @@ -280,7 +304,8 @@ class TreeWalkerChain implements TreeWalker */ public function walkUpdateStatement(AST\UpdateStatement $AST) { - foreach ($this->_walkers as $walker) { + foreach ($this->_walkersClasses as $walkerClass) { + $walker = $this->getWalker($walkerClass); $walker->walkUpdateStatement($AST); } } @@ -290,7 +315,8 @@ class TreeWalkerChain implements TreeWalker */ public function walkDeleteStatement(AST\DeleteStatement $AST) { - foreach ($this->_walkers as $walker) { + foreach ($this->_walkersClasses as $walkerClass) { + $walker = $this->getWalker($walkerClass); $walker->walkDeleteStatement($AST); } } @@ -300,7 +326,8 @@ class TreeWalkerChain implements TreeWalker */ public function walkDeleteClause(AST\DeleteClause $deleteClause) { - foreach ($this->_walkers as $walker) { + foreach ($this->_walkersClasses as $walkerClass) { + $walker = $this->getWalker($walkerClass); $walker->walkDeleteClause($deleteClause); } } @@ -310,7 +337,8 @@ class TreeWalkerChain implements TreeWalker */ public function walkUpdateClause($updateClause) { - foreach ($this->_walkers as $walker) { + foreach ($this->_walkersClasses as $walkerClass) { + $walker = $this->getWalker($walkerClass); $walker->walkUpdateClause($updateClause); } } @@ -320,7 +348,8 @@ class TreeWalkerChain implements TreeWalker */ public function walkUpdateItem($updateItem) { - foreach ($this->_walkers as $walker) { + foreach ($this->_walkersClasses as $walkerClass) { + $walker = $this->getWalker($walkerClass); $walker->walkUpdateItem($updateItem); } } @@ -330,7 +359,8 @@ class TreeWalkerChain implements TreeWalker */ public function walkWhereClause($whereClause) { - foreach ($this->_walkers as $walker) { + foreach ($this->_walkersClasses as $walkerClass) { + $walker = $this->getWalker($walkerClass); $walker->walkWhereClause($whereClause); } } @@ -340,7 +370,8 @@ class TreeWalkerChain implements TreeWalker */ public function walkConditionalExpression($condExpr) { - foreach ($this->_walkers as $walker) { + foreach ($this->_walkersClasses as $walkerClass) { + $walker = $this->getWalker($walkerClass); $walker->walkConditionalExpression($condExpr); } } @@ -350,7 +381,8 @@ class TreeWalkerChain implements TreeWalker */ public function walkConditionalTerm($condTerm) { - foreach ($this->_walkers as $walker) { + foreach ($this->_walkersClasses as $walkerClass) { + $walker = $this->getWalker($walkerClass); $walker->walkConditionalTerm($condTerm); } } @@ -360,7 +392,8 @@ class TreeWalkerChain implements TreeWalker */ public function walkConditionalFactor($factor) { - foreach ($this->_walkers as $walker) { + foreach ($this->_walkersClasses as $walkerClass) { + $walker = $this->getWalker($walkerClass); $walker->walkConditionalFactor($factor); } } @@ -370,7 +403,8 @@ class TreeWalkerChain implements TreeWalker */ public function walkConditionalPrimary($condPrimary) { - foreach ($this->_walkers as $walker) { + foreach ($this->_walkersClasses as $walkerClass) { + $walker = $this->getWalker($walkerClass); $walker->walkConditionalPrimary($condPrimary); } } @@ -380,7 +414,8 @@ class TreeWalkerChain implements TreeWalker */ public function walkExistsExpression($existsExpr) { - foreach ($this->_walkers as $walker) { + foreach ($this->_walkersClasses as $walkerClass) { + $walker = $this->getWalker($walkerClass); $walker->walkExistsExpression($existsExpr); } } @@ -390,7 +425,8 @@ class TreeWalkerChain implements TreeWalker */ public function walkCollectionMemberExpression($collMemberExpr) { - foreach ($this->_walkers as $walker) { + foreach ($this->_walkersClasses as $walkerClass) { + $walker = $this->getWalker($walkerClass); $walker->walkCollectionMemberExpression($collMemberExpr); } } @@ -400,7 +436,8 @@ class TreeWalkerChain implements TreeWalker */ public function walkEmptyCollectionComparisonExpression($emptyCollCompExpr) { - foreach ($this->_walkers as $walker) { + foreach ($this->_walkersClasses as $walkerClass) { + $walker = $this->getWalker($walkerClass); $walker->walkEmptyCollectionComparisonExpression($emptyCollCompExpr); } } @@ -410,7 +447,8 @@ class TreeWalkerChain implements TreeWalker */ public function walkNullComparisonExpression($nullCompExpr) { - foreach ($this->_walkers as $walker) { + foreach ($this->_walkersClasses as $walkerClass) { + $walker = $this->getWalker($walkerClass); $walker->walkNullComparisonExpression($nullCompExpr); } } @@ -420,7 +458,8 @@ class TreeWalkerChain implements TreeWalker */ public function walkInExpression($inExpr) { - foreach ($this->_walkers as $walker) { + foreach ($this->_walkersClasses as $walkerClass) { + $walker = $this->getWalker($walkerClass); $walker->walkInExpression($inExpr); } } @@ -430,7 +469,8 @@ class TreeWalkerChain implements TreeWalker */ function walkInstanceOfExpression($instanceOfExpr) { - foreach ($this->_walkers as $walker) { + foreach ($this->_walkersClasses as $walkerClass) { + $walker = $this->getWalker($walkerClass); $walker->walkInstanceOfExpression($instanceOfExpr); } } @@ -440,7 +480,8 @@ class TreeWalkerChain implements TreeWalker */ public function walkLiteral($literal) { - foreach ($this->_walkers as $walker) { + foreach ($this->_walkersClasses as $walkerClass) { + $walker = $this->getWalker($walkerClass); $walker->walkLiteral($literal); } } @@ -450,7 +491,8 @@ class TreeWalkerChain implements TreeWalker */ public function walkBetweenExpression($betweenExpr) { - foreach ($this->_walkers as $walker) { + foreach ($this->_walkersClasses as $walkerClass) { + $walker = $this->getWalker($walkerClass); $walker->walkBetweenExpression($betweenExpr); } } @@ -460,7 +502,8 @@ class TreeWalkerChain implements TreeWalker */ public function walkLikeExpression($likeExpr) { - foreach ($this->_walkers as $walker) { + foreach ($this->_walkersClasses as $walkerClass) { + $walker = $this->getWalker($walkerClass); $walker->walkLikeExpression($likeExpr); } } @@ -470,7 +513,8 @@ class TreeWalkerChain implements TreeWalker */ public function walkStateFieldPathExpression($stateFieldPathExpression) { - foreach ($this->_walkers as $walker) { + foreach ($this->_walkersClasses as $walkerClass) { + $walker = $this->getWalker($walkerClass); $walker->walkStateFieldPathExpression($stateFieldPathExpression); } } @@ -480,7 +524,8 @@ class TreeWalkerChain implements TreeWalker */ public function walkComparisonExpression($compExpr) { - foreach ($this->_walkers as $walker) { + foreach ($this->_walkersClasses as $walkerClass) { + $walker = $this->getWalker($walkerClass); $walker->walkComparisonExpression($compExpr); } } @@ -490,7 +535,8 @@ class TreeWalkerChain implements TreeWalker */ public function walkInputParameter($inputParam) { - foreach ($this->_walkers as $walker) { + foreach ($this->_walkersClasses as $walkerClass) { + $walker = $this->getWalker($walkerClass); $walker->walkInputParameter($inputParam); } } @@ -500,7 +546,8 @@ class TreeWalkerChain implements TreeWalker */ public function walkArithmeticExpression($arithmeticExpr) { - foreach ($this->_walkers as $walker) { + foreach ($this->_walkersClasses as $walkerClass) { + $walker = $this->getWalker($walkerClass); $walker->walkArithmeticExpression($arithmeticExpr); } } @@ -510,8 +557,9 @@ class TreeWalkerChain implements TreeWalker */ public function walkArithmeticTerm($term) { - foreach ($this->_walkers as $walker) { - $walker->walkArithmeticTerm($term); + foreach ($this->_walkersClasses as $walkerClass) { + $walker = $this->getWalker($walkerClass); + $walkerClass->walkArithmeticTerm($term); } } @@ -520,7 +568,8 @@ class TreeWalkerChain implements TreeWalker */ public function walkStringPrimary($stringPrimary) { - foreach ($this->_walkers as $walker) { + foreach ($this->_walkersClasses as $walkerClass) { + $walker = $this->getWalker($walkerClass); $walker->walkStringPrimary($stringPrimary); } } @@ -530,7 +579,8 @@ class TreeWalkerChain implements TreeWalker */ public function walkArithmeticFactor($factor) { - foreach ($this->_walkers as $walker) { + foreach ($this->_walkersClasses as $walkerClass) { + $walker = $this->getWalker($walkerClass); $walker->walkArithmeticFactor($factor); } } @@ -540,7 +590,8 @@ class TreeWalkerChain implements TreeWalker */ public function walkSimpleArithmeticExpression($simpleArithmeticExpr) { - foreach ($this->_walkers as $walker) { + foreach ($this->_walkersClasses as $walkerClass) { + $walker = $this->getWalker($walkerClass); $walker->walkSimpleArithmeticExpression($simpleArithmeticExpr); } } @@ -550,7 +601,8 @@ class TreeWalkerChain implements TreeWalker */ public function walkPathExpression($pathExpr) { - foreach ($this->_walkers as $walker) { + foreach ($this->_walkersClasses as $walkerClass) { + $walker = $this->getWalker($walkerClass); $walker->walkPathExpression($pathExpr); } } @@ -560,7 +612,8 @@ class TreeWalkerChain implements TreeWalker */ public function walkResultVariable($resultVariable) { - foreach ($this->_walkers as $walker) { + foreach ($this->_walkersClasses as $walkerClass) { + $walker = $this->getWalker($walkerClass); $walker->walkResultVariable($resultVariable); } } @@ -571,4 +624,19 @@ class TreeWalkerChain implements TreeWalker public function getExecutor($AST) { } + + /** + * @param $walkerClass + * + * @return TreeWalker + */ + private function getWalker($walkerClass) + { + $key = array_search($walkerClass, $this->_walkersClasses); + if (isset($this->_walkers[$key])) { + return $this->_walkers[$key]; + } + + return new $walkerClass($this->_query, $this->_parserResult, $this->_queryComponents); + } } From 6fe40b055fe70db755f91316299002000aad3756 Mon Sep 17 00:00:00 2001 From: shustrik Date: Thu, 6 Feb 2014 16:18:35 +0300 Subject: [PATCH 12/13] fix return walker --- lib/Doctrine/ORM/Query/TreeWalkerChain.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/Doctrine/ORM/Query/TreeWalkerChain.php b/lib/Doctrine/ORM/Query/TreeWalkerChain.php index 72027ce14..feb1f2556 100644 --- a/lib/Doctrine/ORM/Query/TreeWalkerChain.php +++ b/lib/Doctrine/ORM/Query/TreeWalkerChain.php @@ -633,10 +633,10 @@ class TreeWalkerChain implements TreeWalker private function getWalker($walkerClass) { $key = array_search($walkerClass, $this->_walkersClasses); - if (isset($this->_walkers[$key])) { - return $this->_walkers[$key]; + if (!isset($this->_walkers[$key])) { + $this->_walkers[$key] = new $walkerClass($this->_query, $this->_parserResult, $this->_queryComponents); } - return new $walkerClass($this->_query, $this->_parserResult, $this->_queryComponents); + return $this->_walkers[$key]; } } From 12985b7811bd63039c0505d22b4cb9f70aedb9b2 Mon Sep 17 00:00:00 2001 From: shustrik Date: Thu, 6 Feb 2014 19:39:40 +0300 Subject: [PATCH 13/13] add iterator to tree walker chain --- lib/Doctrine/ORM/Query/TreeWalkerChain.php | 167 ++++++------------ .../ORM/Query/TreeWalkerChainIterator.php | 126 +++++++++++++ 2 files changed, 176 insertions(+), 117 deletions(-) create mode 100644 lib/Doctrine/ORM/Query/TreeWalkerChainIterator.php diff --git a/lib/Doctrine/ORM/Query/TreeWalkerChain.php b/lib/Doctrine/ORM/Query/TreeWalkerChain.php index feb1f2556..19597ed1a 100644 --- a/lib/Doctrine/ORM/Query/TreeWalkerChain.php +++ b/lib/Doctrine/ORM/Query/TreeWalkerChain.php @@ -29,19 +29,12 @@ namespace Doctrine\ORM\Query; */ class TreeWalkerChain implements TreeWalker { - /** - * The tree walkers. - * - * @var string[] - */ - private $_walkersClasses = array(); - /** * The tree walkers. * * @var TreeWalker[] */ - private $_walkers = array(); + private $_walkers; /** * The original Query. @@ -96,6 +89,7 @@ class TreeWalkerChain implements TreeWalker $this->_query = $query; $this->_parserResult = $parserResult; $this->_queryComponents = $queryComponents; + $this->_walkers = new TreeWalkerChainIterator($this, $query, $parserResult); } /** @@ -107,7 +101,7 @@ class TreeWalkerChain implements TreeWalker */ public function addTreeWalker($walkerClass) { - $this->_walkersClasses[] = $walkerClass; + $this->_walkers[] = $walkerClass; } /** @@ -115,8 +109,7 @@ class TreeWalkerChain implements TreeWalker */ public function walkSelectStatement(AST\SelectStatement $AST) { - foreach ($this->_walkersClasses as $walkerClass) { - $walker = $this->getWalker($walkerClass); + foreach ($this->_walkers as $walker) { $walker->walkSelectStatement($AST); $this->_queryComponents = $walker->getQueryComponents(); @@ -128,8 +121,7 @@ class TreeWalkerChain implements TreeWalker */ public function walkSelectClause($selectClause) { - foreach ($this->_walkersClasses as $walkerClass) { - $walker = $this->getWalker($walkerClass); + foreach ($this->_walkers as $walker) { $walker->walkSelectClause($selectClause); } } @@ -139,8 +131,7 @@ class TreeWalkerChain implements TreeWalker */ public function walkFromClause($fromClause) { - foreach ($this->_walkersClasses as $walkerClass) { - $walker = $this->getWalker($walkerClass); + foreach ($this->_walkers as $walker) { $walker->walkFromClause($fromClause); } } @@ -150,8 +141,7 @@ class TreeWalkerChain implements TreeWalker */ public function walkFunction($function) { - foreach ($this->_walkersClasses as $walkerClass) { - $walker = $this->getWalker($walkerClass); + foreach ($this->_walkers as $walker) { $walker->walkFunction($function); } } @@ -161,8 +151,7 @@ class TreeWalkerChain implements TreeWalker */ public function walkOrderByClause($orderByClause) { - foreach ($this->_walkersClasses as $walkerClass) { - $walker = $this->getWalker($walkerClass); + foreach ($this->_walkers as $walker) { $walker->walkOrderByClause($orderByClause); } } @@ -172,8 +161,7 @@ class TreeWalkerChain implements TreeWalker */ public function walkOrderByItem($orderByItem) { - foreach ($this->_walkersClasses as $walkerClass) { - $walker = $this->getWalker($walkerClass); + foreach ($this->_walkers as $walker) { $walker->walkOrderByItem($orderByItem); } } @@ -183,8 +171,7 @@ class TreeWalkerChain implements TreeWalker */ public function walkHavingClause($havingClause) { - foreach ($this->_walkersClasses as $walkerClass) { - $walker = $this->getWalker($walkerClass); + foreach ($this->_walkers as $walker) { $walker->walkHavingClause($havingClause); } } @@ -194,8 +181,7 @@ class TreeWalkerChain implements TreeWalker */ public function walkJoin($join) { - foreach ($this->_walkersClasses as $walkerClass) { - $walker = $this->getWalker($walkerClass); + foreach ($this->_walkers as $walker) { $walker->walkJoin($join); } } @@ -205,8 +191,7 @@ class TreeWalkerChain implements TreeWalker */ public function walkSelectExpression($selectExpression) { - foreach ($this->_walkersClasses as $walkerClass) { - $walker = $this->getWalker($walkerClass); + foreach ($this->_walkers as $walker) { $walker->walkSelectExpression($selectExpression); } } @@ -216,8 +201,7 @@ class TreeWalkerChain implements TreeWalker */ public function walkQuantifiedExpression($qExpr) { - foreach ($this->_walkersClasses as $walkerClass) { - $walker = $this->getWalker($walkerClass); + foreach ($this->_walkers as $walker) { $walker->walkQuantifiedExpression($qExpr); } } @@ -227,8 +211,7 @@ class TreeWalkerChain implements TreeWalker */ public function walkSubselect($subselect) { - foreach ($this->_walkersClasses as $walkerClass) { - $walker = $this->getWalker($walkerClass); + foreach ($this->_walkers as $walker) { $walker->walkSubselect($subselect); } } @@ -238,8 +221,7 @@ class TreeWalkerChain implements TreeWalker */ public function walkSubselectFromClause($subselectFromClause) { - foreach ($this->_walkersClasses as $walkerClass) { - $walker = $this->getWalker($walkerClass); + foreach ($this->_walkers as $walker) { $walker->walkSubselectFromClause($subselectFromClause); } } @@ -249,8 +231,7 @@ class TreeWalkerChain implements TreeWalker */ public function walkSimpleSelectClause($simpleSelectClause) { - foreach ($this->_walkersClasses as $walkerClass) { - $walker = $this->getWalker($walkerClass); + foreach ($this->_walkers as $walker) { $walker->walkSimpleSelectClause($simpleSelectClause); } } @@ -260,8 +241,7 @@ class TreeWalkerChain implements TreeWalker */ public function walkSimpleSelectExpression($simpleSelectExpression) { - foreach ($this->_walkersClasses as $walkerClass) { - $walker = $this->getWalker($walkerClass); + foreach ($this->_walkers as $walker) { $walker->walkSimpleSelectExpression($simpleSelectExpression); } } @@ -271,8 +251,7 @@ class TreeWalkerChain implements TreeWalker */ public function walkAggregateExpression($aggExpression) { - foreach ($this->_walkersClasses as $walkerClass) { - $walker = $this->getWalker($walkerClass); + foreach ($this->_walkers as $walker) { $walker->walkAggregateExpression($aggExpression); } } @@ -282,8 +261,7 @@ class TreeWalkerChain implements TreeWalker */ public function walkGroupByClause($groupByClause) { - foreach ($this->_walkersClasses as $walkerClass) { - $walker = $this->getWalker($walkerClass); + foreach ($this->_walkers as $walker) { $walker->walkGroupByClause($groupByClause); } } @@ -293,8 +271,7 @@ class TreeWalkerChain implements TreeWalker */ public function walkGroupByItem($groupByItem) { - foreach ($this->_walkersClasses as $walkerClass) { - $walker = $this->getWalker($walkerClass); + foreach ($this->_walkers as $walker) { $walker->walkGroupByItem($groupByItem); } } @@ -304,8 +281,7 @@ class TreeWalkerChain implements TreeWalker */ public function walkUpdateStatement(AST\UpdateStatement $AST) { - foreach ($this->_walkersClasses as $walkerClass) { - $walker = $this->getWalker($walkerClass); + foreach ($this->_walkers as $walker) { $walker->walkUpdateStatement($AST); } } @@ -315,8 +291,7 @@ class TreeWalkerChain implements TreeWalker */ public function walkDeleteStatement(AST\DeleteStatement $AST) { - foreach ($this->_walkersClasses as $walkerClass) { - $walker = $this->getWalker($walkerClass); + foreach ($this->_walkers as $walker) { $walker->walkDeleteStatement($AST); } } @@ -326,8 +301,7 @@ class TreeWalkerChain implements TreeWalker */ public function walkDeleteClause(AST\DeleteClause $deleteClause) { - foreach ($this->_walkersClasses as $walkerClass) { - $walker = $this->getWalker($walkerClass); + foreach ($this->_walkers as $walker) { $walker->walkDeleteClause($deleteClause); } } @@ -337,8 +311,7 @@ class TreeWalkerChain implements TreeWalker */ public function walkUpdateClause($updateClause) { - foreach ($this->_walkersClasses as $walkerClass) { - $walker = $this->getWalker($walkerClass); + foreach ($this->_walkers as $walker) { $walker->walkUpdateClause($updateClause); } } @@ -348,8 +321,7 @@ class TreeWalkerChain implements TreeWalker */ public function walkUpdateItem($updateItem) { - foreach ($this->_walkersClasses as $walkerClass) { - $walker = $this->getWalker($walkerClass); + foreach ($this->_walkers as $walker) { $walker->walkUpdateItem($updateItem); } } @@ -359,8 +331,7 @@ class TreeWalkerChain implements TreeWalker */ public function walkWhereClause($whereClause) { - foreach ($this->_walkersClasses as $walkerClass) { - $walker = $this->getWalker($walkerClass); + foreach ($this->_walkers as $walker) { $walker->walkWhereClause($whereClause); } } @@ -370,8 +341,7 @@ class TreeWalkerChain implements TreeWalker */ public function walkConditionalExpression($condExpr) { - foreach ($this->_walkersClasses as $walkerClass) { - $walker = $this->getWalker($walkerClass); + foreach ($this->_walkers as $walker) { $walker->walkConditionalExpression($condExpr); } } @@ -381,8 +351,7 @@ class TreeWalkerChain implements TreeWalker */ public function walkConditionalTerm($condTerm) { - foreach ($this->_walkersClasses as $walkerClass) { - $walker = $this->getWalker($walkerClass); + foreach ($this->_walkers as $walker) { $walker->walkConditionalTerm($condTerm); } } @@ -392,8 +361,7 @@ class TreeWalkerChain implements TreeWalker */ public function walkConditionalFactor($factor) { - foreach ($this->_walkersClasses as $walkerClass) { - $walker = $this->getWalker($walkerClass); + foreach ($this->_walkers as $walker) { $walker->walkConditionalFactor($factor); } } @@ -403,8 +371,7 @@ class TreeWalkerChain implements TreeWalker */ public function walkConditionalPrimary($condPrimary) { - foreach ($this->_walkersClasses as $walkerClass) { - $walker = $this->getWalker($walkerClass); + foreach ($this->_walkers as $walker) { $walker->walkConditionalPrimary($condPrimary); } } @@ -414,8 +381,7 @@ class TreeWalkerChain implements TreeWalker */ public function walkExistsExpression($existsExpr) { - foreach ($this->_walkersClasses as $walkerClass) { - $walker = $this->getWalker($walkerClass); + foreach ($this->_walkers as $walker) { $walker->walkExistsExpression($existsExpr); } } @@ -425,8 +391,7 @@ class TreeWalkerChain implements TreeWalker */ public function walkCollectionMemberExpression($collMemberExpr) { - foreach ($this->_walkersClasses as $walkerClass) { - $walker = $this->getWalker($walkerClass); + foreach ($this->_walkers as $walker) { $walker->walkCollectionMemberExpression($collMemberExpr); } } @@ -436,8 +401,7 @@ class TreeWalkerChain implements TreeWalker */ public function walkEmptyCollectionComparisonExpression($emptyCollCompExpr) { - foreach ($this->_walkersClasses as $walkerClass) { - $walker = $this->getWalker($walkerClass); + foreach ($this->_walkers as $walker) { $walker->walkEmptyCollectionComparisonExpression($emptyCollCompExpr); } } @@ -447,8 +411,7 @@ class TreeWalkerChain implements TreeWalker */ public function walkNullComparisonExpression($nullCompExpr) { - foreach ($this->_walkersClasses as $walkerClass) { - $walker = $this->getWalker($walkerClass); + foreach ($this->_walkers as $walker) { $walker->walkNullComparisonExpression($nullCompExpr); } } @@ -458,8 +421,7 @@ class TreeWalkerChain implements TreeWalker */ public function walkInExpression($inExpr) { - foreach ($this->_walkersClasses as $walkerClass) { - $walker = $this->getWalker($walkerClass); + foreach ($this->_walkers as $walker) { $walker->walkInExpression($inExpr); } } @@ -469,8 +431,7 @@ class TreeWalkerChain implements TreeWalker */ function walkInstanceOfExpression($instanceOfExpr) { - foreach ($this->_walkersClasses as $walkerClass) { - $walker = $this->getWalker($walkerClass); + foreach ($this->_walkers as $walker) { $walker->walkInstanceOfExpression($instanceOfExpr); } } @@ -480,8 +441,7 @@ class TreeWalkerChain implements TreeWalker */ public function walkLiteral($literal) { - foreach ($this->_walkersClasses as $walkerClass) { - $walker = $this->getWalker($walkerClass); + foreach ($this->_walkers as $walker) { $walker->walkLiteral($literal); } } @@ -491,8 +451,7 @@ class TreeWalkerChain implements TreeWalker */ public function walkBetweenExpression($betweenExpr) { - foreach ($this->_walkersClasses as $walkerClass) { - $walker = $this->getWalker($walkerClass); + foreach ($this->_walkers as $walker) { $walker->walkBetweenExpression($betweenExpr); } } @@ -502,8 +461,7 @@ class TreeWalkerChain implements TreeWalker */ public function walkLikeExpression($likeExpr) { - foreach ($this->_walkersClasses as $walkerClass) { - $walker = $this->getWalker($walkerClass); + foreach ($this->_walkers as $walker) { $walker->walkLikeExpression($likeExpr); } } @@ -513,8 +471,7 @@ class TreeWalkerChain implements TreeWalker */ public function walkStateFieldPathExpression($stateFieldPathExpression) { - foreach ($this->_walkersClasses as $walkerClass) { - $walker = $this->getWalker($walkerClass); + foreach ($this->_walkers as $walker) { $walker->walkStateFieldPathExpression($stateFieldPathExpression); } } @@ -524,8 +481,7 @@ class TreeWalkerChain implements TreeWalker */ public function walkComparisonExpression($compExpr) { - foreach ($this->_walkersClasses as $walkerClass) { - $walker = $this->getWalker($walkerClass); + foreach ($this->_walkers as $walker) { $walker->walkComparisonExpression($compExpr); } } @@ -535,8 +491,7 @@ class TreeWalkerChain implements TreeWalker */ public function walkInputParameter($inputParam) { - foreach ($this->_walkersClasses as $walkerClass) { - $walker = $this->getWalker($walkerClass); + foreach ($this->_walkers as $walker) { $walker->walkInputParameter($inputParam); } } @@ -546,8 +501,7 @@ class TreeWalkerChain implements TreeWalker */ public function walkArithmeticExpression($arithmeticExpr) { - foreach ($this->_walkersClasses as $walkerClass) { - $walker = $this->getWalker($walkerClass); + foreach ($this->_walkers as $walker) { $walker->walkArithmeticExpression($arithmeticExpr); } } @@ -557,9 +511,8 @@ class TreeWalkerChain implements TreeWalker */ public function walkArithmeticTerm($term) { - foreach ($this->_walkersClasses as $walkerClass) { - $walker = $this->getWalker($walkerClass); - $walkerClass->walkArithmeticTerm($term); + foreach ($this->_walkers as $walker) { + $walker->walkArithmeticTerm($term); } } @@ -568,8 +521,7 @@ class TreeWalkerChain implements TreeWalker */ public function walkStringPrimary($stringPrimary) { - foreach ($this->_walkersClasses as $walkerClass) { - $walker = $this->getWalker($walkerClass); + foreach ($this->_walkers as $walker) { $walker->walkStringPrimary($stringPrimary); } } @@ -579,8 +531,7 @@ class TreeWalkerChain implements TreeWalker */ public function walkArithmeticFactor($factor) { - foreach ($this->_walkersClasses as $walkerClass) { - $walker = $this->getWalker($walkerClass); + foreach ($this->_walkers as $walker) { $walker->walkArithmeticFactor($factor); } } @@ -590,8 +541,7 @@ class TreeWalkerChain implements TreeWalker */ public function walkSimpleArithmeticExpression($simpleArithmeticExpr) { - foreach ($this->_walkersClasses as $walkerClass) { - $walker = $this->getWalker($walkerClass); + foreach ($this->_walkers as $walker) { $walker->walkSimpleArithmeticExpression($simpleArithmeticExpr); } } @@ -601,8 +551,7 @@ class TreeWalkerChain implements TreeWalker */ public function walkPathExpression($pathExpr) { - foreach ($this->_walkersClasses as $walkerClass) { - $walker = $this->getWalker($walkerClass); + foreach ($this->_walkers as $walker) { $walker->walkPathExpression($pathExpr); } } @@ -612,8 +561,7 @@ class TreeWalkerChain implements TreeWalker */ public function walkResultVariable($resultVariable) { - foreach ($this->_walkersClasses as $walkerClass) { - $walker = $this->getWalker($walkerClass); + foreach ($this->_walkers as $walker) { $walker->walkResultVariable($resultVariable); } } @@ -624,19 +572,4 @@ class TreeWalkerChain implements TreeWalker public function getExecutor($AST) { } - - /** - * @param $walkerClass - * - * @return TreeWalker - */ - private function getWalker($walkerClass) - { - $key = array_search($walkerClass, $this->_walkersClasses); - if (!isset($this->_walkers[$key])) { - $this->_walkers[$key] = new $walkerClass($this->_query, $this->_parserResult, $this->_queryComponents); - } - - return $this->_walkers[$key]; - } } diff --git a/lib/Doctrine/ORM/Query/TreeWalkerChainIterator.php b/lib/Doctrine/ORM/Query/TreeWalkerChainIterator.php new file mode 100644 index 000000000..d693b422a --- /dev/null +++ b/lib/Doctrine/ORM/Query/TreeWalkerChainIterator.php @@ -0,0 +1,126 @@ +treeWalkerChain = $treeWalkerChain; + $this->query = $query; + $this->parserResult = $parserResult; + } + + /** + * {@inheritdoc} + */ + function rewind() + { + return reset($this->walkers); + } + + /** + * {@inheritdoc} + */ + function current() + { + return $this->offsetGet(key($this->walkers)); + } + + /** + * {@inheritdoc} + */ + function key() + { + return key($this->walkers); + } + + /** + * {@inheritdoc} + */ + function next() + { + next($this->walkers); + + return $this->offsetGet(key($this->walkers)); + } + + /** + * {@inheritdoc} + */ + function valid() + { + return key($this->walkers) !== null; + } + + + /** + * {@inheritdoc} + */ + public function offsetExists($offset) + { + return isset($this->walkers[$offset]); + } + + /** + * {@inheritdoc} + */ + public function offsetGet($offset) + { + if ($this->offsetExists($offset)) { + return new $this->walkers[$offset]( + $this->query, + $this->parserResult, + $this->treeWalkerChain->getQueryComponents() + ); + } + + return null; + } + + /** + * {@inheritdoc} + */ + public function offsetSet($offset, $value) + { + if (is_null($offset)) { + $this->walkers[] = $value; + } else { + $this->walkers[$offset] = $value; + } + } + + /** + * {@inheritdoc} + */ + public function offsetUnset($offset) + { + if ($this->offsetExists($offset)) { + unset($this->walkers[$offset]); + } + } +} \ No newline at end of file