support-2.0.x-dev/modules/support_ticket/src/Controller/SupportTicketRevisionController.php
modules/support_ticket/src/Controller/SupportTicketRevisionController.php
<?php
namespace Drupal\support_ticket\Controller;
use Drupal\Core\Url;
use Drupal\support_ticket\SupportTicketInterface;
use Drupal\Core\Controller\ControllerBase;
use Drupal\diff\DiffEntityComparison;
use Drupal\Component\Utility\Xss;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Returns responses for Support Ticket Revision routes.
*/
class SupportTicketRevisionController extends ControllerBase {
/**
* Wrapper object for writing/reading configuration from diff.plugins.yml.
*
* @var \Drupal\Core\Config\Config
*/
protected $config;
/**
* The diff entity comparison service.
*
* @var \Drupal\diff\DiffEntityComparison
*/
protected DiffEntityComparison $entityComparison;
/**
* Constructs a HackedDiffController object.
*
* @param \Drupal\diff\DiffEntityComparison $entity_comparison
* DiffEntityComparison service.
*/
public function __construct(DiffEntityComparison $entity_comparison) {
$this->config = $this->config('diff.settings');
$this->entityComparison = $entity_comparison;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('diff.entity_comparison')
);
}
/**
* Returns a form for revision overview page.
*
* @param \Drupal\support_ticket\SupportTicketInterface $support_ticket
* The support ticket whose revisions are inspected.
*
* @return array
* Render array containing the revisions table for $support_ticket.
*/
public function revisionOverview(SupportTicketInterface $support_ticket) {
return $this->formBuilder()->getForm('Drupal\support_ticket\Form\RevisionOverviewForm', $support_ticket);
}
/**
* Returns a table that shows the differences in two support ticket revisions.
*
* @param \Drupal\support_ticket\SupportTicketInterface $support_ticket
* The support ticket whose revisions are compared.
* @param string $left_vid
* Vid of the support ticket revision from the left.
* @param string $right_vid
* Vid of the support ticket revision from the right.
* @param string $filter
* If $filter == 'raw' raw text is compared (including html tags)
* If filter == 'raw-plain' markdown function is applied to the text
* before comparison.
*
* @return array
* Table showing the diff between the two support ticket revisions.
*/
public function compareSupportTicketRevisions(SupportTicketInterface $support_ticket, $left_vid, $right_vid, $filter) {
$diff_rows = [];
$build = [
'#title' => $this->t('Revisions for %title', ['%title' => $support_ticket->label()]),
];
if (!in_array($filter, ['raw', 'raw-plain'])) {
$filter = 'raw';
}
elseif ($filter == 'raw-plain') {
$filter = 'raw_plain';
}
// Support Ticket storage service.
$storage = $this->entityManager()->getStorage('support_ticket');
$left_revision = $storage->loadRevision($left_vid);
$right_revision = $storage->loadRevision($right_vid);
$vids = $storage->revisionIds($support_ticket);
$diff_rows[] = $this->buildRevisionsNavigation($support_ticket->id(), $vids, $left_vid, $right_vid);
$diff_rows[] = $this->buildMarkdownNavigation($support_ticket->id(), $left_vid, $right_vid, $filter);
$diff_header = $this->buildTableHeader($left_revision, $right_revision);
// Perform comparison only if both support ticket revisions
// loaded successfully.
if ($left_revision != FALSE && $right_revision != FALSE) {
$fields = $this->compareRevisions($left_revision, $right_revision);
$support_ticket_base_fields = $this->entityManager()->getBaseFieldDefinitions('support_ticket');
// Check to see if we need to display certain fields or not based on
// selected view mode display settings.
foreach ($fields as $field_name => $field) {
// If we are dealing with support tickets only compare those fields
// set as visible from the selected view mode.
$view_mode = $this->config->get('support_ticket_type_settings.' . $support_ticket->getType() . '.view_mode');
// If no view mode is selected use the default view mode.
if ($view_mode == NULL) {
$view_mode = 'default';
}
$visible = entity_get_display('support_ticket', $support_ticket->getType(), $view_mode)->getComponent($field_name);
if ($visible == NULL && !array_key_exists($field_name, $support_ticket_base_fields)) {
unset($fields[$field_name]);
}
}
// Build the diff rows for each field and append the field rows
// to the table rows.
foreach ($fields as $field) {
$field_label_row = '';
if (!empty($field['#name'])) {
$field_label_row = [
'data' => $this->t('Changes to %name', ['%name' => $field['#name']]),
'colspan' => 4,
'class' => ['field-name'],
];
}
$field_diff_rows = $this->entityComparison->getRows(
$field['#states'][$filter]['#left'],
$field['#states'][$filter]['#right']
);
// Add the field label to the table only if there are
// changes to that field.
if (!empty($field_diff_rows) && !empty($field_label_row)) {
$diff_rows[] = [$field_label_row];
}
// Add field diff rows to the table rows.
$diff_rows = array_merge($diff_rows, $field_diff_rows);
}
// Add the CSS for the diff.
$build['#attached']['library'][] = 'diff/diff.general';
$theme = $this->config->get('general_settings.theme');
if ($theme) {
if ($theme == 'default') {
$build['#attached']['library'][] = 'diff/diff.default';
}
elseif ($theme == 'github') {
$build['#attached']['library'][] = 'diff/diff.github';
}
}
// If the setting could not be loaded or is missing use the default theme.
elseif ($theme == NULL) {
$build['#attached']['library'][] = 'diff/diff.github';
}
$build['diff'] = [
'#type' => 'table',
'#header' => $diff_header,
'#rows' => $diff_rows,
'#empty' => $this->t('No visible changes'),
'#attributes' => [
'class' => ['diff'],
],
];
$build['back'] = [
'#type' => 'link',
'#attributes' => [
'class' => [
'button',
'diff-button',
],
],
'#title' => $this->t('Back to Revision Overview'),
'#url' => Url::fromRoute('entity.support_ticket.version_history', ['support_ticket' => $support_ticket->id()]),
];
return $build;
}
else {
// @todo When task 'Convert drupal_set_message() to a service' (2278383)
// will be merged use the corresponding service instead.
drupal_set_message($this->t('Selected support ticket revisions could not be loaded.'), 'error');
}
}
/**
* Build the header for the diff table.
*
* @param string $left_revision
* Revision from the left hand side.
* @param string $right_revision
* Revision from the right hand side.
*
* @return array
* Header for Diff table.
*/
protected function buildTableHeader($left_revision, $right_revision) {
$revisions = [$left_revision, $right_revision];
$header = [];
foreach ($revisions as $revision) {
$revision_log = $this->nonBreakingSpace;
if ($revision->revision_log->value != '') {
$revision_log = Xss::filter($revision->revision_log->value);
}
$revision_date = $this->date->format($revision->getRevisionCreationTime(), 'short');
$revision_link = $this->t('@revision_log @date',
[
'@revision_log' => $revision_log,
'@date' => $this->l($revision_date, Url::fromRoute('entity.support_ticket.revision',
[
'support_ticket' => $revision->id(),
'support_ticket_revision' => $revision->getRevisionId(),
]
)
),
]
);
// @todo When theming think about where in the table to integrate this
// link to the revision user. There is some issue about multi-line
// headers for theme table.
// $header[] = array(
// 'data' => $this->t('by' . '!username',
// array('!username' => drupal_render($username))),
// 'colspan' => 1,
// );
$header[] = [
'data' => ['#markup' => $this->nonBreakingSpace],
'colspan' => 1,
];
$header[] = [
'data' => ['#markup' => $revision_link],
'colspan' => 1,
];
}
return $header;
}
/**
* Returns the navigation row for diff table.
*/
protected function buildRevisionsNavigation($stid, $vids, $left_vid, $right_vid) {
$revisions_count = count($vids);
$i = 0;
$row = [];
// Find the previous revision.
while ($left_vid > $vids[$i]) {
$i += 1;
}
if ($i != 0) {
// Second column.
$row[] = [
'data' => $this->l(
$this->t('< Previous difference'),
Url::fromRoute('support_ticket.revisions_diff',
[
'support_ticket' => $stid,
'left_vid' => $vids[$i - 1],
'right_vid' => $left_vid,
]
)
),
'colspan' => 2,
'class' => 'rev-navigation',
];
}
else {
// Second column.
$row[] = $this->nonBreakingSpace;
}
// Third column.
$row[] = $this->nonBreakingSpace;
// Find the next revision.
$i = 0;
while ($i < $revisions_count && $right_vid >= $vids[$i]) {
$i += 1;
}
if ($revisions_count != $i && $vids[$i - 1] != $vids[$revisions_count - 1]) {
// Forth column.
$row[] = [
'data' => $this->l(
$this->t('Next difference >'),
Url::fromRoute('support_ticket.revisions_diff',
[
'support_ticket' => $stid,
'left_vid' => $right_vid,
'right_vid' => $vids[$i],
]
)
),
'colspan' => 2,
'class' => 'rev-navigation',
];
}
else {
// Forth column.
$row[] = $this->nonBreakingSpace;
}
// If there are only 2 revision return an empty row.
if ($revisions_count == 2) {
return [];
}
else {
return $row;
}
}
/**
* Builds a table row with navigation between raw and raw-plain formats.
*/
protected function buildMarkdownNavigation($stid, $left_vid, $right_vid, $active_filter) {
$links['raw'] = [
'title' => $this->t('Standard'),
'url' => Url::fromRoute('support_ticket.revisions_diff',
[
'support_ticket' => $stid,
'left_vid' => $left_vid,
'right_vid' => $right_vid,
]
),
];
$links['raw_plain'] = [
'title' => $this->t('Markdown'),
'url' => Url::fromRoute('support_ticket.revisions_diff',
[
'support_ticket' => $stid,
'left_vid' => $left_vid,
'right_vid' => $right_vid,
'filter' => 'raw-plain',
]
),
];
// Set as the first element the current filter.
$filter = $links[$active_filter];
// Uunset($links[$active_filter]);.
array_unshift($links, $filter);
$row[] = [
'data' => [
'#type' => 'operations',
'#links' => $links,
],
'colspan' => 4,
];
return $row;
}
}
