Problem/Motivation

PHP displays warning when choosing image formatter "URL to image" on 9.4 fresh installation.

The new attribute 'loading' was introduced with $image_loading = $this->getSetting('image_loading'); on Drupal 9.4 #3173180: Add UI for 'loading' html attribute to images in web/core/modules/image/src/Plugin/Field/FieldFormatter/ImageFormatter.php

Yet the Class extending it web/core/modules/image/src/Plugin/Field/FieldFormatter/ImageUrlFormatter.php does not make use of it while making its parent calls, and doesn't provide the missing setting in its defaultSettings() function. Therefore returning NULL on the getSetting function, which gives the warning below on building settingsForm and settingsSummary.

Warning: Trying to access array offset on value of type null in Drupal\image\Plugin\Field\FieldFormatter\ImageFormatter->settingsForm() (line 167 of /app/web/core/modules/image/src/Plugin/Field/FieldFormatter/ImageFormatter.php)
#0 /app/web/core/includes/bootstrap.inc(347): _drupal_error_handler_real(2, 'Trying to acces...', '/app/web/core/m...', 167)
#1 /app/web/core/modules/image/src/Plugin/Field/FieldFormatter/ImageFormatter.php(167): _drupal_error_handler(2, 'Trying to acces...', '/app/web/core/m...', 167)
#2 /app/web/core/modules/image/src/Plugin/Field/FieldFormatter/ImageUrlFormatter.php(35): Drupal\image\Plugin\Field\FieldFormatter\ImageFormatter->settingsForm(Array, Object(Drupal\Core\Form\FormState))
#3 /app/web/core/modules/field_ui/src/Form/EntityDisplayFormBase.php(446): Drupal\image\Plugin\Field\FieldFormatter\ImageUrlFormatter->settingsForm(Array, Object(Drupal\Core\Form\FormState))
#4 /app/web/core/modules/field_ui/src/Form/EntityViewDisplayEditForm.php(40): Drupal\field_ui\Form\EntityDisplayFormBase->buildFieldRow(Object(Drupal\field\Entity\FieldConfig), Array, Object(Drupal\Core\Form\FormState))
#5 /app/web/core/modules/field_ui/src/Form/EntityDisplayFormBase.php(209): Drupal\field_ui\Form\EntityViewDisplayEditForm->buildFieldRow(Object(Drupal\field\Entity\FieldConfig), Array, Object(Drupal\Core\Form\FormState))
#6 /app/web/core/lib/Drupal/Core/Entity/EntityForm.php(106): Drupal\field_ui\Form\EntityDisplayFormBase->form(Array, Object(Drupal\Core\Form\FormState))

Steps to reproduce

  1. Install Latest 9.4.x dev site
  2. Modify article's image display settings /admin/structure/types/manage/article/display
  3. Change Image format from 'Image' to 'URL to image'
  4. Head to /admin/reports/dblog to see the php warning report

Proposed resolution

1. Skip the generation of loading related array if setting retrieved is NULL.

Remaining tasks

User interface changes

API changes

Data model changes

Release notes snippet

CommentFileSizeAuthor
#61 3291622-61.patch6.3 KBsmustgrave
#61 interdiff-51-61.txt1.19 KBsmustgrave
#56 3291622-56.patch2.79 KBgajendra_sharma
#54 3291622-54.patch1.39 KBdhirendra.mishra
#51 3291622-51.patch7.78 KBsmustgrave
#51 interdiff-49-51.txt3.52 KBsmustgrave
#49 3291622-49.patch5.75 KBsmustgrave
#49 interdiff-35-49.txt2.52 KBsmustgrave
#35 3291622-35.patch3.06 KBsmustgrave
#35 3291622-35-tests-only.patch1.58 KBsmustgrave
#32 3291622-32.patch3.06 KBsmustgrave
#32 interdiff-30-32.txt796 bytessmustgrave
#30 3291622-30.patch3.29 KBsmustgrave
#30 interdiff-28-30.txt611 bytessmustgrave
#28 3291622-28.patch2.92 KBsmustgrave
#28 3291622-28-tests-only.patch1.44 KBsmustgrave
#28 interdiff-26-28.txt1.62 KBsmustgrave
#26 3291622-26.patch3 KBsmustgrave
#26 3291622-26-tests-only.patch1.52 KBsmustgrave
#26 interdiff-24-26.txt1.9 KBsmustgrave
#23 3291622-23.patch3.05 KBsmustgrave
#23 3291622-23-tests-only.patch1.57 KBsmustgrave
#23 interdiff-16-23.txt944 bytessmustgrave
#20 patch applied.png172.73 KBameymudras
#20 Logs empty.png68.35 KBameymudras
#20 Image rendered.png72.45 KBameymudras
#17 Screenshot .png634.96 KBambikahirode
#16 3291622-16.patch3.05 KBsmustgrave
#16 3291622-16-tests-only.patch1.57 KBsmustgrave
#16 interdiff-MR-16.txt3.06 KBsmustgrave
#7 after_patch.png406.55 KBsmustgrave
#7 before_patch.png680.51 KBsmustgrave
image_URL_formatter.png60.99 KBg-brodiei

Issue fork drupal-3291622

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

g-brodiei created an issue. See original summary.

naveenvalecha’s picture

Status: Active » Reviewed & tested by the community

Thank you!

Lendude’s picture

Status: Reviewed & tested by the community » Needs work

Hmm not sure about this. ImageUrlFormatter is loading the settingsForm from the parent but not loading the default settings from the parent, so that discrepancy is what the root cause of this problem is.

See Base64ImageFormatter for what works: that inherits neither the default settings nor the settingsForm, so that doesn't break.

Don't know if this should either inherit both or should inherit neither, but I think the fact that it's doing one of the two is what causes this to break.

g-brodiei’s picture

Hi @Lendude, according to your feedback, I'd went through the use of ImageBase64Formatter, seems like the missing puzzle on ImageUrlFormatter was to add its parent settings as a starting point.

Add additional commit to revert the changes, and added + parent::defaultSettings();

Thanks!

g-brodiei’s picture

Status: Needs work » Needs review

Back to need review

smustgrave’s picture

Status: Needs review » Reviewed & tested by the community
FileSize
680.51 KB
406.55 KB

Tested the PR
Confirmed the issue without the patch
Confirmed the PR fixed the issue.
Attaching screenshots

SnowCoder’s picture

I'm having the same issue on my site. Is there a patch for this at all?

smustgrave’s picture

There's a PR up.

SnowCoder’s picture

@smustgrave I've never had any experience using the PR before. I've always just come to find patches that I applied and have been pretty comfortable with. I seem to be a bit confused about how I would apply this to my site? Its composer run with the drupal/recommended-project starter.

smustgrave’s picture

Gotcha

If you open the PR https://git.drupalcode.org/project/drupal/-/merge_requests/2416 you can append .diff or .patch to the end of the URL and you can past that into composer.json file and use it just like a patch

SnowCoder’s picture

Perfect. Thanks for being helpful and teaching me something new :)

smustgrave’s picture

It was pointed out to me you shouldn't point directly to the URL but download the file instead. For security purposes.

quietone’s picture

Status: Reviewed & tested by the community » Needs review

I have only skimmed the IS and the comments. I notice that the changes made to the code in #5 have been tested but have not had a code review.

Setting to NR for a code review.

Lendude’s picture

Status: Needs review » Needs work
Issue tags: +Needs tests

The change looks good, but the fact that just using this plugin should trigger this warning, it feels we have no test coverage for this plugin, and we should probably add it.

smustgrave’s picture

Status: Needs work » Needs review
Issue tags: -Needs tests
FileSize
3.06 KB
1.57 KB
3.05 KB

Took a shot at the test.

While testing with the original MR I was getting

Drupal\Core\Config\Schema\SchemaIncompleteException : Schema errors for core.entity_view_display.node.article.default with the following errors: core.entity_view_display.node.article.default:content.qymfsdps.settings.image_link missing schema, core.entity_view_display.node.article.default:content.qymfsdps.settings.image_loading missing schema

So maybe the default settings aren't needed because we aren't using those settings? Could be wrong.

ambikahirode’s picture

FileSize
634.96 KB

Patch in #16 Applied Cleanly and working fine on local 9.4

danflanagan8’s picture

@smustgrave, I have ideas about the schema validation error.

The schema for the image_url formatter is as follows:

field.formatter.settings.image_url:
  type: mapping
  label: 'Image URL formatter settings'
  mapping:
    image_style:
      type: string
      label: 'Image style'

When the parent::defaultSettings() are added, we get additional settings for image_link and image_loading. Those settings are not defined in the schema for the image_url formatter, so that is going to lead to schema validation errors.

So I would say definitely do not want to add the parent's default settings. And they aren't even needed as long as the ImageFormatter can account for empty values of image_loading and image_link, which I think has to be the goal here.

Probably at this point it no longer makes sense for ImageUrlFormatter to extend ImageFormatter. But untangling that would be a lot harder than simply making the ImageFormatter code a bit more defensive.

Hope that helps!

carolpettirossi’s picture

I've just tested patch #16, and it renders the image instead of just printing the URL/path.

ameymudras’s picture

Status: Needs review » Reviewed & tested by the community
FileSize
72.45 KB
68.35 KB
172.73 KB

Tested on Drupal 9.4.x and php 8.1

- Issue summary is clear and describes the problem
- was able to reproduce the issue
- The patch applies cleanly and fixes the issue
- Tests pass

Marking this as RTBC

ppblaauw’s picture

Applied #16 Works

danflanagan8’s picture

Status: Reviewed & tested by the community » Needs work
Issue tags: +Needs tests

I believe 100% that the patch fixes the pho error. And the approach in the MR is 100% not what we want, as described in #18. But we can't set this to RTBC yet. We still need a fail test.

@smustgrave made an excellent attempt in #16 for a tests-only patch, but the tests passed. We as a community still need to get the fail test sorted out.

smustgrave’s picture

Status: Needs work » Needs review
FileSize
944 bytes
1.57 KB
3.05 KB

The last submitted patch, 23: 3291622-23-tests-only.patch, failed testing. View results

danflanagan8’s picture

Status: Needs review » Needs work

Thanks, @smustgrave! Fail test fails now, but I think it can be meaningfully improved.

1. I think testImageLoadingAttribute() is the wrong place for this since it doesn't really have anything to do with the loading setting. I would prefer to see this in _testImageFieldFormatters, which is in the same class. At the very end of that method there are some existing assertions related to the image_url formatter. That seems like the most logical place to put an additional assertion like this.

2. I think you can drop the assertion related to the absence of the php warning. If there is a warning, the test will fail before even getting to that assertion.

+++ b/core/modules/image/tests/src/Functional/ImageFieldDisplayTest.php
@@ -464,6 +464,18 @@ public function testImageLoadingAttribute(): void {
+    $this->assertSession()->responseNotContains('Warning: Trying to access array offset on value of type null in Drupal\image\Plugin\Field\FieldFormatter\ImageFormatter->settingsSummary()');

You should be able to just assert that some expected settings summary text is present.

smustgrave’s picture

sure. Made those updates.

danflanagan8’s picture

Status: Needs review » Needs work

@smustgrave, I'm channeling my inner committer and the test is not quite there. I'm feeling like a should have been clearer and more expansive on a couple things in my previous comment.

+++ b/core/modules/image/tests/src/Functional/ImageFieldDisplayTest.php
@@ -230,6 +230,17 @@ public function _testImageFieldFormatters($scheme) {
+    // Test to make sure null error is not appearing.

More accurately we're testing that the settings summary is correct for the image_url formatter. I don't think we want this comment to be so specific to the error in this issue. Can we change to something like "Test the settings summary."?

+++ b/core/modules/image/tests/src/Functional/ImageFieldDisplayTest.php
@@ -230,6 +230,17 @@ public function _testImageFieldFormatters($scheme) {
+    $this->drupalGet("admin/structure/types/manage/" . $node->getType() . "/display");

After getting to the manage display page, we should assert that the settings summary appears as expected, because that's at the heart of what is being tested here. I think the expected summary would be "image_style: Thumbnail (100×100)". Can we assert that this text is present?

+++ b/core/modules/image/tests/src/Functional/ImageFieldDisplayTest.php
@@ -20,8 +20,8 @@ class ImageFieldDisplayTest extends ImageFieldTestBase {
   use TestFileCreationTrait {
-    getTestFiles as drupalGetTestFiles;
-    compareFiles as drupalCompareFiles;
+    TestFileCreationTrait::getTestFiles as drupalGetTestFiles;
+    TestFileCreationTrait::compareFiles as drupalCompareFiles;
   }

I also forgot to comment on this in my previous notes. This looks out of scope and we should revert this change. Even positive changes like this tend to hold up commits when they are out of scope.

Sorry again that my previous comment was not clearer. I swear I'm not trying to make extra work for you!

smustgrave’s picture

No I appreciate all the rapid feedback!

Status: Needs review » Needs work

The last submitted patch, 28: 3291622-28.patch, failed testing. View results

smustgrave’s picture

Status: Needs work » Needs review
FileSize
611 bytes
3.29 KB
danflanagan8’s picture

Status: Needs review » Needs work

Almost done, @smustgrave!

There are two lines at the end of you patch that are duplicated a few lines above. Can you remove these lines?

+++ b/core/modules/image/tests/src/Functional/ImageFieldDisplayTest.php
@@ -230,6 +233,20 @@ public function _testImageFieldFormatters($scheme) {
+    $expected_url = \Drupal::service('file_url_generator')->transformRelative(ImageStyle::load('thumbnail')->buildUrl($image_uri));
+    $this->assertEquals($expected_url, $node->{$field_name}->view($display_options)[0]['#markup']);

Then I'll flip the switch to RTBC! Thanks for all the hard work getting this across the finish line.

smustgrave’s picture

Status: Needs work » Needs review
FileSize
796 bytes
3.06 KB

Sure!

Status: Needs review » Needs work

The last submitted patch, 32: 3291622-32.patch, failed testing. View results

danflanagan8’s picture

Version: 9.4.x-dev » 9.5.x-dev

Those fails all look unrelated, but not random. I think head is broken.

Can we get the test only patch too, @smustgrave? This version of the test has not failed yet here. In #28 it failed because of the logged out state. We need to run it and show that it fails because of the settings summary bug.

I also just noticed we're targeting the wrong branch. I wouldn't expect any re-rolling to be required though.

Back to NW to get the latest test only patch.

smustgrave’s picture

Status: Needs work » Needs review
FileSize
1.58 KB
3.06 KB

Re uploaded the full patch too

The last submitted patch, 35: 3291622-35-tests-only.patch, failed testing. View results

danflanagan8’s picture

Status: Needs review » Reviewed & tested by the community

Alright! That fail test triggers the exact error described in the IS:

1) Drupal\Tests\image\Functional\ImageFieldDisplayTest::testImageFieldFormattersPublic
Exception: Warning: Trying to access array offset on value of type null
Drupal\image\Plugin\Field\FieldFormatter\ImageFormatter->settingsSummary()

The patch fixes it.

The patch has been used by the community.

RTBC!

smustgrave’s picture

thanks for all the help!

catch’s picture

Let's open a follow-up to make ImageUrlFormatter extend directly from ImageFormatterBase instead of ImageFormatter. It looks like the new test coverage will still be relevant once we've done that though too which is great.

quietone’s picture

Issue tags: +Needs followup

Adding tag for #40.

smustgrave’s picture

lauriii’s picture

Status: Reviewed & tested by the community » Needs review

Isn't the config schema for image_loading also incorrect given that the value is not marked as nullable?

smustgrave’s picture

can you elaborate more please?

danflanagan8’s picture

Status: Needs review » Reviewed & tested by the community

Thanks for the review @lauriii

I only find three instances in core of nullable: so it does not appear to be in common usage within our schema. I had never heard of this before.

Locally, I added nullable: true to image_loading and the fail test still fails. To me that indicates that the bug here is unrelated to image_loading being specified as nullable. If the schema should be updated, it should probably be done in a separate issue.

I'm going to throw this back to RTBC.

jennypanighetti’s picture

Patch #32 worked for me on 9.4.5

KurtTrowbridge’s picture

Confirming that #35 fixed the issue for me as well on two sites, both on 9.4.5. Thanks!

catch’s picture

Status: Reviewed & tested by the community » Needs work

Looking at #3306066: Make ImageUrlFormatter extend directly from ImageFormatterBase I think we should fold it back into this issue. It might mean we don't need to change any logic except for what gets subclassed - test coverage will show whether or not that's the case.

smustgrave’s picture

Status: Needs work » Needs review
FileSize
2.52 KB
5.75 KB

Moved over changes from https://www.drupal.org/project/drupal/issues/3306066 and closed it out.

Status: Needs review » Needs work

The last submitted patch, 49: 3291622-49.patch, failed testing. View results

smustgrave’s picture

Status: Needs work » Needs review
FileSize
3.52 KB
7.78 KB

The last submitted patch, 49: 3291622-49.patch, failed testing. View results

smustgrave’s picture

Not sure why it retested #49 so please ignore that.

dhirendra.mishra’s picture

Version: 9.5.x-dev » 9.4.x-dev
FileSize
1.39 KB

Here is the patch against 9.4.5 where only two below notices are coming.

Notice: Trying to access array offset on value of type null in /mnt/www/html/veoliad801dev4/docroot/core/modules/image/src/Plugin/Field/FieldFormatter/ImageFormatter.php on line 210

Notice: Trying to access array offset on value of type null in /mnt/www/html/veoliad801dev4/docroot/core/modules/image/src/Plugin/Field/FieldFormatter/ImageFormatter.php on line 167

catch’s picture

+++ b/core/modules/image/src/Plugin/Field/FieldFormatter/ImageFormatter.php
@@ -164,7 +164,7 @@ public function settingsForm(array $form, FormStateInterface $form_state) {
       '#type' => 'radios',
-      '#default_value' => $image_loading['attribute'],
+      '#default_value' => !empty($image_loading['attribute']) ? $image_loading['attribute'] : '',
       '#options' => $loading_attribute_options,
       '#description' => $this->t('Select the loading attribute for images. <a href=":link">Learn more about the loading attribute for images.</a>', [
         ':link' => 'https://html.spec.whatwg.org/multipage/urls-and-fetching.html#lazy-loading-attributes',
@@ -206,9 +206,11 @@ public function settingsSummary() {

@@ -206,9 +206,11 @@ public function settingsSummary() {
     }
 
     $image_loading = $this->getSetting('image_loading');
-    $summary[] = $this->t('Image loading: @attribute', [
-      '@attribute' => $image_loading['attribute'],
-    ]);
+    if (!empty($image_loading)) {
+      $summary[] = $this->t('Image loading: @attribute', [
+        '@attribute' => $image_loading['attribute'],
+      ]);
+    }
 

Can these hunks be dropped from the patch if the url formatter no longer needs them?

gajendra_sharma’s picture

Status: Needs review » Reviewed & tested by the community
FileSize
2.79 KB

Patch No. #51 tested and applied successfully on drupal 9.4.x version.

catch’s picture

Status: Reviewed & tested by the community » Needs work

Still needs review and an answer to #55.

danflanagan8’s picture

Hi, @gajendra_sharma! Thanks for jumping in here.

We as a community need to be careful about setting an issue to RTBC. That's the sign to core committers that the issue is ready for their attention. Core committers have very little precious time, and we don't want them to waste any of it reviewing issues that aren't actually ready.

If you want to update the patch #54 to address the comments in #55, that would be welcome. And any new patch should (almost) always be accompanied by an interdiff.

If you need help with contribution, the #contribute channel in Drupal Slack is a great resource. And this issue has been tagged by the Bug Smash Initiative, so the #bugsmash channel would be a good place to turn as well.

Cheers!

smustgrave’s picture

Version: 9.4.x-dev » 9.5.x-dev

Moving back to 9.5.x not sure why it was moved to 9.4

#51 should be used going forward for changes. before breaking changes start getting mixed in. Hiding #54 and #56

Looking into #55

smustgrave’s picture

smustgrave’s picture

Status: Needs work » Needs review
FileSize
1.19 KB
6.3 KB

Removing those changes mentioned in #55 didn't cause any issues.

catch’s picture

Status: Needs review » Reviewed & tested by the community

#61 looks like I hoped it would - no longer needs the special casing.

alexpott’s picture

Status: Reviewed & tested by the community » Fixed

Committed and pushed b8ad2d90b4 to 10.1.x and 3cdcdbc45f to 10.0.x and a3c8bb27f1 to 9.5.x. Thanks!

diff --git a/core/modules/image/src/Plugin/Field/FieldFormatter/ImageUrlFormatter.php b/core/modules/image/src/Plugin/Field/FieldFormatter/ImageUrlFormatter.php
index 71bf26bc3a..78ea4061eb 100644
--- a/core/modules/image/src/Plugin/Field/FieldFormatter/ImageUrlFormatter.php
+++ b/core/modules/image/src/Plugin/Field/FieldFormatter/ImageUrlFormatter.php
@@ -113,8 +113,8 @@ public function settingsForm(array $form, FormStateInterface $form_state) {
       '#empty_option' => t('None (original image)'),
       '#options' => $image_styles,
       '#description' => $description_link->toRenderable() + [
-          '#access' => $this->currentUser->hasPermission('administer image styles'),
-        ],
+        '#access' => $this->currentUser->hasPermission('administer image styles'),
+      ],
     ];
 
     return $element;

Fixed coding standards on commit.

diff --git a/core/modules/image/src/Plugin/Field/FieldFormatter/ImageUrlFormatter.php b/core/modules/image/src/Plugin/Field/FieldFormatter/ImageUrlFormatter.php
index 78ea4061eb..dc4557949c 100644
--- a/core/modules/image/src/Plugin/Field/FieldFormatter/ImageUrlFormatter.php
+++ b/core/modules/image/src/Plugin/Field/FieldFormatter/ImageUrlFormatter.php
@@ -107,10 +107,10 @@ public function settingsForm(array $form, FormStateInterface $form_state) {
       Url::fromRoute('entity.image_style.collection')
     );
     $element['image_style'] = [
-      '#title' => t('Image style'),
+      '#title' => $this->t('Image style'),
       '#type' => 'select',
       '#default_value' => $this->getSetting('image_style'),
-      '#empty_option' => t('None (original image)'),
+      '#empty_option' => $this->t('None (original image)'),
       '#options' => $image_styles,
       '#description' => $description_link->toRenderable() + [
         '#access' => $this->currentUser->hasPermission('administer image styles'),
@@ -133,10 +133,10 @@ public function settingsSummary() {
     // their styles in code.
     $image_style_setting = $this->getSetting('image_style');
     if (isset($image_styles[$image_style_setting])) {
-      $summary[] = t('Image style: @style', ['@style' => $image_styles[$image_style_setting]]);
+      $summary[] = $this->t('Image style: @style', ['@style' => $image_styles[$image_style_setting]]);
     }
     else {
-      $summary[] = t('Original image');
+      $summary[] = $this->t('Original image');
     }
 
     return array_merge($summary, parent::settingsSummary());

Also fixing use of t() in plugins... shoudl be $this->t()

  • alexpott committed b8ad2d9 on 10.1.x
    Issue #3291622 by smustgrave, g-brodiei, ameymudras, ambikahirode,...

  • alexpott committed 3cdcdbc on 10.0.x
    Issue #3291622 by smustgrave, g-brodiei, ameymudras, ambikahirode,...

  • alexpott committed a3c8bb2 on 9.5.x
    Issue #3291622 by smustgrave, g-brodiei, ameymudras, ambikahirode,...

Status: Fixed » Closed (fixed)

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