public function testValidateReturnsFalseWhenTwoTablesHaveSamePhpName()
 {
     $table1 = new Table('foo');
     $table2 = new Table('bar');
     $table2->setPhpName('Foo');
     $database = new Database();
     $database->addTable($table1);
     $database->addTable($table2);
     $appData = new AppData();
     $appData->addDatabase($database);
     $validator = new PropelSchemaValidator($appData);
     $this->assertFalse($validator->validate());
     $this->assertContains('Table "bar" declares a phpName already used in another table', $validator->getErrors());
 }
Example #2
0
 /**
  * 
  * @param string $module
  * @param string $action
  */
 public static function update($module, $action = 'create')
 {
     $targetDbName = 'centreon';
     ini_set('memory_limit', '-1');
     $di = Di::getDefault();
     $config = $di->get('config');
     $targetDb = 'db_centreon';
     $db = $di->get($targetDb);
     // Configuration for Propel
     $configParams = array('propel.project' => 'centreon', 'propel.database' => 'mysql', 'propel.database.url' => $config->get($targetDb, 'dsn'), 'propel.database.user' => $config->get($targetDb, 'username'), 'propel.database.password' => $config->get($targetDb, 'password'));
     // Set the Current Platform and DB Connection
     $platform = new CentreonMysqlPlatform($db);
     // Initilize Schema Parser
     $propelDb = new \MysqlSchemaParser($db);
     $propelDb->setGeneratorConfig(new \GeneratorConfig($configParams));
     $propelDb->setPlatform($platform);
     // get Current Db State
     $currentDbAppData = new \AppData($platform);
     $currentDbAppData->setGeneratorConfig(new \GeneratorConfig($configParams));
     $currentDb = $currentDbAppData->addDatabase(array('name' => $targetDbName));
     $propelDb->parse($currentDb);
     // Retreive target DB State
     $updatedAppData = new \AppData($platform);
     self::getDbFromXml($updatedAppData, 'centreon');
     // Get diff between current db state and target db state
     $diff = \PropelDatabaseComparator::computeDiff($currentDb, $updatedAppData->getDatabase('centreon'), false);
     if ($diff !== false) {
         $strDiff = $platform->getModifyDatabaseDDL($diff);
         $sqlToBeExecuted = \PropelSQLParser::parseString($strDiff);
         $finalSql = "\nSET FOREIGN_KEY_CHECKS = 0;\n\n";
         if ($action == 'create') {
             $finalSql .= implode(";\n\n", static::keepCreateStatement($sqlToBeExecuted, $module));
         } elseif ($action == 'delete') {
             $finalSql .= implode(";\n\n", static::keepDeleteStatement($sqlToBeExecuted, $module));
         }
         $finalSql .= ";\n\nSET FOREIGN_KEY_CHECKS = 1;\n\n";
         \PropelSQLParser::executeString($finalSql, $db);
     }
     // Empty Target DB
     self::deleteTargetDbSchema($targetDbName);
 }
 public function testValidateReturnsTrueWhenTwoTablesHaveSamePhpNameInDifferentNamespaces()
 {
     $column1 = new Column('id');
     $column1->setPrimaryKey(true);
     $table1 = new Table('foo');
     $table1->addColumn($column1);
     $table1->setNamespace('Foo');
     $column2 = new Column('id');
     $column2->setPrimaryKey(true);
     $table2 = new Table('bar');
     $table2->addColumn($column2);
     $table2->setPhpName('Foo');
     $table2->setNamespace('Bar');
     $database = new Database();
     $database->addTable($table1);
     $database->addTable($table2);
     $appData = new AppData();
     $appData->addDatabase($database);
     $validator = new PropelSchemaValidator($appData);
     $this->assertTrue($validator->validate());
 }
Example #4
0
 /**
  * Packages the datamodels to one datamodel per package
  *
  * This applies only when the the packageObjectModel option is set. We need to
  * re-package the datamodels to allow the database package attribute to control
  * which tables go into which SQL file.
  *
  * @return array The packaged datamodels
  */
 protected function packageDataModels()
 {
     static $packagedDataModels;
     if (is_null($packagedDataModels)) {
         $dataModels = $this->getDataModels();
         $dataModel = array_shift($dataModels);
         $packagedDataModels = array();
         $platform = $this->getPlatformForTargetDatabase();
         foreach ($dataModel->getDatabases() as $db) {
             foreach ($db->getTables() as $table) {
                 $package = $table->getPackage();
                 if (!isset($packagedDataModels[$package])) {
                     $dbClone = $this->cloneDatabase($db);
                     $dbClone->setPackage($package);
                     $ad = new AppData($platform);
                     $ad->setName($dataModel->getName());
                     $ad->addDatabase($dbClone);
                     $packagedDataModels[$package] = $ad;
                 }
                 $packagedDataModels[$package]->getDatabase($db->getName())->addTable($table);
             }
         }
     }
     return $packagedDataModels;
 }
Example #5
0
 /**
  * Main method builds all the targets for a typical propel project.
  */
 public function main()
 {
     // check to make sure task received all correct params
     $this->validate();
     $generatorConfig = $this->getGeneratorConfig();
     // loading model from database
     $this->log('Reading databases structure...');
     $connections = $generatorConfig->getBuildConnections();
     if (!$connections) {
         throw new Exception('You must define database connection settings in a buildtime-conf.xml file to use diff');
     }
     $totalNbTables = 0;
     $ad = new AppData();
     foreach ($connections as $name => $params) {
         $this->log(sprintf('Connecting to database "%s" using DSN "%s"', $name, $params['dsn']), Project::MSG_VERBOSE);
         $pdo = $generatorConfig->getBuildPDO($name);
         $database = new Database($name);
         $platform = $generatorConfig->getConfiguredPlatform($pdo);
         $database->setPlatform($platform);
         $database->setDefaultIdMethod(IDMethod::NATIVE);
         $parser = $generatorConfig->getConfiguredSchemaParser($pdo);
         $nbTables = $parser->parse($database, $this);
         $ad->addDatabase($database);
         $totalNbTables += $nbTables;
         $this->log(sprintf('%d tables imported from database "%s"', $nbTables, $name), Project::MSG_VERBOSE);
     }
     if ($totalNbTables) {
         $this->log(sprintf('%d tables imported from databases.', $totalNbTables));
     } else {
         $this->log('Database is empty');
     }
     // loading model from XML
     $this->packageObjectModel = true;
     $appDatasFromXml = $this->getDataModels();
     $appDataFromXml = array_pop($appDatasFromXml);
     // comparing models
     $this->log('Comparing models...');
     $manager = new PropelMigrationManager();
     $manager->setConnections($connections);
     $manager->setMigrationDir($this->getOutputDirectory());
     $migrationsUp = array();
     $migrationsDown = array();
     foreach ($ad->getDatabases() as $database) {
         $name = $database->getName();
         $this->log(sprintf('Comparing database "%s"', $name), Project::MSG_VERBOSE);
         if (!$appDataFromXml->hasDatabase($name)) {
             // FIXME: tables present in database but not in XML
             continue;
         }
         $databaseDiff = PropelDatabaseComparator::computeDiff($database, $appDataFromXml->getDatabase($name), $this->isCaseInsensitive());
         if (!$databaseDiff) {
             $this->log(sprintf('Same XML and database structures for datasource "%s" - no diff to generate', $name), Project::MSG_VERBOSE);
             continue;
         }
         $this->log(sprintf('Structure of database was modified in datasource "%s": %s', $name, $databaseDiff->getDescription()));
         $platform = $generatorConfig->getConfiguredPlatform(null, $name);
         $migrationsUp[$name] = $platform->getModifyDatabaseDDL($databaseDiff);
         $migrationsDown[$name] = $platform->getModifyDatabaseDDL($databaseDiff->getReverseDiff());
     }
     if (!$migrationsUp) {
         $this->log('Same XML and database structures for all datasource - no diff to generate');
         return;
     }
     $timestamp = time();
     $migrationFileName = $manager->getMigrationFileName($timestamp);
     $migrationClassBody = $manager->getMigrationClassBody($migrationsUp, $migrationsDown, $timestamp);
     $_f = new PhingFile($this->getOutputDirectory(), $migrationFileName);
     file_put_contents($_f->getAbsolutePath(), $migrationClassBody);
     $this->log(sprintf('"%s" file successfully created in %s', $_f->getName(), $_f->getParent()));
     if ($editorCmd = $this->getEditorCmd()) {
         $this->log(sprintf('Using "%s" as text editor', $editorCmd));
         shell_exec($editorCmd . ' ' . escapeshellarg($_f->getAbsolutePath()));
     } else {
         $this->log('  Please review the generated SQL statements, and add data migration code if necessary.');
         $this->log('  Once the migration class is valid, call the "migrate" task to execute it.');
     }
 }
 /**
  * @see sfTask
  */
 protected function execute($arguments = array(), $options = array())
 {
     $databaseManager = new sfDatabaseManager($this->configuration);
     $connections = $this->getConnections($databaseManager);
     //$connection = $databaseManager->getDatabase($options['connection'] ? $options['connection'] : null)->getConnection();
     $i = new afsDbInfo();
     $this->logSection('propel', 'Reading databases structure...');
     $ad = new AppData();
     $totalNbTables = 0;
     foreach ($connections as $name => $params) {
         $pdo = $databaseManager->getDatabase($name)->getConnection();
         $database = new Database($name);
         $platform = $this->getPlatform($databaseManager, $name);
         $database->setPlatform($platform);
         $database->setDefaultIdMethod(IDMethod::NATIVE);
         $parser = $this->getParser($databaseManager, $name, $pdo);
         //$parser->setMigrationTable($options['migration-table']);
         $parser->setPlatform($platform);
         $nbTables = $parser->parse($database);
         $ad->addDatabase($database);
         $totalNbTables += $nbTables;
         $this->logSection('propel', sprintf('  %d tables imported from database "%s"', $nbTables, $name), null, 'COMMENT');
     }
     if ($totalNbTables) {
         $this->logSection('propel', sprintf('%d tables imported from databases.', $totalNbTables));
     } else {
         $this->logSection('propel', 'Database is empty');
     }
     $this->logSection('propel', 'Loading XML schema files...');
     Phing::startup();
     // required to locate behavior classes...
     $this->schemaToXML(self::DO_NOT_CHECK_SCHEMA, 'generated-');
     $this->copyXmlSchemaFromPlugins('generated-');
     $appData = $this->getModels($databaseManager, true);
     $this->logSection('propel', sprintf('%d tables defined in the schema files.', $appData->countTables()));
     $this->cleanup(true);
     $this->logSection('sql-diff', 'Comparing databases and schemas...');
     $manager = new PropelMigrationManager();
     $manager->setConnections($connections);
     foreach ($ad->getDatabases() as $database) {
         $name = $database->getName();
         $filenameDiff = sfConfig::get('sf_data_dir') . "/sql/{$name}." . time() . ".diff.sql";
         $this->logSection('sql-diff', sprintf('  Comparing database "%s"', $name), null, 'COMMENT');
         if (!$appData->hasDatabase($name)) {
             // FIXME: tables present in database but not in XML
             continue;
         }
         $databaseDiff = PropelDatabaseComparator::computeDiff($database, $appData->getDatabase($name));
         if (!$databaseDiff) {
             //no diff
         }
         $this->logSection('sql-diff', sprintf('Structure of database was modified in datasource "%s": %s', $name, $databaseDiff->getDescription()));
         $platform = $this->getPlatform($databaseManager, $name);
         //up sql
         $upDiff = $platform->getModifyDatabaseDDL($databaseDiff);
         //down sql
         $downDiff = $platform->getModifyDatabaseDDL($databaseDiff->getReverseDiff());
         if ($databaseDiff) {
             $this->logSection('sql-diff', "Writing file {$filenameDiff}");
             afStudioUtil::writeFile($filenameDiff, $upDiff);
             if ($options['insert'] === true || $options['insert'] === 'true') {
                 $this->logSection('sql-diff', "Inserting sql diff");
                 $i->executeSql($upDiff, Propel::getConnection($name));
             }
             if ($options['build'] === true || $options['build'] === 'true') {
                 $this->logSection('sql-diff', 'Creating models from current schema');
                 $this->createTask('propel:build-model')->run();
                 $this->logSection('sql-diff', 'Creating forms from current schema');
                 $this->createTask('propel:build-forms')->run();
                 $this->logSection('sql-diff', 'Setting AppFlower project permissions');
                 $this->createTask('afs:fix-perms')->run();
                 $this->logSection('sql-diff', 'Creating AppFlower validator cache');
                 $this->createTask('appflower:validator-cache')->run(array('frontend', 'cache', 'yes'));
                 $this->logSection('sql-diff', 'Clearing Symfony cache');
                 $this->createTask('cc')->run();
             }
         }
     }
 }
 /** Sets up the Propel model. */
 public function setUp()
 {
     $appData = new AppData(new MysqlPlatform());
     $this->database = new Database();
     $appData->addDatabase($this->database);
 }
 /**
  * @see sfTask
  */
 protected function execute($arguments = array(), $options = array())
 {
     $databaseManager = new sfDatabaseManager($this->configuration);
     $connections = $this->getConnections($databaseManager);
     $this->logSection('propel', 'Reading databases structure...');
     $ad = new AppData();
     $totalNbTables = 0;
     foreach ($connections as $name => $params) {
         if ($options['verbose']) {
             $this->logSection('propel', sprintf('  Connecting to database "%s" using DSN "%s"', $name, $params['dsn']), null, 'COMMENT');
         }
         $pdo = $databaseManager->getDatabase($name)->getConnection();
         $database = new Database($name);
         $platform = $this->getPlatform($databaseManager, $name);
         $database->setPlatform($platform);
         $database->setDefaultIdMethod(IDMethod::NATIVE);
         $parser = $this->getParser($databaseManager, $name, $pdo);
         $parser->setMigrationTable($options['migration-table']);
         $parser->setPlatform($platform);
         $nbTables = $parser->parse($database);
         $ad->addDatabase($database);
         $totalNbTables += $nbTables;
         if ($options['verbose']) {
             $this->logSection('propel', sprintf('  %d tables imported from database "%s"', $nbTables, $name), null, 'COMMENT');
         }
     }
     if ($totalNbTables) {
         $this->logSection('propel', sprintf('%d tables imported from databases.', $totalNbTables));
     } else {
         $this->logSection('propel', 'Database is empty');
     }
     $this->logSection('propel', 'Loading XML schema files...');
     Phing::startup();
     // required to locate behavior classes...
     $this->schemaToXML(self::DO_NOT_CHECK_SCHEMA, 'generated-');
     $this->copyXmlSchemaFromPlugins('generated-');
     $appData = $this->getModels($databaseManager, $options['verbose']);
     $this->logSection('propel', sprintf('%d tables defined in the schema files.', $appData->countTables()));
     $this->cleanup($options['verbose']);
     $this->logSection('propel', 'Comparing databases and schemas...');
     $manager = new PropelMigrationManager();
     $manager->setConnections($connections);
     $migrationsUp = array();
     $migrationsDown = array();
     foreach ($ad->getDatabases() as $database) {
         $name = $database->getName();
         if ($options['verbose']) {
             $this->logSection('propel', sprintf('  Comparing database "%s"', $name), null, 'COMMENT');
         }
         if (!$appData->hasDatabase($name)) {
             // FIXME: tables present in database but not in XML
             continue;
         }
         $databaseDiff = PropelDatabaseComparator::computeDiff($database, $appData->getDatabase($name));
         if (!$databaseDiff) {
             if ($options['verbose']) {
                 $this->logSection('propel', sprintf('  Same XML and database structures for datasource "%s" - no diff to generate', $name), null, 'COMMENT');
             }
             continue;
         }
         $this->logSection('propel', sprintf('Structure of database was modified in datasource "%s": %s', $name, $databaseDiff->getDescription()));
         if ($options['verbose']) {
             $this->logBlock($databaseDiff, 'COMMENT');
         }
         $platform = $this->getPlatform($databaseManager, $name);
         $migrationsUp[$name] = $platform->getModifyDatabaseDDL($databaseDiff);
         $migrationsDown[$name] = $platform->getModifyDatabaseDDL($databaseDiff->getReverseDiff());
     }
     if (!$migrationsUp) {
         $this->logSection('propel', 'Same XML and database structures for all datasources - no diff to generate');
         return;
     }
     $timestamp = time();
     $migrationDirectory = sfConfig::get('sf_root_dir') . DIRECTORY_SEPARATOR . $options['migration-dir'];
     $migrationFileName = $manager->getMigrationFileName($timestamp);
     $migrationFilePath = $migrationDirectory . DIRECTORY_SEPARATOR . $migrationFileName;
     if ($options['ask-confirmation'] && !$this->askConfirmation(array(sprintf('Migration class will be generated in %s', $migrationFilePath), 'Are you sure you want to proceed? (Y/n)'), 'QUESTION_LARGE', true)) {
         $this->logSection('propel', 'Task aborted.');
         return 1;
     }
     $this->getFilesystem()->mkdirs($migrationDirectory);
     $migrationClassBody = $manager->getMigrationClassBody($migrationsUp, $migrationsDown, $timestamp);
     file_put_contents($migrationFilePath, $migrationClassBody);
     $this->logSection('propel', sprintf('"%s" file successfully created in %s', $migrationFileName, $migrationDirectory));
     if ($editorCmd = $options['editor-cmd']) {
         $this->logSection('propel', sprintf('Using "%s" as text editor', $editorCmd));
         shell_exec($editorCmd . ' ' . escapeshellarg($migrationFilePath));
     } else {
         $this->logSection('propel', '  Please review the generated SQL statements, and add data migration code if necessary.');
         $this->logSection('propel', '  Once the migration class is valid, call the "propel:migrate" task to execute it.');
     }
 }
    public function testValidateReturnsFalseWhenCrossRefTableHasTwoFksToTheSameTable()
    {
        $schema = <<<EOF
<database name="bookstore">
    <table name="book">
        <column name="id" required="true" primaryKey="true" autoIncrement="true" type="INTEGER" />
        <column name="title" type="VARCHAR" size="100" primaryString="true" />
    </table>
    <table name="book_book" isCrossRef="true">
        <column name="parent_id" type="INTEGER" primaryKey="true" required="true"/>
        <column name="child_id" type="INTEGER" primaryKey="true" required="true"/>
        <foreign-key foreignTable="book">
            <reference local="child_id" foreign="id"/>
        </foreign-key>
        <foreign-key foreignTable="book">
            <reference local="parent_id" foreign="id"/>
        </foreign-key>
    </table>
</database>
EOF;
        $builder = new PropelQuickBuilder();
        $builder->setSchema($schema);
        $database = $builder->getDatabase();
        $appData = new AppData();
        $appData->addDatabase($database);
        $validator = new PropelSchemaValidator($appData);
        $this->assertFalse($validator->validate());
        $this->assertContains('Table "book_book" implements an equal nest relationship for table "book". This feature is not supported', $validator->getErrors());
    }
Example #10
0
 protected static function initializeCurrentSchema($platform)
 {
     $configParams = array('propel.project' => 'centreon', 'propel.database' => 'mysql', 'propel.database.driver' => 'mysql', 'propel.database.createUrl' => 'mysql://root@localhost/', 'propel.database.url' => 'mysql:dbname=centreon;host=localhost', 'propel.database.user' => 'root', 'propel.database.password' => '', 'propel.database.encoding' => 'utf-8');
     // Initilize Schema Parser
     $db = Di::getDefault()->get('db_centreon');
     $propelDb = new \MysqlSchemaParser($db);
     $propelDb->setGeneratorConfig(new \GeneratorConfig($configParams));
     $propelDb->setPlatform($platform);
     // get Current Db State
     $currentDbAppData = new \AppData($platform);
     $currentDbAppData->setGeneratorConfig(new \GeneratorConfig($configParams));
     $currentDb = $currentDbAppData->addDatabase(array('name' => 'centreon'));
     $propelDb->parse($currentDb);
     return $currentDb;
 }