Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/8.4' into 9.0
Browse files Browse the repository at this point in the history
  • Loading branch information
kitsunet committed Jul 5, 2024
2 parents 0bf6560 + a325561 commit 10c9d39
Show file tree
Hide file tree
Showing 14 changed files with 54 additions and 39 deletions.
4 changes: 2 additions & 2 deletions Neos.Flow/Classes/Command/DatabaseCommandController.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

use Doctrine\DBAL\Connection;
use Doctrine\DBAL\ConnectionException;
use Doctrine\DBAL\DBALException;
use Doctrine\DBAL\Exception as DBALException;
use Doctrine\DBAL\DriverManager;
use Neos\Flow\Annotations as Flow;
use Neos\Flow\Cli\CommandController;
Expand Down Expand Up @@ -124,7 +124,7 @@ protected function convertToCharacterSetAndCollation(string $characterSet, strin

$statements[] = 'ALTER DATABASE ' . $this->connection->quoteIdentifier($this->persistenceSettings['backendOptions']['dbname']) . ' CHARACTER SET ' . $characterSet . ' COLLATE ' . $collation;

$tableNames = $this->connection->getSchemaManager()->listTableNames();
$tableNames = $this->connection->getSchemaManager()?->listTableNames() ?? [];
foreach ($tableNames as $tableName) {
$statements[] = 'ALTER TABLE ' . $this->connection->quoteIdentifier($tableName) . ' DEFAULT CHARACTER SET ' . $characterSet . ' COLLATE ' . $collation;
$statements[] = 'ALTER TABLE ' . $this->connection->quoteIdentifier($tableName) . ' CONVERT TO CHARACTER SET ' . $characterSet . ' COLLATE ' . $collation;
Expand Down
7 changes: 4 additions & 3 deletions Neos.Flow/Classes/Command/DoctrineCommandController.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
*/

use Doctrine\Common\Util\Debug;
use Doctrine\DBAL\Exception as DBALException;
use Doctrine\Migrations\Exception\MigrationException;
use Doctrine\ORM\Tools\ToolsException;
use Doctrine\Persistence\Mapping\ClassMetadata;
Expand Down Expand Up @@ -283,7 +284,7 @@ public function dqlCommand(int $depth = 3, string $hydrationMode = 'array', int
* @param boolean $showMigrations Output a list of all migrations and their status
* @return void
* @throws StopCommandException
* @throws \Doctrine\DBAL\DBALException
* @throws DBALException
* @see neos.flow:doctrine:migrate
* @see neos.flow:doctrine:migrationexecute
* @see neos.flow:doctrine:migrationgenerate
Expand Down Expand Up @@ -392,7 +393,7 @@ public function migrationExecuteCommand(string $version, string $direction = 'up
* @param boolean $delete The migration to mark as not migrated
* @return void
* @throws StopCommandException
* @throws \Doctrine\DBAL\Exception
* @throws DBALException
* @see neos.flow:doctrine:migrate
* @see neos.flow:doctrine:migrationstatus
* @see neos.flow:doctrine:migrationexecute
Expand Down Expand Up @@ -440,7 +441,7 @@ public function migrationVersionCommand(string $version, bool $add = false, bool
* @param string|null $filterExpression Only include tables/sequences matching the filter expression regexp
* @param boolean $force Generate migrations even if there are migrations left to execute
* @return void
* @throws \Doctrine\DBAL\DBALException
* @throws DBALException
* @throws StopCommandException
* @throws FilesException
* @see neos.flow:doctrine:migrate
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
*/

use Doctrine\DBAL\Exception\ConnectionException;
use Doctrine\DBAL\Connection;
use Doctrine\ORM\Event\OnFlushEventArgs;
use Neos\Flow\Annotations as Flow;
use Neos\Flow\Log\ThrowableStorageInterface;
Expand Down Expand Up @@ -88,7 +89,7 @@ public function onFlush(OnFlushEventArgs $args)

$connection = $args->getEntityManager()->getConnection();
try {
if ($connection->ping() === false) {
if ($this->ping($connection) === false) {
$this->logger->info('Reconnecting the Doctrine EntityManager to the persistence backend.', LogEnvironment::fromMethodName(__METHOD__));
$connection->close();
$connection->connect();
Expand All @@ -99,6 +100,19 @@ public function onFlush(OnFlushEventArgs $args)
}
}

/**
* Execute a dummy query on the given connection and return false if the connection is not open
*/
protected function ping(Connection $connection): bool
{
try {
$connection->executeQuery($connection->getDatabasePlatform()->getDummySelectSQL());
return true;
} catch (ConnectionException $e) {
return false;
}
}

/**
* Checks if the given object is allowed and if not, throws an exception
*
Expand Down
2 changes: 2 additions & 0 deletions Neos.Flow/Classes/Persistence/Doctrine/CacheAdapter.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@

/**
* Cache adapter to use Flow caches as Doctrine cache
*
* @deprecated with Flow 8.4 – will be replaced by a dedicated CachePool implementation with Flow 9.0
*/
class CacheAdapter implements Cache
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@
/**
* Extends the default doctrine JsonArrayType to work with entities.
*
* TODO: If doctrine supports a Postgres 9.4 platform we could default to jsonb.
*
* @Flow\Proxy(false)
*/
class JsonArrayType extends JsonType
Expand All @@ -49,12 +47,11 @@ public function getSQLDeclaration(array $column, AbstractPlatform $platform): st
if ($platform instanceof PostgreSQL94Platform) {
return 'jsonb';
}

return $platform->getJsonTypeDeclarationSQL($column);
}

/**
* We map jsonb fields to our datatype by default. Doctrine doesn't use jsonb at all.
* We map jsonb fields to our datatype by default.
*/
public function getMappedDatabaseTypes(AbstractPlatform $platform): array
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
use Doctrine\Common\EventManager;
use Doctrine\Common\EventSubscriber;
use Doctrine\DBAL\Connection;
use Doctrine\DBAL\DBALException;
use Doctrine\DBAL\Exception as DBALException;
use Doctrine\DBAL\Types\Type;
use Doctrine\ORM\Cache\DefaultCacheFactory;
use Doctrine\ORM\Configuration;
Expand Down
8 changes: 4 additions & 4 deletions Neos.Flow/Classes/Persistence/Doctrine/Query.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
*/

use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\DBAL\DBALException;
use Doctrine\DBAL\Exception as DBALException;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\ORMException;
use Doctrine\ORM\Query\Expr\Comparison;
Expand Down Expand Up @@ -193,7 +193,7 @@ public function getResult()
try {
$query = $this->queryBuilder->getQuery();
if ($this->cacheResult === true || $this->settings['cacheAllQueryResults']) {
$query->useResultCache(true);
$query->enableResultCache();
}
return $query->getResult();
} catch (ORMException $ormException) {
Expand Down Expand Up @@ -253,11 +253,11 @@ public function count(): int
$dqlQuery->setHint(\Doctrine\ORM\Query::HINT_CUSTOM_TREE_WALKERS, [CountWalker::class]);
$offset = $dqlQuery->getFirstResult();
$limit = $dqlQuery->getMaxResults();
if ($offset !== null) {
if (!empty($offset)) {
$dqlQuery->setFirstResult(null);
}
$numberOfResults = (int)$dqlQuery->getSingleScalarResult();
if ($offset !== null) {
if (!empty($offset)) {
$numberOfResults = max(0, $numberOfResults - $offset);
}
if ($limit !== null) {
Expand Down
2 changes: 1 addition & 1 deletion Neos.Flow/Configuration/Settings.Persistence.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ Neos:
dbal:
mappingTypes:
'flow_json_array':
dbType: 'json_array'
dbType: 'json'
className: 'Neos\Flow\Persistence\Doctrine\DataTypes\JsonArrayType'
'objectarray':
dbType: 'array'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ class ExtendedTypesEntity

/**
* @var array
* @ORM\Column(type="json_array", nullable=true)
* @ORM\Column(type="flow_json_array", nullable=true)
*/
protected $jsonArray;

Expand Down
2 changes: 1 addition & 1 deletion Neos.Flow/Tests/Functional/Persistence/PersistenceTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -473,10 +473,10 @@ public function extendedTypesEntityIsIsReconstitutedWithProperties()
self::assertNull($persistedExtendedTypesEntity->getDateTimeTz(), 'DateTimeTz');
self::assertNull($persistedExtendedTypesEntity->getDate(), 'Date');
self::assertNull($persistedExtendedTypesEntity->getTime(), 'Time');
self::assertNull($persistedExtendedTypesEntity->getJsonArray(), 'Json Array');

// These types always returns an array, never NULL, even if the property is nullable
self::assertEquals([], $persistedExtendedTypesEntity->getSimpleArray(), 'Simple Array');
self::assertEquals([], $persistedExtendedTypesEntity->getJsonArray(), 'Json Array');
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@
*/

use Doctrine\DBAL\Connection;
use Doctrine\DBAL\DBALException;
use Doctrine\DBAL\Exception\ConnectionException;
use Doctrine\DBAL\Exception as DBALException;
use Doctrine\DBAL\ConnectionException;
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\Event\OnFlushEventArgs;
use Doctrine\ORM\UnitOfWork;
Expand Down Expand Up @@ -65,16 +65,14 @@ protected function setUp(): void
$this->persistenceManager = $this->getMockBuilder(\Neos\Flow\Persistence\Doctrine\PersistenceManager::class)->setMethods(['emitAllObjectsPersisted'])->getMock();

$this->mockEntityManager = $this->getMockBuilder(\Doctrine\ORM\EntityManager::class)->disableOriginalConstructor()->getMock();
$this->mockEntityManager->expects(self::any())->method('isOpen')->willReturn(true);
$this->mockEntityManager->method('isOpen')->willReturn(true);
$this->inject($this->persistenceManager, 'entityManager', $this->mockEntityManager);

$this->mockUnitOfWork = $this->getMockBuilder(\Doctrine\ORM\UnitOfWork::class)->disableOriginalConstructor()->getMock();
$this->mockEntityManager->expects(self::any())->method('getUnitOfWork')->willReturn($this->mockUnitOfWork);
$this->mockEntityManager->method('getUnitOfWork')->willReturn($this->mockUnitOfWork);

$this->mockConnection = $this->getMockBuilder(\Doctrine\DBAL\Connection::class)->disableOriginalConstructor()->getMock();
$this->mockPing = $this->mockConnection->expects($this->atMost(1))->method('ping');
$this->mockPing->willReturn(true);
$this->mockEntityManager->expects(self::any())->method('getConnection')->willReturn($this->mockConnection);
$this->mockEntityManager->method('getConnection')->willReturn($this->mockConnection);

$this->mockSystemLogger = $this->createMock(LoggerInterface::class);
$this->inject($this->persistenceManager, 'logger', $this->mockSystemLogger);
Expand All @@ -85,14 +83,16 @@ protected function setUp(): void

$allowedObjectsContainer = new AllowedObjectsContainer();
$this->inject($this->persistenceManager, 'allowedObjects', $allowedObjectsContainer);
$allowedObjectsListener = new AllowedObjectsListener();
$allowedObjectsListener = $this->getMockBuilder(AllowedObjectsListener::class)->setMethods(['ping'])->getMock();
$this->inject($allowedObjectsListener, 'allowedObjects', $allowedObjectsContainer);
$this->inject($allowedObjectsListener, 'logger', $this->mockSystemLogger);
$this->inject($allowedObjectsListener, 'throwableStorage', $mockThrowableStorage);
$this->inject($allowedObjectsListener, 'persistenceManager', $this->persistenceManager);
$this->mockEntityManager->method('flush')->willReturnCallback(function () use ($allowedObjectsListener) {
$allowedObjectsListener->onFlush(new OnFlushEventArgs($this->mockEntityManager));
});
$this->mockPing = $allowedObjectsListener->method('ping')->withAnyParameters();
$this->mockPing->willReturn(true);
}

/**
Expand All @@ -104,8 +104,8 @@ public function getIdentifierByObjectUsesUnitOfWorkIdentityWithEmptyFlowPersiste
'Persistence_Object_Identifier' => null
];

$this->mockEntityManager->expects(self::any())->method('contains')->with($entity)->willReturn(true);
$this->mockUnitOfWork->expects(self::any())->method('getEntityIdentifier')->with($entity)->willReturn(['SomeIdentifier']);
$this->mockEntityManager->method('contains')->with($entity)->willReturn(true);
$this->mockUnitOfWork->method('getEntityIdentifier')->with($entity)->willReturn(['SomeIdentifier']);

self::assertEquals('SomeIdentifier', $this->persistenceManager->getIdentifierByObject($entity));
}
Expand All @@ -121,9 +121,9 @@ public function persistAllowedObjectsThrowsExceptionIfTryingToPersistNonAllowedO
$scheduledEntityUpdates = [spl_object_hash($mockObject) => $mockObject];
$scheduledEntityDeletes = [];
$scheduledEntityInsertions = [];
$this->mockUnitOfWork->expects(self::any())->method('getScheduledEntityUpdates')->willReturn($scheduledEntityUpdates);
$this->mockUnitOfWork->expects(self::any())->method('getScheduledEntityDeletions')->willReturn($scheduledEntityDeletes);
$this->mockUnitOfWork->expects(self::any())->method('getScheduledEntityInsertions')->willReturn($scheduledEntityInsertions);
$this->mockUnitOfWork->method('getScheduledEntityUpdates')->willReturn($scheduledEntityUpdates);
$this->mockUnitOfWork->method('getScheduledEntityDeletions')->willReturn($scheduledEntityDeletes);
$this->mockUnitOfWork->method('getScheduledEntityInsertions')->willReturn($scheduledEntityInsertions);

$this->persistenceManager->persistAllowedObjects();
}
Expand All @@ -137,9 +137,9 @@ public function persistAllowedObjectsRespectsObjectAllowed()
$scheduledEntityUpdates = [spl_object_hash($mockObject) => $mockObject];
$scheduledEntityDeletes = [];
$scheduledEntityInsertions = [];
$this->mockUnitOfWork->expects(self::any())->method('getScheduledEntityUpdates')->willReturn($scheduledEntityUpdates);
$this->mockUnitOfWork->expects(self::any())->method('getScheduledEntityDeletions')->willReturn($scheduledEntityDeletes);
$this->mockUnitOfWork->expects(self::any())->method('getScheduledEntityInsertions')->willReturn($scheduledEntityInsertions);
$this->mockUnitOfWork->method('getScheduledEntityUpdates')->willReturn($scheduledEntityUpdates);
$this->mockUnitOfWork->method('getScheduledEntityDeletions')->willReturn($scheduledEntityDeletes);
$this->mockUnitOfWork->method('getScheduledEntityInsertions')->willReturn($scheduledEntityInsertions);

$this->mockEntityManager->expects(self::once())->method('flush');

Expand Down Expand Up @@ -190,7 +190,7 @@ public function persistAllReconnectsConnectionWhenConnectionLost()
public function persistAllThrowsOriginalExceptionWhenEntityManagerGotClosed()
{
$this->expectException(DBALException::class);
$this->mockEntityManager->method('flush')->willThrowException(new \Doctrine\DBAL\DBALException('Dummy error that closed the entity manager'));
$this->mockEntityManager->method('flush')->willThrowException(new DBALException('Dummy error that closed the entity manager'));

$this->mockConnection->expects(self::never())->method('close');
$this->mockConnection->expects(self::never())->method('connect');
Expand All @@ -200,10 +200,11 @@ public function persistAllThrowsOriginalExceptionWhenEntityManagerGotClosed()

/**
* @test
* @doesNotPerformAssertions
*/
public function persistAllCatchesConnectionExceptions()
{
$this->mockPing->willThrowException($this->getMockBuilder(ConnectionException::class)->disableOriginalConstructor()->getMock());
$this->mockConnection->method('connect')->withAnyParameters()->willThrowException(new ConnectionException());
$this->persistenceManager->persistAll();
}
}
2 changes: 1 addition & 1 deletion Neos.Flow/composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@

"doctrine/orm": "^2.12.0",
"doctrine/migrations": "^3.0",
"doctrine/dbal": "^2.13",
"doctrine/dbal": "^2.13 || ^3",
"doctrine/common": "^3.0.3",
"doctrine/annotations": "^1.12",

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -375,7 +375,7 @@ protected function renderOptionTag(mixed $value, string $label)
$output .= ' selected="selected"';
}

$output .= '>' . htmlspecialchars($label) . '</option>';
$output .= '>' . htmlspecialchars((string)$label) . '</option>';

return $output;
}
Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
"laminas/laminas-code": "^4.10",
"doctrine/orm": "^2.12.0",
"doctrine/migrations": "^3.0",
"doctrine/dbal": "^2.13",
"doctrine/dbal": "^2.13 || ^3",
"doctrine/common": "^3.0.3",
"doctrine/annotations": "^1.12",
"symfony/yaml": "^5.1||^6.0",
Expand Down

0 comments on commit 10c9d39

Please sign in to comment.