Skip to content

Commit 38486f0

Browse files
Mingsong HuMingsong Hu
Mingsong Hu
authored and
Mingsong Hu
committed
Initial commit.
0 parents  commit 38486f0

File tree

45 files changed

+3486
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+3486
-0
lines changed

README.md

+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
CONTENTS OF THIS FILE
2+
---------------------
3+
4+
* Introduction
5+
* Requirements
6+
* Installation
7+
* Configuration
8+
* Maintainers
9+
10+
INTRODUCTION
11+
------------
12+
13+
Drupal Diff module https://www.drupal.org/project/diff provide the capability to compare the difference between node revisions.
14+
Since Drupal 8.7.x, taxonomy, block and media are all revisionable, but there is no UI available yet. This module introduces API and UI for comparing content revisions for content entities other than node.
15+
This module consists of following sub modules:
16+
17+
* Block content diff UI plugin
18+
Provide UI for comparing block contents.
19+
20+
* Media diff UI plugin
21+
Provide UI for comparing media contents.
22+
23+
* Taxonomy diff UI plugin
24+
Provide UI for comparing taxonomy terms.
25+
26+
REQUIREMENTS
27+
------------
28+
Drupal core 8.7.7 and above.
29+
30+
Diff module 8.x-1.0 and above.
31+
32+
INSTALLATION
33+
------------
34+
35+
* Install as you would normally install a contributed Drupal module.
36+
37+
CONFIGURATION
38+
-------------
39+
* Enable the submodules
40+
* Tick the 'Create new revision' box for the Media type which you want to compare the revisions for.
41+
* Tick the 'Create new revision' box for the Block type which you want to compare the revisions for.
42+
* A new tab called 'Revisions' should show up in the Taxonomy term, Block and Media edit page, which is similar to the way how the Diff module works for Node content.
43+
44+
MAINTAINERS
45+
-----------
46+
47+
Mingsong Hu (Mingsong) - https://www.drupal.org/u/mingsong

entity_diff_ui.info.yml

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
name: Entity diff UI plugins
2+
type: module
3+
description: Provide UI plugins of diff for entities.
4+
package: Entity Revision Diff
5+
core_version_requirement: ^8.7.7 || ^9
6+
7+
dependencies:
8+
- drupal:node
9+
- diff:diff (>= 8.x-1.0)

entity_diff_ui.module

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?php
2+
/**
3+
* Implements hook diff_layout_builder_info_alter()
4+
*
5+
* The plugins delivered by Diff module have following issues:
6+
* 1. Undefined index in VisualInlineDiffLayout plugin.
7+
* @see https://www.drupal.org/project/diff/issues/3204468
8+
* 2. Call to a member function getDisplayName() on null
9+
* @see https://www.drupal.org/project/diff/issues/3206057
10+
*
11+
* In order to fix the issues above, the plugin classes need to
12+
* be replaced with those provided by this module.
13+
* Once those issues are fixed by Diff module, this hook function
14+
* can be removed.
15+
*/
16+
function entity_diff_ui_diff_layout_builder_info_alter(array &$definitions) {
17+
if (isset($definitions['visual_inline'])) {
18+
$definitions['visual_inline']['class'] = 'Drupal\entity_diff_ui\Plugin\diff\Layout\EntityVisualInlineDiffLayout';
19+
}
20+
21+
if (isset($definitions['split_fields'])) {
22+
$definitions['split_fields']['class'] = 'Drupal\entity_diff_ui\Plugin\diff\Layout\EntitySplitFieldsDiffLayout';
23+
}
24+
25+
if (isset($definitions['unified_fields'])) {
26+
$definitions['unified_fields']['class'] = 'Drupal\entity_diff_ui\Plugin\diff\Layout\EntityUnifiedFieldsDiffLayout';
27+
}
28+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
name: Block content diff UI plugin
2+
type: module
3+
description: Provide Diff UI plugin for Block content entity.
4+
package: Entity Revision Diff
5+
core_version_requirement: ^8.7.7 || ^9
6+
7+
dependencies:
8+
- entity_diff_ui:entity_diff_ui
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
entity.block_content.version_history:
2+
route_name: entity.block_content.version_history
3+
base_route: entity.block_content.canonical
4+
title: 'Revisions'
5+
weight: 20
+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?php
2+
3+
/**
4+
* Implements hook_entity_type_alter()
5+
*
6+
*/
7+
function block_diff_ui_entity_type_alter(array &$entity_types) {
8+
9+
/** @var $entity_types \Drupal\Core\Entity\EntityTypeInterface[] */
10+
11+
// Set the revision link.
12+
$entity_types['block_content']->setLinkTemplate('revision', '/block/{block_content}/revisions/{block_content_revision}/view');
13+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
view all block content revisions:
2+
title: 'View all block content revisions'
3+
description: 'To view a revision, you also need permission to view the block content.'
4+
revert all block content revisions:
5+
title: 'Revert all block content revisions'
6+
description: 'To revert a revision, you also need permission to edit the block content.'
7+
delete all block content revisions:
8+
title: 'Delete all block content revisions'
9+
description: 'To delete a revision, you also need permission to delete the block content.'
10+
11+
permission_callbacks:
12+
- \Drupal\block_diff_ui\BlockContentPermissions::blockTypePermissions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
entity.block_content.revisions_diff:
2+
path: '/block/{block_content}/revisions/view/{left_revision}/{right_revision}/{filter}'
3+
defaults:
4+
_controller: '\Drupal\block_diff_ui\Controller\BlockContentRevisionController::compareRevisions'
5+
_title: Diff General Settings
6+
requirements:
7+
_access_block_revision: 'view'
8+
block_content: \d+
9+
left_revision: \d+
10+
right_revision: \d+
11+
options:
12+
_admin_route: TRUE
13+
14+
entity.block_content.version_history:
15+
path: '/block/{block_content}/revisions'
16+
defaults:
17+
_title: 'Revisions'
18+
_controller: '\Drupal\block_diff_ui\Controller\BlockContentRevisionController::revisionOverview'
19+
requirements:
20+
_access_block_revision: 'view'
21+
block_content: \d+
22+
options:
23+
_admin_route: TRUE
24+
25+
entity.block_content.revision:
26+
path: '/block/{block_content}/revisions/{block_content_revision}/view'
27+
defaults:
28+
_controller: '\Drupal\block_diff_ui\Controller\BlockContentRevisionController::revisionShow'
29+
_title_callback: '\Drupal\block_diff_ui\Controller\BlockContentRevisionController::revisionPageTitle'
30+
requirements:
31+
_access_block_revision: 'view'
32+
block_content: \d+
33+
block_content_revision: \d+
34+
35+
block_content.revision_revert_confirm:
36+
path: '/block/{block_content}/revisions/{block_content_revision}/revert'
37+
defaults:
38+
_form: '\Drupal\block_diff_ui\Form\BlockContentRevisionRevertForm'
39+
_title: 'Revert to earlier revision'
40+
requirements:
41+
_access_block_revision: 'update'
42+
block_content: \d+
43+
block_content_revision: \d+
44+
options:
45+
_admin_route: TRUE
46+
47+
block_content.revision_revert_translation_confirm:
48+
path: '/block/{block_content}/revisions/{block_content_revision}/revert/{langcode}'
49+
defaults:
50+
_form: '\Drupal\block_diff_ui\Form\BlockContentRevisionRevertTranslationForm'
51+
_title: 'Revert to earlier revision of a translation'
52+
requirements:
53+
_access_block_revision: 'update'
54+
block_content: \d+
55+
block_content_revision: \d+
56+
options:
57+
_admin_route: TRUE
58+
59+
block_content.revision_delete_confirm:
60+
path: '/block/{block_content}/revisions/{block_content_revision}/delete'
61+
defaults:
62+
_form: '\Drupal\block_diff_ui\Form\BlockContentRevisionDeleteForm'
63+
_title: 'Delete earlier revision'
64+
requirements:
65+
_access_block_revision: 'delete'
66+
block_content: \d+
67+
block_content_revision: \d+
68+
options:
69+
_admin_route: TRUE
70+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
services:
2+
access_check.block.revision:
3+
class: Drupal\block_diff_ui\Access\BlockRevisionAccessCheck
4+
arguments: ['@entity_type.manager']
5+
tags:
6+
- { name: access_check, applies_to: _access_block_revision }
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
<?php
2+
3+
namespace Drupal\block_diff_ui\Access;
4+
5+
use Drupal\Core\Entity\EditorialContentEntityBase;
6+
use Drupal\Core\Entity\EntityTypeManagerInterface;
7+
use Drupal\Core\Routing\Access\AccessInterface;
8+
use Drupal\Core\Session\AccountInterface;
9+
use Drupal\entity_diff_ui\Access\EntityRevisionAccessCheckBase;
10+
use Symfony\Component\Routing\Route;
11+
12+
/**
13+
* Provides an access checker for Block Content revisions.
14+
*
15+
* @ingroup block_access
16+
*/
17+
class BlockRevisionAccessCheck extends EntityRevisionAccessCheckBase implements AccessInterface {
18+
19+
const BLOCK_CONTENT_ENTITY = 'block_content';
20+
21+
/**
22+
* Constructs a new BlockRevisionAccessCheck.
23+
*
24+
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
25+
* The entity type manager.
26+
*/
27+
public function __construct(EntityTypeManagerInterface $entity_type_manager) {
28+
$this->entityStorage = $entity_type_manager->getStorage(self::BLOCK_CONTENT_ENTITY);
29+
$this->entityAccess = $entity_type_manager->getAccessControlHandler(self::BLOCK_CONTENT_ENTITY);
30+
}
31+
32+
/**
33+
* Checks routing access for the Block Content revision.
34+
*
35+
* @param \Symfony\Component\Routing\Route $route
36+
* The route to check against.
37+
* @param \Drupal\Core\Session\AccountInterface $account
38+
* The currently logged in account.
39+
* @param int $block_content_revision
40+
* (optional) The block content revision ID. If not specified, but $block_content is, access
41+
* is checked for that object's revision.
42+
* @param EditorialContentEntityBase $block_content
43+
* (optional) A Block Content object. Used for checking access to a block's default
44+
* revision when $block_content_revision is unspecified. Ignored when $block_content_revision
45+
* is specified. If neither $block_content_revision nor $block_content are specified, then
46+
* access is denied.
47+
*
48+
* @return \Drupal\Core\Access\AccessResultInterface
49+
* The access result.
50+
*/
51+
public function access(Route $route, AccountInterface $account, int $block_content_revision = NULL, EditorialContentEntityBase $block_content = NULL) {
52+
$operation = $route->getRequirement('_access_block_revision');
53+
$map = [
54+
'view' => 'view all block content revisions',
55+
'update' => 'revert all block content revisions',
56+
'delete' => 'delete all block content revisions',
57+
];
58+
59+
return parent::getAccessResult($route, $account, $block_content_revision, $block_content, $map, $operation);
60+
}
61+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
<?php
2+
3+
namespace Drupal\block_diff_ui;
4+
5+
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
6+
use Drupal\Core\Entity\EntityInterface;
7+
use Drupal\Core\Entity\EntityTypeManagerInterface;
8+
use Drupal\Core\StringTranslation\StringTranslationTrait;
9+
use Symfony\Component\DependencyInjection\ContainerInterface;
10+
11+
/**
12+
* Provides dynamic permissions for block content of different types.
13+
*/
14+
class BlockContentPermissions implements ContainerInjectionInterface {
15+
16+
use StringTranslationTrait;
17+
18+
/**
19+
* The entity type manager service.
20+
*
21+
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
22+
*/
23+
protected $entityTypeManager;
24+
25+
/**
26+
* BlockContentPermissions constructor.
27+
*
28+
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
29+
* The entity type manager service.
30+
*/
31+
public function __construct(EntityTypeManagerInterface $entity_type_manager) {
32+
$this->entityTypeManager = $entity_type_manager;
33+
}
34+
35+
/**
36+
* {@inheritdoc}
37+
*/
38+
public static function create(ContainerInterface $container) {
39+
return new static($container->get('entity_type.manager'));
40+
}
41+
42+
/**
43+
* Returns an array of block content type permissions.
44+
*
45+
* @return array
46+
* The block content type permissions.
47+
* @see \Drupal\user\PermissionHandlerInterface::getPermissions()
48+
*/
49+
public function blockTypePermissions() {
50+
$perms = [];
51+
// Generate block content permissions for all block content types.
52+
$block_types = $this->entityTypeManager
53+
->getStorage('block_content_type')->loadMultiple();
54+
foreach ($block_types as $type) {
55+
$perms += $this->buildPermissions($type);
56+
}
57+
return $perms;
58+
}
59+
60+
/**
61+
* Returns a list of block content permissions for a given block type.
62+
*
63+
* @param EntityInterface $type
64+
* The block type.
65+
*
66+
* @return array
67+
* An associative array of permission names and descriptions.
68+
*/
69+
protected function buildPermissions(EntityInterface $type) {
70+
$type_id = $type->id();
71+
$type_params = ['%type_name' => $type->label()];
72+
73+
return [
74+
"view $type_id revisions" => [
75+
'title' => $this->t('%type_name: View revisions', $type_params),
76+
'description' => t('To view a revision, you also need permission to view the block content.'),
77+
],
78+
"revert $type_id revisions" => [
79+
'title' => $this->t('%type_name: Revert revisions', $type_params),
80+
'description' => t('To revert a revision, you also need permission to edit the block content.'),
81+
],
82+
"delete $type_id revisions" => [
83+
'title' => $this->t('%type_name: Delete revisions', $type_params),
84+
'description' => $this->t('To delete a revision, you also need permission to delete the block content.'),
85+
],
86+
];
87+
}
88+
89+
}

0 commit comments

Comments
 (0)