3 namespace Drupal\diff\Plugin\diff\Layout;
5 use Drupal\Core\Config\ConfigFactoryInterface;
6 use Drupal\Core\Datetime\DateFormatter;
7 use Drupal\Core\Entity\EntityDisplayRepositoryInterface;
8 use Drupal\Core\Entity\ContentEntityInterface;
9 use Drupal\Core\Entity\EntityTypeManagerInterface;
10 use Drupal\Core\PhpStorage\PhpStorageFactory;
11 use Drupal\Core\Render\RendererInterface;
12 use Drupal\diff\Controller\PluginRevisionController;
13 use Drupal\diff\DiffEntityComparison;
14 use Drupal\diff\DiffEntityParser;
15 use Drupal\diff\DiffLayoutBase;
16 use Symfony\Component\DependencyInjection\ContainerInterface;
17 use HtmlDiffAdvancedInterface;
18 use Symfony\Component\HttpFoundation\RequestStack;
21 * Provides Visual Inline diff layout.
24 * id = "visual_inline",
25 * label = @Translation("Visual Inline"),
26 * description = @Translation("Visual layout, displays revision comparison using the entity type view mode."),
29 class VisualInlineDiffLayout extends DiffLayoutBase {
34 * @var \Drupal\Core\Render\RendererInterface
39 * The diff entity comparison service.
41 * @var \Drupal\diff\DiffEntityComparison
43 protected $entityComparison;
46 * The html diff service.
48 * @var \HtmlDiffAdvancedInterface
55 * @var \Symfony\Component\HttpFoundation\RequestStack
57 protected $requestStack;
60 * The entity display repository.
62 * @var \Drupal\Core\Entity\EntityDisplayRepositoryInterface
64 protected $entityDisplayRepository;
67 * Constructs a VisualInlineDiffLayout object.
69 * @param array $configuration
70 * A configuration array containing information about the plugin instance.
71 * @param string $plugin_id
72 * The plugin_id for the plugin instance.
73 * @param mixed $plugin_definition
74 * The plugin implementation definition.
75 * @param \Drupal\Core\Config\ConfigFactoryInterface $config
76 * The configuration factory object.
77 * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
78 * The entity type manager.
79 * @param \Drupal\diff\DiffEntityParser $entity_parser
81 * @param \Drupal\Core\DateTime\DateFormatter $date
83 * @param \Drupal\Core\Render\RendererInterface $renderer
85 * @param \Drupal\diff\DiffEntityComparison $entity_comparison
86 * The diff entity comparison service.
87 * @param \HtmlDiffAdvancedInterface $html_diff
88 * The html diff service.
89 * @param \Symfony\Component\HttpFoundation\RequestStack $request_stack
91 * @param \Drupal\Core\Entity\EntityDisplayRepositoryInterface $entity_display_repository
92 * The entity display repository.
94 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, HtmlDiffAdvancedInterface $html_diff, RequestStack $request_stack, EntityDisplayRepositoryInterface $entity_display_repository) {
95 parent::__construct($configuration, $plugin_id, $plugin_definition, $config, $entity_type_manager, $entity_parser, $date);
96 $this->renderer = $renderer;
97 $this->entityComparison = $entity_comparison;
98 $storage = PhpStorageFactory::get('html_purifier_serializer');
99 if (!$storage->exists('cache.php')) {
100 $storage->save('cache.php', 'dummy');
102 $html_diff->getConfig()->setPurifierCacheLocation(dirname($storage->getFullPath('cache.php')));
103 $this->htmlDiff = $html_diff;
104 $this->requestStack = $request_stack;
105 $this->entityDisplayRepository = $entity_display_repository;
111 public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
116 $container->get('config.factory'),
117 $container->get('entity_type.manager'),
118 $container->get('diff.entity_parser'),
119 $container->get('date.formatter'),
120 $container->get('renderer'),
121 $container->get('diff.entity_comparison'),
122 $container->get('diff.html_diff'),
123 $container->get('request_stack'),
124 $container->get('entity_display.repository')
131 public function build(ContentEntityInterface $left_revision, ContentEntityInterface $right_revision, ContentEntityInterface $entity) {
132 // Build the revisions data.
133 $build = $this->buildRevisionsData($left_revision, $right_revision);
135 $this->entityTypeManager->getStorage($entity->getEntityTypeId())->resetCache([$entity->id()]);
136 // Build the view modes filter.
138 // Get all view modes for entity type.
139 $view_modes = $this->entityDisplayRepository->getViewModeOptionsByBundle($entity->getEntityTypeId(), $entity->bundle());
140 foreach ($view_modes as $view_mode => $view_mode_info) {
141 // Skip view modes that are not used in the front end.
142 if (in_array($view_mode, ['rss', 'search_index'])) {
145 $options[$view_mode] = [
146 'title' => $view_mode_info,
147 'url' => PluginRevisionController::diffRoute($entity,
148 $left_revision->getRevisionId(),
149 $right_revision->getRevisionId(),
151 ['view_mode' => $view_mode]
156 $active_option = array_keys($options);
157 $active_view_mode = $this->requestStack->getCurrentRequest()->query->get('view_mode') ?: reset($active_option);
159 $filter = $options[$active_view_mode];
160 unset($options[$active_view_mode]);
161 array_unshift($options, $filter);
163 $build['controls']['view_mode'] = [
165 '#title' => $this->t('View mode'),
166 '#wrapper_attributes' => ['class' => 'diff-controls__item'],
168 '#type' => 'operations',
169 '#links' => $options,
173 $view_builder = $this->entityTypeManager->getViewBuilder($entity->getEntityTypeId());
174 // Trigger exclusion of interactive items like on preview.
175 $left_revision->in_preview = TRUE;
176 $right_revision->in_preview = TRUE;
177 $left_view = $view_builder->view($left_revision, $active_view_mode);
178 $right_view = $view_builder->view($right_revision, $active_view_mode);
180 // Avoid render cache from being built.
181 unset($left_view['#cache']);
182 unset($right_view['#cache']);
184 $html_1 = $this->renderer->render($left_view);
185 $html_2 = $this->renderer->render($right_view);
187 $this->htmlDiff->setOldHtml($html_1);
188 $this->htmlDiff->setNewHtml($html_2);
189 $this->htmlDiff->build();
192 '#markup' => $this->htmlDiff->getDifference(),
196 $build['#attached']['library'][] = 'diff/diff.visual_inline';