Commit bd240b58 authored by Julian Pustkuchen's avatar Julian Pustkuchen Committed by Mark Casias
Browse files

Issue #3301743 by Anybody, Grevil: Support tokens in more text and replace in...

Issue #3301743 by Anybody, Grevil: Support tokens in more text and replace in content before trimming' --author="Joshua Sedler <55201-Grevil@users.noreply.drupalcode.org>
parent aff7f287
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -42,3 +42,6 @@ field.formatter.settings.smart_trim:
        trim_zero:
          type: boolean
          label: 'Honor a zero trim length'
        replace_tokens:
          type: boolean
          label: 'Replace tokens before trimming'
+39 −5
Original line number Diff line number Diff line
@@ -11,6 +11,7 @@ namespace Drupal\smart_trim\Plugin\Field\FieldFormatter;
 use Drupal\Component\Utility\Unicode;
 use Drupal\smart_trim\TruncateHTML;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 use Drupal\Core\Utility\Token;

/**
 * Plugin implementation of the 'smart_trim' formatter.
@@ -45,6 +46,20 @@ class SmartTrimFormatter extends FormatterBase implements ContainerFactoryPlugin
   */
  protected $truncateHtml;

  /**
   * Token service.
   *
   * @var \Drupal\Core\Utility\Token
   */
   protected $token;

  /**
   * Module handler.
   *
   * @var \Drupal\Core\Extension\ModuleHandlerInterface
   */
  protected $moduleHandler;

  /**
   * Constructs a FormatterBase object.
   *
@@ -64,10 +79,13 @@ class SmartTrimFormatter extends FormatterBase implements ContainerFactoryPlugin
   *   Any third party settings.
   * @param \Drupal\smart_trim\TruncateHTML $truncate_html
   *   The truncate HTML service.
   * @param \Drupal\Core\Utility\Token $token
   *   The token service.
   */
  public function __construct($plugin_id, $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, $label, $view_mode, array $third_party_settings, TruncateHTML $truncate_html) {
  public function __construct($plugin_id, $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, $label, $view_mode, array $third_party_settings, TruncateHTML $truncate_html, Token $token) {
    parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings, $label, $view_mode, $third_party_settings);
    $this->truncateHtml = $truncate_html;
    $this->token = $token;
  }

  /**
@@ -82,7 +100,8 @@ class SmartTrimFormatter extends FormatterBase implements ContainerFactoryPlugin
      $configuration['label'],
      $configuration['view_mode'],
      $configuration['third_party_settings'],
      $container->get('smart_trim.truncate_html')
      $container->get('smart_trim.truncate_html'),
      $container->get('token')
    );
  }

@@ -171,7 +190,7 @@ class SmartTrimFormatter extends FormatterBase implements ContainerFactoryPlugin
      '#type' => 'textfield',
      '#size' => 20,
      '#default_value' => $this->getSetting('more_text'),
      '#description' => $this->t('If displaying more link, enter the text for the link.'),
      '#description' => $this->t('If displaying more link, enter the text for the link. This field supports tokens.'),
      '#states' => [
        'visible' => [
          ':input[name="fields[' . $field_name . '][settings_edit_form][settings][more_link]"]' => ['checked' => TRUE],
@@ -184,7 +203,7 @@ class SmartTrimFormatter extends FormatterBase implements ContainerFactoryPlugin
      '#type' => 'textfield',
      '#size' => 30,
      '#default_value' => $this->getSetting('more_aria_label'),
      '#description' => $this->t('If displaying more link, provide additional context for screen-reader users. Tokens supported. In most cases, the aria-label value will be announced instead of the link text.'),
      '#description' => $this->t('If displaying more link, provide additional context for screen-reader users. In most cases, the aria-label value will be announced instead of the link text. This field supports tokens.'),
      '#states' => [
        'visible' => [
          ':input[name="fields[body][settings_edit_form][settings][more_link]"]' => ['checked' => TRUE],
@@ -236,6 +255,7 @@ class SmartTrimFormatter extends FormatterBase implements ContainerFactoryPlugin
      '#options' => [
        'text' => $this->t('Strip HTML'),
        'trim_zero' => $this->t('Honor a zero trim length'),
        'replace_tokens' => $this->t('Replace tokens before trimming'),
      ],
      '#default_value' => empty($trim_options_value) ? [] : array_keys(array_filter($trim_options_value)),
    ];
@@ -273,6 +293,7 @@ class SmartTrimFormatter extends FormatterBase implements ContainerFactoryPlugin
    $setting_trim_options = $this->getSetting('trim_options');
    $settings_summary_handler = $this->getSetting('summary_handler');
    $entity = $items->getEntity();
    $tokenData = [$entity->getEntityTypeId() => $entity];

    foreach ($items as $delta => $item) {
      if ($settings_summary_handler != 'ignore' && !empty($item->summary)) {
@@ -295,6 +316,14 @@ class SmartTrimFormatter extends FormatterBase implements ContainerFactoryPlugin
          }
        }

        // Replace tokens before trimming.
        if (!empty($setting_trim_options['replace_tokens'])) {
          $output = $this->token->replace($output, $tokenData, [
            'langcode' => $langcode
          ]);
        }


        if (!empty($setting_trim_options['text'])) {
          // Strip caption.
          $output = preg_replace('/<figcaption[^>]*>.*?<\/figcaption>/is', ' ', $output);
@@ -352,6 +381,9 @@ class SmartTrimFormatter extends FormatterBase implements ContainerFactoryPlugin
        // But wait! Don't add a more link if the field ends in <!--break-->.
        if (strpos(strrev($output), strrev('<!--break-->')) !== 0) {
          $more = $this->t($this->getSetting('more_text'));
          $this->token->replace($more, $tokenData, [
            'langcode' => $langcode
          ]);
          $class = $this->getSetting('more_class');

          // Allow other modules to modify the read more link before it's created.
@@ -365,7 +397,9 @@ class SmartTrimFormatter extends FormatterBase implements ContainerFactoryPlugin
          // Ensure we don't create an empty aria-label attribute.
          $aria_label = $this->t($this->getSetting('more_aria_label'));
          if ($aria_label) {
            $project_link['#attributes']['aria-label'] = \Drupal::token()->replace($aria_label, [$entity->getEntityTypeId() => $entity]);
            $project_link['#attributes']['aria-label'] = $this->token->replace($aria_label, $tokenData, [
              'langcode' => $langcode
            ]);
          }
          $project_link['#prefix'] = '<div class="' . $class . '">';
          $project_link['#suffix'] = '</div>';
+185 −0
Original line number Diff line number Diff line
<?php

namespace Drupal\Tests\smart_trim\Functional;

use Drupal\Tests\BrowserTestBase;

/**
 * This class provides methods specifically for testing something.
 *
 * @group smart_trim
 */
class SmartTrimFunctionalTest extends BrowserTestBase {

  /**
   * {@inheritdoc}
   */
  protected static $modules = [
    'node',
    'test_page_test',
    'field',
    'filter',
    'text',
    'token',
    'token_filter',
    'smart_trim',
    'filter_test',
  ];

  /**
   * A user with authenticated permissions.
   *
   * @var \Drupal\Core\Session\AccountInterface
   */
  protected $user;

  /**
   * A user with admin permissions.
   *
   * @var \Drupal\Core\Session\AccountInterface
   */
  protected $adminUser;

  /**
   * {@inheritdoc}
   */
  protected $defaultTheme = 'stark';

  /**
   * {@inheritdoc}
   */
  protected function setUp(): void {
    parent::setUp();

    $this->createContentType(['type' => 'article', 'name' => 'Article']);

    $this->config('system.site')->set('page.front', '/test-page')->save();
    $this->user = $this->drupalCreateUser([]);
    $this->adminUser = $this->drupalCreateUser([]);
    $this->adminUser->addRole($this->createAdminRole('admin', 'admin'));
    $this->adminUser->save();
    $this->drupalLogin($this->adminUser);
  }

  /**
   * Tests if installing the module, won't break the site.
   */
  public function testInstallation() {
    $session = $this->assertSession();
    $this->drupalGet('<front>');
    // Ensure the status code is success:
    $session->statusCodeEquals(200);
    // Ensure the correct test page is loaded as front page:
    $session->pageTextContains('Test page text.');
  }

  /**
   * Tests if uninstalling the module, won't break the site.
   */
  public function testUninstallation() {
    // Go to uninstallation page an uninstall smart_trim:
    $session = $this->assertSession();
    $page = $this->getSession()->getPage();
    $this->drupalGet('/admin/modules/uninstall');
    $session->statusCodeEquals(200);
    $page->checkField('edit-uninstall-smart-trim');
    $page->pressButton('edit-submit');
    $session->statusCodeEquals(200);
    // Confirm uninstall:
    $page->pressButton('edit-submit');
    $session->statusCodeEquals(200);
    $session->pageTextContains('The selected modules have been uninstalled.');
    // Retest the frontpage:
    $this->drupalGet('<front>');
    // Ensure the status code is success:
    $session->statusCodeEquals(200);
    // Ensure the correct test page is loaded as front page:
    $session->pageTextContains('Test page text.');
  }

  /**
   * Tests if the token will not get cut off when using the.
   */
  public function testTokenNotCutOffTrimTypeCharacters() {
    $session = $this->assertSession();
    $display_repository = \Drupal::service('entity_display.repository');
    // Editing our "filter_test" format:
    $edit = [
      'edit-filters-token-filter-status' => 1,
      'edit-filters-filter-html-escape-status' => 0,
    ];
    $this->drupalGet('admin/config/content/formats/manage/filter_test');
    $this->submitForm($edit, 'Save configuration');
    // Edit formatter settings:
    $display_repository->getViewDisplay('node', 'article')
      ->setComponent('body', [
        'type' => 'smart_trim',
        'settings' => [
          'trim_length' => 10,
          'trim_type' => 'chars',
          'summary_handler' => 'trim',
          'trim_options' => [
            'replace_tokens' => TRUE,
          ],
        ],
      ])
      ->save();

    $this->drupalCreateNode([
      'title' => $this->randomString(),
      'id' => 1,
      'type' => 'article',
      'body' => [
        'value' => 'Test [node:content-type]',
        'format' => 'filter_test',
      ],
    ])->save();
    $this->drupalGet('/node/1');
    // @todo This might change to "Test Artic" in the future, because the
    // "trim_type" is a bit confusing, see
    // https://www.drupal.org/project/smart_trim/issues/3308868.
    $session->elementTextEquals('css', 'article > div > div > div:nth-child(2) > p', 'Test');
  }

  /**
   * Tests if the token will not get cut off when using the.
   */
  public function testTokenNotCutOffTrimTypeWords() {
    $session = $this->assertSession();
    $display_repository = \Drupal::service('entity_display.repository');
    // Editing our "filter_test" format:
    $edit = [
      'edit-filters-token-filter-status' => 1,
      'edit-filters-filter-html-escape-status' => 0,
    ];
    $this->drupalGet('admin/config/content/formats/manage/filter_test');
    $this->submitForm($edit, 'Save configuration');
    // Edit formatter settings:
    $display_repository->getViewDisplay('node', 'article')
      ->setComponent('body', [
        'type' => 'smart_trim',
        'settings' => [
          'trim_length' => 10,
          'trim_type' => 'words',
          'summary_handler' => 'trim',
          'trim_options' => [
            'replace_tokens' => TRUE,
          ],
        ],
      ])
      ->save();

    $this->drupalCreateNode([
      'title' => $this->randomString(),
      'id' => 1,
      'type' => 'article',
      'body' => [
        'value' => 'Test [node:content-type]',
        'format' => 'filter_test',
      ],
    ])->save();
    $this->drupalGet('/node/1');
    $session->elementTextEquals('css', 'article > div > div > div:nth-child(2) > p', 'Test Article');
  }

}