Skip to content

Instantly share code, notes, and snippets.

@anyt
Created April 25, 2018 16:26
Show Gist options
  • Save anyt/53619b281e716db440416eb38f322f02 to your computer and use it in GitHub Desktop.
Save anyt/53619b281e716db440416eb38f322f02 to your computer and use it in GitHub Desktop.
<?php
namespace Demo\Bundle\CalendarBundle\Migrations\Schema\v2_3;
use Doctrine\DBAL\Schema\Schema;
use Oro\Bundle\EntityExtendBundle\Tools\ExtendDbIdentifierNameGenerator;
use Oro\Bundle\MigrationBundle\Migration\Extension\NameGeneratorAwareInterface;
use Oro\Bundle\MigrationBundle\Migration\Migration;
use Oro\Bundle\MigrationBundle\Migration\QueryBag;
use Oro\Bundle\MigrationBundle\Tools\DbIdentifierNameGenerator;
/**
* This migration should not be executed during install,
* because during install many-to-many relation associatedContacts is not created.
*/
class RemoveAssociatedContacts implements Migration, NameGeneratorAwareInterface
{
const ACCOUNT_CLASS = 'OroCRM\\Bundle\\AccountBundle\\Entity\\Account';
const CALENDAR_EVENT_CLASS = 'Oro\\Bundle\\CalendarBundle\\Entity\\CalendarEvent';
/**
* @var ExtendDbIdentifierNameGenerator
*/
protected $nameGenerator;
/**
* {@inheritdoc}
*/
public function up(Schema $schema, QueryBag $queries)
{
// Cleanup entity config of field associatedContacts
$this->deleteEntityFieldConfig(
self::CALENDAR_EVENT_CLASS,
'associatedContacts',
$queries
);
// Cleanup entity config of calendar event entity
$queries->addPostQuery(
new UpdateEntityConfigDataQuery(
function ($data) {
$relationKey =
'manyToMany|'
. self::CALENDAR_EVENT_CLASS . '|'
. self::ACCOUNT_CLASS . '|' .
'associatedContacts';
unset($data['extend']['relation'][$relationKey]);
unset($data['extend']['schema']['relation']['associatedContacts']);
unset($data['extend']['schema']['default']['default_associatedContacts']);
unset($data['extend']['schema']['addremove']['associatedContacts']);
return $data;
},
self::CALENDAR_EVENT_CLASS
)
);
// Cleanup entity config of account entity
$queries->addPostQuery(
new UpdateEntityConfigDataQuery(
function ($data) {
$relationKey =
'manyToMany|'
. self::CALENDAR_EVENT_CLASS . '|'
. self::ACCOUNT_CLASS . '|'
. 'associatedContacts';
unset($data['extend']['relation'][$relationKey]);
unset($data['extend']['schema']['relation']['calendarevent_associatedContacts']);
unset($data['extend']['schema']['addremove']['calendarevent_associatedContacts']);
return $data;
},
self::ACCOUNT_CLASS
)
);
// Drop many-to-many table
$manyToManyTableName = $this->nameGenerator->generateManyToManyJoinTableName(
self::CALENDAR_EVENT_CLASS,
'associatedContacts',
self::ACCOUNT_CLASS
);
$schema->dropTable($manyToManyTableName);
// Drop column for default value of many-to-many relation
$table = $schema->getTable('oro_calendar_event');
$table->dropIndex('uniq_2ddc40dd47325b55');
$table->removeForeignKey('fk_2ddc40dd47325b55');
$table->dropColumn('default_associatedcontacts_id');
}
/**
* @param string $entityClassName
* @param string $fieldName
* @param QueryBag $queries
*/
protected function deleteEntityFieldConfig($entityClassName, $fieldName, QueryBag $queries)
{
$entityClassName = addslashes($entityClassName);
$sql = <<<DQL
DELETE FROM oro_entity_config_index_value
WHERE entity_id IS NULL AND field_id IN (
SELECT oecf.id FROM oro_entity_config_field AS oecf
WHERE
oecf.field_name = '$fieldName'
AND
oecf.entity_id = (
SELECT oec.id
FROM oro_entity_config AS oec
WHERE oec.class_name = ''
)
);
DELETE FROM oro_entity_config_field
WHERE field_name = '$fieldName' AND
entity_id IN (
SELECT id FROM oro_entity_config
WHERE class_name = '$entityClassName'
);
DQL;
$queries->addPostQuery($sql);
}
/**
* {@inheritdoc}
*/
public function setNameGenerator(DbIdentifierNameGenerator $nameGenerator)
{
$this->nameGenerator = $nameGenerator;
}
}
<?php
namespace Demo\Bundle\CalendarBundle\Migrations\Schema\v2_3;
use Psr\Log\LoggerInterface;
use Oro\Bundle\MigrationBundle\Migration\ArrayLogger;
use Oro\Bundle\MigrationBundle\Migration\ParametrizedMigrationQuery;
/**
* Update entity config data using callback.
*/
class UpdateEntityConfigDataQuery extends ParametrizedMigrationQuery
{
const CALENDAR_EVENT_CLASS = 'Oro\\Bundle\\CalendarBundle\\Entity\\CalendarEvent';
const ACCOUNT_CLASS = 'OroCRM\\Bundle\\AccountBundle\\Entity\\Account';
/**
* @var callable
*/
protected $updateCallback;
/**
* @var string
*/
protected $className;
/**
* @param callable $updateCallback
* @param string $className
*/
public function __construct($updateCallback, $className)
{
$this->updateCallback = $updateCallback;
$this->className = $className;
}
/**
* {@inheritdoc}
*/
public function getDescription()
{
$logger = new ArrayLogger();
$this->doExecute($logger, true);
return $logger->getMessages();
}
/**
* {@inheritdoc}
*/
public function execute(LoggerInterface $logger)
{
$this->doExecute($logger);
}
/**
* @param LoggerInterface $logger
* @param bool $dryRun
*
* @SuppressWarnings(PHPMD.NPathComplexity)
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
*/
public function doExecute(LoggerInterface $logger, $dryRun = false)
{
$data = $this->loadEntityConfigData($logger, $this->className);
$data = call_user_func($this->updateCallback, $data);
$query = 'UPDATE oro_entity_config SET data = :data WHERE class_name = :class_name';
$params = ['data' => $data, 'class_name' => $this->className];
$types = ['data' => 'array', 'class_name' => 'string'];
$this->logQuery($logger, $query, $params, $types);
if (!$dryRun) {
$this->connection->executeUpdate($query, $params, $types);
}
}
/**
* @param LoggerInterface $logger
*
* @return array
*/
protected function loadEntityConfigData(LoggerInterface $logger)
{
$sql = 'SELECT data FROM oro_entity_config WHERE class_name = :class_name';
$params = ['class_name' => $this->className];
$types = ['class_name' => 'string'];
$this->logQuery($logger, $sql, $params, $types);
$result = [];
$rows = $this->connection->fetchAll($sql, $params, $types);
if (isset($rows[0])) {
$result = $this->connection->convertToPHPValue($rows[0]['data'], 'array');
}
return $result;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment