-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathminisite.module
242 lines (207 loc) · 8.32 KB
/
minisite.module
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
<?php
/**
* @file
* Main functions of the Minisite module.
*/
use Drupal\Component\Plugin\Exception\PluginNotFoundException;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\FieldableEntityInterface;
use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Url;
use Drupal\field\Entity\FieldStorageConfig;
use Drupal\file\FileInterface;
use Drupal\minisite\AssetInterface;
use Drupal\minisite\Exception\ArchiveException;
use Drupal\minisite\Minisite;
require_once dirname(__FILE__) . '/minisite.theme.inc';
/**
* Implements hook_help().
*/
function minisite_help($route_name, RouteMatchInterface $route_match) {
switch ($route_name) {
case 'help.page.minisite':
$output = '';
$output .= '<h3>' . t('About') . '</h3>';
$output .= '<p>' . t('Used to upload and run self contained structured but static content as "mini websites".') . '</p>';
$output .= '<h3>' . t('Archives') . '</h3>';
$output .= '<p>' . t('Supported archive files are <code>@archives</code>.', ['@archives' => implode(', ', Minisite::supportedArchiveExtensions())]) . '</p>';
$output .= '<p>' . t('Archives must abide by the following constraints:') . '</p>';
$output .= '<ul>';
$output .= ' <li>' . t('Must contain only one top-level directory.') . '</li>';
$output .= ' <li>' . t('Must contain only files with extensions from the "allowed list" (configured for each field).') . '</li>';
$output .= ' <li>' . t('Must contain <code>@index</code> page under topmost root directory.', ['@index' => AssetInterface::INDEX_FILE]) . '</li>';
$output .= ' <li>' . t('Should contain pages with relative links.') . '</li>';
$output .= '</ul>';
$output .= '<h3>' . t('URL rewrite (alias)') . '</h3>';
$output .= '<p>' . t('Applies when the "Use alias" option is selected after a mini-site archive is uploaded.</p>');
$output .= '<p>' . t('A mini-site served through an aliased URL updates internal links that are rewritten based on the following rules:') . '</p>';
$output .= '<ul>';
$output .= ' <li>';
$output .= ' <p>' . t('For <code><a></code> tag:') . '</p>';
$output .= ' <ul>';
$output .= ' <li>' . t('If link is external, do not alter it.') . '</li>';
$output .= ' <li>' . t('If link is to the HTML document and relative to root (starts with <code>./</code> or <code>/</code>), rewrite it to point to the aliased path.') . '</li>';
$output .= ' <li>' . t('If link is to the HTML document and relative to other documents (starts with <code>../</code>), rewrite it to always point to the aliased path.') . '</li>';
$output .= ' <li>' . t('If link is to the non-HTML file, rewrite it to always point to the expanded file in the file system.') . '</li>';
$output .= ' </ul>';
$output .= ' </li>';
$output .= ' <li>';
$output .= ' <p>' . t('For <code><link></code>, <code><script></code> and <code><img></code> tags:') . '</p>';
$output .= ' <ul>';
$output .= ' <li>' . t('If link is external, do not alter it.') . '</li>';
$output .= ' <li>' . t('All other types of links are rewritten to always point to the expanded file in the file system.') . '</li>';
$output .= ' </ul>';
$output .= ' </li>';
$output .= ' <li>' . t('The <code><base></code> tag in <code><head></code> is always removed.') . '</li>';
$output .= '</ul>';
return $output;
}
}
/**
* Validation callback.
*
* @param \Drupal\file\FileInterface $file
* The file to validate.
* @param string $content_extensions
* String list of the allowed archive content extensions.
*
* @return array
* Array of errors, if any.
*/
function minisite_validate_archive(FileInterface $file, $content_extensions) {
$errors = [];
try {
Minisite::validateArchive($file, $content_extensions);
}
catch (ArchiveException $exception) {
$errors[] = $exception->getMessage();
}
catch (\Exception $exception) {
$errors[] = t('Unable to use uploaded file as a Minisite');
}
return $errors;
}
/**
* Implements hook_path_insert().
*/
function minisite_path_insert($path) {
$entity = _minisite_get_entity_from_path($path['source']);
if (!$entity) {
return;
}
$path_alias = isset($path['alias']) ? $path['alias'] : '';
$minisite_fields = _minisite_get_fields($entity);
foreach ($minisite_fields as $minisite_field) {
if ($entity->hasField($minisite_field->getName())) {
$minisite = Minisite::createInstance($entity->{$minisite_field->getName()});
if ($minisite) {
$minisite->setAlias($path_alias);
$minisite->save();
}
}
}
}
/**
* Implements hook_path_update().
*/
function minisite_path_update($path) {
minisite_path_insert($path);
}
/**
* Get information about all entities that have a minisite archive attached.
*
* @param bool $flatten
* (optional) Flatten a list instead of providing as a tree.
* Defaults to FALSE.
* @param string $flatten_delimiter
* (optional) The delimiter to use if $flatten is TRUE. Defaults to '__'.
*
* @return array
* If $flatten is FALSE, returns a multidimentional array with hierarchy
* entity_type => field_name => id.
* If $flatten is TRUE, returns an array of flatenned values in format
* "entity_type__field_name__entity_id".
*/
function minisite_get_info_all($flatten = FALSE, $flatten_delimiter = '__') {
$info = [];
// Collect all entity types with field names.
$map = \Drupal::service('entity_field.manager')->getFieldMapByFieldType('minisite');
foreach ($map as $entity_type_id => $entity_type_info) {
foreach (array_keys($entity_type_info) as $name) {
if (FieldStorageConfig::loadByName($entity_type_id, $name)->getSetting('target_type') == 'file') {
$minisite_field_ids[] = "$entity_type_id.$name";
}
}
}
foreach ($minisite_field_ids as $minisite_field_id) {
/** @var \Drupal\field\FieldStorageConfigInterface $field_storage */
$field_storage = FieldStorageConfig::load($minisite_field_id);
$entity_type_id = $field_storage->getTargetEntityTypeId();
$field_name = $field_storage->getName();
$target_entity_type_definition = \Drupal::entityTypeManager()->getDefinition($entity_type_id);
$id_key = $target_entity_type_definition->getKey('id');
// Get all entities for this field that have values.
$entity_ids = \Drupal::entityQuery($entity_type_id)
->condition($field_name, NULL, 'IS NOT NULL')
->sort($id_key, 'ASC')
->accessCheck(FALSE)
->execute();
if ($entity_ids) {
if ($flatten) {
foreach ($entity_ids as $entity_id) {
$info[] = $entity_type_id . $flatten_delimiter . $field_name . $flatten_delimiter . $entity_id;
}
}
else {
$info[$entity_type_id][$field_name] = array_values($entity_ids);
}
}
}
return $info;
}
/**
* Get Minisite fields from the entity.
*
* @param \Drupal\Core\Entity\EntityInterface $entity
* Entity to get fields from.
*
* @return array
* Array of Minisite field names.
*/
function _minisite_get_fields(EntityInterface $entity) {
if (!$entity instanceof FieldableEntityInterface) {
return [];
}
/** @var \Drupal\Core\Entity\EntityFieldManagerInterface $entity_field_manager */
$entity_field_manager = Drupal::service('entity_field.manager');
/** @var \Drupal\Core\Field\FieldDefinitionInterface[] $minisite_fields */
return array_filter($entity_field_manager->getFieldDefinitions($entity->getEntityTypeId(), $entity->bundle()), function (FieldDefinitionInterface $field_definition) {
return $field_definition->getType() == 'minisite';
});
}
/**
* Get entity from provided path.
*
* @param string $path
* Source path to find the entity.
*
* @return \Drupal\Core\Entity\FieldableEntityInterface|null
* Found entity or NULL if the entity was not found.
*/
function _minisite_get_entity_from_path($path) {
try {
$params = Url::fromUri('internal:' . $path)->getRouteParameters();
}
catch (\InvalidArgumentException $exception) {
return NULL;
}
$entity_type = key($params);
try {
$storage = \Drupal::entityTypeManager()->getStorage($entity_type);
}
catch (PluginNotFoundException $exception) {
return NULL;
}
return $storage->load($params[$entity_type]);
}