Bug when viewing PDF if the display has a Header

Created on 5 August 2023, over 1 year ago
Updated 12 February 2024, 11 months ago

Problem/Motivation

The module breaks when trying to view a PDF generated using views_pdf if the display has a header. This is because
FPDI->_format_header_footer() uses format_string() - a Drupal function which was deprecated in Drupal 8 and removed in Drupal 9.

Steps to reproduce

  • Install Drupal 10
  • Install views_pdf and dependencies using composer
  • Create a new view
  • Add a PDF display and give it a path
  • View the PDF display at the path you gave it
  • Add any Views Header (I've tried Global: Text area, Global: Unfiltered text and Global: View area) and save the view.
  • View the PDF display at the path you gave it
  • The view is now broken with the error
  • Error: Call to undefined function Drupal\views_pdf\PdfLibrary\format_string() in Drupal\views_pdf\PdfLibrary\FPDI->_format_header_footer() (line 198 of [snip]/web/modules/contrib/views_pdf/src/PdfLibrary/FPDI.php).

Proposed resolution

Use \Drupal\Component\Render\FormattableMarkup instead of format_string()

So far I've not had massive success, but I'm working on it. But would welcome any assistance.

I've tried changing the original function from

  function _format_header_footer($h_f) {
    $display = $this->display;
    // Get the leading/trailing header/footer option (e.g. "succeed_header").
    if ((empty($this->position) || $this->position == 'closing' || $display->getOption("{$this->position}_{$h_f}")) &&
      !empty($rendered = $display->renderArea("$h_f"))) {
      $this->SetTextColorArray($display->getOption("{$h_f}_font_color"));
      $this->SetFont(
        $display->getOption("{$h_f}_font_family"),
        implode('', $display->getOption("{$h_f}_font_style")),
        $display->getOption("{$h_f}_font_size")
      );
      $yvar = "y_$h_f";
      $this->writeHTMLCell(0, 0,
        (float)$this->lMargin, (float)$this->$yvar,
        format_string($rendered, array('!page' => $this->getPage())),
        0, 0,
        FALSE, TRUE,
        $display->getOption("{$h_f}_text_align")
      );
    }
    if ($h_f == 'footer' && $this->position == 'closing') {
      $this->position = 'succeed';
    }
  }

to this

  use Drupal\Component\Render\FormattableMarkup;

  function _format_header_footer($h_f) {
    $display = $this->display;
    // Get the leading/trailing header/footer option (e.g. "succeed_header").
    if ((empty($this->position) || $this->position == 'closing' || $display->getOption("{$this->position}_{$h_f}")) &&
      !empty($rendered = $display->renderArea("$h_f"))) {
      $this->SetTextColorArray($display->getOption("{$h_f}_font_color"));
      $this->SetFont(
        $display->getOption("{$h_f}_font_family"),
        implode('', $display->getOption("{$h_f}_font_style")),
        $display->getOption("{$h_f}_font_size")
      );
      $yvar = "y_$h_f";
      $text = new FormattableMarkup($rendered, array('!page' => $this->getPage()));
      $this->writeHTMLCell(0, 0,
        (float)$this->lMargin, (float)$this->$yvar,
        $text,
        0, 0,
        FALSE, TRUE,
        $display->getOption("{$h_f}_text_align")
      );
    }
    if ($h_f == 'footer' && $this->position == 'closing') {
      $this->position = 'succeed';
    }
  }

which stops it breaking, but is passing in the header as an array. So far I've not quite worked out how to resolve that.

πŸ› Bug report
Status

Needs review

Version

3.0

Component

Code

Created by

πŸ‡¬πŸ‡§United Kingdom sagraham

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

Merge Requests

Comments & Activities

  • Issue created by @sagraham
  • πŸ‡³πŸ‡±Netherlands hanskuipers

    This seems to work, replace the original

    
          $yvar = "y_$h_f";
          $this->writeHTMLCell(0, 0,
            (float)$this->lMargin, (float)$this->$yvar,
            format_string($rendered, array('!page' => $this->getPage())),
            0, 0,
            FALSE, TRUE,
            $display->getOption("{$h_f}_text_align")
          );
    
    

    with this

          $yvar = "y_$h_f";
          $renderer = \Drupal::service('renderer');
          $html = $renderer->render($rendered);
          $markup = new  \Drupal\Component\Render\FormattableMarkup($html, array('!page' => $this->getPage()));
          $this->writeHTMLCell(0, 0,
            (float)$this->lMargin, (float)$this->$yvar,
            $markup->__toString(),
            //format_string($rendered, array('!page' => $this->getPage())),
            0, 0,
            FALSE, TRUE,
            $display->getOption("{$h_f}_text_align")
          );
    
    
  • First commit to issue fork.
  • Status changed to Needs review 11 months ago
  • πŸ‡ΊπŸ‡ΈUnited States rclemings

    Patch for those who prefer the old-fashioned way (including me).

Production build 0.71.5 2024