Skip to content

Commit

Permalink
Update for Symfony 3.4 and 4.4 (#7)
Browse files Browse the repository at this point in the history
  • Loading branch information
roukmoute authored Jan 14, 2020
1 parent d020f33 commit 08684ad
Show file tree
Hide file tree
Showing 5 changed files with 120 additions and 88 deletions.
9 changes: 5 additions & 4 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@
"name": "roukmoute/doctrine-prefix-bundle",
"description": "Listener that prefixes tables and sequences",
"require": {
"doctrine/orm": "~2.4",
"symfony/dependency-injection": "~2.3",
"symfony/config": "~2.3",
"symfony/http-kernel": "~2.3"
"doctrine/event-manager": "^1.1",
"symfony/config": "3.4.*|4.4.*",
"symfony/http-kernel": "3.4.*|4.4.*",
"symfony/dependency-injection": "3.4.*|4.4.*",
"doctrine/orm": "^2.7"
},
"license": "MIT",
"authors": [
Expand Down
2 changes: 2 additions & 0 deletions src/DependencyInjection/Configuration.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<?php

declare(strict_types=1);

namespace Roukmoute\DoctrinePrefixBundle\DependencyInjection;

use Symfony\Component\Config\Definition\Builder\TreeBuilder;
Expand Down
8 changes: 5 additions & 3 deletions src/DependencyInjection/RoukmouteDoctrinePrefixExtension.php
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
<?php

declare(strict_types=1);

namespace Roukmoute\DoctrinePrefixBundle\DependencyInjection;

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Loader;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;

class RoukmouteDoctrinePrefixExtension extends Extension
{
Expand All @@ -14,7 +16,7 @@ public function load(array $configs, ContainerBuilder $container)
$configuration = new Configuration();
$config = $this->processConfiguration($configuration, $configs);

$loader = new Loader\XmlFileLoader($container, new FileLocator(__DIR__.'/../../Resources/config'));
$loader = new Loader\XmlFileLoader($container, new FileLocator(__DIR__ . '/../../Resources/config'));
$loader->load('services.xml');

$container->setParameter('roukmoute_doctrineprefixbundle.prefix', $config['prefix']);
Expand Down
2 changes: 2 additions & 0 deletions src/RoukmouteDoctrinePrefixBundle.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<?php

declare(strict_types=1);

namespace Roukmoute\DoctrinePrefixBundle;

use Symfony\Component\HttpKernel\Bundle\Bundle;
Expand Down
187 changes: 106 additions & 81 deletions src/Subscriber/PrefixSubscriber.php
Original file line number Diff line number Diff line change
@@ -1,15 +1,21 @@
<?php

declare(strict_types=1);

namespace Roukmoute\DoctrinePrefixBundle\Subscriber;

use Doctrine\Common\EventSubscriber;
use Doctrine\ORM\Event\LoadClassMetadataEventArgs;
use Doctrine\ORM\Id\IdentityGenerator;
use Doctrine\ORM\Id\BigIntegerIdentityGenerator;
use Doctrine\ORM\Id\IdentityGenerator;
use Doctrine\ORM\Mapping\ClassMetadata;

class PrefixSubscriber implements \Doctrine\Common\EventSubscriber
class PrefixSubscriber implements EventSubscriber
{
protected $prefix = '';

protected $bundles = [];

protected $encoding = '';

/**
Expand All @@ -19,8 +25,8 @@ class PrefixSubscriber implements \Doctrine\Common\EventSubscriber
*/
public function __construct($prefix, $bundles, $encoding)
{
$this->prefix = mb_convert_encoding($prefix, $encoding);
$this->bundles = $bundles;
$this->prefix = mb_convert_encoding($prefix, $encoding);
$this->bundles = $bundles;
$this->encoding = $encoding;
}

Expand All @@ -37,97 +43,116 @@ public function getPrefix()
*/
public function getSubscribedEvents()
{
return array('loadClassMetadata');
return ['loadClassMetadata'];
}

/**
* @param LoadClassMetadataEventArgs $args
*/
public function loadClassMetadata(LoadClassMetadataEventArgs $args)
{
/** @var \Doctrine\ORM\Mapping\ClassMetadata $classMetadata */
/** @var ClassMetadata $classMetadata */
$classMetadata = $args->getClassMetadata();

$entity = strtr($classMetadata->namespace, array('\\' => '\\\\'));
$filter = (bool)(empty($this->bundles)
|| new \RegexIterator(new \ArrayIterator($this->bundles), '/' . $entity . '/i'));
if ($filter) {
// Generate Table
$classMetadata->setPrimaryTable(array('name' => $this->addPrefix($classMetadata->getTableName())));

// Generate indexes
if (isset($classMetadata->table['indexes'])) {
foreach ($classMetadata->table['indexes'] as $index => $value) {
unset($classMetadata->table['indexes'][$index]);
$classMetadata->table['indexes'][$this->addPrefix($index)] = $value;
}
}

foreach ($classMetadata->getAssociationMappings() as $fieldName => $mapping) {
if ($mapping['type'] == \Doctrine\ORM\Mapping\ClassMetadataInfo::MANY_TO_MANY
&& isset($classMetadata->associationMappings[$fieldName]['joinTable']['name'])
) {
$mappedTableName
= $classMetadata->associationMappings[$fieldName]['joinTable']['name'];
$classMetadata->associationMappings[$fieldName]['joinTable']['name']
= $this->addPrefix($mappedTableName);
}
}

// Generate Sequence
$em = $args->getEntityManager();
$platform = $em->getConnection()->getDatabasePlatform();
if ($platform instanceof \Doctrine\DBAL\Platforms\PostgreSqlPlatform) {
if ($classMetadata->isIdGeneratorSequence()) {
$newDefinition = $classMetadata->sequenceGeneratorDefinition;
$newDefinition['sequenceName'] = $this->addPrefix($newDefinition['sequenceName']);

$classMetadata->setSequenceGeneratorDefinition($newDefinition);
if (isset($classMetadata->idGenerator)) {
$sequenceGenerator = new \Doctrine\ORM\Id\SequenceGenerator(
$em->getConfiguration()->getQuoteStrategy()->getSequenceName(
$newDefinition,
$classMetadata,
$platform
),
$newDefinition['allocationSize']
);
$classMetadata->setIdGenerator($sequenceGenerator);
}
} elseif ($classMetadata->isIdGeneratorIdentity()) {
$sequenceName = null;
$fieldName = $classMetadata->identifier ? $classMetadata->getSingleIdentifierFieldName() : null;
$columnName = $classMetadata->getSingleIdentifierColumnName();
$quoted = isset($classMetadata->fieldMappings[$fieldName]['quoted'])
|| isset($classMetadata->table['quoted']);
$sequenceName = $classMetadata->getTableName() . '_' . $columnName . '_seq';
$definition = array('sequenceName' => $platform->fixSchemaElementName($sequenceName));

if ($quoted) {
$definition['quoted'] = true;
}

$sequenceName = $em->getConfiguration()->getQuoteStrategy()->getSequenceName(
$definition,
$classMetadata,
$platform
);
$generator = ($fieldName && $classMetadata->fieldMappings[$fieldName]['type'] === 'bigint')
? new BigIntegerIdentityGenerator($sequenceName)
: new IdentityGenerator($sequenceName);

$classMetadata->setIdGenerator($generator);
}
}
if (!$this->isFiltered($classMetadata)) {
return;
}

$this->generateTable($classMetadata);
$this->generateIndexes($classMetadata);
$this->generateSequence($args, $classMetadata);
}

private function addPrefix($name)
{
if (strpos($name, $this->prefix) === 0) {
if (mb_strpos($name, $this->prefix) === 0) {
return $name;
}

return $this->prefix . $name;
}

private function isFiltered(ClassMetadata $classMetadata): bool
{
return (bool) (empty($this->bundles)
|| iterator_to_array(
new \RegexIterator(
new \ArrayIterator($this->bundles),
sprintf('/%s/i', strtr($classMetadata->namespace, ['\\' => '\\\\']))
)
)
);
}

private function generateTable(ClassMetadata $classMetadata): void
{
$classMetadata->setPrimaryTable(['name' => $this->addPrefix($classMetadata->getTableName())]);
}

private function generateIndexes(ClassMetadata $classMetadata): void
{
if (isset($classMetadata->table['indexes'])) {
foreach ($classMetadata->table['indexes'] as $index => $value) {
unset($classMetadata->table['indexes'][$index]);
$classMetadata->table['indexes'][$this->addPrefix($index)] = $value;
}
}

foreach ($classMetadata->getAssociationMappings() as $fieldName => $mapping) {
if ($mapping['type'] == \Doctrine\ORM\Mapping\ClassMetadataInfo::MANY_TO_MANY
&& isset($classMetadata->associationMappings[$fieldName]['joinTable']['name'])
) {
$mappedTableName
= $classMetadata->associationMappings[$fieldName]['joinTable']['name'];
$classMetadata->associationMappings[$fieldName]['joinTable']['name']
= $this->addPrefix($mappedTableName);
}
}
}

private function generateSequence(LoadClassMetadataEventArgs $args, ClassMetadata $classMetadata): void
{
$em = $args->getEntityManager();
$platform = $em->getConnection()->getDatabasePlatform();
if ($platform instanceof \Doctrine\DBAL\Platforms\PostgreSqlPlatform) {
if ($classMetadata->isIdGeneratorSequence()) {
$newDefinition = $classMetadata->sequenceGeneratorDefinition;
$newDefinition['sequenceName'] = $this->addPrefix($newDefinition['sequenceName']);

$classMetadata->setSequenceGeneratorDefinition($newDefinition);
if (isset($classMetadata->idGenerator)) {
$sequenceGenerator = new \Doctrine\ORM\Id\SequenceGenerator(
$em->getConfiguration()->getQuoteStrategy()->getSequenceName(
$newDefinition,
$classMetadata,
$platform
),
$newDefinition['allocationSize']
);
$classMetadata->setIdGenerator($sequenceGenerator);
}
} elseif ($classMetadata->isIdGeneratorIdentity()) {
$sequenceName = null;
$fieldName = $classMetadata->identifier ? $classMetadata->getSingleIdentifierFieldName() : null;
$columnName = $classMetadata->getSingleIdentifierColumnName();
$quoted = isset($classMetadata->fieldMappings[$fieldName]['quoted'])
|| isset($classMetadata->table['quoted']);
$sequenceName = $classMetadata->getTableName() . '_' . $columnName . '_seq';
$definition = ['sequenceName' => $platform->fixSchemaElementName($sequenceName)];

if ($quoted) {
$definition['quoted'] = true;
}

$sequenceName = $em->getConfiguration()->getQuoteStrategy()->getSequenceName(
$definition,
$classMetadata,
$platform
)
;
$generator = ($fieldName && $classMetadata->fieldMappings[$fieldName]['type'] === 'bigint')
? new BigIntegerIdentityGenerator($sequenceName)
: new IdentityGenerator($sequenceName);

$classMetadata->setIdGenerator($generator);
}
}
}
}

0 comments on commit 08684ad

Please sign in to comment.