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
|
<?php
/**
* @file
* Hooks related to the File management system.
*/
use Drupal\Core\StreamWrapper\StreamWrapperManager;
/**
* @addtogroup hooks
* @{
*/
/**
* Control access to private file downloads and specify HTTP headers.
*
* This hook allows modules to enforce permissions on file downloads whenever
* Drupal is handling file download, as opposed to the web server bypassing
* Drupal and returning the file from a public directory. Modules can also
* provide headers to specify information like the file's name or MIME type.
*
* @param string $uri
* The URI of the file.
*
* @return string[]|int|null
* If the user does not have permission to access the file, return -1. If the
* user has permission, return an array with the appropriate headers. If the
* file is not controlled by the current module, the return value should be
* NULL.
*
* @see \Drupal\system\FileDownloadController::download()
*/
function hook_file_download($uri): array|int|null {
// Check to see if this is a config download.
$scheme = StreamWrapperManager::getScheme($uri);
$target = StreamWrapperManager::getTarget($uri);
if ($scheme == 'temporary' && $target == 'config.tar.gz') {
return [
'Content-disposition' => 'attachment; filename="config.tar.gz"',
];
}
return NULL;
}
/**
* Alter the URL to a file.
*
* This hook is called from \Drupal\Core\File\FileUrlGenerator::generate(),
* and is called fairly frequently (10+ times per page), depending on how many
* files there are in a given page.
* If CSS and JS aggregation are disabled, this can become very frequently
* (50+ times per page) so performance is critical.
*
* This function should alter the URI, if it wants to rewrite the file URL.
*
* @param string $uri
* The URI to a file for which we need an external URL, or the path to a
* shipped file.
*/
function hook_file_url_alter(&$uri) {
$user = \Drupal::currentUser();
// User 1 will always see the local file in this example.
if ($user->id() == 1) {
return;
}
$cdn1 = 'http://cdn1.example.com';
$cdn2 = 'http://cdn2.example.com';
$cdn_extensions = ['css', 'js', 'gif', 'jpg', 'jpeg', 'png'];
// Most CDNs don't support private file transfers without a lot of hassle,
// so don't support this in the common case.
$schemes = ['public'];
/** @var \Drupal\Core\StreamWrapper\StreamWrapperManagerInterface $stream_wrapper_manager */
$stream_wrapper_manager = \Drupal::service('stream_wrapper_manager');
$scheme = $stream_wrapper_manager::getScheme($uri);
// Only serve shipped files and public created files from the CDN.
if (!$scheme || in_array($scheme, $schemes)) {
// Shipped files.
if (!$scheme) {
$path = $uri;
}
// Public created files.
else {
$wrapper = $stream_wrapper_manager->getViaScheme($scheme);
$path = $wrapper->getDirectoryPath() . '/' . $stream_wrapper_manager::getTarget($uri);
}
// Clean up Windows paths.
$path = str_replace('\\', '/', $path);
// Serve files with one of the CDN extensions from CDN 1, all others from
// CDN 2.
$pathinfo = pathinfo($path);
if (isset($pathinfo['extension']) && in_array($pathinfo['extension'], $cdn_extensions)) {
$uri = $cdn1 . '/' . $path;
}
else {
$uri = $cdn2 . '/' . $path;
}
}
}
/**
* Alter MIME type mappings used to determine MIME type from a file extension.
*
* @param array $mapping
* An array of mimetypes correlated to the extensions that relate to them.
* The array has 'mimetypes' and 'extensions' elements, each of which is an
* array.
*
* @deprecated in drupal:11.2.0 and is removed from drupal:12.0.0. Create a
* \Drupal\Core\File\Event\MimeTypeMapLoadedEvent subscriber instead.
*
* It is used to allow modules to add to or modify the default mapping of
* MIME type to file extensions.
*
* @see https://www.drupal.org/node/3494040
* @see \Drupal\Core\File\EventSubscriber\LegacyMimeTypeMapLoadedSubscriber
* @see \Drupal\Core\File\MimeType\ExtensionMimeTypeGuesser::guessMimeType()
* @see \Drupal\Core\File\MimeType\ExtensionMimeTypeGuesser::$defaultMapping
*/
function hook_file_mimetype_mapping_alter(&$mapping) {
// Add new MIME type 'drupal/info'.
$mapping['mimetypes']['example_info'] = 'drupal/info';
// Add new extension '.info.yml' and map it to the 'drupal/info' MIME type.
$mapping['extensions']['info'] = 'example_info';
// Override existing extension mapping for '.ogg' files.
$mapping['extensions']['ogg'] = 189;
}
/**
* Alter archiver information declared by other modules.
*
* @param array $info
* An associative array of archivers, keyed by archiver ID. Each value
* consists of the plugin definition for that archiver.
*
* @see \Drupal\Core\Archiver\ArchiverManager
* @see \Drupal\Core\Archiver\Attribute\Archiver
*/
function hook_archiver_info_alter(&$info) {
$info['tar']['extensions'][] = 'tgz';
}
/**
* Register information about FileTransfer classes provided by a module.
*
* The FileTransfer class allows transferring files over a specific type of
* connection. Core provides classes for FTP and SSH. Contributed modules are
* free to extend the FileTransfer base class to add other connection types,
* and if these classes are registered via hook_filetransfer_info(), those
* connection types will be available to site administrators using the Update
* manager when they are redirected to the authorize.php script to authorize
* the file operations.
*
* @return array
* Nested array of information about FileTransfer classes. Each key is a
* FileTransfer type (not human readable, used for form elements and
* variable names, etc), and the values are subarrays that define properties
* of that type. The keys in each subarray are:
* - 'title': Required. The human-readable name of the connection type.
* - 'class': Required. The name of the FileTransfer class. The constructor
* will always be passed the full path to the root of the site that should
* be used to restrict where file transfer operations can occur (the $jail)
* and an array of settings values returned by the settings form.
* - 'weight': Optional. Integer weight used for sorting connection types on
* the authorize.php form.
*
* @deprecated in drupal:11.2.0 and is removed from drupal:12.0.0. There is no
* replacement. Use composer to manage the code for your site.
*
* @see https://www.drupal.org/node/3512364
* @see \Drupal\Core\FileTransfer\FileTransfer
* @see authorize.php
* @see hook_filetransfer_info_alter()
* @see drupal_get_filetransfer_info()
*/
function hook_filetransfer_info(): array {
$info['sftp'] = [
'title' => t('SFTP (Secure FTP)'),
'class' => 'Drupal\Core\FileTransfer\SFTP',
'weight' => 10,
];
return $info;
}
/**
* Alter the FileTransfer class registry.
*
* @param array $filetransfer_info
* Reference to a nested array containing information about the FileTransfer
* class registry.
*
* @deprecated in drupal:11.2.0 and is removed from drupal:12.0.0. There is no
* replacement. Use composer to manage the code for your site.
*
* @see https://www.drupal.org/node/3512364
* @see hook_filetransfer_info()
*/
function hook_filetransfer_info_alter(&$filetransfer_info) {
// Remove the FTP option entirely.
unset($filetransfer_info['ftp']);
// Make sure the SSH option is listed first.
$filetransfer_info['ssh']['weight'] = -10;
}
/**
* @} End of "addtogroup hooks".
*/
|