Problem/Motivation

Some background: I have placed a ctools block, for a field based on a custom field type, which works almost as expected. The custom field type is extended from the text_long field type in Core. Ordinarily, if the field is empty, then the block will not render. My understanding is that is the correct and desired behavior in general. I have not been able to successfully reproduce the below problem outside of this instance of my custom field type:

What's happening is that when the field is empty, despite the isEmpty() method, as defined in the field type definition, returning TRUE, the ctools block provides an empty field when building the block, which results in a block rendered without any content in it. The expectation is that the block wouldn't render at all since the field is empty. For the purposes of block rendering, an element is considered empty by the renderer if the element is either empty, or only contains the #cache index. The build() method in EntityField.php adds a field index to the element without checking whether the field is empty or not.

Proposed resolution

Add a conditional to check if the field is empty, before adding the field index to the $build variable, that way the renderer will consider the element empty if the field is empty, and continue to render content as usual if the field is not empty.

Remaining tasks

Needs review.

User interface changes

None.

API changes

None.

Data model changes

None

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

mroycroft created an issue. See original summary.

mroycroft’s picture

mroycroft’s picture

Issue summary: View changes
Status: Active » Needs review
hctom’s picture

I am experiencing a related issue with "empty" fields, which require a quite different solution:

Currently the EntityField::blockAccess() method only grants access to an entity field block, if the field has a value (by checking $entity->{$this->fieldName}->getValue()). Unfortunately this returns FALSE in the case you have an image field that provides a default image, if no image is uploaded. The problem is here that the default image is added on the formatter level, so the field itself is considered empty, while it would output the default image.

So my proposed solution is to render the field and check if there are actual renderable children by using Element::children($build). If so, access to the block is granted. Otherwise access is forbidden and so the block won't even be rendered.

See my attached patch for the solution.

mroycroft’s picture

This seems like a more sensible approach to fix this issue. Code changes look fine, I haven't had time to manually test it.

japerry’s picture

DamienMcKenna’s picture

phenaproxima’s picture

FileSize
11.96 KB
10.42 KB

W00t! I updated @hctom's patch in #4 with a test against an image field, plus a bit of refactoring. Sorry for the big interdiff; I moved ctools_block's functional test into PHPUnit.

EclipseGc’s picture

Status: Needs review » Fixed

looks good to me.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.