/** * 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()); }