Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce Doctrine ORM #33127

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion 3rdparty
Submodule 3rdparty updated 848 files
9 changes: 9 additions & 0 deletions core/register_command.php
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,15 @@
$application->add(new OC\Core\Command\Db\Migrations\MigrateCommand(\OC::$server->get(\OC\DB\Connection::class)));
$application->add(new OC\Core\Command\Db\Migrations\GenerateCommand(\OC::$server->get(\OC\DB\Connection::class), \OC::$server->getAppManager()));
$application->add(new OC\Core\Command\Db\Migrations\ExecuteCommand(\OC::$server->get(\OC\DB\Connection::class), \OC::$server->getConfig()));
Doctrine\ORM\Tools\Console\ConsoleRunner::addCommands($application, new class implements \Doctrine\ORM\Tools\Console\EntityManagerProvider {
public function getDefaultManager(): \Doctrine\ORM\EntityManagerInterface {
return \OCP\Server::get(\OCP\DB\ORM\IEntityManager::class)->get();
}

public function getManager(string $name): \Doctrine\ORM\EntityManagerInterface {
return \OCP\Server::get(\OCP\DB\ORM\IEntityManager::class)->get();
}
});
}

$application->add(new OC\Core\Command\Encryption\Disable(\OC::$server->getConfig()));
Expand Down
15 changes: 15 additions & 0 deletions lib/composer/composer/autoload_classmap.php
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,15 @@
'OCP\\DB\\IPreparedStatement' => $baseDir . '/lib/public/DB/IPreparedStatement.php',
'OCP\\DB\\IResult' => $baseDir . '/lib/public/DB/IResult.php',
'OCP\\DB\\ISchemaWrapper' => $baseDir . '/lib/public/DB/ISchemaWrapper.php',
'OCP\\DB\\ORM\\IEntityManager' => $baseDir . '/lib/public/DB/ORM/IEntityManager.php',
'OCP\\DB\\ORM\\IEntityRepository' => $baseDir . '/lib/public/DB/ORM/IEntityRepository.php',
'OCP\\DB\\ORM\\IParameter' => $baseDir . '/lib/public/DB/ORM/IParameter.php',
'OCP\\DB\\ORM\\IQuery' => $baseDir . '/lib/public/DB/ORM/IQuery.php',
'OCP\\DB\\ORM\\LockMode' => $baseDir . '/lib/public/DB/ORM/LockMode.php',
'OCP\\DB\\ORM\\NoResultException' => $baseDir . '/lib/public/DB/ORM/NoResultException.php',
'OCP\\DB\\ORM\\NonUniqueResultException' => $baseDir . '/lib/public/DB/ORM/NonUniqueResultException.php',
'OCP\\DB\\ORM\\OptimisticLockException' => $baseDir . '/lib/public/DB/ORM/OptimisticLockException.php',
'OCP\\DB\\ORM\\PessimisticLockException' => $baseDir . '/lib/public/DB/ORM/PessimisticLockException.php',
'OCP\\DB\\QueryBuilder\\ICompositeExpression' => $baseDir . '/lib/public/DB/QueryBuilder/ICompositeExpression.php',
'OCP\\DB\\QueryBuilder\\IExpressionBuilder' => $baseDir . '/lib/public/DB/QueryBuilder/IExpressionBuilder.php',
'OCP\\DB\\QueryBuilder\\IFunctionBuilder' => $baseDir . '/lib/public/DB/QueryBuilder/IFunctionBuilder.php',
Expand Down Expand Up @@ -1066,6 +1075,12 @@
'OC\\DB\\MySQLMigrator' => $baseDir . '/lib/private/DB/MySQLMigrator.php',
'OC\\DB\\MySqlTools' => $baseDir . '/lib/private/DB/MySqlTools.php',
'OC\\DB\\OCSqlitePlatform' => $baseDir . '/lib/private/DB/OCSqlitePlatform.php',
'OC\\DB\\ORM\\EntityManagerAdapter' => $baseDir . '/lib/private/DB/ORM/EntityManagerAdapter.php',
'OC\\DB\\ORM\\EntityRepositoryAdapter' => $baseDir . '/lib/private/DB/ORM/EntityRepositoryAdapter.php',
'OC\\DB\\ORM\\ParameterAdapter' => $baseDir . '/lib/private/DB/ORM/ParameterAdapter.php',
'OC\\DB\\ORM\\Psr6CacheAdapter' => $baseDir . '/lib/private/DB/ORM/Psr6CacheAdapter.php',
'OC\\DB\\ORM\\QueryAdapter' => $baseDir . '/lib/private/DB/ORM/QueryAdapter.php',
'OC\\DB\\ORM\\TablePrefix' => $baseDir . '/lib/private/DB/ORM/TablePrefix.php',
'OC\\DB\\ObjectParameter' => $baseDir . '/lib/private/DB/ObjectParameter.php',
'OC\\DB\\OracleConnection' => $baseDir . '/lib/private/DB/OracleConnection.php',
'OC\\DB\\OracleMigrator' => $baseDir . '/lib/private/DB/OracleMigrator.php',
Expand Down
15 changes: 15 additions & 0 deletions lib/composer/composer/autoload_static.php
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,15 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2
'OCP\\DB\\IPreparedStatement' => __DIR__ . '/../../..' . '/lib/public/DB/IPreparedStatement.php',
'OCP\\DB\\IResult' => __DIR__ . '/../../..' . '/lib/public/DB/IResult.php',
'OCP\\DB\\ISchemaWrapper' => __DIR__ . '/../../..' . '/lib/public/DB/ISchemaWrapper.php',
'OCP\\DB\\ORM\\IEntityManager' => __DIR__ . '/../../..' . '/lib/public/DB/ORM/IEntityManager.php',
'OCP\\DB\\ORM\\IEntityRepository' => __DIR__ . '/../../..' . '/lib/public/DB/ORM/IEntityRepository.php',
'OCP\\DB\\ORM\\IParameter' => __DIR__ . '/../../..' . '/lib/public/DB/ORM/IParameter.php',
'OCP\\DB\\ORM\\IQuery' => __DIR__ . '/../../..' . '/lib/public/DB/ORM/IQuery.php',
'OCP\\DB\\ORM\\LockMode' => __DIR__ . '/../../..' . '/lib/public/DB/ORM/LockMode.php',
'OCP\\DB\\ORM\\NoResultException' => __DIR__ . '/../../..' . '/lib/public/DB/ORM/NoResultException.php',
'OCP\\DB\\ORM\\NonUniqueResultException' => __DIR__ . '/../../..' . '/lib/public/DB/ORM/NonUniqueResultException.php',
'OCP\\DB\\ORM\\OptimisticLockException' => __DIR__ . '/../../..' . '/lib/public/DB/ORM/OptimisticLockException.php',
'OCP\\DB\\ORM\\PessimisticLockException' => __DIR__ . '/../../..' . '/lib/public/DB/ORM/PessimisticLockException.php',
'OCP\\DB\\QueryBuilder\\ICompositeExpression' => __DIR__ . '/../../..' . '/lib/public/DB/QueryBuilder/ICompositeExpression.php',
'OCP\\DB\\QueryBuilder\\IExpressionBuilder' => __DIR__ . '/../../..' . '/lib/public/DB/QueryBuilder/IExpressionBuilder.php',
'OCP\\DB\\QueryBuilder\\IFunctionBuilder' => __DIR__ . '/../../..' . '/lib/public/DB/QueryBuilder/IFunctionBuilder.php',
Expand Down Expand Up @@ -1099,6 +1108,12 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2
'OC\\DB\\MySQLMigrator' => __DIR__ . '/../../..' . '/lib/private/DB/MySQLMigrator.php',
'OC\\DB\\MySqlTools' => __DIR__ . '/../../..' . '/lib/private/DB/MySqlTools.php',
'OC\\DB\\OCSqlitePlatform' => __DIR__ . '/../../..' . '/lib/private/DB/OCSqlitePlatform.php',
'OC\\DB\\ORM\\EntityManagerAdapter' => __DIR__ . '/../../..' . '/lib/private/DB/ORM/EntityManagerAdapter.php',
'OC\\DB\\ORM\\EntityRepositoryAdapter' => __DIR__ . '/../../..' . '/lib/private/DB/ORM/EntityRepositoryAdapter.php',
'OC\\DB\\ORM\\ParameterAdapter' => __DIR__ . '/../../..' . '/lib/private/DB/ORM/ParameterAdapter.php',
'OC\\DB\\ORM\\Psr6CacheAdapter' => __DIR__ . '/../../..' . '/lib/private/DB/ORM/Psr6CacheAdapter.php',
'OC\\DB\\ORM\\QueryAdapter' => __DIR__ . '/../../..' . '/lib/private/DB/ORM/QueryAdapter.php',
'OC\\DB\\ORM\\TablePrefix' => __DIR__ . '/../../..' . '/lib/private/DB/ORM/TablePrefix.php',
'OC\\DB\\ObjectParameter' => __DIR__ . '/../../..' . '/lib/private/DB/ObjectParameter.php',
'OC\\DB\\OracleConnection' => __DIR__ . '/../../..' . '/lib/private/DB/OracleConnection.php',
'OC\\DB\\OracleMigrator' => __DIR__ . '/../../..' . '/lib/private/DB/OracleMigrator.php',
Expand Down
2 changes: 1 addition & 1 deletion lib/private/DB/ConnectionFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
namespace OC\DB;

use Doctrine\Common\EventManager;
use Doctrine\DBAL\Configuration;
use Doctrine\ORM\Configuration;
use Doctrine\DBAL\DriverManager;
use Doctrine\DBAL\Event\Listeners\OracleSessionInit;
use Doctrine\DBAL\Event\Listeners\SQLSessionInit;
Expand Down
92 changes: 92 additions & 0 deletions lib/private/DB/ORM/EntityManagerAdapter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
<?php

namespace OC\DB\ORM;

use Doctrine\Common\EventManager;
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\EntityRepository;
use Doctrine\ORM\ORMSetup;
use OC\DB\ConnectionAdapter;
use OCP\DB\ORM\IQuery;
use OCP\DB\ORM\IEntityManager;
use OCP\DB\ORM\IEntityRepository;
use OCP\IDBConnection;

class EntityManagerAdapter implements IEntityManager {

private EntityManager $em;
private ConnectionAdapter $connection;

public function __construct(ConnectionAdapter $connection) {
$paths = array_filter(array_map(fn ($appId) => \OC_App::getAppPath($appId) . '/lib/Entity/', \OC_App::getEnabledApps()), fn ($path) => is_dir($path));
$isDevMode = true;
$proxyDir = null;
$cache = null;


$evm = $connection->getInner()->getEventManager();
$tablePrefix = new TablePrefix('oc_');

$evm->addEventListener(\Doctrine\ORM\Events::loadClassMetadata, $tablePrefix);
// TODO actually use our cache with a psr6 cache wrapper or at least our cache config
$config = ORMSetup::createAnnotationMetadataConfiguration($paths, $isDevMode, $proxyDir, $cache);

$this->em = EntityManager::create($connection->getInner(), $config, $evm);
$this->connection = $connection;
}

public function createQueryBuilder(): IQueryBuilder {
return new QueryBuilderAdapter($this->em->createQueryBuilder());
}

public function createQuery($dql = ''): IQuery
{
return new QueryAdapter($this->em->createQuery($dql));
}

public function flush(): void {
$this->em->flush();
}

public function find(string $className, $id, ?int $lockMode = null, ?int $lockVersion = null): ?object {
return $this->em->find($className, $id, $lockMode, $lockVersion);
}

public function clear(): void {
$this->em->clear();
}

public function persist(object $entity): void {
$this->em->persist($entity);
}

public function remove(object $entity): void {
$this->em->remove($entity);
}

public function lock(object $entity, int $lockMode, $lockVersion = null): void {
$this->em->lock($entity, $lockMode, $lockVersion);
}

public function getRepository($className): IEntityRepository {
/** @var EntityRepository $internalRepo */
$internalRepo = $this->em->getRepository($className);
return new EntityRepositoryAdapter($internalRepo);
}

public function contains(object $entity): bool {
return $this->em->contains($entity);
}

public function getConnection(): IDBConnection {
return $this->connection;
}

/**
* Only for internal use
*/
public function get(): EntityManager {
return $this->em;
}

}
35 changes: 35 additions & 0 deletions lib/private/DB/ORM/EntityRepositoryAdapter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php

namespace OC\DB\ORM;

use Doctrine\ORM\EntityRepository;
use OCP\DB\ORM\IEntityRepository;

class EntityRepositoryAdapter implements IEntityRepository
{
private EntityRepository $entityRepository;

public function __construct(EntityRepository $entityRepository) {
$this->entityRepository = $entityRepository;
}

public function find($id): ?object {
return $this->entityRepository->find($id);
}

public function findAll(): array {
return $this->entityRepository->findAll();
}

public function findBy(array $criteria, ?array $orderBy = null, ?int $limit = null, ?int $offset = null): array {
return $this->entityRepository->findBy($criteria, $orderBy, $limit, $offset);
}

public function findOneBy(array $criteria): ?object {
return $this->entityRepository->findOneBy($criteria);
}

public function getClassName(): string {
return $this->entityRepository->getClassName();
}
}
25 changes: 25 additions & 0 deletions lib/private/DB/ORM/ExpressionAdapter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

declare(strict_types=1);

// SPDX-FileCopyrightText: Carl Schwan <[email protected]>
// SPDX-License-Identifier: AGPL-3.0-or-later

namespace OC\DB\ORM;

use Doctrine\Common\EventManager;
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\EntityRepository;
use Doctrine\ORM\ORMSetup;
use Doctrine\ORM\Query\Expr;
use OC\DB\ConnectionAdapter;
use OCP\DB\ORM\Query\IExpression;
use OCP\IDBConnection;

class ExpressionAdapter implements IExpression {
private Expr $expr;

public function __construct(Expr $expr) {
$this->expr = $expr;
}
}
34 changes: 34 additions & 0 deletions lib/private/DB/ORM/ParameterAdapter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php

namespace OC\DB\ORM;

use Doctrine\ORM\Query\Parameter;
use OCP\DB\ORM\IParameter;

class ParameterAdapter implements IParameter {
private Parameter $parameter;

public function __construct(Parameter $parameter) {
$this->parameter = $parameter;
}

public function getName(): string {
return $this->parameter->getName();
}

public function getValue() {
return $this->parameter->getValue();
}

public function getType() {
return $this->parameter->getType();
}

public function setValue($value, $type = null): void {
$this->parameter->setValue($value, $type);
}

public function typeWasSpecified(): bool {
return $this->parameter->typeWasSpecified();
}
}
116 changes: 116 additions & 0 deletions lib/private/DB/ORM/Psr6CacheAdapter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
<?php
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO finish


namespace OC\DB\ORM;

use OCP\ICache;
use Psr\Cache\CacheItemInterface;
use Psr\Cache\CacheItemPoolInterface;

class CacheItemAdapter implements CacheItemInterface {
private ICache $cacheAdapter;
private string $key;
private $value;
private bool $fetched = false;
private ?\DateTime $_expireAt = null;
private int $_expireAfter = -1;

public function __construct(ICache $cache, $key) {
$this->cache = $cache;
$this->key = $key;
}

private function fetch(): void {
if (!$this->fetched) {
$this->value = $this->cache->get($this->key);
$this->fetched = true;
}
}

public function getKey() {
return $this->key;
}

public function get() {
$this->fetch();
return $this->value;
}

public function isHit() {
$this->fetch();
return $this->value !== null;
}

public function set($value) {
$this->value = $value;
}

public function expiresAt($expiration) {
$this->_expireAt = $expiration;
}

public function expiresAfter($time) {
$this->_expireAfter = $time;
}

public function getExpireAt(): ?\DateTime
{
return $this->_expireAt;
}

public function getExpireAfter(): int
{
return $this->_expireAfter;
}
}

class Psr6CacheAdapter implements CacheItemPoolInterface {
private ICache $cache;

public function __construct(ICache $cache) {
$this->cache = $cache;
}

public function getItem($key) {
return new CacheItemAdapter($this->cache, $key);
}

public function getItems(array $keys = array()) {
for (int )
// TODO: Implement getItems() method.
}

public function hasItem($key)
{
// TODO: Implement hasItem() method.
}

public function clear()
{
// TODO: Implement clear() method.
}

public function deleteItem($key)
{
// TODO: Implement deleteItem() method.
}

public function deleteItems(array $keys)
{
// TODO: Implement deleteItems() method.
}

public function save(CacheItemInterface $item)
{
// TODO: Implement save() method.
}

public function saveDeferred(CacheItemInterface $item)
{
// TODO: Implement saveDeferred() method.
}

public function commit()
{
// TODO: Implement commit() method.
}
}
Loading