diff --git a/lib/Doctrine/ORM/Query/ParserResult.php b/lib/Doctrine/ORM/Query/ParserResult.php index 0f685a054fd..e16b5ebc351 100644 --- a/lib/Doctrine/ORM/Query/ParserResult.php +++ b/lib/Doctrine/ORM/Query/ParserResult.php @@ -6,6 +6,8 @@ use Doctrine\ORM\Query\Exec\AbstractSqlExecutor; +use function sprintf; + /** * Encapsulates the resulting components from a DQL query parsing process that * can be serialized. @@ -14,6 +16,12 @@ */ class ParserResult { + private const LEGACY_PROPERTY_MAPPING = [ + 'sqlExecutor' => '_sqlExecutor', + 'resultSetMapping' => '_resultSetMapping', + 'parameterMappings' => '_parameterMappings', + ]; + /** * The SQL executor used for executing the SQL. * @@ -122,4 +130,20 @@ public function getSqlParameterPositions($dqlPosition) { return $this->parameterMappings[$dqlPosition]; } + + public function __wakeup(): void + { + $this->__unserialize((array) $this); + } + + /** @param array $data */ + public function __unserialize(array $data): void + { + foreach (self::LEGACY_PROPERTY_MAPPING as $property => $legacyProperty) { + $this->$property = $data[sprintf("\0%s\0%s", self::class, $legacyProperty)] + ?? $data[sprintf("\0%s\0%s", self::class, $property)] + ?? $this->$property + ?? null; + } + } } diff --git a/tests/Doctrine/Tests/ORM/Functional/ParserResultSerializationTest.php b/tests/Doctrine/Tests/ORM/Functional/ParserResultSerializationTest.php new file mode 100644 index 00000000000..f5718715e2a --- /dev/null +++ b/tests/Doctrine/Tests/ORM/Functional/ParserResultSerializationTest.php @@ -0,0 +1,70 @@ +useModelSet('company'); + + parent::setUp(); + } + + public function testSerializeParserResult(): void + { + $query = $this->_em + ->createQuery('SELECT u FROM Doctrine\Tests\Models\Company\CompanyEmployee u WHERE u.name = :name'); + + $parserResult = self::parseQuery($query); + $serialized = serialize($parserResult); + $unserialized = unserialize($serialized); + + $this->assertInstanceOf(ParserResult::class, $unserialized); + $this->assertInstanceOf(ResultSetMapping::class, $unserialized->getResultSetMapping()); + $this->assertEquals(['name' => [0]], $unserialized->getParameterMappings()); + $this->assertInstanceOf(SingleSelectExecutor::class, $unserialized->getSqlExecutor()); + } + + /** + * @dataProvider provideSerializedSingleSelectResults + */ + public function testUnserializeSingleSelectResult(string $serialized): void + { + $unserialized = unserialize($serialized); + + $this->assertInstanceOf(ParserResult::class, $unserialized); + $this->assertInstanceOf(ResultSetMapping::class, $unserialized->getResultSetMapping()); + $this->assertEquals(['name' => [0]], $unserialized->getParameterMappings()); + $this->assertInstanceOf(SingleSelectExecutor::class, $unserialized->getSqlExecutor()); + } + + /** @return Generator */ + public static function provideSerializedSingleSelectResults(): Generator + { + yield '2.14.3' => [file_get_contents(__DIR__ . '/ParserResults/single_select_2_14_3.txt')]; + yield '2.15.0' => [file_get_contents(__DIR__ . '/ParserResults/single_select_2_15_0.txt')]; + } + + private static function parseQuery(Query $query): ParserResult + { + $r = new ReflectionMethod($query, 'parse'); + $r->setAccessible(true); + + return $r->invoke($query); + } +} diff --git a/tests/Doctrine/Tests/ORM/Functional/ParserResults/single_select_2_14_3.txt b/tests/Doctrine/Tests/ORM/Functional/ParserResults/single_select_2_14_3.txt new file mode 100644 index 00000000000..db83fe2de48 Binary files /dev/null and b/tests/Doctrine/Tests/ORM/Functional/ParserResults/single_select_2_14_3.txt differ diff --git a/tests/Doctrine/Tests/ORM/Functional/ParserResults/single_select_2_15_0.txt b/tests/Doctrine/Tests/ORM/Functional/ParserResults/single_select_2_15_0.txt new file mode 100644 index 00000000000..2c306211b86 Binary files /dev/null and b/tests/Doctrine/Tests/ORM/Functional/ParserResults/single_select_2_15_0.txt differ