public function saveField(SuperTableField $field, ElementInterface $owner)
    {
        // Is the owner being duplicated?
        /** @var Element $owner */
        if ($owner->duplicateOf !== null) {
            /** @var SuperTableBlockQuery $query */
            $query = $owner->duplicateOf->getFieldValue($field->handle);
            // If this is the first site the element is being duplicated for, or if the element is set to manage blocks
            // on a per-site basis, then we need to duplicate them for the new element
            $duplicateBlocks = !$owner->propagating || $field->localizeBlocks;
        } else {
            /** @var SuperTableBlockQuery $query */
            $query = $owner->getFieldValue($field->handle);
            // If the element is brand new and propagating, and the field manages blocks on a per-site basis,
            // then we will need to duplicate the blocks for this site
            $duplicateBlocks = !$query->ownerId && $owner->propagating && $field->localizeBlocks;
        }

        // Skip if the element is propagating right now, and we don't need to duplicate the blocks
        if ($owner->propagating && !$duplicateBlocks) {
            return;
        }

        // Fetch the Super Table blocks
        /** @var SuperTableBlock[] $blocks */
        $blocks = $query->getCachedResult() ?? (clone $query)->anyStatus()->all();

        $elementsService = Craft::$app->getElements();

        $transaction = Craft::$app->getDb()->beginTransaction();
        try {
            // If we're duplicating an element, or the owner was a preexisting element,
            // make sure that the blocks for this field/owner respect the field's translation setting
            if ($owner->duplicateOf || $query->ownerId) {
                $this->_applyFieldTranslationSetting($owner->duplicateOf ?? $owner, $field);
            }

            $blockIds = [];

            // Only propagate the blocks if the owner isn't being propagated
            $propagate = !$owner->propagating;

            foreach ($blocks as $block) {
                if ($duplicateBlocks) {
                    $block = $elementsService->duplicateElement($block, [
                        'ownerId' => $owner->id,
                        'ownerSiteId' => $field->localizeBlocks ? $owner->siteId : null,
                        'siteId' => $owner->siteId,
                        'propagating' => false,
                    ]);
                } else {
                    $block->ownerId = $owner->id;
                    $block->ownerSiteId = ($field->localizeBlocks ? $owner->siteId : null);
                    $block->propagating = $owner->propagating;
                    $elementsService->saveElement($block, false, $propagate);
                }

                $blockIds[] = $block->id;
            }

            // Delete any blocks that shouldn't be there anymore
            $deleteBlocksQuery = SuperTableBlockElement::find()
                ->anyStatus()
                ->ownerId($owner->id)
                ->fieldId($field->id)
                ->where(['not', ['elements.id' => $blockIds]]);

            if ($field->localizeBlocks) {
                $deleteBlocksQuery->ownerSiteId($owner->siteId);
            } else {
                $deleteBlocksQuery->siteId($owner->siteId);
            }

            foreach ($deleteBlocksQuery->all() as $deleteBlock) {
                $elementsService->deleteElement($deleteBlock);
            }

            $transaction->commit();
        } catch (\Throwable $e) {
            $transaction->rollBack();

            throw $e;
        }
    }
public function saveField(SuperTableField $field, ElementInterface $owner)
    {
        // Is the owner being duplicated?
        /** @var Element $owner */
        if ($owner->duplicateOf !== null) {
            /** @var SuperTableBlockQuery $query */
            $query = $owner->duplicateOf->getFieldValue($field->handle);
            // If this is the first site the element is being duplicated for, or if the element is set to manage blocks
            // on a per-site basis, then we need to duplicate them for the new element
            $duplicateBlocks = !$owner->propagating || $field->localizeBlocks;
        } else {
            /** @var SuperTableBlockQuery $query */
            $query = $owner->getFieldValue($field->handle);
            // If the element is brand new and propagating, and the field manages blocks on a per-site basis,
            // then we will need to duplicate the blocks for this site
            $duplicateBlocks = !$query->ownerId && $owner->propagating && $field->localizeBlocks;
        }

        // Skip if the element is propagating right now, and we don't need to duplicate the blocks
        if ($owner->propagating && !$duplicateBlocks) {
            return;
        }

        // Fetch the Super Table blocks
        /** @var SuperTableBlock[] $blocks */
        $blocks = $query->getCachedResult() ?? (clone $query)->anyStatus()->all();

        $elementsService = Craft::$app->getElements();

        $transaction = Craft::$app->getDb()->beginTransaction();
        try {
            // If we're duplicating an element, or the owner was a preexisting element,
            // make sure that the blocks for this field/owner respect the field's translation setting
            if ($owner->duplicateOf || $query->ownerId) {
                $this->_applyFieldTranslationSetting($owner->duplicateOf ?? $owner, $field);
            }

            $blockIds = [];

            // Only propagate the blocks if the owner isn't being propagated
            $propagate = !$owner->propagating;

            foreach ($blocks as $block) {
                if ($duplicateBlocks) {
                    $block = $elementsService->duplicateElement($block, [
                        'ownerId' => $owner->id,
                        'ownerSiteId' => $field->localizeBlocks ? $owner->siteId : null,
                        'siteId' => $owner->siteId,
                        'propagating' => false,
                    ]);
                } else {
                    $block->ownerId = $owner->id;
                    $block->ownerSiteId = ($field->localizeBlocks ? $owner->siteId : null);
                    $block->propagating = $owner->propagating;
                    $elementsService->saveElement($block, false, $propagate);
                }

                $blockIds[] = $block->id;
            }

            // Delete any blocks that shouldn't be there anymore
            $deleteBlocksQuery = SuperTableBlockElement::find()
                ->anyStatus()
                ->ownerId($owner->id)
                ->fieldId($field->id)
                ->where(['not', ['elements.id' => $blockIds]]);

            if ($field->localizeBlocks) {
                $deleteBlocksQuery->ownerSiteId($owner->siteId);
            } else {
                $deleteBlocksQuery->siteId($owner->siteId);
            }

            foreach ($deleteBlocksQuery->all() as $deleteBlock) {
                $elementsService->deleteElement($deleteBlock);
            }

            $transaction->commit();
        } catch (\Throwable $e) {
            $transaction->rollBack();

            throw $e;
        }
    }
public function saveField ( SuperTableField $ field , ElementInterface $ owner ) { // Is the owner being duplicated? /** @var Element $owner */ if ( $ owner -> duplicateOf !== null ) { /** @var SuperTableBlockQuery $query */ $ query = $ owner -> duplicateOf -> getFieldValue ( $ field -> handle ) ; // If this is the first site the element is being duplicated for, or if the element is set to manage blocks // on a per-site basis, then we need to duplicate them for the new element $ duplicateBlocks = ! $ owner -> propagating || $ field -> localizeBlocks ; } else { /** @var SuperTableBlockQuery $query */ $ query = $ owner -> getFieldValue ( $ field -> handle ) ; // If the element is brand new and propagating, and the field manages blocks on a per-site basis, // then we will need to duplicate the blocks for this site $ duplicateBlocks = ! $ query -> ownerId && $ owner -> propagating && $ field -> localizeBlocks ; } // Skip if the element is propagating right now, and we don't need to duplicate the blocks if ( $ owner -> propagating && ! $ duplicateBlocks ) { return ; } // Fetch the Super Table blocks /** @var SuperTableBlock[] $blocks */ $ blocks = $ query -> getCachedResult ( ) ?? ( clone $ query ) -> anyStatus ( ) -> all ( ) ; $ elementsService = Craft :: $ app -> getElements ( ) ; $ transaction = Craft :: $ app -> getDb ( ) -> beginTransaction ( ) ; try { // If we're duplicating an element, or the owner was a preexisting element, // make sure that the blocks for this field/owner respect the field's translation setting if ( $ owner -> duplicateOf || $ query -> ownerId ) { $ this -> _applyFieldTranslationSetting ( $ owner -> duplicateOf ?? $ owner , $ field ) ; } $ blockIds = [ ] ; // Only propagate the blocks if the owner isn't being propagated $ propagate = ! $ owner -> propagating ; foreach ( $ blocks as $ block ) { if ( $ duplicateBlocks ) { $ block = $ elementsService -> duplicateElement ( $ block , [ 'ownerId' => $ owner -> id , 'ownerSiteId' => $ field -> localizeBlocks ? $ owner -> siteId : null , 'siteId' => $ owner -> siteId , 'propagating' => false , ] ) ; } else { $ block -> ownerId = $ owner -> id ; $ block -> ownerSiteId = ( $ field -> localizeBlocks ? $ owner -> siteId : null ) ; $ block -> propagating = $ owner -> propagating ; $ elementsService -> saveElement ( $ block , false , $ propagate ) ; } $ blockIds [ ] = $ block -> id ; } // Delete any blocks that shouldn't be there anymore $ deleteBlocksQuery = SuperTableBlockElement :: find ( ) -> anyStatus ( ) -> ownerId ( $ owner -> id ) -> fieldId ( $ field -> id ) -> where ( [ 'not' , [ 'elements.id' => $ blockIds ] ] ) ; if ( $ field -> localizeBlocks ) { $ deleteBlocksQuery -> ownerSiteId ( $ owner -> siteId ) ; } else { $ deleteBlocksQuery -> siteId ( $ owner -> siteId ) ; } foreach ( $ deleteBlocksQuery -> all ( ) as $ deleteBlock ) { $ elementsService -> deleteElement ( $ deleteBlock ) ; } $ transaction -> commit ( ) ; } catch ( \ Throwable $ e ) { $ transaction -> rollBack ( ) ; throw $ e ; } }
Saves a Super Table field.

@param SuperTableField      $field The Super Table field
@param ElementInterface $owner The element the field is associated with

@throws \Throwable if reasons
Saves a Super Table field .