public function saveBlockType(SuperTable_BlockTypeModel $blockType, $validate = true) { if (!$validate || $this->validateBlockType($blockType)) { $transaction = craft()->db->getCurrentTransaction() === null ? craft()->db->beginTransaction() : null; try { $contentService = craft()->content; $fieldsService = craft()->fields; $originalFieldContext = $contentService->fieldContext; $originalFieldColumnPrefix = $contentService->fieldColumnPrefix; $originalOldFieldColumnPrefix = $fieldsService->oldFieldColumnPrefix; // Get the block type record $blockTypeRecord = $this->_getBlockTypeRecord($blockType); $isNewBlockType = $blockType->isNew(); if (!$isNewBlockType) { // Get the old block type fields $oldBlockTypeRecord = SuperTable_BlockTypeRecord::model()->findById($blockType->id); $oldBlockType = SuperTable_BlockTypeModel::populateModel($oldBlockTypeRecord); $contentService->fieldContext = 'superTableBlockType:' . $blockType->id; $contentService->fieldColumnPrefix = 'field_'; $fieldsService->oldFieldColumnPrefix = 'field_'; $oldFieldsById = array(); foreach ($oldBlockType->getFields() as $field) { $oldFieldsById[$field->id] = $field; } // Figure out which ones are still around foreach ($blockType->getFields() as $field) { if (!$field->isNew()) { unset($oldFieldsById[$field->id]); } } // Drop the old fields that aren't around anymore foreach ($oldFieldsById as $field) { $fieldsService->deleteField($field); } // Refresh the schema cache craft()->db->getSchema()->refresh(); } // Set the basic info on the new block type record $blockTypeRecord->fieldId = $blockType->fieldId; // Save it, minus the field layout for now $blockTypeRecord->save(false); if ($isNewBlockType) { // Set the new ID on the model $blockType->id = $blockTypeRecord->id; } // Save the fields and field layout // ------------------------------------------------------------- $fieldLayoutFields = array(); $sortOrder = 0; // Resetting the fieldContext here might be redundant if this isn't a new blocktype but whatever $contentService->fieldContext = 'superTableBlockType:' . $blockType->id; $contentService->fieldColumnPrefix = 'field_'; foreach ($blockType->getFields() as $field) { // Hack to allow blank field names if (!$field->name) { $field->name = '__blank__'; } if (!$fieldsService->saveField($field, false)) { throw new Exception(Craft::t('An error occurred while saving this SuperTable block type.')); } $fieldLayoutField = new FieldLayoutFieldModel(); $fieldLayoutField->fieldId = $field->id; $fieldLayoutField->required = $field->required; $fieldLayoutField->sortOrder = ++$sortOrder; $fieldLayoutFields[] = $fieldLayoutField; } $contentService->fieldContext = $originalFieldContext; $contentService->fieldColumnPrefix = $originalFieldColumnPrefix; $fieldsService->oldFieldColumnPrefix = $originalOldFieldColumnPrefix; $fieldLayoutTab = new FieldLayoutTabModel(); $fieldLayoutTab->name = 'Content'; $fieldLayoutTab->sortOrder = 1; $fieldLayoutTab->setFields($fieldLayoutFields); $fieldLayout = new FieldLayoutModel(); $fieldLayout->type = 'SuperTable_Block'; $fieldLayout->setTabs(array($fieldLayoutTab)); $fieldLayout->setFields($fieldLayoutFields); $fieldsService->saveLayout($fieldLayout); // Update the block type model & record with our new field layout ID $blockType->setFieldLayout($fieldLayout); $blockType->fieldLayoutId = $fieldLayout->id; $blockTypeRecord->fieldLayoutId = $fieldLayout->id; // Update the block type with the field layout ID $blockTypeRecord->save(false); if (!$isNewBlockType) { // Delete the old field layout $fieldsService->deleteLayoutById($oldBlockType->fieldLayoutId); } if ($transaction !== null) { $transaction->commit(); } } catch (\Exception $e) { if ($transaction !== null) { $transaction->rollback(); } throw $e; } return true; } else { return false; } }