area17 / twill

Twill is an open source CMS toolkit for Laravel that helps developers rapidly create a custom admin console that is intuitive, powerful and flexible. Chat with us on Discord at https://discord.gg/cnWk7EFv8R.
https://twillcms.com
Apache License 2.0
3.72k stars 568 forks source link

blockable relation not available in module (revision) preview, caused by missing model id => missing blockable_id (in block relation) #2483

Closed emanueljacob closed 6 months ago

emanueljacob commented 6 months ago

Description

In revision previews the relation "blockable" is always null. This means that all block views or its block class that make use of a blockable relation either throw an exception or at least look wrong compared to the real rendering. This error seems to be rather rare, because I guess most people do not use the relation from a block to the related blockable type.

The reason behind this behavior seems to be the way Twill hydrates the fields that are stored in revisions (see HandleRevisions:L80):

  1. get fields from revision table
  2. create a new empty model (of type "blockable_type") using $this->model->newInstance()
  3. hydrate the fields from step 1.
  4. set the model id again that was still null (see 2.) )

The problem in this approach is, that at the time of hydration (step 3.) the blockable_type/model is a fresh model instance and therefore has NO id yet. And when the hydration takes place, especially when hydrating the blocks relation, the id of the blockable type is null and theblockable_id can not be set and is from there on null. Only afterwards (after the hydration has taken place) the id of the blockable_type will be set, leaving all blocks without blockable_id...

The fix is relatively simple: instead of adding the model id to the fresh model instance AFTER the hydration, instead do that BEFORE.

Steps to reproduce

Due to the fact that this issue is related to revisions and/or preview we have to fulfill some prerequisits:

Prerequisits

example block view myblock.blade.php should display the value of the attribute 'something' of the related blockable_type.

{{$block->blockable->something}} 

Reproduction

  1. create a new record of a module that has revisions and blocks.
  2. make sure you have set at least one block and save
  3. change the block and save
  4. make sure you have a new revision
  5. click on the old revision in the twill administration, so a preview modal should be opened

Expected result

The preview can be displayed showing the block with data from the clicked revision. Taking the example from above, it should display the value of the attribute 'something' of the related blockable_type.

Actual result

A Illuminate\View\ViewException exception is being thrown, implicitly saying the relation is null. Taking the example from above, the exceptions message was Attempt to read property "something" on null.

Therefore the preview can not be shown.

Versions

Twill version: 3.1.0 Laravel version: 10.45.1 PHP version: 8.3 Database engine: MySQL

Related

797

https://github.com/area17/twill/blob/703308854bbef11ff2bf2d61406f00bda351f84c/src/Repositories/Behaviors/HandleBlocks.php#L313 https://github.com/area17/twill/blob/703308854bbef11ff2bf2d61406f00bda351f84c/src/Repositories/Behaviors/HandleRevisions.php#L80