Add inline SVG support for stage_file_proxy

Created on 16 January 2023, almost 2 years ago
Updated 20 February 2023, almost 2 years ago

Problem/Motivation

A fatal error occurs when trying to display a SVG image that does not exist when:

  • The field formatter is configured to display the SVG image inline;
  • And the module stage_file_proxy is enabled.

The following error gets logged:

ValueError: DOMDocument::loadXML(): Argument #1 ($source) must not be empty in DOMDocument->loadXML() (line 241 of /web/modules/contrib/svg_image_field/src/Plugin/Field/FieldFormatter/SvgImageFieldFormatter.php)

This situation can occur when putting a site locally: use a copy of the live database, but do not download all files (from sites/default/files) from the live site.

Steps to reproduce

  1. Enable modules svg_image_field, node and stage_file_proxy.
  2. Create a node type and add a field of type "svg_image_field" on it.
  3. On the display settings, for the svg field, choose the formatter "SVG Image Field formatter" and enable the option "Output SVG inline".
  4. Create a node and upload a SVG.
  5. Manually remove the SVG from the file system.
  6. Load the node page.

A fatal error occurs and the error noted above gets logged.

Proposed resolution

In SvgImageFieldFormatter there is a check if file exists before trying to display the image, but that check gets skipped when the stage_file_proxy module is enabled.
Add a check when the SVG file failed to load in memory before trying to pass it to DOMDocument::loadXML().

Remaining tasks

  • Review & commit

User interface changes

None.

API changes

None.

Data model changes

None.

A fix and tests will follow.

🐛 Bug report
Status

Fixed

Version

2.2

Component

Code

Created by

🇳🇱Netherlands megachriz

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

  • Assigned to jwilson3
  • Status changed to Needs work almost 2 years ago
  • Issue was unassigned.
  • Status changed to Needs review almost 2 years ago
  • 🇳🇱Netherlands megachriz

    I updated the code, made it somewhat cleaner.

    There is now a method called generateInlineSvgData(). I added "Data" to the end, because its return value is going to be assigned to $element['#svg_data'] if it is not empty.

    The inline setting check now looks as follows:

          // Set properties based on if the SVG is displayed inline or not.
          if ($this->getSetting('inline') && $svg_data = $this->generateInlineSvgData($uri, $attributes)) {
            $element['#inline'] = TRUE;
            $element['#svg_data'] = $svg_data;
          }
          else {
            $element['#inline'] = FALSE;
            $element['#uri'] = $uri;
          }
    

    I thought about the following approach too, where #inline and #uri are set earlier and then overridden here:

          if ($this->getSetting('inline') && $svg_data = $this->generateInlineSvgData($uri, $attributes)) {
            $element['#inline'] = TRUE;
            $element['#uri'] = NULL;
            $element['#svg_data'] = $svg_data;
          }
    

    I this case there is no else code block. I went the else block because then #uri didn't have to be set and unset again. I think an approach like that would make more sense if inline SVG image generation would have taken place in a subclass of SvgImageFieldFormatter. Then there would have been a method that would call the parent method if generating an inline SVG failed.

  • Status changed to Needs work almost 2 years ago
  • 🇪🇨Ecuador jwilson3
    • A read through of the code changes looks good at first glance, haven't taken a chance to test this manually, and I do want to do that first.
    • I'd like to change the verb "generate" in the method signature to "load", which seems more accurate in this context.
    • Should we add the new #uri variable to the theme hook info?
    • Looks like the MR is no longer mergeable due to some issue queue activity from Martin. Apologies for dropping the ball — I got busy on other things. :(
  • Status changed to Needs review almost 2 years ago
  • 🇳🇱Netherlands megachriz

    I rebased the code on the latest 2.2.x. That was quite a thing! I hope I did it correctly. The rebase caused double moduleHandler code that I cleaned up in a new commit.

    I'd like to change the verb "generate" in the method signature to "load", which seems more accurate in this context.

    Method generateInlineSvgData() is renamed to loadInlineSvgData().

    Should we add the new #uri variable to the theme hook info?

    "uri" looks like to be already part of that:

    /**
     * Implements hook_theme().
     */
    function svg_image_field_theme() {
      return [
        'svg_image_field_formatter' => [
          'variables' => [
            'inline' => FALSE,
            'attributes' => NULL,
            'uri' => NULL,
            'svg_data' => NULL,
            'link_url' => NULL,
          ],
        ],
      ];
    }
    
  • First commit to issue fork.
  • Status changed to Fixed almost 2 years ago
  • 🇪🇨Ecuador jwilson3

    Tested locally and confirmed the rebase is working correctly. Merged after a little bit of comment improvements.

    Thanks @MegaChriz!

Production build 0.71.5 2024