From a given set of metadata classes this method creates a Schema instance.
public getSchemaFromMetadata ( array $classes ) : Schema | ||
$classes | array | |
return | Schema |
/** * Updates DB Schema. * @throws \Exception if there are no changes in entities */ protected function updateDbSchema() { /** * @var $em \Doctrine\ORM\EntityManager */ $em = $this->getContainer()->get('doctrine.orm.entity_manager'); $event = $em->getEventManager(); $sm = $em->getConnection()->getSchemaManager(); $allMetadata = $em->getMetadataFactory()->getAllMetadata(); $schemaTool = new SchemaTool($em); $entitiesMetadata = array($em->getClassMetadata(ApiUser::getClassName()), $em->getClassMetadata(DiamanteUser::getClassName())); $event->disableListeners(); $currentSchema = $sm->createSchema(); $schemaFromMetadata = $schemaTool->getSchemaFromMetadata($allMetadata); $entitiesSchema = $schemaTool->getSchemaFromMetadata($entitiesMetadata); $entitiesTables = $entitiesSchema->getTables(); $entitiesTableName = array_keys($entitiesTables); $currentDiamanteSchema = $this->getTargetSchema($currentSchema, $entitiesTableName); $diamanteSchemaFromMetadata = $this->getTargetSchema($schemaFromMetadata, $entitiesTableName); $comparator = new Comparator(); $diff = $comparator->compare($currentDiamanteSchema, $diamanteSchemaFromMetadata); $toUpdate = $diff->toSql($em->getConnection()->getDatabasePlatform()); if (empty($toUpdate)) { throw new \Exception('No new updates found. Diamante Api Bundle is up to date!'); } $conn = $em->getConnection(); foreach ($toUpdate as $sql) { $conn->executeQuery($sql); } }
/** * Updates DB Schema. Changes from Diamante only will be applied for current schema. Other bundles updating skips * @throws \Exception if there are no changes in entities */ protected function updateDbSchema() { /** * @var $em \Doctrine\ORM\EntityManager */ $em = $this->getContainer()->get('doctrine.orm.entity_manager'); $event = $em->getEventManager(); $sm = $em->getConnection()->getSchemaManager(); $allMetadata = $em->getMetadataFactory()->getAllMetadata(); $schemaTool = new SchemaTool($em); $entitiesMetadata = array($em->getClassMetadata(\Diamante\DeskBundle\Entity\Branch::getClassName()), $em->getClassMetadata(\Diamante\DeskBundle\Entity\Ticket::getClassName()), $em->getClassMetadata(\Diamante\DeskBundle\Entity\Comment::getClassName()), $em->getClassMetadata(\Diamante\DeskBundle\Entity\Attachment::getClassName()), $em->getClassMetadata(\Diamante\DeskBundle\Entity\BranchEmailConfiguration::getClassName()), $em->getClassMetadata(\Diamante\DeskBundle\Entity\MessageReference::getClassName()), $em->getClassMetadata(\Diamante\DeskBundle\Entity\TicketHistory::getClassName()), $em->getClassMetadata(\Diamante\DeskBundle\Entity\WatcherList::getClassName()), $em->getClassMetadata(\Diamante\DeskBundle\Entity\TicketTimeline::getClassName()), $em->getClassMetadata(\Diamante\DeskBundle\Entity\Audit::getClassName()), $em->getClassMetadata(\Diamante\DeskBundle\Entity\AuditField::getClassName()), $em->getClassMetadata(\Diamante\DeskBundle\Entity\Article::getClassName())); $event->disableListeners(); $currentSchema = $sm->createSchema(); $schemaFromMetadata = $schemaTool->getSchemaFromMetadata($allMetadata); $entitiesSchema = $schemaTool->getSchemaFromMetadata($entitiesMetadata); $entitiesTables = $entitiesSchema->getTables(); $entitiesTableName = array_keys($entitiesTables); $currentDiamanteSchema = $this->getTargetSchema($currentSchema, $entitiesTableName); $diamanteSchemaFromMetadata = $this->getTargetSchema($schemaFromMetadata, $entitiesTableName); $comparator = new Comparator(); $diff = $comparator->compare($currentDiamanteSchema, $diamanteSchemaFromMetadata); $toUpdate = $diff->toSql($em->getConnection()->getDatabasePlatform()); if (empty($toUpdate)) { throw new \Exception('No new updates found. DiamanteDesk is up to date!'); } $conn = $em->getConnection(); foreach ($toUpdate as $sql) { $conn->executeQuery($sql); } }
protected function getTaggingSchema($em) { $tool = new \Doctrine\ORM\Tools\SchemaTool($em); $classes = array($em->getClassMetadata('Poc\\PocPlugins\\Tagging\\Driver\\Doctrine2\\Entities\\Cache'), $em->getClassMetadata('Poc\\PocPlugins\\Tagging\\Driver\\Doctrine2\\Entities\\CacheTag'), $em->getClassMetadata('Poc\\PocPlugins\\Tagging\\Driver\\Doctrine2\\Entities\\Tag')); $schema = $tool->getSchemaFromMetadata($classes); return $schema; }
/** * Down method * * @param Schema $schema */ public function down(Schema $schema) { if (Version::isSupportGetInstanceFunction()) { $app = Application::getInstance(); $meta = $this->getMetadata($app['orm.em']); $tool = new SchemaTool($app['orm.em']); $schemaFromMetadata = $tool->getSchemaFromMetadata($meta); // テーブル削除 foreach ($schemaFromMetadata->getTables() as $table) { if ($schema->hasTable($table->getName())) { $schema->dropTable($table->getName()); } } // シーケンス削除 foreach ($schemaFromMetadata->getSequences() as $sequence) { if ($schema->hasSequence($sequence->getName())) { $schema->dropSequence($sequence->getName()); } } } else { if ($schema->hasTable(self::MAKER)) { $schema->dropTable(self::MAKER); } if ($schema->hasTable(self::PRODUCTMAKER)) { $schema->dropTable(self::PRODUCTMAKER); } } if ($this->connection->getDatabasePlatform()->getName() == 'postgresql') { foreach ($this->sequence as $sequence) { if ($schema->hasSequence($sequence)) { $schema->dropSequence($sequence); } } } }
public function execute(InputInterface $input, OutputInterface $output) { $configuration = $this->_getMigrationConfiguration($input, $output); $em = $this->getHelper('em')->getEntityManager(); $conn = $em->getConnection(); $platform = $conn->getDatabasePlatform(); $metadata = $em->getMetadataFactory()->getAllMetadata(); if (empty($metadata)) { $output->writeln('No mapping information to process.', 'ERROR'); return; } $tool = new SchemaTool($em); $fromSchema = $conn->getSchemaManager()->createSchema(); $toSchema = $tool->getSchemaFromMetadata($metadata); $up = $this->_buildCodeFromSql($configuration, $fromSchema->getMigrateToSql($toSchema, $platform)); $down = $this->_buildCodeFromSql($configuration, $fromSchema->getMigrateFromSql($toSchema, $platform)); if ( ! $up && ! $down) { $output->writeln('No changes detected in your mapping information.', 'ERROR'); return; } $version = date('YmdHis'); $path = $this->_generateMigration($configuration, $input, $version, $up, $down); $output->writeln(sprintf('Generated new migration class to "<info>%s</info>" from schema differences.', $path)); }
/** * remove table. * * @param Schema $schema */ public function down(Schema $schema) { //current version >= 3.0.9 if (Version::isSupportGetInstanceFunction()) { $app = Application::getInstance(); $meta = $this->getMetadata($app['orm.em']); $tool = new SchemaTool($app['orm.em']); $schemaFromMetadata = $tool->getSchemaFromMetadata($meta); // テーブル削除 foreach ($schemaFromMetadata->getTables() as $table) { if ($schema->hasTable($table->getName())) { $schema->dropTable($table->getName()); } } // シーケンス削除 foreach ($schemaFromMetadata->getSequences() as $sequence) { if ($schema->hasSequence($sequence->getName())) { $schema->dropSequence($sequence->getName()); } } //for delete sequence in postgresql if ($this->connection->getDatabasePlatform()->getName() == 'postgresql') { $schema->dropSequence('plg_related_product_id_seq'); } } else { // this down() migration is auto-generated, please modify it to your needs $schema->dropTable(self::NAME); $schema->dropSequence('plg_related_product_id_seq'); } }
/** * Remove data. * * @param Schema $schema */ public function down(Schema $schema) { if (Version::isSupportGetInstanceFunction()) { $app = Application::getInstance(); $meta = $this->getMetadata($app['orm.em']); $tool = new SchemaTool($app['orm.em']); $schemaFromMetadata = $tool->getSchemaFromMetadata($meta); // テーブル削除 foreach ($schemaFromMetadata->getTables() as $table) { if ($schema->hasTable($table->getName())) { $schema->dropTable($table->getName()); } } // シーケンス削除 foreach ($schemaFromMetadata->getSequences() as $sequence) { if ($schema->hasSequence($sequence->getName())) { $schema->dropSequence($sequence->getName()); } } } else { // this down() migration is auto-generated, please modify it to your needs $schema->dropTable(self::NAME); $schema->dropSequence('plg_recommend_product_recommend_product_id_seq'); } }
public function testNullDefaultNotAddedToCustomSchemaOptions() { $em = $this->_getTestEntityManager(); $schemaTool = new SchemaTool($em); $classes = array($em->getClassMetadata('Doctrine\\Tests\\Models\\NullDefault\\NullDefaultColumn')); $customSchemaOptions = $schemaTool->getSchemaFromMetadata($classes)->getTable('NullDefaultColumn')->getColumn('nullDefault')->getCustomSchemaOptions(); $this->assertSame(array(), $customSchemaOptions); }
/** * {@inheritdoc} */ public function createSchema() { $metadata = $this->entityManager->getMetadataFactory()->getAllMetadata(); if (empty($metadata)) { throw new \UnexpectedValueException('No mapping information to process'); } $tool = new SchemaTool($this->entityManager); return $tool->getSchemaFromMetadata($metadata); }
/** * @group DDC-283 */ public function testPostGenerateEvents() { $listener = new GenerateSchemaEventListener(); $em = $this->_getTestEntityManager(); $em->getEventManager()->addEventListener(array(ToolEvents::postGenerateSchemaTable, ToolEvents::postGenerateSchema), $listener); $schemaTool = new SchemaTool($em); $classes = array($em->getClassMetadata('Doctrine\\Tests\\Models\\CMS\\CmsAddress'), $em->getClassMetadata('Doctrine\\Tests\\Models\\CMS\\CmsArticle'), $em->getClassMetadata('Doctrine\\Tests\\Models\\CMS\\CmsComment'), $em->getClassMetadata('Doctrine\\Tests\\Models\\CMS\\CmsEmployee'), $em->getClassMetadata('Doctrine\\Tests\\Models\\CMS\\CmsGroup'), $em->getClassMetadata('Doctrine\\Tests\\Models\\CMS\\CmsPhonenumber'), $em->getClassMetadata('Doctrine\\Tests\\Models\\CMS\\CmsUser')); $schema = $schemaTool->getSchemaFromMetadata($classes); $this->assertEquals(count($classes), $listener->tableCalls); $this->assertTrue($listener->schemaCalled); }
/** * Generate sql queries and create new migration class * * @param InputInterface $input * @param OutputInterface $output * * @return null * @throws \InvalidArgumentException */ public function execute(\Symfony\Component\Console\Input\InputInterface $input, \Symfony\Component\Console\Output\OutputInterface $output) { $isDbalOld = DbalVersion::compare('2.2.0') > 0; $configuration = $this->getMigrationConfiguration($input, $output); $em = $this->getHelper('em')->getEntityManager(); $conn = $em->getConnection(); $platform = $conn->getDatabasePlatform(); $metadata = $em->getMetadataFactory()->getAllMetadata(); if (empty($metadata)) { $output->writeln('No mapping information to process.', 'ERROR'); return; } if ($filterExpr = $input->getOption('filter-expression')) { if ($isDbalOld) { throw new \InvalidArgumentException('The "--filter-expression" option can only be used as of Doctrine DBAL 2.2'); } $conn->getConfiguration()->setFilterSchemaAssetsExpression($filterExpr); } $tool = new SchemaTool($em); $fromSchema = $conn->getSchemaManager()->createSchema(); $toSchema = $tool->getSchemaFromMetadata($metadata); foreach ($fromSchema->getTables() as $tableName => $table) { if (!$toSchema->hasTable($tableName)) { // if drop the table from the $fromSchema, could not generate the DROP TABLE sql $fromSchema->dropTable($tableName); } } //Not using value from options, because filters can be set from config.yml if (!$isDbalOld && ($filterExpr = $conn->getConfiguration()->getFilterSchemaAssetsExpression())) { $tableNames = $toSchema->getTableNames(); foreach ($tableNames as $tableName) { $tableName = substr($tableName, strpos($tableName, '.') + 1); if (!preg_match($filterExpr, $tableName)) { $toSchema->dropTable($tableName); } } } $up = $this->buildCodeFromSql($configuration, $fromSchema->getMigrateToSql($toSchema, $platform)); $down = $this->buildCodeFromSql($configuration, $fromSchema->getMigrateFromSql($toSchema, $platform)); if (!$up && !$down) { $output->writeln('No changes detected in your mapping information.', 'ERROR'); return; } $version = date('YmdHis'); $path = $this->generateMigration($configuration, $input, $version, $up, $down); $output->writeln(sprintf('Generated new migration class to "<info>%s</info>" from schema differences.', $path)); }
public function assertCreatedSchemaNeedsNoUpdates($classes) { $classMetadata = array(); foreach ($classes as $class) { $classMetadata[] = $this->_em->getClassMetadata($class); } $schemaTool = new Tools\SchemaTool($this->_em); $schemaTool->dropSchema($classMetadata); $schemaTool->createSchema($classMetadata); $sm = $this->_em->getConnection()->getSchemaManager(); $fromSchema = $sm->createSchema(); $toSchema = $schemaTool->getSchemaFromMetadata($classMetadata); $comparator = new \Doctrine\DBAL\Schema\Comparator(); $schemaDiff = $comparator->compare($fromSchema, $toSchema); $sql = $schemaDiff->toSql($this->_em->getConnection()->getDatabasePlatform()); $this->assertEquals(0, count($sql)); }
/** * Down method. * * @param Schema $schema */ public function down(Schema $schema) { if (Version::isSupportMethod()) { $app = Application::getInstance(); $meta = $this->getMetadata($app['orm.em']); $tool = new SchemaTool($app['orm.em']); $schemaFromMetadata = $tool->getSchemaFromMetadata($meta); // テーブル削除 foreach ($schemaFromMetadata->getTables() as $table) { if ($schema->hasTable($table->getName())) { $schema->dropTable($table->getName()); } } } else { if ($schema->hasTable(self::TABLE)) { $schema->dropTable(self::TABLE); } } }
/** * Generates table for entity DatabaseVersion. Does not check if this table already exists. * * @throws \Doctrine\DBAL\DBALException * @throws \Doctrine\ORM\ORMException * @throws \Exception */ private function generateDatabaseVersionTable() { $metadata = $this->entityManager->getMetadataFactory()->getAllMetadata(); $tool = new SchemaTool($this->entityManager); $schema = $tool->getSchemaFromMetadata($metadata); $versionTable = null; foreach ($schema->getTables() as $table) { if ($table->getShortestName($schema->getName()) == self::VERSION_TABLE) { $versionTable = $table; break; } } if ($versionTable) { $platform = $this->entityManager->getConnection()->getDatabasePlatform(); $sql = $platform->getCreateTableSQL($versionTable, AbstractPlatform::CREATE_INDEXES); $this->entityManager->getConnection()->executeQuery($sql[0]); } else { throw new \Exception('Error: Couldn\'t find database version entity definition.'); } }
/** * @group DDC-2138 */ public function testForeignKeyOnSTIWithMultipleMapping() { $em = $this->_em; $schemaTool = new SchemaTool($em); $classes = array($em->getClassMetadata(__NAMESPACE__ . '\\DDC2138User'), $em->getClassMetadata(__NAMESPACE__ . '\\DDC2138Structure'), $em->getClassMetadata(__NAMESPACE__ . '\\DDC2138UserFollowedObject'), $em->getClassMetadata(__NAMESPACE__ . '\\DDC2138UserFollowedStructure'), $em->getClassMetadata(__NAMESPACE__ . '\\DDC2138UserFollowedUser')); $schema = $schemaTool->getSchemaFromMetadata($classes); $this->assertTrue($schema->hasTable('users_followed_objects'), "Table users_followed_objects should exist."); /* @var $table \Doctrine\DBAL\Schema\Table */ $table = $schema->getTable('users_followed_objects'); $this->assertTrue($table->columnsAreIndexed(array('object_id'))); $this->assertTrue($table->columnsAreIndexed(array('user_id'))); $foreignKeys = $table->getForeignKeys(); $this->assertCount(1, $foreignKeys, 'user_id column has to have FK, but not object_id'); /* @var $fk \Doctrine\DBAL\Schema\ForeignKeyConstraint */ $fk = reset($foreignKeys); $this->assertEquals('users', $fk->getForeignTableName()); $localColumns = $fk->getLocalColumns(); $this->assertContains('user_id', $localColumns); $this->assertCount(1, $localColumns); }
/** * @param SchemaTool $tool * @param array $classes * @return array */ private function removeTablePrefix(SchemaTool $tool, array $classes) { $schema = $tool->getSchemaFromMetadata($classes); $tableNames = []; foreach ($schema->getTableNames() as $tableName) { $tableNames[] = array_pop(explode('.', $tableName)); } return $tableNames; }
/** * Performs the database installation * * @param array $dbParams * * @return array|boolean Array containing the flash message data on a failure, boolean true on success */ private function performDatabaseInstallation($dbParams) { $dbName = $dbParams['dbname']; $dbParams['dbname'] = null; $dbParams['charset'] = 'UTF8'; //suppress display of errors as we know its going to happen while testing the connection ini_set('display_errors', 0); //test credentials try { $db = DriverManager::getConnection($dbParams); $db->connect(); } catch (\Exception $exception) { $db->close(); return array('type' => 'error', 'msg' => 'mautic.installer.error.connecting.database', 'msgVars' => array('%exception%' => $exception->getMessage())); } //test database existence $dbParams['dbname'] = $dbName; $db = DriverManager::getConnection($dbParams); if ($db->isConnected()) { $db->close(); } try { //test credentials $db->connect(); $schemaManager = $db->getSchemaManager(); } catch (\Exception $exception) { $db->close(); //it failed to connect so remove the dbname and try to create it $dbParams['dbname'] = null; $db = DriverManager::getConnection($dbParams); $db->connect(); try { //database does not exist so try to create it $schemaManager = $db->getSchemaManager(); $schemaManager->createDatabase($dbName); //close the connection and reconnect with the new database name $db->close(); $dbParams['dbname'] = $dbName; $db = DriverManager::getConnection($dbParams); $schemaManager = $db->getSchemaManager(); } catch (\Exception $exception) { $db->close(); return array('type' => 'error', 'msg' => 'mautic.installer.error.creating.database', 'msgVars' => array('%name%' => $dbName)); } } try { //check to see if the table already exist $tables = $schemaManager->listTableNames(); } catch (\Exception $e) { $db->close(); return array('type' => 'error', 'msg' => 'mautic.installer.error.connecting.database', 'msgVars' => array('%exception%' => $e->getMessage())); } $sql = array(); $platform = $schemaManager->getDatabasePlatform(); $backupPrefix = !empty($dbParams['backup_prefix']) ? $dbParams['backup_prefix'] : 'bak_'; // Generate install schema $entityManager = $this->getEntityManager($dbParams); $metadatas = $entityManager->getMetadataFactory()->getAllMetadata(); $schemaTool = new SchemaTool($entityManager); $installSchema = $schemaTool->getSchemaFromMetadata($metadatas); $mauticTables = $applicableSequences = array(); foreach ($installSchema->getTables() as $m) { $tableName = $m->getName(); $mauticTables[$tableName] = $this->generateBackupName($dbParams['table_prefix'], $backupPrefix, $tableName); } //backup sequences for databases that support try { $allSequences = $schemaManager->listSequences(); } catch (\Exception $e) { $allSequences = array(); } // Collect list of sequences /** @var \Doctrine\DBAL\Schema\Sequence $sequence */ foreach ($allSequences as $sequence) { $name = $sequence->getName(); $tableName = str_replace('_id_seq', '', $name); if (isset($mauticTables[$tableName]) || in_array($tableName, $mauticTables)) { $applicableSequences[$tableName] = $sequence; } } unset($allSequences); if ($dbParams['backup_tables']) { //backup existing tables $backupRestraints = $backupSequences = $backupIndexes = $backupTables = $dropSequences = $dropTables = array(); //cycle through the first time to drop all the foreign keys foreach ($tables as $t) { if (!isset($mauticTables[$t]) && !in_array($t, $mauticTables)) { // Not an applicable table continue; } $restraints = $schemaManager->listTableForeignKeys($t); if (isset($mauticTables[$t])) { //to be backed up $backupRestraints[$mauticTables[$t]] = $restraints; $backupTables[$t] = $mauticTables[$t]; $backupIndexes[$t] = $schemaManager->listTableIndexes($t); if (isset($applicableSequences[$t])) { //backup the sequence $backupSequences[$t] = $applicableSequences[$t]; } } else { //existing backup to be dropped $dropTables[] = $t; if (isset($applicableSequences[$t])) { //drop the sequence $dropSequences[$t] = $applicableSequences[$t]; } } foreach ($restraints as $restraint) { $sql[] = $platform->getDropForeignKeySQL($restraint, $t); } } //now drop all the backup tables foreach ($dropTables as $t) { $sql[] = $platform->getDropTableSQL($t); if (isset($dropSequences[$t])) { $sql[] = $platform->getDropSequenceSQL($dropSequences[$t]); } } //now backup tables foreach ($backupTables as $t => $backup) { //drop old sequences if (isset($backupSequences[$t])) { $oldSequence = $backupSequences[$t]; $name = $oldSequence->getName(); $newName = $this->generateBackupName($dbParams['table_prefix'], $backupPrefix, $name); $newSequence = new Sequence($newName, $oldSequence->getAllocationSize(), $oldSequence->getInitialValue()); $sql[] = $platform->getDropSequenceSQL($oldSequence); } //drop old indexes /** @var \Doctrine\DBAL\Schema\Index $oldIndex */ foreach ($backupIndexes[$t] as $indexName => $oldIndex) { if ($indexName == 'primary') { continue; } $oldName = $oldIndex->getName(); $newName = $this->generateBackupName($dbParams['table_prefix'], $backupPrefix, $oldName); $newIndex = new Index($newName, $oldIndex->getColumns(), $oldIndex->isUnique(), $oldIndex->isPrimary(), $oldIndex->getFlags()); // Handle postgres primary key constraint if (strpos($oldName, '_pkey') !== false) { $newConstraint = $newIndex; $sql[] = $platform->getDropConstraintSQL($oldName, $t); } else { $newIndexes[] = $newIndex; $sql[] = $platform->getDropIndexSQL($oldIndex, $t); } } //rename table $tableDiff = new TableDiff($t); $tableDiff->newName = $backup; $queries = $platform->getAlterTableSQL($tableDiff); $sql = array_merge($sql, $queries); //create new index if (!empty($newIndexes)) { foreach ($newIndexes as $newIndex) { $sql[] = $platform->getCreateIndexSQL($newIndex, $backup); } unset($newIndexes); } //create new sequence if (!empty($newSequence)) { $sql[] = $platform->getCreateSequenceSQL($newSequence); unset($newSequence); } //create new constraint if (!empty($newConstraint)) { $sql[] = $platform->getCreateConstraintSQL($newConstraint, $backup); } } //apply foreign keys to backup tables foreach ($backupRestraints as $table => $oldRestraints) { foreach ($oldRestraints as $or) { $foreignTable = $or->getForeignTableName(); $foreignTableName = $this->generateBackupName($dbParams['table_prefix'], $backupPrefix, $foreignTable); $r = new ForeignKeyConstraint($or->getLocalColumns(), $foreignTableName, $or->getForeignColumns(), $backupPrefix . $or->getName(), $or->getOptions()); $sql[] = $platform->getCreateForeignKeySQL($r, $table); } } } else { //drop and create new sequences /** @var \Doctrine\DBAL\Schema\Sequence $sequence */ foreach ($applicableSequences as $sequence) { $sql[] = $platform->getDropSequenceSQL($sequence); } //drop tables foreach ($tables as $t) { if (isset($mauticTables[$t])) { //drop foreign keys first in order to be able to drop the tables $restraints = $schemaManager->listTableForeignKeys($t); foreach ($restraints as $restraint) { $sql[] = $platform->getDropForeignKeySQL($restraint, $t); } } } foreach ($tables as $t) { if (isset($mauticTables[$t])) { $sql[] = $platform->getDropTableSQL($t); } } } if (!empty($sql)) { foreach ($sql as $q) { try { $db->query($q); } catch (\Exception $e) { $db->close(); return array('type' => 'error', 'msg' => 'mautic.installer.error.installing.data', 'msgVars' => array('%exception%' => $e->getMessage())); } } } if (!empty($metadatas)) { $queries = $installSchema->toSql($platform); foreach ($queries as $q) { try { $db->query($q); } catch (\Exception $e) { $db->close(); return array('type' => 'error', 'msg' => 'mautic.installer.error.installing.data', 'msgVars' => array('%exception%' => $e->getMessage())); } } } else { $db->close(); return array('type' => 'error', 'msg' => 'mautic.installer.error.no.metadata'); } $db->close(); return true; }
/** * Generates SQL for installation. * * @param object $originalData * * @return array|bool Array containing the flash message data on a failure, boolean true on success */ public function installSchema() { $sm = $this->db->getSchemaManager(); try { //check to see if the table already exist $tables = $sm->listTableNames(); } catch (\Exception $e) { $this->db->close(); throw $e; } $this->platform = $sm->getDatabasePlatform(); $backupPrefix = !empty($this->dbParams['backup_prefix']) ? $this->dbParams['backup_prefix'] : 'bak_'; $metadatas = $this->em->getMetadataFactory()->getAllMetadata(); if (empty($metadatas)) { $this->db->close(); return false; } $schemaTool = new SchemaTool($this->em); $installSchema = $schemaTool->getSchemaFromMetadata($metadatas); $mauticTables = []; foreach ($installSchema->getTables() as $m) { $tableName = $m->getName(); $mauticTables[$tableName] = $this->generateBackupName($this->dbParams['table_prefix'], $backupPrefix, $tableName); } $sql = ['SET foreign_key_checks = 0;']; if ($this->dbParams['backup_tables']) { $sql = array_merge($sql, $this->backupExistingSchema($tables, $mauticTables, $backupPrefix)); } else { $sql = array_merge($sql, $this->dropExistingSchema($tables, $mauticTables)); } $sql = array_merge($sql, $installSchema->toSql($this->platform)); // Execute drop queries if (!empty($sql)) { foreach ($sql as $q) { try { $this->db->query($q); } catch (\Exception $exception) { $this->db->close(); throw $exception; } } } $this->db->close(); return true; }
/** * Update plugin schema based on Doctrine metadata. * * WARNING - this is not recommended as Doctrine does not guarantee results. There is a risk * that Doctrine will generate an incorrect query leading to lost data. If using this method, * be sure to thoroughly test the queries Doctrine generates * * @param array $metadata * @param Schema $installedSchema * @param MauticFactory $factory * * @throws \Doctrine\DBAL\ConnectionException * @throws \Exception */ public static function updatePluginSchema(array $metadata, Schema $installedSchema, MauticFactory $factory) { $db = $factory->getDatabase(); $schemaTool = new SchemaTool($factory->getEntityManager()); $toSchema = $schemaTool->getSchemaFromMetadata($metadata); $queries = $installedSchema->getMigrateToSql($toSchema, $db->getDatabasePlatform()); $db->beginTransaction(); try { foreach ($queries as $q) { $db->query($q); } $db->commit(); } catch (\Exception $e) { $db->rollback(); throw $e; } }
/** * Generates a new migration file and returns the path to it. * * If $diffAgainstCurrent is TRUE, it generates a migration file with the * diff between current DB structure and the found mapping metadata. * * Only include tables/sequences matching the $filterExpression regexp when * diffing models and existing schema. * * Otherwise an empty migration skeleton is generated. * * @param boolean $diffAgainstCurrent * @param string $filterExpression * @return string Path to the new file */ public function generateMigration($diffAgainstCurrent = true, $filterExpression = null) { $configuration = $this->getMigrationConfiguration(); $up = null; $down = null; if ($diffAgainstCurrent === true) { /** @var \Doctrine\DBAL\Connection $connection */ $connection = $this->entityManager->getConnection(); if ($filterExpression) { $connection->getConfiguration()->setFilterSchemaAssetsExpression($filterExpression); } $metadata = $this->entityManager->getMetadataFactory()->getAllMetadata(); if (empty($metadata)) { return ['No mapping information to process.', null]; } $tool = new SchemaTool($this->entityManager); $fromSchema = $connection->getSchemaManager()->createSchema(); $toSchema = $tool->getSchemaFromMetadata($metadata); if ($filterExpression) { foreach ($toSchema->getTables() as $table) { $tableName = $table->getName(); if (!preg_match($filterExpression, $this->resolveTableName($tableName))) { $toSchema->dropTable($tableName); } } foreach ($toSchema->getSequences() as $sequence) { $sequenceName = $sequence->getName(); if (!preg_match($filterExpression, $this->resolveTableName($sequenceName))) { $toSchema->dropSequence($sequenceName); } } } $platform = $connection->getDatabasePlatform(); $up = $this->buildCodeFromSql($configuration, $fromSchema->getMigrateToSql($toSchema, $platform)); $down = $this->buildCodeFromSql($configuration, $fromSchema->getMigrateFromSql($toSchema, $platform)); if (!$up && !$down) { return ['No changes detected in your mapping information.', null]; } } return ['Generated new migration class!', $this->writeMigrationClassToFile($configuration, $up, $down)]; }
/** * Helper function that uses Doctrine's SchemaTool to generate the difference between mapping and database both ways. Ignores table names specified in 'doctrine.ignore_tables' config setting * * @return array Associative array containing the 'up' and 'down' values */ protected static function getDiff() { $em = \D::manager(); $conn = $em->getConnection(); $platform = $conn->getDatabasePlatform(); $metadata = $em->getMetadataFactory()->getAllMetadata(); $result = array(); // Polyfill for some DB types... if (!$platform->hasDoctrineTypeMappingFor('enum')) { $platform->registerDoctrineTypeMapping('enum', 'string'); } if (empty($metadata)) { return array('error' => "\tNo mapping information to process."); } $tool = new SchemaTool($em); $fromSchema = $conn->getSchemaManager()->createSchema(); $toSchema = $tool->getSchemaFromMetadata($metadata); // Ignore tables... $ignored_tables = \Config::get('db.doctrine2.ignore_tables', array()); // Check if languages are enabled $languages = \Config::get('cmf.languages.enabled', false); // Construct an array of wildcard-checking lambda functions $wildcard_checks = array(); foreach ($ignored_tables as $num => $ignored_table) { if (($pos = strpos($ignored_table, '*')) !== false) { $search_str = str_replace('*', '', $ignored_table); if ($pos === 0) { // Check at the end of the string $wildcard_checks[] = function ($str) use($search_str) { return strpos($str, $search_str) === strlen($str) - strlen($search_str); }; } else { // Check at the beginning of the string $wildcard_checks[] = function ($str) use($search_str) { return strpos($str, $search_str) === 0; }; } unset($ignored_tables[$num]); } } // Go through all the table names and check for wildcard matches $table_names = array_merge($fromSchema->getTableNames(), $toSchema->getTableNames()); foreach ($table_names as $table_name) { // Remove the schema name from the table name $table_name = str_replace(array($fromSchema->getName() . ".", $toSchema->getName() . "."), '', $table_name); if (in_array($table_name, $ignored_tables)) { continue; } foreach ($wildcard_checks as $check) { if ($check($table_name) === true) { $ignored_tables[] = $table_name; break; } } } // Strip the ignored tables from the schemas foreach ($ignored_tables as $ignored_table) { if ($fromSchema->hasTable($ignored_table)) { $fromSchema->dropTable($ignored_table); } if ($toSchema->hasTable($ignored_table)) { $toSchema->dropTable($ignored_table); } } $up = static::buildCodeFromSql($fromSchema->getMigrateToSql($toSchema, $platform)); $down = static::buildCodeFromSql($fromSchema->getMigrateFromSql($toSchema, $platform)); // TODO: Create a more generic way of implementing data fixtures for each class if ($toSchema->hasTable('languages') && !$fromSchema->hasTable('languages')) { $up .= "\n\t\t// Creating the first language"; $up .= "\n\t\t\$lang = new \\CMF\\Model\\Language();"; $up .= "\n\t\t\$lang->set('code', \\Lang::get_lang());"; $up .= "\n\t\t\\D::manager()->persist(\$lang);"; $up .= "\n\t\t\\D::manager()->flush();"; } if (!$up && !$down) { return array('error' => "\tNo changes detected in your mapping information.\n"); } return array('up' => $up, 'down' => $down); }
/** * @test */ public function doctrineEmbeddablesAreActuallyEmbedded() { /* @var $entityManager ObjectManager */ $entityManager = $this->objectManager->get(ObjectManager::class); $schemaTool = new SchemaTool($entityManager); $metaData = $entityManager->getClassMetadata(Fixtures\TestEntity::class); $this->assertTrue($metaData->hasField('embedded.value'), 'ClassMetadata does not contain embedded value'); $schema = $schemaTool->getSchemaFromMetadata(array($metaData)); $this->assertTrue($schema->getTable('persistence_testentity')->hasColumn('embedded_value'), 'Database schema does not contain embedded value field'); $embeddable = new Fixtures\TestEmbeddable('someValue'); $testEntity = new Fixtures\TestEntity(); $testEntity->setEmbedded($embeddable); $this->testEntityRepository->add($testEntity); $this->persistenceManager->persistAll(); $this->persistenceManager->clearState(); /* @var $testEntity Fixtures\TestEntity */ $testEntity = $this->testEntityRepository->findAll()->getFirst(); $this->assertEquals('someValue', $testEntity->getEmbedded()->getValue()); }
/** * @test */ public function oneToOneRelationsAreMappedCorrectly() { $classMetadata = new ClassMetadata(Fixtures\OneToOneEntity::class); $driver = $this->objectManager->get(FlowAnnotationDriver::class); $driver->loadMetadataForClass(Fixtures\OneToOneEntity::class, $classMetadata); $selfReferencingMapping = $classMetadata->getAssociationMapping('selfReferencing'); $this->assertNotEmpty($selfReferencingMapping['joinColumns']); $this->assertTrue($selfReferencingMapping['isOwningSide']); $bidirectionalMapping = $classMetadata->getAssociationMapping('bidirectionalRelation'); $this->assertNotEmpty($bidirectionalMapping['joinColumns']); $this->assertEquals('bidirectionalRelation', $bidirectionalMapping['inversedBy']); $this->assertTrue($bidirectionalMapping['isOwningSide']); $classMetadata2 = new ClassMetadata(Fixtures\OneToOneEntity2::class); $driver->loadMetadataForClass(Fixtures\OneToOneEntity2::class, $classMetadata2); $bidirectionalMapping2 = $classMetadata2->getAssociationMapping('bidirectionalRelation'); $this->assertFalse(isset($bidirectionalMapping2['joinColumns'])); $this->assertEquals('bidirectionalRelation', $bidirectionalMapping2['mappedBy']); $this->assertFalse($bidirectionalMapping2['isOwningSide']); $unidirectionalMapping = $classMetadata->getAssociationMapping('unidirectionalRelation'); $this->assertNotEmpty($unidirectionalMapping['joinColumns']); $this->assertTrue($unidirectionalMapping['isOwningSide']); /* @var $entityManager \Doctrine\Common\Persistence\ObjectManager */ $entityManager = $this->objectManager->get(\Doctrine\Common\Persistence\ObjectManager::class); $schemaTool = new SchemaTool($entityManager); $schema = $schemaTool->getSchemaFromMetadata([$entityManager->getClassMetadata(Fixtures\OneToOneEntity2::class)]); /* @var $foreignKey \Doctrine\DBAL\Schema\ForeignKeyConstraint */ foreach ($schema->getTable('persistence_onetooneentity2')->getForeignKeys() as $foreignKey) { if ($foreignKey->getForeignTableName() === 'persistence_onetooneentity') { $this->assertTrue(false); } } }