spicywebau / craft-neo

A Matrix-like field type for Craft CMS that uses existing fields
Other
402 stars 63 forks source link

"Undefined array key" after deleting same neo blocks #783

Closed alexanderloewe closed 1 year ago

alexanderloewe commented 1 year ago

Bug Description

After removing same old no longer needed blocks, we get the error:

Undefined array key "blockType"

It looks like that error only appears after removing child blocks of other blocks. We removed level 2 blocks without this issue

2. in /home/wiqusaha/public_html/p4/vendor/craftcms/cms/src/web/ErrorHandler.php at line 79– [yii\base\ErrorHandler::handleError](https://www.yiiframework.com/doc-2.0/yii-base-errorhandler.html#handleError()-detail)(2, 'Undefined array key "innerBenefi...', '/home/wiqusaha/public_html/p4/ve...', 162)
73747576777879808182838485    {
        // Because: https://bugs.php.net/bug.php?id=74980
        if (str_contains($message, 'Narrowing occurred during type inference. Please file a bug report')) {
            return true;
        }

        return parent::handleError($code, $message, $file, $line);
    }

    /**
     * @inheritdoc
     */
    public function getExceptionName($exception): ?string
3. in /home/wiqusaha/public_html/p4/vendor/spicyweb/craft-neo/src/validators/FieldValidator.php at line 162– craft\web\ErrorHandler::handleError(2, 'Undefined array key "innerBenefi...', '/home/wiqusaha/public_html/p4/ve...', 162)
156157158159160161162163164165166167168            $atTopLevel = $parent === null;

            // Create the sibling count for this parent block if this block is the first of its children
            if (!isset($blockSiblingCount[$parentId])) {
                $blockSiblingCount[$parentId] = array_fill_keys(
                    array_map(
                        fn($handle) => $blockTypesByHandle[$handle]->id,
                        $atTopLevel ? $topLevelBlockTypeHandles : $childBlockTypes[$parent->typeId]
                    ),
                    0
                );
            }

4. benf\neo\validators\FieldValidator::benf\neo\validators\{closure}('innerBenefitList')
5. in /home/wiqusaha/public_html/p4/vendor/spicyweb/craft-neo/src/validators/FieldValidator.php at line 163– array_map(Closure, ['innerTitle', 'innerText', 'innerQuote', 'innerBenefitList', ...])
157158159160161162163164165166167168169 
            // Create the sibling count for this parent block if this block is the first of its children
            if (!isset($blockSiblingCount[$parentId])) {
                $blockSiblingCount[$parentId] = array_fill_keys(
                    array_map(
                        fn($handle) => $blockTypesByHandle[$handle]->id,
                        $atTopLevel ? $topLevelBlockTypeHandles : $childBlockTypes[$parent->typeId]
                    ),
                    0
                );
            }

            $lastBlock = $block;
6. in /home/wiqusaha/public_html/p4/vendor/spicyweb/craft-neo/src/Field.php at line 890– benf\neo\validators\FieldValidator::validateAttribute(craft\elements\Entry, 'mainBuilder')
884885886887888889890891892893894895896            $fieldValidator = new FieldValidator([
                'minTopBlocks' => $this->minTopBlocks ?: null,
                'maxTopBlocks' => $this->maxTopBlocks ?: null,
                'minLevels' => $this->minLevels ?: null,
                'maxLevels' => $this->maxLevels ?: null,
            ]);
            $fieldValidator->validateAttribute($element, $this->handle);
        }
    }

    /**
     * @inheritdoc
     */
7. in /home/wiqusaha/public_html/p4/vendor/craftcms/cms/src/base/Element.php at line 2590– benf\neo\Field::validateBlocks(craft\elements\Entry, null)
2584258525862587258825892590259125922593259425952596        [$field, $method, $fieldParams] = $params;

        if (is_string($method) && !is_callable($method)) {
            $method = [$field, $method];
        }

        $method($this, $fieldParams);
    }

    /**
     * @inheritdoc
     */
    public function isFieldEmpty(string $handle): bool
8. in /home/wiqusaha/public_html/p4/vendor/yiisoft/yii2/validators/InlineValidator.php at line 77– craft\base\Element::validateCustomFieldAttribute('field:mainBuilder', [benf\neo\Field, 'validateBlocks', null], yii\validators\InlineValidator, benf\neo\elements\db\BlockQuery)
9. in /home/wiqusaha/public_html/p4/vendor/yiisoft/yii2/validators/Validator.php at line 260– [yii\validators\InlineValidator::validateAttribute](https://www.yiiframework.com/doc-2.0/yii-validators-inlinevalidator.html#validateAttribute()-detail)(craft\elements\Entry, 'field:mainBuilder')
10. in /home/wiqusaha/public_html/p4/vendor/craftcms/cms/src/base/Element.php at line 2491– [yii\validators\Validator::validateAttributes](https://www.yiiframework.com/doc-2.0/yii-validators-validator.html#validateAttributes()-detail)(craft\elements\Entry)
2485248624872488248924902491249224932494249524962497                foreach ($field->getElementValidationRules() as $rule) {
                    $validator = $this->_normalizeFieldValidator($attribute, $rule, $field, $isEmpty);
                    if (
                        in_array($scenario, $validator->on) ||
                        (empty($validator->on) && !in_array($scenario, $validator->except))
                    ) {
                        $validator->validateAttributes($this);
                    }
                }

                if ($field::hasContentColumn()) {
                    $columnType = $field->getContentColumnType();
                    $value = $field->serializeValue($this->getFieldValue($field->handle), $this);
11. in /home/wiqusaha/public_html/p4/vendor/yiisoft/yii2/base/Model.php at line 370– craft\base\Element::afterValidate()
12. in /home/wiqusaha/public_html/p4/vendor/craftcms/cms/src/base/Element.php at line 2452– [yii\base\Model::validate](https://www.yiiframework.com/doc-2.0/yii-base-model.html#validate()-detail)(['id', 'contentId', 'parentId', 'root', ...], true)
2446244724482449245024512452245324542455245624572458    /**
     * @inheritdoc
     */
    public function validate($attributeNames = null, $clearErrors = true)
    {
        $this->_attributeNames = $attributeNames ? array_flip((array)$attributeNames) : null;
        $result = parent::validate($attributeNames, $clearErrors);
        $this->_attributeNames = null;
        return $result;
    }

    /**
     * @inheritdoc
13. in /home/wiqusaha/public_html/p4/vendor/craftcms/cms/src/services/Elements.php at line 3194– craft\base\Element::validate()
3188318931903191319231933194319531963197319831993200                    $element->title = $element::displayName() . ' ' . $element->id;
                }
            }
        }

        // Validate
        if ($runValidation && !$element->validate()) {
            Craft::info('Element not saved due to validation error: ' . print_r($element->errors, true), __METHOD__);
            $element->firstSave = $originalFirstSave;
            $element->propagateAll = $originalPropagateAll;
            return false;
        }

14. in /home/wiqusaha/public_html/p4/vendor/craftcms/cms/src/services/Elements.php at line 1098– craft\services\Elements::_saveElementInternal(craft\elements\Entry, true, false, null, ...)
1092109310941095109610971098109911001101110211031104 
        // Not currently being duplicated
        $duplicateOf = $element->duplicateOf;
        $element->duplicateOf = null;

        $success = $this->_saveElementInternal(
            $element,
            $runValidation,
            $propagate,
            $updateSearchIndex,
            forceTouch: $forceTouch,
            crossSiteValidate: $crossSiteValidate,
        );
15. in /home/wiqusaha/public_html/p4/vendor/craftcms/cms/src/controllers/ElementsController.php at line 1439– craft\services\Elements::saveElement(craft\elements\Entry, true, true, null, ...)
1433143414351436143714381439144014411442144314441445        // Validate and save the draft
        if ($element->enabled && $element->getEnabledForSite()) {
            $element->setScenario(Element::SCENARIO_LIVE);
        }

        $namespace = $this->request->getHeaders()->get('X-Craft-Namespace');
        if (!$elementsService->saveElement($element, crossSiteValidate: ($namespace === null && Craft::$app->getIsMultiSite()))) {
            return $this->_asAppyDraftFailure($element);
        }

        if (!$isUnpublishedDraft) {
            $lockKey = "element:$element->canonicalId";
            $mutex = Craft::$app->getMutex();
16. craft\controllers\ElementsController::actionApplyDraft()
17. in /home/wiqusaha/public_html/p4/vendor/yiisoft/yii2/base/InlineAction.php at line 57– call_user_func_array([craft\controllers\ElementsController, 'actionApplyDraft'], [])
18. in /home/wiqusaha/public_html/p4/vendor/yiisoft/yii2/base/Controller.php at line 178– [yii\base\InlineAction::runWithParams](https://www.yiiframework.com/doc-2.0/yii-base-inlineaction.html#runWithParams()-detail)(['p' => 'admin/entries/site/58'])
19. in /home/wiqusaha/public_html/p4/vendor/yiisoft/yii2/base/Module.php at line 552– [yii\base\Controller::runAction](https://www.yiiframework.com/doc-2.0/yii-base-controller.html#runAction()-detail)('apply-draft', ['p' => 'admin/entries/site/58'])
20. in /home/wiqusaha/public_html/p4/vendor/craftcms/cms/src/web/Application.php at line 304– [yii\base\Module::runAction](https://www.yiiframework.com/doc-2.0/yii-base-module.html#runAction()-detail)('elements/apply-draft', ['p' => 'admin/entries/site/58'])
298299300301302303304305306307308309310     * @param string $route
     * @param array $params
     * @return Response|null The result of the action, normalized into a Response object
     */
    public function runAction($route, $params = []): ?BaseResponse
    {
        $result = parent::runAction($route, $params);

        if ($result === null || $result instanceof Response) {
            return $result;
        }

        $response = $this->getResponse();
21. in /home/wiqusaha/public_html/p4/vendor/craftcms/cms/src/web/Application.php at line 607– craft\web\Application::runAction('elements/apply-draft', ['p' => 'admin/entries/site/58'])
601602603604605606607608609610611612613        if ($request->getIsActionRequest()) {
            $route = implode('/', $request->getActionSegments());

            try {
                Craft::debug("Route requested: '$route'", __METHOD__);
                $this->requestedRoute = $route;
                return $this->runAction($route, $_GET);
            } catch (Throwable $e) {
                $this->_unregisterDebugModule();
                if ($e instanceof InvalidRouteException) {
                    throw new NotFoundHttpException(Craft::t('yii', 'Page not found.'), $e->getCode(), $e);
                }
                throw $e;
22. in /home/wiqusaha/public_html/p4/vendor/craftcms/cms/src/web/Application.php at line 283– craft\web\Application::_processActionRequest(craft\web\Request)
277278279280281282283284285286287288289                    throw new ForbiddenHttpException();
                }
            }
        }

        // If this is an action request, call the controller
        if (($response = $this->_processActionRequest($request)) !== null) {
            return $response;
        }

        // If we’re still here, finally let Yii do its thing.
        try {
            return parent::handleRequest($request);
23. in /home/wiqusaha/public_html/p4/vendor/yiisoft/yii2/base/Application.php at line 384– craft\web\Application::handleRequest(craft\web\Request)
24. in /home/wiqusaha/public_html/p4/web/index.php at line 23– [yii\base\Application::run](https://www.yiiframework.com/doc-2.0/yii-base-application.html#run()-detail)()
17181920212223    Dotenv\Dotenv::createUnsafeMutable(CRAFT_BASE_PATH)->safeLoad();
}

// Load and run Craft
define('CRAFT_ENVIRONMENT', getenv('ENVIRONMENT') ?: 'production');
$app = require CRAFT_VENDOR_PATH.'/craftcms/cms/bootstrap/web.php';
$app->run();

Steps to reproduce

Remove level 2 Blocks from a Neo block and try to save an entry.

Expected behaviour

No response

Neo version

3.8.6

Craft CMS version

4.5.3

What is the affected Neo field's propagation method?

No response

Does this issue involve templating, and if so, is eager-loading used?

This is not a templating issue

ttempleton commented 1 year ago

Thanks for reporting that - just fixed it for the next release.

brianrivet-tilt commented 1 year ago

thanks! Do you have an eta for the release?

ttempleton commented 1 year ago

The next release is likely next week.

brianrivet-tilt commented 1 year ago

Hi Thomas, just checking in on the ETA for this release. The error in question is preventing me from saving anything on the site having the issue. Thanks!

ttempleton commented 1 year ago

Neo 3.9.0 has now been released.