craftcms / craftcms/cms

[4.x]: Propagation error when adding custom validation to an entry field inside a matrix block

Open
#13,755 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug craft4
Dominant language
PHP
Stars
3.6k
Forks
705
Avg merge
1d 5h
Merged PRs (30d)
134

Description

What happened?
Description

We have a matrix field set up, and in one of the blocks is an entry relationship field. With our site module, we have added custom validation to ensure the entries selected in this field pass certain business logic criteria.

The site is multisite; the matrix field's "Propagation Method" is set to "Save blocks to all sites the owner element is saved in"; the entry relationship field has "Manage relations on a per-site basis" un-ticked. As a result, the same entry field relationships are saved across all enabled sites.

Our validation rules run fine, except once the editor tries to fix the error (either by removing the selection, and/or picking a new valid entry). At this point an exception is thrown: Couldn’t propagate element to other site.

Here is the distilled code we are using. First up, in our site module we add validation rules to the matrix block:

use craft\base\Model;
use craft\elements\MatrixBlock;
use craft\events\DefineRulesEvent;
use yii\base\Event;

Event::on(
  MatrixBlock::class,
  Model::EVENT_DEFINE_RULES,
  static function(DefineRulesEvent $event) {

    // business logic to bind the validation rule only to relevant matrix block goes here...

    $event->rules[] = [
      [
        'fieldHandle',
      ],
      CustomValidator::class
    ];
  } 
);

And here is our CustomValidator class:

<?php
namespace modules\sitemodule\validators;

use craft\helpers\ElementHelper;
use yii\validators\Validator;

class CustomValidator extends Validator
{
  public function validateAttribute($model, $attribute): void
    {
      if (ElementHelper::isDraftOrRevision($model)) {
        return;
    }

    // No errors if no entry
    $entry = $model->$attribute->status(null)->one();
    if(! $entry) {
      return;
    }

    // business logic validation goes here...

    $model->addError($attribute, 'Custom validation error message');
  }
}
Steps to reproduce

First, set the scene:

  1. Set up a multisite, at least 2 sites
  2. Set up a section of any kind, and enable for all sites
  3. Set up a matrix field containing a single block; set its "Propagation Method" to "Save blocks to all sites the owner element is saved in"
  4. Add an entry relationship custom field to this matrix block; be sure that "Manage relations on a per-site basis" is un-ticked (recommend relating to a separate entry section, its configuration does not matter)
  5. Add the matrix field to the section created in step 2
  6. Add a custom site module with the above code

Then, follow these steps:

  1. Create a new entry
  2. Fill out mandatory fields (e.g. title)
  3. Hit Save & Continue Editing so that the entry is published and propagated
  4. Add one matrix block, and select/add an entry relationship
  5. Hit "Save and continue editing"

If everything works, at this point the page should come back and show our error message on the matrix block's relationship field, "Custom validation error message".

Now, attempt to resolve the error:

  1. Remove the entry relationship
    (If you do nothing, Craft will attempt to auto-save your work, but the autosave icon will turn into an alert !)
  2. Hit "Save and continue editing"
Expected behavior

The page should come back without any errors.

Actual behavior

The yii\base\Exception is thrown: "Couldn’t propagate element to other site."

Craft CMS version

4.4.17

PHP version

8.1.16

Operating system and version

Linux 5.15.49-linuxkit-pr

Database type and version

MariaDB 10.3.38

Image driver and version

Imagick 3.7.0 (ImageMagick 6.9.11-60)

Installed plugins and versions

No response

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with MatrixBlock validation through Model::EVENT_DEFINE_RULES and the multisite propagation path described in the reproduction. Reproduce the error using the custom validator and the matrix entry relationship with propagation enabled. Done means removing the invalid relationship and saving no longer throws “Couldn’t propagate element to other site,” while the custom validation message still appears when appropriate.

Written by the indexing model from the issue text.

Assessment

Tech stack
php
Domain
backend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.