mirror of
https://github.com/jbcr/core.git
synced 2026-03-30 21:02:07 +02:00
EM based table prefixing
This commit is contained in:
@@ -4,33 +4,38 @@ declare(strict_types=1);
|
||||
|
||||
namespace Bolt\Doctrine;
|
||||
|
||||
use Bolt\Common\Str;
|
||||
use Doctrine\ORM\Event\LoadClassMetadataEventArgs;
|
||||
use Doctrine\ORM\Mapping\ClassMetadataInfo;
|
||||
use Symfony\Bridge\Doctrine\ManagerRegistry;
|
||||
|
||||
class TablePrefix
|
||||
{
|
||||
private $tablePrefix;
|
||||
use TablePrefixTrait;
|
||||
|
||||
public function __construct(string $tablePrefix)
|
||||
public function __construct($tablePrefixes, ManagerRegistry $managerRegistry)
|
||||
{
|
||||
$this->tablePrefix = Str::ensureEndsWith($tablePrefix, '_');
|
||||
$this->setTablePrefixes($tablePrefixes, $managerRegistry);
|
||||
}
|
||||
|
||||
public function loadClassMetadata(LoadClassMetadataEventArgs $eventArgs): void
|
||||
{
|
||||
$classMetadata = $eventArgs->getClassMetadata();
|
||||
if ($tablePrefix = $this->getTablePrefix($eventArgs->getEntityManager())) {
|
||||
$classMetadata = $eventArgs->getClassMetadata();
|
||||
|
||||
if (! $classMetadata->isInheritanceTypeSingleTable() || $classMetadata->getName() === $classMetadata->rootEntityName) {
|
||||
$classMetadata->setPrimaryTable([
|
||||
'name' => $this->tablePrefix . $classMetadata->getTableName(),
|
||||
]);
|
||||
}
|
||||
if (!$classMetadata->isInheritanceTypeSingleTable()
|
||||
|| $classMetadata->getName() === $classMetadata->rootEntityName) {
|
||||
$classMetadata->setPrimaryTable(
|
||||
[
|
||||
'name' => $tablePrefix.$classMetadata->getTableName(),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
foreach ($classMetadata->getAssociationMappings() as $fieldName => $mapping) {
|
||||
if ($mapping['type'] === ClassMetadataInfo::MANY_TO_MANY && $mapping['isOwningSide']) {
|
||||
$mappedTableName = $mapping['joinTable']['name'];
|
||||
$classMetadata->associationMappings[$fieldName]['joinTable']['name'] = $this->tablePrefix . $mappedTableName;
|
||||
foreach ($classMetadata->getAssociationMappings() as $fieldName => $mapping) {
|
||||
if ($mapping['type'] === ClassMetadataInfo::MANY_TO_MANY && $mapping['isOwningSide']) {
|
||||
$mappedTableName = $mapping['joinTable']['name'];
|
||||
$classMetadata->associationMappings[$fieldName]['joinTable']['name'] = $tablePrefix.$mappedTableName;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
45
src/Doctrine/TablePrefixTrait.php
Normal file
45
src/Doctrine/TablePrefixTrait.php
Normal file
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
/**
|
||||
* @author Rix Beck <rix@neologik.hu>
|
||||
*/
|
||||
|
||||
namespace Bolt\Doctrine;
|
||||
|
||||
use Bolt\Common\Str;
|
||||
use Doctrine\Persistence\ObjectManager;
|
||||
use Symfony\Bridge\Doctrine\ManagerRegistry;
|
||||
|
||||
trait TablePrefixTrait
|
||||
{
|
||||
private $tablePrefixes = [];
|
||||
|
||||
protected function setTablePrefix(ObjectManager $manager, string $prefix)
|
||||
{
|
||||
$key = spl_object_hash($manager);
|
||||
$this->tablePrefixes[$key] = Str::ensureEndsWith($prefix, '_');
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected function setTablePrefixes($tablePrefixes, ManagerRegistry $managerRegistry)
|
||||
{
|
||||
$prefixes = (array)$tablePrefixes;
|
||||
$this->registry = $managerRegistry;
|
||||
|
||||
foreach ($prefixes as $em => $tablePrefix) {
|
||||
$manager = $managerRegistry->getManager(is_int($em) ? 'default' : $em);
|
||||
if ($manager) {
|
||||
$this->setTablePrefix($manager, $tablePrefix);
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected function getTablePrefix(ObjectManager $manager)
|
||||
{
|
||||
$key = spl_object_hash($manager);
|
||||
|
||||
return $this->tablePrefixes[$key] ?? '';
|
||||
}
|
||||
}
|
||||
@@ -4,14 +4,17 @@ declare(strict_types=1);
|
||||
|
||||
namespace Bolt\Event\Subscriber;
|
||||
|
||||
use Bolt\Common\Str;
|
||||
use Bolt\Doctrine\TablePrefixTrait;
|
||||
use Carbon\Carbon;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Symfony\Bridge\Doctrine\ManagerRegistry;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\HttpKernel\KernelEvents;
|
||||
|
||||
class TimedPublishSubscriber implements EventSubscriberInterface
|
||||
{
|
||||
use TablePrefixTrait;
|
||||
|
||||
public const PRIORITY = 30;
|
||||
|
||||
/** @var EntityManagerInterface */
|
||||
@@ -20,10 +23,22 @@ class TimedPublishSubscriber implements EventSubscriberInterface
|
||||
/** @var string */
|
||||
private $tablePrefix;
|
||||
|
||||
public function __construct(string $tablePrefix, EntityManagerInterface $entityManager)
|
||||
public function __construct($tablePrefixes, ManagerRegistry $managerRegistry)
|
||||
{
|
||||
$this->entityManager = $entityManager;
|
||||
$this->tablePrefix = Str::ensureEndsWith($tablePrefix, '_');
|
||||
$this->entityManager = $managerRegistry->getManager('default');
|
||||
$this->tablePrefix = $this
|
||||
->setTablePrefixes($tablePrefixes, $managerRegistry)
|
||||
->getTablePrefix($this->entityManager);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the events to subscribe to.
|
||||
*/
|
||||
public static function getSubscribedEvents(): array
|
||||
{
|
||||
return [
|
||||
KernelEvents::REQUEST => [['onKernelRequest', self::PRIORITY]], // Right after route is matched
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -36,8 +51,14 @@ class TimedPublishSubscriber implements EventSubscriberInterface
|
||||
|
||||
// Publish timed Content records when 'publish_at' has passed and Depublish published Content
|
||||
// records when 'depublish_at' has passed. Note: Placeholders in DBAL don't work for tablenames.
|
||||
$queryPublish = sprintf('update %scontent SET status = "published", published_at = :now WHERE status = "timed" AND published_at < :now', $this->tablePrefix);
|
||||
$queryDepublish = sprintf('update %scontent SET status = "held", depublished_at = :now WHERE status = "published" AND depublished_at < :now', $this->tablePrefix);
|
||||
$queryPublish = sprintf(
|
||||
'update %scontent SET status = "published", published_at = :now WHERE status = "timed" AND published_at < :now',
|
||||
$this->tablePrefix
|
||||
);
|
||||
$queryDepublish = sprintf(
|
||||
'update %scontent SET status = "held", depublished_at = :now WHERE status = "published" AND depublished_at < :now',
|
||||
$this->tablePrefix
|
||||
);
|
||||
|
||||
try {
|
||||
$conn->executeUpdate($queryPublish, [':now' => $now]);
|
||||
@@ -46,14 +67,4 @@ class TimedPublishSubscriber implements EventSubscriberInterface
|
||||
// Fail silently, output user-friendly exception elsewhere.
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the events to subscribe to.
|
||||
*/
|
||||
public static function getSubscribedEvents(): array
|
||||
{
|
||||
return [
|
||||
KernelEvents::REQUEST => [['onKernelRequest', self::PRIORITY]], // Right after route is matched
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user