diff --git a/CRM/Core/BAO/CustomField.php b/CRM/Core/BAO/CustomField.php index 0fbb5b0242bd..13ea02f406f9 100644 --- a/CRM/Core/BAO/CustomField.php +++ b/CRM/Core/BAO/CustomField.php @@ -260,19 +260,38 @@ protected static function prepareCreateParams($field, $operation) { /** * Create several fields at once in a mysql efficient way. * + * https://lab.civicrm.org/dev/core/issues/1093 + * * The intention is that apiv4 would expose any BAO with bulkCreate as a new action. * * Note that in the first instance this supports 'create' only. It's possible edit * is fine in the same function - just treading slowly. * - * @param array $params + * @param array $bulkParams * Array of arrays as would be passed into create * @param array $defaults * Default parameters to be be merged into each of the params. */ - public function bulkCreate($params, $defaults) { - foreach ($params as $fieldParams) { - $fieldParams = array_merge($defaults, $fieldParams); + public static function bulkCreate($bulkParams, $defaults) { + $sql = []; + $customFields = []; + foreach ($bulkParams as $fieldParams) { + $params = array_merge($defaults, $fieldParams); + $params = self::prepareCreate($params); + $customField = self::doCreate($params); + // Only doing 'add' for now - so hard coded & no indexExists. + $fieldSQL = self::getAlterFieldSQL($customField, 'add', $params); + $sql[$params['table_name']][] = $fieldSQL; + $customFields[] = $customField; + } + foreach ($sql as $tableName => $statements) { + // CRM-7007: do not i18n-rewrite this query + CRM_Core_DAO::executeQuery("ALTER TABLE $tableName " . implode(', ', $statements), [], TRUE, NULL, FALSE, FALSE); + } + Civi::service('sql_triggers')->rebuild($params['table_name'], TRUE); + CRM_Utils_System::flushCache(); + foreach ($customFields as $customField) { + CRM_Utils_Hook::post('create', 'CustomField', $customField->id, $customField); } } @@ -1762,8 +1781,12 @@ public static function defaultCustomTableSchema($params) { * @param bool $triggerRebuild */ public static function createField($field, $operation, $indexExist = FALSE, $triggerRebuild = TRUE) { - $params = []; - $sql = self::getAlterFieldSQL($field, $operation, $params, $indexExist); + $params = [ + 'table_name' => CRM_Core_DAO::getFieldValue('CRM_Core_DAO_CustomGroup', $field->custom_group_id, 'table_name'), + ]; + $sql = str_repeat(' ', 8); + $sql .= "ALTER TABLE {$params['table_name']}"; + $sql .= self::getAlterFieldSQL($field, $operation, $params, $indexExist); // CRM-7007: do not i18n-rewrite this query CRM_Core_DAO::executeQuery($sql, [], TRUE, NULL, FALSE, FALSE); @@ -1798,7 +1821,7 @@ public static function getAlterFieldSQL($field, $operation, &$params, $indexExis // lets suppress the required flag, since that can cause sql issue $params['required'] = FALSE; - return CRM_Core_BAO_SchemaHandler::buildFieldChangeSql($params, $indexExist); + return CRM_Core_BAO_SchemaHandler::getFieldAlterSQL($params, $indexExist); } /** diff --git a/CRM/Core/BAO/SchemaHandler.php b/CRM/Core/BAO/SchemaHandler.php index 72ab0408a6b6..26a8be979e05 100644 --- a/CRM/Core/BAO/SchemaHandler.php +++ b/CRM/Core/BAO/SchemaHandler.php @@ -724,6 +724,18 @@ public static function createMissingIndices($missingIndices) { public static function buildFieldChangeSql($params, $indexExist) { $sql = str_repeat(' ', 8); $sql .= "ALTER TABLE {$params['table_name']}"; + $sql = self::getFieldAlterSQL($params, $indexExist, $sql); + return $sql; + } + + /** + * @param array $params + * @param bool $indexExist + * + * @return string + */ + public static function getFieldAlterSQL($params, $indexExist) { + $sql = ''; switch ($params['operation']) { case 'add': $separator = "\n"; diff --git a/CRM/Utils/Migrate/Import.php b/CRM/Utils/Migrate/Import.php index 340e10d51a6d..9315339212d6 100644 --- a/CRM/Utils/Migrate/Import.php +++ b/CRM/Utils/Migrate/Import.php @@ -386,6 +386,7 @@ public function customFields(&$xml, &$idMap) { // Only rebuild the table's trigger on the last field added to avoid un-necessary // and slow rebuilds when adding many fields at the same time. + // @todo - call bulkCreate instead. $triggerRebuild = FALSE; if ($count == $total) { $triggerRebuild = TRUE; diff --git a/tests/phpunit/CRM/Core/BAO/CustomFieldTest.php b/tests/phpunit/CRM/Core/BAO/CustomFieldTest.php index 19aa373f72e7..321e66d51d9a 100644 --- a/tests/phpunit/CRM/Core/BAO/CustomFieldTest.php +++ b/tests/phpunit/CRM/Core/BAO/CustomFieldTest.php @@ -644,7 +644,29 @@ public function testBulkCreate() { 'extends' => 'Individual', 'title' => 'my bulk group', ]); - CRM_Core_BAO_CustomField::bulkCreate([]); + CRM_Core_BAO_CustomField::bulkCreate([ + [ + 'label' => 'Test', + 'data_type' => 'String', + 'html_type' => 'Text', + 'column_name' => 'my_text', + ], + [ + 'label' => 'test_link', + 'data_type' => 'Link', + 'html_type' => 'Link', + 'is_search_range' => '0', + ], + ], + [ + 'custom_group_id' => $customGroup['id'], + 'is_active' => 1, + 'is_searchable' => 1, + ]); + $dao = CRM_Core_DAO::executeQuery(('SHOW CREATE TABLE ' . $customGroup['values'][$customGroup['id']]['table_name'])); + $dao->fetch(); + $this->assertContains('`test_link` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL', $dao->Create_Table); + $this->assertContains('KEY `INDEX_my_text` (`my_text`)', $dao->Create_Table); } }