Fieldsets are lost using 3.1.2

Created on 1 March 2024, 9 months ago
Updated 25 July 2024, 4 months ago

First, thank you for a great module!

Problem/Motivation

I am using fieldsets implemented by the field_group module on my nodes and they are lost with version 3.1.2 when generating the PDF version of the node. All was working fine with version 3.0.2 before trying to upgrade to 3.1.2.

I found the cause of this problem inside the buildPdfContent function in file "printable/modules/printable_pdf/src/Plugin/PrintableFormat/PdfFormat.php".

With version 3.0.2, the buildPdfContent was returning a string of the rendered content and now with version 3.1.2, it is returning a Drupal\Core\Render\Markup Object. I do not understand why it is working at all with 3.1.2...

Here is the buildPdfContent function in 3.1.2 :

  public function buildPdfContent() {
    $content = parent::buildContent();

    $renderedContent = $this->renderer->executeInRenderContext(new RenderContext(),
      function () use ($content) {
        return $this->renderer->render($content['#content']);
      });
    $renderedContent = preg_replace(['#printable://#', '/\?itok=.*"/'], [
      '',
      '"',
    ], $renderedContent);

    $content['#content'] = [
      '#markup' => $this->extractLinks($renderedContent),
    ];

    return $this->renderer->executeInRenderContext(new RenderContext(),
      function () use ($content) {
        return $this->renderer->render($content);
      });
  }

And in version 3.0.2, it used to be :

  public function buildPdfContent() {
    $content = parent::buildContent();

    $content = $this->renderer->executeInRenderContext(new RenderContext(),
      function () use ($content) {
        return $this->renderer->render($content);
      });

    $content = preg_replace(['#printable://#', '/\?itok=.*"/'], ['', '"'], $content);
    $rendered_page = parent::extractLinks($content);
    return $rendered_page;
  }

The first renderer in version 3.1.2 is now using $content['#content'] instead of $content directly and I believe that new second renderer in 3.1.2 to be in error since it is not returning the correct function's return type.

Both functions are not functionally equivalent and when I use the buildPdfContent from version 3.0.2 inside 3.1.2 without any other modification, all is working well again.

Steps to reproduce

Simply use the field_group module to create a fieldset containing some fields on a node and try to generate the PDF.

Proposed resolution

Fix the buildPdfContent function so it returns the right HTML string for the rendered content to print as PDF.

Remaining tasks

Determine why the buildPdfContent function was refactored like that and fix it for good.

Any help would be greatly appreciated!

Thank you.

🐛 Bug report
Status

Fixed

Version

3.1

Component

Code

Created by

🇨🇦Canada leducdubleuet Chicoutimi QC

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

Comments & Activities

  • Issue created by @leducdubleuet
  • 🇦🇺Australia nigelcunningham Geelong

    Thanks for the report.

    I'll download the field group module and seek to reproduce the issue.

  • Status changed to Postponed: needs info 9 months ago
  • 🇦🇺Australia nigelcunningham Geelong

    Hi again.

    I've not had success in reproducing the issue. Could I get you to give me a step-by-step, starting with a site install, please?

    Thanks!

  • 🇨🇦Canada leducdubleuet Chicoutimi QC

    I agree that at first glance the fieldset seems to be there since its legend is displayed but I assure you, the fieldset itself is not rendered as it is now using 3.1.2.

    You can use the custom CSS feature to include some CSS for fieldsets in your print.css for example :

    fieldset {
      padding: 30px;
      border-radius: 8px;
      border: 1px solid #ccc;
    }

    You will then see more easily that the fieldset is non-existent in the generated PDF.

    You can also put a \Drupal::logger inside the getOutput function in the file "printable/modules/printable_pdf/src/Plugin/PrintableFormat/PdfFormat.php" like so :

        if ($this->pdfGenerator->usePrintableDisplay()) {
          $raw_content = $this->buildPdfContent();
          \Drupal::logger('buildPdfContent')->debug('buildPdfContent @raw_content', array('@raw_content' => print_r($raw_content, true)));
          ...
    

    You will then observe the following rendered code for example using the buildPdfContent from 3.1.2 with the double rendering:

    Version 3.1.2
    -----------------------------------------
    <div class="field field--name-field-societe field--type-string field--label-inline clearfix">
      <div class="field__label">Société</div>
      <div class="field__item">TEST</div>
    </div>
    
    <span class="fieldset-legend">Coordonnées</span>
    <div class="fieldset-wrapper">
      <div class="field field--name-field-telephone-principal field--type-string field--label-above">
        <div class="field__label">Téléphone principal</div>
        <div class="field__item">418-555-1212</div>
      </div>
      ...
    </div>
    

    And using the buildPdfContent code from 3.0.2, you get the following code which includes the fieldset rendered correctly :

    Version 3.0.2
    -----------------------------------------
    <div class="field field--name-field-societe field--type-string field--label-inline clearfix">
      <div class="field__label">Société</div>
      <div class="field__item">TEST</div>
    </div>
    
    <fieldset class="group-contact-details js-form-item form-item js-form-wrapper form-wrapper">
      <legend>
        <span class="fieldset-legend">Coordonnées</span>
      </legend>
      <div class="fieldset-wrapper">
        <div class="field field--name-field-telephone-principal field--type-string field--label-above">
          <div class="field__label">Téléphone principal</div>
          <div class="field__item">418-555-1212</div>
        </div>
        ...
      </div>
    </fieldset>

    Visiting the path /node/[NID]/printable/print for the same content, we get the fieldset rendered correctly and the corresponding code that renders the content is in the getOutput() function inside the file "printable/src/Plugin/PrintableFormatBase.php" :

      public function getOutput() {
        $content = $this->buildContent();
    
        $content = $this->renderer->executeInRenderContext(new RenderContext(),
          function () use ($content) {
            return $this->renderer->render($content);
          });
        return $this->extractLinks($content);
      }
    

    There is no double rendering there like it is done in buildPdfContent() now in version 3.1.2.

    That is why I believe the buildPdfContent() function should be like it was in version 3.0.2 with the only difference in the rendering between PrintableFormatBase.php and PdfFormat.php being the preg_match call to make images working...

    Let me know if you need more details?

    Thank you.

  • Status changed to Active 9 months ago
  • 🇨🇦Canada leducdubleuet Chicoutimi QC
  • 🇨🇦Canada leducdubleuet Chicoutimi QC

    Hello @Nigel Cunningham

    I've provided more infos a couple weeks ago, could you have a look into this please?

    Thank you!

  • 🇨🇦Canada leducdubleuet Chicoutimi QC

    Here is a patch that simply put back the code for buildPdfContent from 3.0.2 which works like a charm.

    Can somebody have a look at this please, I really believe that version 3.1.2 is broken as it is!

    Thank you!

  • 🇦🇺Australia nigelcunningham Geelong

    Sorry for the slow reply; looking at it now.

  • Status changed to Fixed 5 months ago
  • 🇦🇺Australia nigelcunningham Geelong

    The markup just needed to be a Markup object rather than a raw string - it was getting XSS cleanup applied to it again (it should be safe already because the markup has been generated via rendering once already).

    Thanks for your report and help towards debugging the issue.

  • 🇨🇦Canada leducdubleuet Chicoutimi QC

    Hello Nigel!

    Thank you for your reply, no problem for the delay, life happens!

    I tested current dev and it is working properly now! Although I still do not understand why the function buildPdfContent() is rendering the content twice now? But it does not really matter, it is working like this so since this is major for people using fieldsets, would it be possible to have a new release with this fix please?

    Thanks again for your time!

  • 🇦🇺Australia nigelcunningham Geelong

    I've forgotten the gory details, but it's not rendering the whole thing again - it renders the inner part and then adds the other bits.

    Re a new release, sure!

  • 🇨🇦Canada leducdubleuet Chicoutimi QC

    Great job for the quick new release, thank you very much!

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

Production build 0.71.5 2024