5 use Drupal\Component\Plugin\PluginBase;
6 use Drupal\Component\Utility\Xss;
7 use Drupal\Core\Datetime\DateFormatter;
8 use Drupal\Core\Entity\ContentEntityInterface;
9 use Drupal\Core\Entity\EntityTypeManagerInterface;
10 use Drupal\Core\Entity\RevisionLogInterface;
11 use Drupal\Core\Form\FormStateInterface;
12 use Drupal\Core\Config\ConfigFactoryInterface;
13 use Drupal\Core\Mail\MailFormatHelper;
14 use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
16 use Drupal\Core\StringTranslation\StringTranslationTrait;
18 use Drupal\diff\Controller\PluginRevisionController;
19 use Drupal\node\NodeInterface;
20 use Symfony\Component\DependencyInjection\ContainerInterface;
23 * Base class for diff layout plugins.
25 abstract class DiffLayoutBase extends PluginBase implements DiffLayoutInterface, ContainerFactoryPluginInterface {
27 use StringTranslationTrait;
30 * Contains the configuration object factory.
32 * @var \Drupal\Core\Config\ConfigFactoryInterface
34 protected $configFactory;
37 * The entity type manager.
39 * @var \Drupal\Core\Entity\EntityTypeManagerInterface
41 protected $entityTypeManager;
46 * @var \Drupal\diff\DiffEntityParser
48 protected $entityParser;
53 * @var \Drupal\Core\Datetime\DateFormatter
58 * Constructs a DiffLayoutBase object.
60 * @param array $configuration
61 * A configuration array containing information about the plugin instance.
62 * @param string $plugin_id
63 * The plugin_id for the plugin instance.
64 * @param mixed $plugin_definition
65 * The plugin implementation definition.
66 * @param \Drupal\Core\Config\ConfigFactoryInterface $config
67 * The configuration factory object.
68 * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
69 * The entity type manager.
70 * @param \Drupal\diff\DiffEntityParser $entity_parser
72 * @param \Drupal\Core\DateTime\DateFormatter $date
75 public function __construct(array $configuration, $plugin_id, $plugin_definition, ConfigFactoryInterface $config, EntityTypeManagerInterface $entity_type_manager, DiffEntityParser $entity_parser, DateFormatter $date) {
76 parent::__construct($configuration, $plugin_id, $plugin_definition);
77 $this->configFactory = $config;
78 $this->entityTypeManager = $entity_type_manager;
79 $this->entityParser = $entity_parser;
81 $this->configuration += $this->defaultConfiguration();
87 public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
92 $container->get('config.factory'),
93 $container->get('entity_type.manager'),
94 $container->get('diff.entity_parser'),
95 $container->get('date.formatter')
100 * Build the revision link for a revision.
102 * @param \Drupal\Core\Entity\ContentEntityInterface $revision
103 * A revision where to add a link.
105 * @return \Drupal\Core\Link
106 * Header link for a revision in the table.
108 protected function buildRevisionLink(ContentEntityInterface $revision) {
109 $entity_type_id = $revision->getEntityTypeId();
110 if ($revision instanceof RevisionLogInterface) {
111 $revision_date = $this->date->format($revision->getRevisionCreationTime(), 'short');
112 $route_name = $entity_type_id != 'node' ? "entity.$entity_type_id.revisions_diff" : 'entity.node.revision';
113 $revision_link = Link::fromTextAndUrl($revision_date, Url::fromRoute($route_name, [
114 $entity_type_id => $revision->id(),
115 $entity_type_id . '_revision' => $revision->getRevisionId(),
119 $revision_link = Link::fromTextAndUrl($revision->label(), $revision->toUrl('revision'))
122 return $revision_link;
126 * Build the revision link for the compared revisions.
128 * @param \Drupal\Core\Entity\ContentEntityInterface $left_revision
129 * Left revision that is compared.
130 * @param \Drupal\Core\Entity\ContentEntityInterface $right_revision
131 * Right revision that is compared.
134 * Header link for a revision in the revision comparison display.
136 public function buildRevisionsData(ContentEntityInterface $left_revision, ContentEntityInterface $right_revision) {
137 $right_revision = $this->buildRevisionData($right_revision);
138 $right_revision['#prefix'] = '<div class="diff-revision__items-group">';
139 $right_revision['#suffix'] = '</div>';
141 $left_revision = $this->buildRevisionData($left_revision);
142 $left_revision['#prefix'] = '<div class="diff-revision__items-group">';
143 $left_revision['#suffix'] = '</div>';
145 // Show the revisions that are compared.
148 'diff_revisions' => [
150 '#title' => $this->t('Comparing'),
151 '#wrapper_attributes' => ['class' => 'diff-revision'],
153 '#prefix' => '<div class="diff-revision__items">',
154 '#suffix' => '</div></div>',
155 'right_revision' => $right_revision,
156 'left_revision' => $left_revision,
164 * Build the revision link for a revision.
166 * @param \Drupal\Core\Entity\ContentEntityInterface $revision
167 * Left revision that is compared.
170 * Revision data about author, creation date and log.
172 protected function buildRevisionData(ContentEntityInterface $revision) {
173 $entity_type_id = $revision->getEntityTypeId();
174 if ($revision instanceof RevisionLogInterface) {
175 $revision_log = Xss::filter($revision->getRevisionLogMessage());
176 $user_id = $revision->getRevisionUserId();
177 $route_name = $entity_type_id != 'node' ? "entity.$entity_type_id.revisions_diff" : 'entity.node.revision';
179 $revision_link['date'] = [
181 '#title' => $this->date->format($revision->getRevisionCreationTime(), 'short'),
182 '#url' => Url::fromRoute($route_name, [
183 $entity_type_id => $revision->id(),
184 $entity_type_id . '_revision' => $revision->getRevisionId(),
186 '#prefix' => '<div class="diff-revision__item diff-revision__item-date">',
187 '#suffix' => '</div>',
190 $revision_link['author'] = [
192 '#title' => $revision->getRevisionUser()->getDisplayName(),
193 '#url' => Url::fromUri(\Drupal::request()->getUriForPath('/user/' . $user_id)),
194 '#theme' => 'username',
195 '#account' => $revision->getRevisionUser(),
196 '#prefix' => '<div class="diff-revision__item diff-revision__item-author">',
197 '#suffix' => '</div>',
201 $revision_link['message'] = [
203 '#prefix' => '<div class="diff-revision__item diff-revision__item-message">',
204 '#suffix' => '</div>',
205 '#markup' => $revision_log,
210 $revision_link['label'] = [
212 '#title' => $revision->label(),
213 '#url' => $revision->toUrl('revision'),
214 '#prefix' => '<div class="diff-revision__item diff-revision__item-date">',
215 '#suffix' => '</div>',
218 return $revision_link;
222 * Build the filter navigation for the diff comparison.
224 * @param \Drupal\Core\Entity\ContentEntityInterface $entity
226 * @param \Drupal\Core\Entity\ContentEntityInterface $left_revision
227 * Revision from the left side.
228 * @param \Drupal\Core\Entity\ContentEntityInterface $right_revision
229 * Revision from the right side.
230 * @param string $layout
231 * The layout plugin selected.
232 * @param string $active_filter
236 * The filter options.
238 protected function buildFilterNavigation(ContentEntityInterface $entity, ContentEntityInterface $left_revision, ContentEntityInterface $right_revision, $layout, $active_filter) {
239 // Build the view modes filter.
241 'title' => $this->t('Raw'),
242 'url' => PluginRevisionController::diffRoute($entity,
243 $left_revision->getRevisionId(),
244 $right_revision->getRevisionId(),
250 $options['strip_tags'] = [
251 'title' => $this->t('Strip tags'),
252 'url' => PluginRevisionController::diffRoute($entity,
253 $left_revision->getRevisionId(),
254 $right_revision->getRevisionId(),
256 ['filter' => 'strip_tags']
260 $filter = $options[$active_filter];
261 unset($options[$active_filter]);
262 array_unshift($options, $filter);
264 $build['options'] = [
265 '#type' => 'operations',
266 '#links' => $options,
272 * Applies a markdown function to a string.
274 * @param string $markdown
275 * Key of the markdown function to be applied to the items.
276 * One of drupal_html_to_text, filter_xss, filter_xss_all.
277 * @param string $items
278 * String to be processed.
280 * @return array|string
281 * Result after markdown was applied on $items.
283 protected function applyMarkdown($markdown, $items) {
288 if ($markdown == 'drupal_html_to_text') {
289 return trim(MailFormatHelper::htmlToText($items), "\n");
291 elseif ($markdown == 'filter_xss') {
292 return trim(Xss::filter($items), "\n");
294 elseif ($markdown == 'filter_xss_all') {
295 return trim(Xss::filter($items, []), "\n");
305 public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
311 public function validateConfigurationForm(array &$form, FormStateInterface $form_state) {
317 public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
323 public function defaultConfiguration() {
330 public function getConfiguration() {
331 return $this->configFactory->getEditable('diff.layout_plugins');
337 public function setConfiguration(array $configuration) {
338 $config = $this->configFactory->getEditable('diff.layout_plugins');
339 $config->set($this->pluginId, $configuration);
346 public function calculateDependencies() {