/**
  * Provided an array of modelClassNames database schema generation is performed using each model's metadata.
  * @param array $modelClassNames
  * @param $messageLogger
  */
 public static function generateTablesFromModelClassNames(array $modelClassNames, &$messageLogger)
 {
     $tables = array();
     if (empty($modelClassNames)) {
         return;
     }
     $messageLogger->addInfoMessage(Zurmo::t('Core', 'Building Table Schema for {{count}} Models', array('{{count}}' => count($modelClassNames))));
     foreach ($modelClassNames as $modelClassName) {
         $table = RedBeanModelToTableSchemaAdapter::resolve($modelClassName, $messageLogger);
         if ($table) {
             $tables[] = $table;
         }
     }
     foreach ($tables as $schemaDefinition) {
         $tableName = key($schemaDefinition);
         $polymorphicColumns = RedBeanModelRelationToColumnAdapter::resolvePolymorphicColumnsByTableName($tableName);
         if (!empty($polymorphicColumns)) {
             $columns = CMap::mergeArray($schemaDefinition[$tableName]['columns'], $polymorphicColumns);
             $schemaDefinition[$tableName]['columns'] = $columns;
         }
         CreateOrUpdateExistingTableFromSchemaDefinitionArrayUtil::generateOrUpdateTableBySchemaDefinition($schemaDefinition, $messageLogger);
         $messageLogger->addInfoMessage(Zurmo::t('Core', 'Scheme generated for {{table}}.', array('{{table}}' => $tableName)));
     }
     $messageLogger->addInfoMessage(Zurmo::t('Core', 'Schema generation completed'));
 }
 /**
  * Adds externalSystemId column to specific table if it does not exist
  * @param $tableName
  * @param $maxLength
  * @param $columnName
  */
 public static function addExternalIdColumnIfMissing($tableName, $maxLength = 255, $columnName = null)
 {
     if (!isset($columnName)) {
         $columnName = static::EXTERNAL_SYSTEM_ID_COLUMN_NAME;
     }
     // check if external_system_id exists in fields
     $columnExists = ZurmoRedBean::$writer->doesColumnExist($tableName, $columnName);
     if (!$columnExists) {
         // if not, update model and add an external_system_id field
         $type = 'string';
         $length = null;
         RedBeanModelMemberRulesToColumnAdapter::resolveStringTypeAndLengthByMaxLength($type, $length, $maxLength);
         $columns = array();
         $columns[] = RedBeanModelMemberToColumnUtil::resolveColumnMetadataByHintType($columnName, $type, $length);
         $schema = CreateOrUpdateExistingTableFromSchemaDefinitionArrayUtil::getTableSchema($tableName, $columns);
         CreateOrUpdateExistingTableFromSchemaDefinitionArrayUtil::generateOrUpdateTableBySchemaDefinition($schema, new MessageLogger());
     }
 }
 /**
  * Generates junction table for a MANY_MANY relationship
  * @param string $modelClassName
  * @param array $relationMetadata
  * @param $messageLogger
  */
 public static function resolve($modelClassName, array $relationMetadata, &$messageLogger)
 {
     if (empty($modelClassName) || !@class_exists($modelClassName) || empty($relationMetadata) || count($relationMetadata) < 2 || $relationMetadata[0] != RedBeanModel::MANY_MANY || !@class_exists($relationMetadata[1])) {
         return;
     }
     $relatedModelClassName = $relationMetadata[1];
     $relationLinkName = null;
     if (isset($relationMetadata[4])) {
         $relationLinkName = $relationMetadata[4];
     }
     $tableName = RedBeanManyToManyRelatedModels::getTableNameByModelClassNames($modelClassName, $relatedModelClassName, $relationLinkName);
     if (ProcessedTableCache::isProcessed($tableName, static::CACHE_KEY)) {
         return;
     }
     $columns = array();
     $columns[] = RedBeanModelMemberToColumnUtil::resolveForeignKeyColumnMetadata(null, $modelClassName);
     $columns[] = RedBeanModelMemberToColumnUtil::resolveForeignKeyColumnMetadata(null, $relatedModelClassName);
     $indexes = static::resolveIndexesByColumnNames($columns);
     $schemaDefinition = array($tableName => array('columns' => $columns, 'indexes' => $indexes));
     CreateOrUpdateExistingTableFromSchemaDefinitionArrayUtil::generateOrUpdateTableBySchemaDefinition($schemaDefinition, $messageLogger);
     ProcessedTableCache::setAsProcessed($tableName, static::CACHE_KEY);
 }
 /**
  * @depends testGenerateTablesFromModelClassNamesForModelClassWithNoOwnMetadataAndCannotHaveBean
  */
 public function testGenerateTablesFromModelClassNamesForModelClassWithNoOwnMetadataAndCanHaveBean()
 {
     $modelClassName = array('OwnedSecurableItem');
     RedBeanModelsToTablesAdapter::generateTablesFromModelClassNames($modelClassName, static::$messageLogger);
     $processedTables = CreateOrUpdateExistingTableFromSchemaDefinitionArrayUtil::resolveProcessedTables();
     $this->assertNotEmpty($processedTables);
     $this->assertCount(1, $processedTables);
     $this->assertEquals('ownedsecurableitem', $processedTables[0]);
     // trying again to ensure its only done once, not twice.
     $modelClassName = array('OwnedSecurableItem');
     RedBeanModelsToTablesAdapter::generateTablesFromModelClassNames($modelClassName, static::$messageLogger);
     $processedTables = CreateOrUpdateExistingTableFromSchemaDefinitionArrayUtil::resolveProcessedTables();
     $this->assertNotEmpty($processedTables);
     $this->assertCount(1, $processedTables);
     $this->assertEquals('ownedsecurableitem', $processedTables[0]);
 }
 /**
  * Build modelcreationapisync table
  */
 public static function buildTable()
 {
     $schema = static::getTableSchema();
     CreateOrUpdateExistingTableFromSchemaDefinitionArrayUtil::generateOrUpdateTableBySchemaDefinition($schema, new MessageLogger());
 }
 /**
  * @depends testGenerateOrUpdateTableBySchemaDefinitionWithValidButChangedSchemaForExistingTableWithNoIsFreshInstall
  */
 public function testGenerateOrUpdateTableBySchemaDefinitionChangingColumnLength()
 {
     // try decreasing length, shouldn't work
     $schema = array('tablename3' => array('columns' => array(array('name' => 'language', 'type' => 'VARCHAR(10)', 'unsigned' => null, 'notNull' => 'NULL', 'collation' => 'COLLATE utf8_unicode_ci', 'default' => 'DEFAULT NULL'), array('name' => 'role_id', 'type' => 'INT(5)', 'unsigned' => 'UNSIGNED', 'notNull' => 'NULL', 'collation' => null, 'default' => 'DEFAULT NULL')), 'indexes' => array()));
     CreateOrUpdateExistingTableFromSchemaDefinitionArrayUtil::generateOrUpdateTableBySchemaDefinition($schema, static::$messageLogger);
     $processedTables = CreateOrUpdateExistingTableFromSchemaDefinitionArrayUtil::resolveProcessedTables();
     $this->assertNotEmpty($processedTables);
     $this->assertCount(3, $processedTables);
     $this->assertEquals('tablewithnocolumns', $processedTables[0]);
     $this->assertEquals('tablename1', $processedTables[1]);
     $this->assertEquals('tablename3', $processedTables[2]);
     // we do not need try-catch here as if there was an exception it would have been thrown already.
     $existingFields = ZurmoRedBean::$writer->getColumnsWithDetails('tablename3');
     $this->assertNotEmpty($existingFields);
     $this->assertCount(15, $existingFields);
     $this->assertArrayHasKey('language', $existingFields);
     $this->assertArrayHasKey('role_id', $existingFields);
     $this->assertEquals('int(11) unsigned', $existingFields['role_id']['Type']);
     $this->assertEquals('varchar(100)', $existingFields['language']['Type']);
     // try increasing lengths, should work
     $schema = array('tablename3' => array('columns' => array(array('name' => 'language', 'type' => 'VARCHAR(120)', 'unsigned' => null, 'notNull' => 'NULL', 'collation' => 'COLLATE utf8_unicode_ci', 'default' => 'DEFAULT NULL'), array('name' => 'role_id', 'type' => 'INT(15)', 'unsigned' => 'UNSIGNED', 'notNull' => 'NULL', 'collation' => null, 'default' => 'DEFAULT NULL')), 'indexes' => array()));
     CreateOrUpdateExistingTableFromSchemaDefinitionArrayUtil::generateOrUpdateTableBySchemaDefinition($schema, static::$messageLogger);
     $processedTables = CreateOrUpdateExistingTableFromSchemaDefinitionArrayUtil::resolveProcessedTables();
     $this->assertNotEmpty($processedTables);
     $this->assertCount(3, $processedTables);
     $this->assertEquals('tablewithnocolumns', $processedTables[0]);
     $this->assertEquals('tablename1', $processedTables[1]);
     $this->assertEquals('tablename3', $processedTables[2]);
     // we do not need try-catch here as if there was an exception it would have been thrown already.
     $existingFields = ZurmoRedBean::$writer->getColumnsWithDetails('tablename3');
     $this->assertNotEmpty($existingFields);
     $this->assertCount(15, $existingFields);
     $this->assertArrayHasKey('language', $existingFields);
     $this->assertArrayHasKey('role_id', $existingFields);
     $this->assertEquals('int(15) unsigned', $existingFields['role_id']['Type']);
     $this->assertEquals('varchar(120)', $existingFields['language']['Type']);
 }
 public static function recreateAccountBuildTable()
 {
     $schema = static::getReadSubscriptionTableSchemaForAccountTempTable();
     CreateOrUpdateExistingTableFromSchemaDefinitionArrayUtil::generateOrUpdateTableBySchemaDefinition($schema, new MessageLogger());
 }
 /**
  * Public for testing only. Need to manually create test model tables that would not be picked up normally.
  */
 public static function recreateTable($mungeTableName)
 {
     assert('is_string($mungeTableName) && $mungeTableName  != ""');
     ZurmoRedBean::$writer->dropTableByTableName($mungeTableName);
     $schema = static::getMungeTableSchemaByName($mungeTableName);
     CreateOrUpdateExistingTableFromSchemaDefinitionArrayUtil::generateOrUpdateTableBySchemaDefinition($schema, new MessageLogger());
 }
 /**
  * Creates table in db give table name and import columns
  * Public due to import/DemoController
  * @param $tableName
  * @param $columns
  */
 public static function createTableByTableNameAndImportColumns($tableName, array $columns)
 {
     // this dropTable is here just because as fail-safe for direct invocations from other classes.
     ZurmoRedBean::$writer->dropTableByTableName($tableName);
     $schema = static::getTableSchemaByNameAndImportColumns($tableName, $columns);
     CreateOrUpdateExistingTableFromSchemaDefinitionArrayUtil::generateOrUpdateTableBySchemaDefinition($schema, new MessageLogger());
 }