Commit 07c47cd0 authored by Marcin Grabias's avatar Marcin Grabias
Browse files

Issue #3295371 by Graber: Implement pdf export

parent 830f7a5c
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -5,6 +5,7 @@
  "license": "GPL-2.0+",
  "require": {
    "drupal/views_bulk_operations": ">=3.5",
    "phpoffice/phpspreadsheet": "^1.6"
    "phpoffice/phpspreadsheet": "^1.6",
    "dompdf/dompdf": "^1.0 | ^2.0"
  }
}
+41 −4
Original line number Diff line number Diff line
@@ -8,7 +8,14 @@ views_bulk_operations.action_config.vbo_export_generate_csv_action:
    field_override:
      type: boolean
    field_config:
      type: ignore
      type: sequence
      sequence:
        type: mapping
        mapping:
          active:
            type: boolean
          label:
            type: string
    separator:
      type: string
      label: 'CSV separator'
@@ -17,10 +24,40 @@ views_bulk_operations.action_config.vbo_export_generate_xlsx_action:
  type: views_bulk_operations_action_config
  label: 'Export to xlsx'
  mapping:
    strip_tags:
      type: boolean
      label: 'Should HTML be stripped?'
    field_override:
      type: boolean
    field_config:
      type: ignore
    separator:
      type: sequence
      sequence:
        type: mapping
        mapping:
          active:
            type: boolean
          label:
            type: string

views_bulk_operations.action_config.vbo_export_generate_pdf_action:
  type: views_bulk_operations_action_config
  label: 'Export to xlsx'
  mapping:
    strip_tags:
      type: boolean
      label: 'Should HTML be stripped?'
    field_override:
      type: boolean
    field_config:
      type: sequence
      sequence:
        type: mapping
        mapping:
          active:
            type: boolean
          label:
            type: string
    orientation:
      type: string
    paper_size:
      type: string
      label: 'CSV separator'
+27 −20
Original line number Diff line number Diff line
@@ -22,6 +22,14 @@ abstract class VboExportBase extends ViewsBulkOperationsActionBase implements Co

  const EXTENSION = '';

  /**
   * Some fields should always be excluded from exports.
   */
  const EXCLUDED_FIELDS = [
    'views_bulk_operations_bulk_form',
    'entity_operations',
  ];

  /**
   * The tempstore object.
   *
@@ -65,7 +73,7 @@ abstract class VboExportBase extends ViewsBulkOperationsActionBase implements Co
    array $configuration,
    $plugin_id,
    $plugin_definition,
    StreamWrapperManagerInterface $streamWrapperManager,
    StreamWrapperManagerInterface $stream_wrapper_manager,
    PrivateTempStoreFactory $temp_store_factory,
    TimeInterface $time,
    FileRepositoryInterface $file_repository,
@@ -73,7 +81,7 @@ abstract class VboExportBase extends ViewsBulkOperationsActionBase implements Co
  ) {
    parent::__construct($configuration, $plugin_id, $plugin_definition);

    $this->streamWrapperManager = $streamWrapperManager;
    $this->streamWrapperManager = $stream_wrapper_manager;
    $this->tempStore = $temp_store_factory->get('vbo_export_multiple');
    $this->time = $time;
    $this->fileRepository = $file_repository;
@@ -293,33 +301,32 @@ abstract class VboExportBase extends ViewsBulkOperationsActionBase implements Co
  protected function setHeader() {
    $this->context['sandbox']['header'] = [];
    $header = &$this->context['sandbox']['header'];
    $functional_fields = [
      'views_bulk_operations_bulk_form',
      'entity_operations',
    ];

    foreach ($this->view->field as $id => $field) {
    if ($this->configuration['field_override']) {
      foreach ($this->configuration['field_config'] as $id => $field_settings) {
        if ($field_settings['active']) {
            if (!empty($field_settings['label'])) {
          if ($field_settings['label'] !== '') {
            $header[$id] = $field_settings['label'];
          }
            elseif (isset($this->view->field[$id])) {
          elseif (array_key_exists($id, $this->view->field)) {
            $header[$id] = $this->view->field[$id]->options['label'];
          }
        }
      }
    }

    else {
        $is_excluded = in_array($field->options['plugin_id'], $functional_fields) || $field->options['exclude'];
        // Skip Views Bulk Operations field and excluded fields.
        if ($is_excluded) {
      foreach ($this->view->field as $id => $field) {
        if (
          in_array($field->options['plugin_id'], static::EXCLUDED_FIELDS) ||
          $field->options['exclude']
        ) {
          continue;
        }
        $header[$id] = $field->options['label'];
      }
    }

    return $header;
  }

+142 −0
Original line number Diff line number Diff line
<?php

namespace Drupal\vbo_export\Plugin\Action;

use Dompdf\Adapter\CPDF;
use Dompdf\Dompdf;
use Drupal\Component\Datetime\TimeInterface;
use Drupal\Core\File\FileUrlGeneratorInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Render\Markup;
use Drupal\Core\Render\RendererInterface;
use Drupal\Core\StreamWrapper\StreamWrapperManagerInterface;
use Drupal\Core\TempStore\PrivateTempStoreFactory;
use Drupal\file\FileRepositoryInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
 * Generates pdf.
 *
 * @Action(
 *   id = "vbo_export_generate_pdf_action",
 *   label = @Translation("Generate pdf from selected view results"),
 *   type = ""
 * )
 */
class VboExportPdf extends VboExportBase {

  const EXTENSION = 'pdf';

  /**
   * The renderer.
   */
  protected $renderer;

  /**
   * {@inheritdoc}
   */
  public function __construct(
    array $configuration,
    $plugin_id,
    $plugin_definition,
    StreamWrapperManagerInterface $stream_wrapper_manager,
    PrivateTempStoreFactory $temp_store_factory,
    TimeInterface $time,
    FileRepositoryInterface $file_repository,
    FileUrlGeneratorInterface $file_url_generator,
    RendererInterface $renderer
  ) {
    parent::__construct($configuration, $plugin_id, $plugin_definition, $stream_wrapper_manager, $temp_store_factory, $time, $file_repository, $file_url_generator);

    $this->renderer = $renderer;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
    return new static(
      $configuration,
      $plugin_id,
      $plugin_definition,
      $container->get('stream_wrapper_manager'),
      $container->get('tempstore.private'),
      $container->get('datetime.time'),
      $container->get('file.repository'),
      $container->get('file_url_generator'),
      $container->get('renderer')
    );
  }

  /**
   * {@inheritdoc}
   *
   * Add csv separator setting to preliminary config.
   */
  public function buildPreConfigurationForm(array $form, array $values, FormStateInterface $form_state) {
    $paper_sizes = array_keys(CPDF::$PAPER_SIZES);
    $form['paper_size'] = [
      '#title' => $this->t('Paper size'),
      '#type' => 'select',
      '#options' => array_combine($paper_sizes, $paper_sizes),
      '#default_value' => isset($values['paper_size']) ? $values['paper_size'] : 'letter',
    ];
    $form['orientation'] = [
      '#title' => $this->t('Orientation'),
      '#type' => 'radios',
      '#options' => [
        'portrait' => $this->t('Portrait'),
        'landscape' => $this->t('Landscape'),
      ],
      '#default_value' => isset($values['orientation']) ? $values['orientation'] : 'portrait',
    ];

    $form = parent::buildPreConfigurationForm($form, $values, $form_state);

    return $form;
  }

  /**
   * {@inheritdoc}
   */
  protected function generateOutput() {
    if (!_vbo_export_library_exists(Dompdf::class)) {
      $this->messenger()->addError('Dompdf library not installed.');
      return '';
    }

    $header = $this->getHeader();
    $rows = $this->getCurrentRows();

    $renderable = [
      '#theme' => 'vbo_export_pdf',
      '#items' => [],
      '#title' => $this->view->getTitle() . ' - ' . $this->view->getDisplay()->display['display_title'],
      '#empty_text' => $this->t('There are no items.'),
      '#view_id' => $this->view->id(),
      '#display_id' => $this->view->current_display,
    ];

    foreach ($rows as $row) {
      $item = [
        'fields' => [],
      ];
      foreach ($header as $field_id => $label) {
        $item['fields'][] = [
          'label' => $label,
          'value' => $this->configuration['strip_tags'] ? strip_tags($row[$field_id]) : Markup::create($row[$field_id]),
        ];
      }
      $renderable['#items'][] = $item;
    }

    $html = $this->renderer->renderPlain($renderable);

    $dompdf = new Dompdf();
    $dompdf->loadHtml((string) $html);
    $dompdf->setPaper($this->configuration['paper_size'], $this->configuration['orientation']);
    $dompdf->render();

    return $dompdf->output();
  }

}
+17 −0
Original line number Diff line number Diff line
<h2>{{ title }}</h2>
{% if items %}
  <ol>
    {% for item in items %}
      <li>
        {% for field in item.fields %}
          <h3>{{ field.label }}</h3>
          <p>{{ field.value }}</p>
        {% endfor %}
      </li>
    {% endfor %}
  </ol>
{% else %}
  {% if empty_text %}
    {{ empty_text }}
  {% endif %}
{% endif %}
Loading