public function saveFieldValue(NeoFieldType $fieldType)
{
$owner = $fieldType->element;
$field = $fieldType->model;
$blocks = $owner->getContent()->getAttribute($field->handle);
if ($blocks === null) {
return;
}
$structure = new StructureModel();
// $structure->maxLevels = ...->maxLevels; // This might be useful somebody. Keeping it around as a reminder.
if (!is_array($blocks)) {
$blocks = [];
}
$transaction = $this->beginTransaction();
try {
// Make sure that the blocks for this field/owner respect the field's translation setting
$this->_applyFieldTranslationSetting($owner, $field, $blocks);
$this->saveStructure($structure, $fieldType);
// Build the block structure by mapping block sort orders and levels to parent/child relationships
$blockIds = [];
$parentStack = [];
foreach ($blocks as $block) {
$block->ownerId = $owner->id;
$block->ownerLocale = $this->_getFieldLocale($fieldType);
// Remove parent blocks until either empty or a parent block is only one level below this one (meaning
// it'll be the parent of this block)
while (!empty($parentStack) && $block->level <= $parentStack[count($parentStack) - 1]->level) {
array_pop($parentStack);
}
$this->saveBlock($block, false);
// If there are no blocks in our stack, it must be a root level block
if (empty($parentStack)) {
craft()->structures->appendToRoot($structure->id, $block);
} else {
$parentBlock = $parentStack[count($parentStack) - 1];
craft()->structures->append($structure->id, $block, $parentBlock);
}
// The current block may potentially be a parent block as well, so save it to the stack
array_push($parentStack, $block);
$blockIds[] = $block->id;
}
// Get the IDs of blocks that are row deleted
$deletedBlockConditions = ['and', 'ownerId = :ownerId', 'fieldId = :fieldId', ['not in', 'id', $blockIds]];
$deletedBlockParams = [':ownerId' => $owner->id, ':fieldId' => $field->id];
if ($field->translatable) {
$deletedBlockConditions[] = 'ownerLocale = :ownerLocale';
$deletedBlockParams[':ownerLocale'] = $owner->locale;
}
$deletedBlockIds = craft()->db->createCommand()->select('id')->from('neoblocks')->where($deletedBlockConditions, $deletedBlockParams)->queryColumn();
$this->deleteBlockById($deletedBlockIds);
$this->commitTransaction($transaction);
} catch (\Exception $e) {
$this->rollbackTransaction($transaction);
throw $e;
}
}