Posibility to transform link View PDF to button.

Created on 26 January 2025, 5 months ago

Problem/Motivation

I make some changes in code for make posibility to transform link "View PDF" from module to button.

Its must nicer view and for mi best option.

If you want add this is your module and your decision.

Here before:

And after:

And view:

I add sinitize function for security reazon.

And for default button classes is empty, user need add some css for button, in mi example I use Olivero default button css:

button button-action button--primary button--small

Thanks for your module.

Gracias

Steps to reproduce

Proposed resolution

Remaining tasks

User interface changes

<?php

namespace Drupal\entity_print_views\Plugin\views\area;

use Drupal\Component\Utility\Xss;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Url;
use Drupal\entity_print\Plugin\ExportTypeManagerInterface;
use Drupal\views\Plugin\views\area\AreaPluginBase;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Views area handler for a Print button.
 *
 * @ingroup views_area_handlers
 *
 * @ViewsArea("entity_print_views_link")
 */
class EntityPrintViewsLink extends AreaPluginBase {

  /**
   * The export type manager.
   *
   * @var \Drupal\entity_print\Plugin\ExportTypeManagerInterface
   */
  protected $exportTypeManager;

  /**
   * Constructs a new Entity instance.
   *
   * @param array $configuration
   *   A configuration array containing information about the plugin instance.
   * @param string $plugin_id
   *   The plugin_id for the plugin instance.
   * @param mixed $plugin_definition
   *   The plugin implementation definition.
   * @param \Drupal\entity_print\Plugin\ExportTypeManagerInterface $export_type_manager
   *   The export type manager.
   */
  public function __construct(array $configuration, $plugin_id, $plugin_definition, ExportTypeManagerInterface $export_type_manager) {
    parent::__construct($configuration, $plugin_id, $plugin_definition);
    $this->exportTypeManager = $export_type_manager;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
    return new static(
      $configuration,
      $plugin_id,
      $plugin_definition,
      $container->get('plugin.manager.entity_print.export_type')
    );
  }

  /**
   * {@inheritdoc}
   */
  public function buildOptionsForm(&$form, FormStateInterface $form_state): void {
    parent::buildOptionsForm($form, $form_state);
    $form['export_type'] = [
      '#type' => 'select',
      '#title' => $this->t('Export Type'),
      '#options' => $this->exportTypeManager->getFormOptions(),
      '#required' => TRUE,
      '#default_value' => $this->options['export_type'],
    ];
    $form['link_text'] = [
      '#type' => 'textfield',
      '#title' => $this->t('Link text'),
      '#required' => TRUE,
      '#default_value' => $this->options['link_text'],
    ];
    $form['class'] = [
      '#title' => $this->t('Class'),
      '#description' => $this->t('A CSS class to apply to the link. If using multiple classes, separate them by spaces.'),
      '#type' => 'textfield',
      '#default_value' => $this->options['class'],
    ];

    $displays = $this->view->displayHandlers->getConfiguration();
    $display_options = [];
    foreach ($displays as $display_id => $display_info) {
      $display_options[$display_id] = $display_info['display_title'];
    }
    $form['display_id'] = [
      '#type' => 'select',
      '#title' => $this->t('View Display'),
      '#options' => $display_options,
      '#required' => TRUE,
      '#default_value' => $this->options['display_id'],
    ];
  }

  /**
   * {@inheritdoc}
   */
  public function render($empty = FALSE): array {
    if ($empty && empty($this->options['empty'])) {
      return [];
    }

    // Check if the user add css for button.
    if (!empty($this->options['class'])) {
      // Definir las clases proporcionadas.
      $user_defined_classes = $this->options['class'];
      // Sanitizar cada clase usando Xss::filter().
      $sanitized_classes = explode(' ', $user_defined_classes);
      foreach ($sanitized_classes as $class) {
      $sanitized_classes[] = Xss::filter($class);
      }
    } else {
      $sanitized_classes = [];
    }

    $route_params = [
      'export_type' => !empty($this->options['export_type']) ? $this->options['export_type'] : 'pdf',
      'view_name' => $this->view->storage->id(),
      'display_id' => $this->options['display_id'],
    ];

    return [
      '#type' => 'link',
      '#title' => $this->options['link_text'],
      '#url' => Url::fromRoute('entity_print_views.view', $route_params, [
        'query' => $this->view->getExposedInput() + ['view_args' => $this->view->args],
        'attributes' => [
          'class' => $sanitized_classes,
        ],
      ]),
    ];
  }

  /**
   * {@inheritdoc}
   */
  protected function defineOptions(): array {
    $options = parent::defineOptions();
    $options['export_type'] = ['default' => 'pdf'];
    $options['link_text'] = ['default' => 'View PDF'];
    $options['class'] = ['default' => ''];
    $options['display_id'] = ['default' => $this->view->current_display];
    return $options;
  }
}

API changes

Data model changes

Feature request
Status

Active

Version

2.0

Component

Code

Created by

🇪🇸Spain ady1503

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

Merge Requests

Comments & Activities

  • Issue created by @ady1503
  • 🇪🇸Spain ady1503

    I have little time now, the next option is to also transform the "View PDF" link into a button in the nodes.

    It would be necessary to add this option in the module configuration form to be able to alter the link label per button with a CSS format.

    When I have it I'm going to share it in case it works for someone.

    If anyone wants to help, I say thank you in advance.

    Thank you.

  • First commit to issue fork.
  • 🇦🇺Australia jannakha Brisbane!

    @ady1503 thanks for code you've provided. I've moved code to MR and updated task description.

    Problem/Motivation

    Hello.

    I make some changes in code for make posibility to transform link "View PDF" in Views, from module to button.

    Its must nicer view and for mi best option.

    If you want add this is your module and your decision.

    Here before:

    And after:

    And view:

    I add sinitize function for security reazon.

    And for default button classes is empty, user need add some css for button, in mi example I use Olivero default button css:

    button button-action button--primary button--small

    Thanks for your module.

    Gracias

    Steps to reproduce

    Proposed resolution

    Remaining tasks

    User interface changes

    <?php
    
    namespace Drupal\entity_print_views\Plugin\views\area;
    
    use Drupal\Component\Utility\Xss;
    use Drupal\Core\Form\FormStateInterface;
    use Drupal\Core\Url;
    use Drupal\entity_print\Plugin\ExportTypeManagerInterface;
    use Drupal\views\Plugin\views\area\AreaPluginBase;
    use Symfony\Component\DependencyInjection\ContainerInterface;
    
    /**
     * Views area handler for a Print button.
     *
     * @ingroup views_area_handlers
     *
     * @ViewsArea("entity_print_views_link")
     */
    class EntityPrintViewsLink extends AreaPluginBase {
    
      /**
       * The export type manager.
       *
       * @var \Drupal\entity_print\Plugin\ExportTypeManagerInterface
       */
      protected $exportTypeManager;
    
      /**
       * Constructs a new Entity instance.
       *
       * @param array $configuration
       *   A configuration array containing information about the plugin instance.
       * @param string $plugin_id
       *   The plugin_id for the plugin instance.
       * @param mixed $plugin_definition
       *   The plugin implementation definition.
       * @param \Drupal\entity_print\Plugin\ExportTypeManagerInterface $export_type_manager
       *   The export type manager.
       */
      public function __construct(array $configuration, $plugin_id, $plugin_definition, ExportTypeManagerInterface $export_type_manager) {
        parent::__construct($configuration, $plugin_id, $plugin_definition);
        $this->exportTypeManager = $export_type_manager;
      }
    
      /**
       * {@inheritdoc}
       */
      public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
        return new static(
          $configuration,
          $plugin_id,
          $plugin_definition,
          $container->get('plugin.manager.entity_print.export_type')
        );
      }
    
      /**
       * {@inheritdoc}
       */
      public function buildOptionsForm(&$form, FormStateInterface $form_state): void {
        parent::buildOptionsForm($form, $form_state);
        $form['export_type'] = [
          '#type' => 'select',
          '#title' => $this->t('Export Type'),
          '#options' => $this->exportTypeManager->getFormOptions(),
          '#required' => TRUE,
          '#default_value' => $this->options['export_type'],
        ];
        $form['link_text'] = [
          '#type' => 'textfield',
          '#title' => $this->t('Link text'),
          '#required' => TRUE,
          '#default_value' => $this->options['link_text'],
        ];
        $form['class'] = [
          '#title' => $this->t('Class'),
          '#description' => $this->t('A CSS class to apply to the link. If using multiple classes, separate them by spaces.'),
          '#type' => 'textfield',
          '#default_value' => $this->options['class'],
        ];
    
        $displays = $this->view->displayHandlers->getConfiguration();
        $display_options = [];
        foreach ($displays as $display_id => $display_info) {
          $display_options[$display_id] = $display_info['display_title'];
        }
        $form['display_id'] = [
          '#type' => 'select',
          '#title' => $this->t('View Display'),
          '#options' => $display_options,
          '#required' => TRUE,
          '#default_value' => $this->options['display_id'],
        ];
      }
    
      /**
       * {@inheritdoc}
       */
      public function render($empty = FALSE): array {
        if ($empty && empty($this->options['empty'])) {
          return [];
        }
    
        // Check if the user add css for button.
        if (!empty($this->options['class'])) {
          // Definir las clases proporcionadas.
          $user_defined_classes = $this->options['class'];
          // Sanitizar cada clase usando Xss::filter().
          $sanitized_classes = explode(' ', $user_defined_classes);
          foreach ($sanitized_classes as $class) {
          $sanitized_classes[] = Xss::filter($class);
          }
        } else {
          $sanitized_classes = [];
        }
    
        $route_params = [
          'export_type' => !empty($this->options['export_type']) ? $this->options['export_type'] : 'pdf',
          'view_name' => $this->view->storage->id(),
          'display_id' => $this->options['display_id'],
        ];
    
        return [
          '#type' => 'link',
          '#title' => $this->options['link_text'],
          '#url' => Url::fromRoute('entity_print_views.view', $route_params, [
            'query' => $this->view->getExposedInput() + ['view_args' => $this->view->args],
            'attributes' => [
              'class' => $sanitized_classes,
            ],
          ]),
        ];
      }
    
      /**
       * {@inheritdoc}
       */
      protected function defineOptions(): array {
        $options = parent::defineOptions();
        $options['export_type'] = ['default' => 'pdf'];
        $options['link_text'] = ['default' => 'View PDF'];
        $options['class'] = ['default' => ''];
        $options['display_id'] = ['default' => $this->view->current_display];
        return $options;
      }
    }
    

    API changes

    Data model changes

  • 🇦🇺Australia jannakha Brisbane!
  • Pipeline finished with Success
    about 17 hours ago
    Total: 295s
    #536735
  • 🇦🇺Australia jannakha Brisbane!
  • 🇦🇺Australia jannakha Brisbane!

    @ady1503 thanks for your work!
    Re comment #4: create a new issue for optional css classes View PDF link on a node (to keep different features separate for easy testing/merging).

Production build 0.71.5 2024