@amazeelabs/silverback-preview-link 1.6.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +8 -0
- package/drupal/silverback_preview_link/CHANGELOG.md +195 -0
- package/drupal/silverback_preview_link/README.md +30 -0
- package/drupal/silverback_preview_link/composer.json +13 -0
- package/drupal/silverback_preview_link/config/install/silverback_preview_link.settings.yml +3 -0
- package/drupal/silverback_preview_link/config/schema/silverback_preview_link.schema.yml +14 -0
- package/drupal/silverback_preview_link/css/modal.css +17 -0
- package/drupal/silverback_preview_link/js/copy.js +39 -0
- package/drupal/silverback_preview_link/silverback_preview_link.info.yml +12 -0
- package/drupal/silverback_preview_link/silverback_preview_link.install +6 -0
- package/drupal/silverback_preview_link/silverback_preview_link.libraries.yml +9 -0
- package/drupal/silverback_preview_link/silverback_preview_link.links.menu.yml +5 -0
- package/drupal/silverback_preview_link/silverback_preview_link.module +79 -0
- package/drupal/silverback_preview_link/silverback_preview_link.permissions.yml +9 -0
- package/drupal/silverback_preview_link/silverback_preview_link.routing.yml +40 -0
- package/drupal/silverback_preview_link/silverback_preview_link.services.yml +31 -0
- package/drupal/silverback_preview_link/src/Access/PreviewEnabledAccessCheck.php +80 -0
- package/drupal/silverback_preview_link/src/Access/PreviewLinkAccessCheck.php +49 -0
- package/drupal/silverback_preview_link/src/Authentication/Provider/PreviewToken.php +118 -0
- package/drupal/silverback_preview_link/src/Controller/PreviewController.php +83 -0
- package/drupal/silverback_preview_link/src/Entity/SilverbackPreviewLink.php +224 -0
- package/drupal/silverback_preview_link/src/Entity/SilverbackPreviewLinkInterface.php +110 -0
- package/drupal/silverback_preview_link/src/Form/PreviewLinkForm.php +320 -0
- package/drupal/silverback_preview_link/src/Form/SettingsForm.php +204 -0
- package/drupal/silverback_preview_link/src/Plugin/EntityReferenceSelection/SilverbackPreviewLinkSelection.php +25 -0
- package/drupal/silverback_preview_link/src/Plugin/Field/FieldWidget/PreviewLinkEntitiesWidget.php +103 -0
- package/drupal/silverback_preview_link/src/Plugin/Validation/Constraint/SilverbackPreviewLinkEntitiesUniqueConstraint.php +26 -0
- package/drupal/silverback_preview_link/src/Plugin/Validation/Constraint/SilverbackPreviewLinkEntitiesUniqueConstraintValidator.php +44 -0
- package/drupal/silverback_preview_link/src/PreviewLinkExpiry.php +55 -0
- package/drupal/silverback_preview_link/src/PreviewLinkHooks.php +61 -0
- package/drupal/silverback_preview_link/src/PreviewLinkHost.php +70 -0
- package/drupal/silverback_preview_link/src/PreviewLinkHostInterface.php +49 -0
- package/drupal/silverback_preview_link/src/PreviewLinkStorage.php +99 -0
- package/drupal/silverback_preview_link/src/PreviewLinkStorageInterface.php +19 -0
- package/drupal/silverback_preview_link/src/PreviewLinkUtility.php +27 -0
- package/drupal/silverback_preview_link/src/QRCodeWithLogo.php +84 -0
- package/drupal/silverback_preview_link/src/QRMarkupSVGWithLogo.php +51 -0
- package/drupal/silverback_preview_link/src/Routing/PreviewLinkRouteProvider.php +61 -0
- package/drupal/silverback_preview_link/src/images/amazee-labs_logo-square-green.svg +13 -0
- package/drupal/silverback_preview_link/templates/preview-link.html.twig +39 -0
- package/package.json +13 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# Change Log
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
|
+
|
|
6
|
+
## 1.6.15 (2026-01-22)
|
|
7
|
+
|
|
8
|
+
**Note:** Version bump only for package @amazeelabs/silverback-preview-link
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
# Change Log
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
|
+
|
|
6
|
+
## [1.6.14](https://github.com/AmazeeLabs/silverback-mono/compare/@-amazeelabs/silverback_preview_link@1.6.13...@-amazeelabs/silverback_preview_link@1.6.14) (2025-09-09)
|
|
7
|
+
|
|
8
|
+
**Note:** Version bump only for package @-amazeelabs/silverback_preview_link
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
## [1.6.13](https://github.com/AmazeeLabs/silverback-mono/compare/@-amazeelabs/silverback_preview_link@1.6.12...@-amazeelabs/silverback_preview_link@1.6.13) (2025-08-21)
|
|
15
|
+
|
|
16
|
+
**Note:** Version bump only for package @-amazeelabs/silverback_preview_link
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
## [1.6.12](https://github.com/AmazeeLabs/silverback-mono/compare/@-amazeelabs/silverback_preview_link@1.6.11...@-amazeelabs/silverback_preview_link@1.6.12) (2025-05-14)
|
|
23
|
+
|
|
24
|
+
**Note:** Version bump only for package @-amazeelabs/silverback_preview_link
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
## [1.6.11](https://github.com/AmazeeLabs/silverback-mono/compare/@-amazeelabs/silverback_preview_link@1.6.10...@-amazeelabs/silverback_preview_link@1.6.11) (2025-05-12)
|
|
31
|
+
|
|
32
|
+
**Note:** Version bump only for package @-amazeelabs/silverback_preview_link
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
## [1.6.10](https://github.com/AmazeeLabs/silverback-mono/compare/@-amazeelabs/silverback_preview_link@1.6.9...@-amazeelabs/silverback_preview_link@1.6.10) (2025-05-06)
|
|
39
|
+
|
|
40
|
+
**Note:** Version bump only for package @-amazeelabs/silverback_preview_link
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
## [1.6.9](https://github.com/AmazeeLabs/silverback-mono/compare/@-amazeelabs/silverback_preview_link@1.6.8...@-amazeelabs/silverback_preview_link@1.6.9) (2025-04-09)
|
|
47
|
+
|
|
48
|
+
**Note:** Version bump only for package @-amazeelabs/silverback_preview_link
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
## [1.6.8](https://github.com/AmazeeLabs/silverback-mono/compare/@-amazeelabs/silverback_preview_link@1.6.7...@-amazeelabs/silverback_preview_link@1.6.8) (2025-03-18)
|
|
55
|
+
|
|
56
|
+
**Note:** Version bump only for package @-amazeelabs/silverback_preview_link
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
## [1.6.7](https://github.com/AmazeeLabs/silverback-mono/compare/@-amazeelabs/silverback_preview_link@1.6.6...@-amazeelabs/silverback_preview_link@1.6.7) (2025-03-10)
|
|
63
|
+
|
|
64
|
+
**Note:** Version bump only for package @-amazeelabs/silverback_preview_link
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
## [1.6.6](https://github.com/AmazeeLabs/silverback-mono/compare/@-amazeelabs/silverback_preview_link@1.6.5...@-amazeelabs/silverback_preview_link@1.6.6) (2025-03-09)
|
|
71
|
+
|
|
72
|
+
**Note:** Version bump only for package @-amazeelabs/silverback_preview_link
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
## [1.6.5](https://github.com/AmazeeLabs/silverback-mono/compare/@-amazeelabs/silverback_preview_link@1.6.4...@-amazeelabs/silverback_preview_link@1.6.5) (2025-01-27)
|
|
79
|
+
|
|
80
|
+
**Note:** Version bump only for package @-amazeelabs/silverback_preview_link
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
## [1.6.4](https://github.com/AmazeeLabs/silverback-mono/compare/@-amazeelabs/silverback_preview_link@1.6.3...@-amazeelabs/silverback_preview_link@1.6.4) (2024-08-20)
|
|
87
|
+
|
|
88
|
+
**Note:** Version bump only for package @-amazeelabs/silverback_preview_link
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
## [1.6.3](https://github.com/AmazeeLabs/silverback-mono/compare/@-amazeelabs/silverback_preview_link@1.6.2...@-amazeelabs/silverback_preview_link@1.6.3) (2024-08-15)
|
|
95
|
+
|
|
96
|
+
**Note:** Version bump only for package @-amazeelabs/silverback_preview_link
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
## [1.6.2](https://github.com/AmazeeLabs/silverback-mono/compare/@-amazeelabs/silverback_preview_link@1.6.1...@-amazeelabs/silverback_preview_link@1.6.2) (2024-08-14)
|
|
103
|
+
|
|
104
|
+
**Note:** Version bump only for package @-amazeelabs/silverback_preview_link
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
## [1.6.1](https://github.com/AmazeeLabs/silverback-mono/compare/@-amazeelabs/silverback_preview_link@1.6.0...@-amazeelabs/silverback_preview_link@1.6.1) (2024-08-14)
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
### Bug Fixes
|
|
114
|
+
|
|
115
|
+
* **SLB-458:** branded preview link qr ([#1566](https://github.com/AmazeeLabs/silverback-mono/issues/1566)) ([f2585b6](https://github.com/AmazeeLabs/silverback-mono/commit/f2585b65a5166303a45d12249b5bbd0f5769dc53))
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
# [1.6.0](https://github.com/AmazeeLabs/silverback-mono/compare/@-amazeelabs/silverback_preview_link@1.5.0...@-amazeelabs/silverback_preview_link@1.6.0) (2024-08-14)
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
### Features
|
|
125
|
+
|
|
126
|
+
* **SLB-458:** branded preview qr ([#1565](https://github.com/AmazeeLabs/silverback-mono/issues/1565)) ([2330e1f](https://github.com/AmazeeLabs/silverback-mono/commit/2330e1f467e70f1508904e2d7c1778b6cdd43b73))
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
# [1.5.0](https://github.com/AmazeeLabs/silverback-mono/compare/@-amazeelabs/silverback_preview_link@1.4.0...@-amazeelabs/silverback_preview_link@1.5.0) (2024-07-27)
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
### Features
|
|
136
|
+
|
|
137
|
+
* **SLB-416:** re-remove branded qr code ([9f8518e](https://github.com/AmazeeLabs/silverback-mono/commit/9f8518e960a0ca93dab00430a1b059afb0478964))
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
# [1.4.0](https://github.com/AmazeeLabs/silverback-mono/compare/@-amazeelabs/silverback_preview_link@1.3.0...@-amazeelabs/silverback_preview_link@1.4.0) (2024-07-27)
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
### Features
|
|
147
|
+
|
|
148
|
+
* **SLB-416:** re-add branded qr code ([4efc4de](https://github.com/AmazeeLabs/silverback-mono/commit/4efc4de944de9f9fdf993eb723e8eed7d1b70400))
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
# [1.3.0](https://github.com/AmazeeLabs/silverback-mono/compare/@-amazeelabs/silverback_preview_link@1.2.0...@-amazeelabs/silverback_preview_link@1.3.0) (2024-07-27)
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
### Features
|
|
158
|
+
|
|
159
|
+
* **SLB-416:** revert branded qr code ([f941c81](https://github.com/AmazeeLabs/silverback-mono/commit/f941c819bc6013ef11cf2cfcfd5c05bcb7ebdb7c))
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
# [1.2.0](https://github.com/AmazeeLabs/silverback-mono/compare/@-amazeelabs/silverback_preview_link@1.1.1...@-amazeelabs/silverback_preview_link@1.2.0) (2024-07-24)
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
### Features
|
|
169
|
+
|
|
170
|
+
* **SLB-416:** branded QR ([399b102](https://github.com/AmazeeLabs/silverback-mono/commit/399b102728179e9330f6cec403643439cd6a77e9))
|
|
171
|
+
* **SLB-416:** copy preview link, refactor form ([3888116](https://github.com/AmazeeLabs/silverback-mono/commit/3888116ec334d6f01c1541e23187134f00ba9546))
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
## [1.1.1](https://github.com/AmazeeLabs/silverback-mono/compare/@-amazeelabs/silverback_preview_link@1.1.0...@-amazeelabs/silverback_preview_link@1.1.1) (2024-07-12)
|
|
178
|
+
|
|
179
|
+
**Note:** Version bump only for package @-amazeelabs/silverback_preview_link
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
# 1.1.0 (2024-07-12)
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
### Bug Fixes
|
|
189
|
+
|
|
190
|
+
* **SLB-416:** remove drupal namespace ([#1548](https://github.com/AmazeeLabs/silverback-mono/issues/1548)) ([52b7fec](https://github.com/AmazeeLabs/silverback-mono/commit/52b7fec31a7b99ce9c409aa5943a90861988d467))
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
### Features
|
|
194
|
+
|
|
195
|
+
* **SLB-416:** preview link ([#1542](https://github.com/AmazeeLabs/silverback-mono/issues/1542)) ([bd9d312](https://github.com/AmazeeLabs/silverback-mono/commit/bd9d31276d0ffb4da45cbe475ec03386d66cc722)), closes [#1547](https://github.com/AmazeeLabs/silverback-mono/issues/1547)
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Silverback Preview Link
|
|
2
|
+
|
|
3
|
+
Decoupled shareable preview with access token. Integrates with Silverback
|
|
4
|
+
autosave.
|
|
5
|
+
|
|
6
|
+
This module is inspired by
|
|
7
|
+
[Preview Link](https://www.drupal.org/project/preview_link) but does not depend
|
|
8
|
+
on it as the use case is different.
|
|
9
|
+
|
|
10
|
+
This module
|
|
11
|
+
|
|
12
|
+
- is suitable for a decoupled setup
|
|
13
|
+
- handles access based on GraphQL
|
|
14
|
+
- uses silverback_autosave to share instant preview updates
|
|
15
|
+
- integrates with the Gutenberg editor
|
|
16
|
+
|
|
17
|
+
Due to the decoupled nature, it does not cover additional logic brought by the
|
|
18
|
+
Preview Link module:
|
|
19
|
+
|
|
20
|
+
- Most of the route subscribers
|
|
21
|
+
- Entity canonical access control handlers
|
|
22
|
+
- Route provider and Controller for preview links
|
|
23
|
+
- Event subscribers for node canonical redirect
|
|
24
|
+
- ...
|
|
25
|
+
|
|
26
|
+
## Configuration
|
|
27
|
+
|
|
28
|
+
- Enable entity types and bundles
|
|
29
|
+
`/admin/config/content/silverback_preview_link`
|
|
30
|
+
- Optionally change the default expiry time that is set to 1 day
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "amazeelabs/silverback_preview_link",
|
|
3
|
+
"type": "drupal-module",
|
|
4
|
+
"version": "dev-main",
|
|
5
|
+
"description": "Decoupled preview with access token.",
|
|
6
|
+
"homepage": "https://silverback.netlify.app",
|
|
7
|
+
"license": "GPL-2.0+",
|
|
8
|
+
"require": {
|
|
9
|
+
"php": ">=8.3",
|
|
10
|
+
"drupal/dynamic_entity_reference": "^3 || ^4",
|
|
11
|
+
"chillerlan/php-qrcode": "^5"
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
silverback_preview_link.settings:
|
|
2
|
+
type: config_object
|
|
3
|
+
mapping:
|
|
4
|
+
enabled_entity_types:
|
|
5
|
+
type: sequence
|
|
6
|
+
sequence:
|
|
7
|
+
type: sequence
|
|
8
|
+
sequence:
|
|
9
|
+
type: string
|
|
10
|
+
expiry_seconds:
|
|
11
|
+
type: integer
|
|
12
|
+
multiple_entities:
|
|
13
|
+
label: Whether Preview Links can reference multiple entities.
|
|
14
|
+
type: boolean
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
.preview-link .preview-link__copy,
|
|
2
|
+
.preview-link p {
|
|
3
|
+
margin: 0;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
.silverback-preview-link-entity-form .messages__header {
|
|
7
|
+
display: none;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
.silverback-preview-link-entity-form .messages-list {
|
|
11
|
+
margin-block: 0;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
.silverback-preview-link-entity-form .messages {
|
|
15
|
+
padding-block: 8px;
|
|
16
|
+
padding-inline: 0;
|
|
17
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
(function (Drupal) {
|
|
2
|
+
Drupal.behaviors.previewLinkCopyToClipBoard = {
|
|
3
|
+
attach: function (context) {
|
|
4
|
+
const copyText = document.querySelector('.preview-link__copy .form-text');
|
|
5
|
+
const copyButton = document.querySelector('.preview-link__copy button');
|
|
6
|
+
|
|
7
|
+
if (!copyText || !copyButton) {
|
|
8
|
+
return;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const setSuccessMessage = () => {
|
|
12
|
+
const originalLabel = copyButton.textContent;
|
|
13
|
+
const copySuccessLabel = Drupal.t('Copied ✨');
|
|
14
|
+
copyButton.textContent = copySuccessLabel;
|
|
15
|
+
setTimeout(() => {
|
|
16
|
+
copyButton.textContent = originalLabel;
|
|
17
|
+
}, 2000);
|
|
18
|
+
};
|
|
19
|
+
// Fallback for browsers that don't support navigator.clipboard.
|
|
20
|
+
let copy = () => {
|
|
21
|
+
copyText.select();
|
|
22
|
+
document.execCommand('copy');
|
|
23
|
+
setSuccessMessage();
|
|
24
|
+
};
|
|
25
|
+
if (navigator.clipboard) {
|
|
26
|
+
copy = () => {
|
|
27
|
+
navigator.clipboard.writeText(copyText.value).then(
|
|
28
|
+
() => setSuccessMessage(),
|
|
29
|
+
(err) => console.log('Error: ' + err),
|
|
30
|
+
);
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
copyButton.addEventListener('click', (event) => {
|
|
34
|
+
event.preventDefault();
|
|
35
|
+
copy();
|
|
36
|
+
});
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
})(Drupal);
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
name: 'Silverback Preview Link'
|
|
2
|
+
type: module
|
|
3
|
+
description:
|
|
4
|
+
'Decoupled preview with access token. Integrates with Silverback autosave.'
|
|
5
|
+
package: Silverback
|
|
6
|
+
configure: silverback_preview_link.settings
|
|
7
|
+
core_version_requirement: ^10 || ^11
|
|
8
|
+
dependencies:
|
|
9
|
+
- dynamic_entity_reference:dynamic_entity_reference
|
|
10
|
+
- silverback_autosave:silverback_autosave
|
|
11
|
+
- silverback_gatsby:silverback_gatsby
|
|
12
|
+
- silverback_external_preview:silverback_external_preview
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
<?php
|
|
2
|
+
|
|
3
|
+
use Drupal\Core\Access\AccessResult;
|
|
4
|
+
use Drupal\Core\Access\AccessResultInterface;
|
|
5
|
+
use Drupal\Core\Field\FieldDefinitionInterface;
|
|
6
|
+
use Drupal\Core\Field\FieldItemListInterface;
|
|
7
|
+
use Drupal\Core\Session\AccountInterface;
|
|
8
|
+
use Drupal\silverback_preview_link\PreviewLinkHooks;
|
|
9
|
+
use Drupal\silverback_preview_link\PreviewLinkUtility;
|
|
10
|
+
use Drupal\silverback_preview_link\Routing\PreviewLinkRouteProvider;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Implements hook_entity_type_alter().
|
|
14
|
+
*/
|
|
15
|
+
function silverback_preview_link_entity_type_alter(array &$entity_types): void {
|
|
16
|
+
$supported_entity_types = array_filter(
|
|
17
|
+
$entity_types,
|
|
18
|
+
[PreviewLinkUtility::class, 'isEntityTypeSupported'],
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
/** @var \Drupal\Core\Entity\ContentEntityType $type */
|
|
22
|
+
foreach ($supported_entity_types as $type) {
|
|
23
|
+
$providers = $type->getRouteProviderClasses() ?: [];
|
|
24
|
+
if (count($providers['silverback_preview_link'] ?? []) === 0) {
|
|
25
|
+
$providers['silverback_preview_link'] = PreviewLinkRouteProvider::class;
|
|
26
|
+
$type->setHandlerClass('route_provider', $providers);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if (!$type->hasLinkTemplate('preview-link-generate')) {
|
|
30
|
+
$type->setLinkTemplate('preview-link-generate', $type->getLinkTemplate('canonical') . '/generate-preview-link');
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Implements hook_cron().
|
|
37
|
+
*/
|
|
38
|
+
function silverback_preview_link_cron(): void {
|
|
39
|
+
\Drupal::classResolver(PreviewLinkHooks::class)->cron();
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Implements hook_theme().
|
|
44
|
+
*/
|
|
45
|
+
function silverback_preview_link_theme(array $existing, string $type, string $theme, string $path): array {
|
|
46
|
+
return [
|
|
47
|
+
'preview_link' => [
|
|
48
|
+
'path' => $path . '/templates',
|
|
49
|
+
'template' => 'preview-link',
|
|
50
|
+
'variables' => [
|
|
51
|
+
'title' => NULL,
|
|
52
|
+
'preview_link_has_expired' => FALSE,
|
|
53
|
+
'preview_url' => NULL,
|
|
54
|
+
'preview_qr_code_url' => NULL,
|
|
55
|
+
'preview_qr_code_fallback' => NULL,
|
|
56
|
+
'expiry_description' => NULL,
|
|
57
|
+
'actions_description' => NULL,
|
|
58
|
+
'display_gif' => FALSE,
|
|
59
|
+
],
|
|
60
|
+
],
|
|
61
|
+
];
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Implements hook_entity_field_access().
|
|
66
|
+
*/
|
|
67
|
+
function silverback_preview_link_entity_field_access(string $operation, FieldDefinitionInterface $field_definition, AccountInterface $account, ?FieldItemListInterface $items = NULL): AccessResultInterface {
|
|
68
|
+
$storageDefinition = $field_definition->getFieldStorageDefinition();
|
|
69
|
+
if ($storageDefinition->getTargetEntityTypeId() !== 'silverback_preview_link') {
|
|
70
|
+
return AccessResult::neutral();
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if ($storageDefinition->getName() === 'entities' && $operation === 'edit') {
|
|
74
|
+
return AccessResult::forbiddenIf(\Drupal::configFactory()->get('silverback_preview_link.settings')->get('multiple_entities') !== TRUE)
|
|
75
|
+
->addCacheTags(['config:preview_link.settings']);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return AccessResult::neutral();
|
|
79
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
administer silverback preview link settings:
|
|
2
|
+
title: 'Administer Silverback preview link settings'
|
|
3
|
+
description: 'Allows the user to administer the preview link settings'
|
|
4
|
+
restrict access: TRUE
|
|
5
|
+
|
|
6
|
+
generate silverback preview links:
|
|
7
|
+
title: 'Generate Silverback preview links'
|
|
8
|
+
description:
|
|
9
|
+
'Allows the user to generate a preview link for a piece of content'
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
silverback_preview_link.settings:
|
|
2
|
+
path: '/admin/config/content/silverback_preview_link'
|
|
3
|
+
defaults:
|
|
4
|
+
_form: '\Drupal\silverback_preview_link\Form\SettingsForm'
|
|
5
|
+
_title: 'Silverback preview link'
|
|
6
|
+
_description: 'Manage Preview link settings.'
|
|
7
|
+
requirements:
|
|
8
|
+
_permission: 'administer silverback preview link settings'
|
|
9
|
+
|
|
10
|
+
silverback_preview_link.preview.access:
|
|
11
|
+
path: '/preview/access'
|
|
12
|
+
defaults:
|
|
13
|
+
_controller: '\Drupal\silverback_preview_link\Controller\PreviewController::hasAccess'
|
|
14
|
+
methods: [POST]
|
|
15
|
+
requirements:
|
|
16
|
+
# Required for the refresh token.
|
|
17
|
+
_access: 'TRUE'
|
|
18
|
+
_format: 'json'
|
|
19
|
+
options:
|
|
20
|
+
_auth: ['oauth2']
|
|
21
|
+
no_cache: TRUE
|
|
22
|
+
|
|
23
|
+
silverback_preview_link.qr_code:
|
|
24
|
+
path: '/preview/qr-code/{base64_url}'
|
|
25
|
+
defaults:
|
|
26
|
+
_controller: '\Drupal\silverback_preview_link\Controller\PreviewController::getQRCode'
|
|
27
|
+
requirements:
|
|
28
|
+
# Keep it very generic, it's just to prevent anonymous access / bots.
|
|
29
|
+
_permission: 'access administration pages'
|
|
30
|
+
|
|
31
|
+
silverback_preview_link.preview_link.access:
|
|
32
|
+
path: '/preview/link-access'
|
|
33
|
+
defaults:
|
|
34
|
+
_controller: '\Drupal\silverback_preview_link\Controller\PreviewController::hasLinkAccess'
|
|
35
|
+
methods: [POST]
|
|
36
|
+
requirements:
|
|
37
|
+
_access: 'TRUE'
|
|
38
|
+
_format: 'json'
|
|
39
|
+
options:
|
|
40
|
+
no_cache: TRUE
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
services:
|
|
2
|
+
access_check.silverback_preview_link:
|
|
3
|
+
class: Drupal\silverback_preview_link\Access\PreviewLinkAccessCheck
|
|
4
|
+
arguments: ['@silverback_preview_link.host']
|
|
5
|
+
tags:
|
|
6
|
+
- { name: access_check, applies_to: _access_preview_link }
|
|
7
|
+
access_check.preview_enabled:
|
|
8
|
+
class: Drupal\silverback_preview_link\Access\PreviewEnabledAccessCheck
|
|
9
|
+
arguments: ['@config.factory']
|
|
10
|
+
tags:
|
|
11
|
+
- { name: access_check, applies_to: _access_preview_enabled }
|
|
12
|
+
silverback_preview_link.link_expiry:
|
|
13
|
+
class: Drupal\silverback_preview_link\PreviewLinkExpiry
|
|
14
|
+
arguments: ['@config.factory']
|
|
15
|
+
silverback_preview_link.host:
|
|
16
|
+
class: Drupal\silverback_preview_link\PreviewLinkHost
|
|
17
|
+
arguments:
|
|
18
|
+
- '@entity_type.manager'
|
|
19
|
+
- '@datetime.time'
|
|
20
|
+
logger.channel.silverback_preview_link:
|
|
21
|
+
parent: logger.channel_base
|
|
22
|
+
arguments: ['silverback_preview_link']
|
|
23
|
+
silverback_preview_link.authentication.preview_token:
|
|
24
|
+
class: Drupal\silverback_preview_link\Authentication\Provider\PreviewToken
|
|
25
|
+
tags:
|
|
26
|
+
- {
|
|
27
|
+
name: authentication_provider,
|
|
28
|
+
provider_id: 'preview_token',
|
|
29
|
+
priority: -10000,
|
|
30
|
+
global: TRUE,
|
|
31
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
<?php
|
|
2
|
+
|
|
3
|
+
declare(strict_types = 1);
|
|
4
|
+
|
|
5
|
+
namespace Drupal\silverback_preview_link\Access;
|
|
6
|
+
|
|
7
|
+
use Drupal\Core\Access\AccessResult;
|
|
8
|
+
use Drupal\Core\Access\AccessResultInterface;
|
|
9
|
+
use Drupal\Core\Config\ConfigFactoryInterface;
|
|
10
|
+
use Drupal\Core\Config\ImmutableConfig;
|
|
11
|
+
use Drupal\Core\Entity\EntityInterface;
|
|
12
|
+
use Drupal\Core\Routing\Access\AccessInterface;
|
|
13
|
+
use Drupal\Core\Routing\RouteMatchInterface;
|
|
14
|
+
use Symfony\Component\Routing\Route;
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Generate preview link access check.
|
|
18
|
+
*/
|
|
19
|
+
class PreviewEnabledAccessCheck implements AccessInterface {
|
|
20
|
+
|
|
21
|
+
protected ImmutableConfig $config;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* PreviewEnabledAccessCheck constructor.
|
|
25
|
+
*/
|
|
26
|
+
public function __construct(ConfigFactoryInterface $configFactory) {
|
|
27
|
+
$this->config = $configFactory->get('silverback_preview_link.settings');
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Checks access to both the generate route and the preview route.
|
|
32
|
+
*/
|
|
33
|
+
public function access(Route $route, RouteMatchInterface $route_match): AccessResultInterface {
|
|
34
|
+
// Get the entity for both the preview route and the generate preview link
|
|
35
|
+
// route.
|
|
36
|
+
$entity = match($route->getOption('silverback_preview_link.entity_type_id')) {
|
|
37
|
+
NULL => $route_match->getParameter('entity'),
|
|
38
|
+
default => $route_match->getParameter($route->getOption('silverback_preview_link.entity_type_id')),
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
return AccessResult::allowedIf($this->entityTypeAndBundleEnabled($entity))
|
|
42
|
+
->addCacheableDependency($entity)
|
|
43
|
+
->addCacheContexts(['route'])
|
|
44
|
+
->addCacheableDependency($this->config);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Check if the entity type and bundle are enabled.
|
|
49
|
+
*
|
|
50
|
+
* @param \Drupal\Core\Entity\EntityInterface $entity
|
|
51
|
+
* The entity.
|
|
52
|
+
*
|
|
53
|
+
* @return bool
|
|
54
|
+
* TRUE if enabled, FALSE otherwise.
|
|
55
|
+
*/
|
|
56
|
+
protected function entityTypeAndBundleEnabled(EntityInterface $entity): bool {
|
|
57
|
+
$enabled_entity_types = $this->config->get('enabled_entity_types');
|
|
58
|
+
|
|
59
|
+
// If no entity types are specified, fallback to allowing all.
|
|
60
|
+
if (count($enabled_entity_types) === 0) {
|
|
61
|
+
return TRUE;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// If the entity type exists in the configuration object.
|
|
65
|
+
if (isset($enabled_entity_types[$entity->getEntityTypeId()])) {
|
|
66
|
+
$enabled_bundles = $enabled_entity_types[$entity->getEntityTypeId()];
|
|
67
|
+
// If no bundles were specified, assume all bundles are enabled.
|
|
68
|
+
if (count($enabled_bundles) === 0) {
|
|
69
|
+
return TRUE;
|
|
70
|
+
}
|
|
71
|
+
// Otherwise fallback to requiring the specific bundle.
|
|
72
|
+
if (in_array($entity->bundle(), $enabled_bundles, TRUE)) {
|
|
73
|
+
return TRUE;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return FALSE;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
<?php
|
|
2
|
+
|
|
3
|
+
declare(strict_types = 1);
|
|
4
|
+
|
|
5
|
+
namespace Drupal\silverback_preview_link\Access;
|
|
6
|
+
|
|
7
|
+
use Drupal\Core\Access\AccessResult;
|
|
8
|
+
use Drupal\Core\Access\AccessResultInterface;
|
|
9
|
+
use Drupal\Core\Entity\EntityInterface;
|
|
10
|
+
use Drupal\Core\Routing\Access\AccessInterface;
|
|
11
|
+
use Drupal\silverback_preview_link\PreviewLinkHostInterface;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Preview link access check.
|
|
15
|
+
*/
|
|
16
|
+
class PreviewLinkAccessCheck implements AccessInterface {
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* PreviewLinkAccessCheck constructor.
|
|
20
|
+
*/
|
|
21
|
+
public function __construct(
|
|
22
|
+
protected PreviewLinkHostInterface $previewLinkHost,
|
|
23
|
+
) {
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Checks access to the preview link.
|
|
28
|
+
*/
|
|
29
|
+
public function access(EntityInterface $entity = NULL, string $preview_token = NULL): AccessResultInterface {
|
|
30
|
+
$neutral = AccessResult::neutral()->addCacheableDependency($entity);
|
|
31
|
+
if (!$preview_token || !$entity) {
|
|
32
|
+
return $neutral;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// If we can't find a valid preview link then ignore this.
|
|
36
|
+
if (!$this->previewLinkHost->hasPreviewLinks($entity)) {
|
|
37
|
+
return $neutral->setReason('This entity does not have a preview link.');
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// If an entity has a preview link that doesn't match up,
|
|
41
|
+
// then explicitly deny access.
|
|
42
|
+
if (!$this->previewLinkHost->isToken($entity, [$preview_token])) {
|
|
43
|
+
return AccessResult::forbidden('Preview token is invalid.')->addCacheableDependency($entity);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return AccessResult::allowed()->addCacheableDependency($entity);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
}
|