You are here

SplitFieldsDiffLayout.php in Diff 8

File

src/Plugin/diff/Layout/SplitFieldsDiffLayout.php
View source
<?php

namespace Drupal\diff\Plugin\diff\Layout;

use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Datetime\DateFormatter;
use Drupal\Core\Entity\ContentEntityInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Render\RendererInterface;
use Drupal\diff\DiffEntityComparison;
use Drupal\diff\DiffEntityParser;
use Drupal\diff\DiffLayoutBase;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\RequestStack;

/**
 * Provides Split fields diff layout.
 *
 * @DiffLayoutBuilder(
 *   id = "split_fields",
 *   label = @Translation("Split fields"),
 *   description = @Translation("Field based layout, displays revision comparison side by side."),
 * )
 */
class SplitFieldsDiffLayout extends DiffLayoutBase {

  /**
   * The renderer.
   *
   * @var \Drupal\Core\Render\RendererInterface
   */
  protected $renderer;

  /**
   * The diff entity comparison service.
   *
   * @var \Drupal\diff\DiffEntityComparison
   */
  protected $entityComparison;

  /**
   * The request stack.
   *
   * @var \Symfony\Component\HttpFoundation\RequestStack
   */
  protected $requestStack;

  /**
   * Constructs a SplitFieldsDiffLayout object.
   *
   * @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\Core\Config\ConfigFactoryInterface $config
   *   The configuration factory object.
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
   *   The entity type manager.
   * @param \Drupal\diff\DiffEntityParser $entity_parser
   *   The entity parser.
   * @param \Drupal\Core\DateTime\DateFormatter $date
   *   The date service.
   * @param \Drupal\Core\Render\RendererInterface $renderer
   *   The renderer.
   * @param \Drupal\diff\DiffEntityComparison $entity_comparison
   *   The diff entity comparison service.
   * @param \Symfony\Component\HttpFoundation\RequestStack $request_stack
   *   The request stack.
   */
  public function __construct(array $configuration, $plugin_id, $plugin_definition, ConfigFactoryInterface $config, EntityTypeManagerInterface $entity_type_manager, DiffEntityParser $entity_parser, DateFormatter $date, RendererInterface $renderer, DiffEntityComparison $entity_comparison, RequestStack $request_stack) {
    parent::__construct($configuration, $plugin_id, $plugin_definition, $config, $entity_type_manager, $entity_parser, $date);
    $this->renderer = $renderer;
    $this->entityComparison = $entity_comparison;
    $this->requestStack = $request_stack;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
    return new static($configuration, $plugin_id, $plugin_definition, $container
      ->get('config.factory'), $container
      ->get('entity_type.manager'), $container
      ->get('diff.entity_parser'), $container
      ->get('date.formatter'), $container
      ->get('renderer'), $container
      ->get('diff.entity_comparison'), $container
      ->get('request_stack'));
  }

  /**
   * {@inheritdoc}
   */
  public function build(ContentEntityInterface $left_revision, ContentEntityInterface $right_revision, ContentEntityInterface $entity) {

    // Build the revisions data.
    $build = $this
      ->buildRevisionsData($left_revision, $right_revision);
    $active_filter = $this->requestStack
      ->getCurrentRequest()->query
      ->get('filter') ?: 'raw';
    $build['controls']['filter'] = [
      '#type' => 'item',
      '#title' => $this
        ->t('Filter'),
      '#wrapper_attributes' => [
        'class' => 'diff-controls__item',
      ],
      'options' => $this
        ->buildFilterNavigation($entity, $left_revision, $right_revision, 'split_fields', $active_filter),
    ];

    // Build the diff comparison table.
    $diff_header = $this
      ->buildTableHeader($left_revision, $right_revision);

    // Perform comparison only if both entity revisions loaded successfully.
    $fields = $this->entityComparison
      ->compareRevisions($left_revision, $right_revision);

    // Build the diff rows for each field and append the field rows
    // to the table rows.
    $diff_rows = [];
    $raw_active = $active_filter == 'raw';
    foreach ($fields as $field) {
      $field_label_row = '';
      if (!empty($field['#name'])) {
        $field_label_row = [
          'data' => $field['#name'],
          'colspan' => 8,
          'class' => [
            'field-name',
          ],
        ];
      }
      if (!$raw_active) {
        $field_settings = $field['#settings'];
        if (!empty($field_settings['settings']['markdown'])) {
          $field['#data']['#left'] = $this
            ->applyMarkdown($field_settings['settings']['markdown'], $field['#data']['#left']);
          $field['#data']['#right'] = $this
            ->applyMarkdown($field_settings['settings']['markdown'], $field['#data']['#right']);
        }
        else {
          $field['#data']['#left'] = $this
            ->applyMarkdown('drupal_html_to_text', $field['#data']['#left']);
          $field['#data']['#right'] = $this
            ->applyMarkdown('drupal_html_to_text', $field['#data']['#right']);
        }
      }

      // Process the array (split the strings into single line strings)
      // and get line counts per field.
      $this->entityComparison
        ->processStateLine($field);
      $field_diff_rows = $this->entityComparison
        ->getRows($field['#data']['#left'], $field['#data']['#right']);

      // EXPERIMENTAL: Deal with magic thumbnail image data.
      if (isset($field['#data']['#left_thumbnail'])) {
        $field_diff_rows['#thumbnail'][1] = [
          'data' => $field['#data']['#left_thumbnail'],
          'class' => '',
        ];
      }
      if (isset($field['#data']['#right_thumbnail'])) {
        $field_diff_rows['#thumbnail'][3] = [
          'data' => $field['#data']['#right_thumbnail'],
          'class' => '',
        ];
      }
      $final_diff = [];
      $row_count_left = NULL;
      $row_count_right = NULL;
      foreach ($field_diff_rows as $key => $value) {
        $show_left = FALSE;
        $show_right = FALSE;
        if (isset($field_diff_rows[$key][1]['data'])) {
          $show_left = TRUE;
          $row_count_left++;
        }
        if (isset($field_diff_rows[$key][3]['data'])) {
          $show_right = TRUE;
          $row_count_right++;
        }
        $final_diff[] = [
          'left-line-number' => [
            'data' => $show_left ? $row_count_left : NULL,
            'class' => [
              'diff-line-number',
              isset($field_diff_rows[$key][1]['data']) ? $field_diff_rows[$key][1]['class'] : NULL,
            ],
          ],
          'left-row-sign' => [
            'data' => isset($field_diff_rows[$key][0]['data']) ? $field_diff_rows[$key][0]['data'] : NULL,
            'class' => [
              isset($field_diff_rows[$key][0]['class']) ? $field_diff_rows[$key][0]['class'] : NULL,
              isset($field_diff_rows[$key][1]['data']) ? $field_diff_rows[$key][1]['class'] : NULL,
            ],
          ],
          'left-row-data' => [
            'data' => isset($field_diff_rows[$key][1]['data']) ? $field_diff_rows[$key][1]['data'] : NULL,
            'class' => isset($field_diff_rows[$key][1]['data']) ? $field_diff_rows[$key][1]['class'] : NULL,
          ],
          'right-line-number' => [
            'data' => $show_right ? $row_count_right : NULL,
            'class' => [
              'diff-line-number',
              isset($field_diff_rows[$key][3]['data']) ? $field_diff_rows[$key][3]['class'] : NULL,
            ],
          ],
          'right-row-sign' => [
            'data' => isset($field_diff_rows[$key][2]['data']) ? $field_diff_rows[$key][2]['data'] : NULL,
            'class' => [
              isset($field_diff_rows[$key][2]['class']) ? $field_diff_rows[$key][2]['class'] : NULL,
              isset($field_diff_rows[$key][3]['data']) ? $field_diff_rows[$key][3]['class'] : NULL,
            ],
          ],
          'right-row-data' => [
            'data' => isset($field_diff_rows[$key][3]['data']) ? $field_diff_rows[$key][3]['data'] : NULL,
            'class' => isset($field_diff_rows[$key][3]['data']) ? $field_diff_rows[$key][3]['class'] : NULL,
          ],
        ];
      }

      // Add field label to the table only if there are changes to that field.
      if (!empty($final_diff) && !empty($field_label_row)) {
        $diff_rows[] = [
          $field_label_row,
        ];
      }

      // Add field diff rows to the table rows.
      $diff_rows = array_merge($diff_rows, $final_diff);
    }
    if (!$raw_active) {

      // Remove line numbers.
      foreach ($diff_rows as $i => $row) {
        unset($diff_rows[$i]['left-line-number']);
        unset($diff_rows[$i]['right-line-number']);
      }

      // Reduce the colspan.
      $diff_header[0]['colspan'] = 2;
    }
    $build['diff'] = [
      '#type' => 'table',
      '#header' => $diff_header,
      '#rows' => $diff_rows,
      '#weight' => 10,
      '#empty' => $this
        ->t('No visible changes'),
      '#attributes' => [
        'class' => [
          'diff',
        ],
      ],
    ];
    $build['#attached']['library'][] = 'diff/diff.double_column';
    $build['#attached']['library'][] = 'diff/diff.colors';
    return $build;
  }

  /**
   * Build the header for the diff table.
   *
   * @param \Drupal\Core\Entity\ContentEntityInterface $left_revision
   *   Revision from the left hand side.
   * @param \Drupal\Core\Entity\ContentEntityInterface $right_revision
   *   Revision from the right hand side.
   *
   * @return array
   *   Header for Diff table.
   */
  protected function buildTableHeader(ContentEntityInterface $left_revision, ContentEntityInterface $right_revision) {
    $header = [];
    $header[] = [
      'data' => [
        '#markup' => $this
          ->buildRevisionLink($left_revision),
      ],
      'colspan' => 3,
    ];
    $header[] = [
      'data' => [
        '#markup' => $this
          ->buildRevisionLink($right_revision),
      ],
      'colspan' => 3,
    ];
    return $header;
  }

}

Classes

Namesort descending Description
SplitFieldsDiffLayout Provides Split fields diff layout.