Chris@0
|
1 <?php
|
Chris@0
|
2
|
Chris@0
|
3 /**
|
Chris@0
|
4 * @file
|
Chris@0
|
5 * API for handling file uploads and server file management.
|
Chris@0
|
6 */
|
Chris@0
|
7
|
Chris@0
|
8 use Drupal\Component\FileSystem\FileSystem as ComponentFileSystem;
|
Chris@18
|
9 use Drupal\Component\PhpStorage\FileStorage;
|
Chris@18
|
10 use Drupal\Component\Utility\Environment;
|
Chris@0
|
11 use Drupal\Component\Utility\UrlHelper;
|
Chris@18
|
12 use Drupal\Core\File\Exception\FileException;
|
Chris@18
|
13 use Drupal\Core\File\Exception\FileWriteException;
|
Chris@0
|
14 use Drupal\Core\File\FileSystem;
|
Chris@18
|
15 use Drupal\Core\File\FileSystemInterface;
|
Chris@0
|
16 use Drupal\Core\Site\Settings;
|
Chris@18
|
17 use Drupal\Core\StreamWrapper\PrivateStream;
|
Chris@0
|
18 use Drupal\Core\StreamWrapper\PublicStream;
|
Chris@0
|
19
|
Chris@0
|
20 /**
|
Chris@18
|
21 * Default mode for new directories.
|
Chris@0
|
22 *
|
Chris@0
|
23 * @deprecated in Drupal 8.0.x-dev, will be removed before Drupal 9.0.0.
|
Chris@0
|
24 * Use \Drupal\Core\File\FileSystem::CHMOD_DIRECTORY.
|
Chris@0
|
25 *
|
Chris@18
|
26 * @see \Drupal\Core\File\FileSystemInterface::chmod()
|
Chris@0
|
27 * @see https://www.drupal.org/node/2418133
|
Chris@0
|
28 */
|
Chris@0
|
29 const FILE_CHMOD_DIRECTORY = FileSystem::CHMOD_DIRECTORY;
|
Chris@0
|
30
|
Chris@0
|
31 /**
|
Chris@18
|
32 * Default mode for new files.
|
Chris@0
|
33 *
|
Chris@0
|
34 * @deprecated in Drupal 8.0.x-dev, will be removed before Drupal 9.0.0.
|
Chris@0
|
35 * Use \Drupal\Core\File\FileSystem::CHMOD_FILE.
|
Chris@0
|
36 *
|
Chris@18
|
37 * @see \Drupal\Core\File\FileSystemInterface::chmod()
|
Chris@0
|
38 * @see https://www.drupal.org/node/2418133
|
Chris@0
|
39 */
|
Chris@0
|
40 const FILE_CHMOD_FILE = FileSystem::CHMOD_FILE;
|
Chris@0
|
41
|
Chris@0
|
42 /**
|
Chris@0
|
43 * @defgroup file File interface
|
Chris@0
|
44 * @{
|
Chris@0
|
45 * Common file handling functions.
|
Chris@0
|
46 */
|
Chris@0
|
47
|
Chris@0
|
48 /**
|
Chris@18
|
49 * Flag used to create a directory if not present.
|
Chris@18
|
50 *
|
Chris@18
|
51 * @deprecated in Drupal 8.7.0, will be removed before Drupal 9.0.0.
|
Chris@18
|
52 * Use \Drupal\Core\File\FileSystemInterface::CREATE_DIRECTORY.
|
Chris@0
|
53 */
|
Chris@18
|
54 const FILE_CREATE_DIRECTORY = FileSystemInterface::CREATE_DIRECTORY;
|
Chris@0
|
55
|
Chris@0
|
56 /**
|
Chris@18
|
57 * Flag used to indicate file permissions may be changed.
|
Chris@18
|
58 *
|
Chris@18
|
59 * @deprecated in Drupal 8.7.0, will be removed before Drupal 9.0.0.
|
Chris@18
|
60 * Use \Drupal\Core\File\FileSystemInterface::MODIFY_PERMISSIONS.
|
Chris@0
|
61 */
|
Chris@18
|
62 const FILE_MODIFY_PERMISSIONS = FileSystemInterface::MODIFY_PERMISSIONS;
|
Chris@0
|
63
|
Chris@0
|
64 /**
|
Chris@0
|
65 * Flag for dealing with existing files: Appends number until name is unique.
|
Chris@18
|
66 *
|
Chris@18
|
67 * @deprecated in Drupal 8.7.0, will be removed before Drupal 9.0.0.
|
Chris@18
|
68 * Use \Drupal\Core\File\FileSystemInterface::EXISTS_RENAME.
|
Chris@0
|
69 */
|
Chris@18
|
70 const FILE_EXISTS_RENAME = FileSystemInterface::EXISTS_RENAME;
|
Chris@0
|
71
|
Chris@0
|
72 /**
|
Chris@0
|
73 * Flag for dealing with existing files: Replace the existing file.
|
Chris@18
|
74 *
|
Chris@18
|
75 * @deprecated in Drupal 8.7.0, will be removed before Drupal 9.0.0.
|
Chris@18
|
76 * Use \Drupal\Core\File\FileSystemInterface::EXISTS_REPLACE.
|
Chris@0
|
77 */
|
Chris@18
|
78 const FILE_EXISTS_REPLACE = FileSystemInterface::EXISTS_REPLACE;
|
Chris@0
|
79
|
Chris@0
|
80 /**
|
Chris@0
|
81 * Flag for dealing with existing files: Do nothing and return FALSE.
|
Chris@18
|
82 *
|
Chris@18
|
83 * @deprecated in Drupal 8.7.0, will be removed before Drupal 9.0.0.
|
Chris@18
|
84 * Use \Drupal\Core\File\FileSystemInterface::EXISTS_ERROR.
|
Chris@0
|
85 */
|
Chris@18
|
86 const FILE_EXISTS_ERROR = FileSystemInterface::EXISTS_ERROR;
|
Chris@0
|
87
|
Chris@0
|
88 /**
|
Chris@0
|
89 * Indicates that the file is permanent and should not be deleted.
|
Chris@0
|
90 *
|
Chris@0
|
91 * Temporary files older than the system.file.temporary_maximum_age
|
Chris@0
|
92 * configuration value will be, if clean-up not disabled, removed during cron
|
Chris@0
|
93 * runs, but permanent files will not be removed during the file garbage
|
Chris@0
|
94 * collection process.
|
Chris@0
|
95 */
|
Chris@0
|
96 const FILE_STATUS_PERMANENT = 1;
|
Chris@0
|
97
|
Chris@0
|
98 /**
|
Chris@0
|
99 * Returns the scheme of a URI (e.g. a stream).
|
Chris@0
|
100 *
|
Chris@0
|
101 * @deprecated in Drupal 8.0.x-dev, will be removed before Drupal 9.0.0.
|
Chris@0
|
102 * Use \Drupal\Core\File\FileSystem::uriScheme().
|
Chris@0
|
103 *
|
Chris@0
|
104 * @see https://www.drupal.org/node/2418133
|
Chris@0
|
105 */
|
Chris@0
|
106 function file_uri_scheme($uri) {
|
Chris@0
|
107 return \Drupal::service('file_system')->uriScheme($uri);
|
Chris@0
|
108 }
|
Chris@0
|
109
|
Chris@0
|
110 /**
|
Chris@0
|
111 * Checks that the scheme of a stream URI is valid.
|
Chris@0
|
112 *
|
Chris@0
|
113 * @deprecated in Drupal 8.0.x-dev, will be removed before Drupal 9.0.0.
|
Chris@0
|
114 * Use \Drupal\Core\File\FileSystem::validScheme().
|
Chris@0
|
115 *
|
Chris@0
|
116 * @see https://www.drupal.org/node/2418133
|
Chris@0
|
117 */
|
Chris@0
|
118 function file_stream_wrapper_valid_scheme($scheme) {
|
Chris@0
|
119 return \Drupal::service('file_system')->validScheme($scheme);
|
Chris@0
|
120 }
|
Chris@0
|
121
|
Chris@0
|
122 /**
|
Chris@0
|
123 * Returns the part of a URI after the schema.
|
Chris@0
|
124 *
|
Chris@0
|
125 * @param string $uri
|
Chris@0
|
126 * A stream, referenced as "scheme://target" or "data:target".
|
Chris@0
|
127 *
|
Chris@0
|
128 * @return string|bool
|
Chris@0
|
129 * A string containing the target (path), or FALSE if none.
|
Chris@0
|
130 * For example, the URI "public://sample/test.txt" would return
|
Chris@0
|
131 * "sample/test.txt".
|
Chris@0
|
132 *
|
Chris@0
|
133 * @see file_uri_scheme()
|
Chris@0
|
134 */
|
Chris@0
|
135 function file_uri_target($uri) {
|
Chris@0
|
136 // Remove the scheme from the URI and remove erroneous leading or trailing,
|
Chris@0
|
137 // forward-slashes and backslashes.
|
Chris@0
|
138 $target = trim(preg_replace('/^[\w\-]+:\/\/|^data:/', '', $uri), '\/');
|
Chris@0
|
139
|
Chris@0
|
140 // If nothing was replaced, the URI doesn't have a valid scheme.
|
Chris@0
|
141 return $target !== $uri ? $target : FALSE;
|
Chris@0
|
142 }
|
Chris@0
|
143
|
Chris@0
|
144 /**
|
Chris@0
|
145 * Gets the default file stream implementation.
|
Chris@0
|
146 *
|
Chris@0
|
147 * @return string
|
Chris@0
|
148 * 'public', 'private' or any other file scheme defined as the default.
|
Chris@0
|
149 */
|
Chris@0
|
150 function file_default_scheme() {
|
Chris@0
|
151 return \Drupal::config('system.file')->get('default_scheme');
|
Chris@0
|
152 }
|
Chris@0
|
153
|
Chris@0
|
154 /**
|
Chris@0
|
155 * Normalizes a URI by making it syntactically correct.
|
Chris@0
|
156 *
|
Chris@0
|
157 * A stream is referenced as "scheme://target".
|
Chris@0
|
158 *
|
Chris@0
|
159 * The following actions are taken:
|
Chris@0
|
160 * - Remove trailing slashes from target
|
Chris@0
|
161 * - Trim erroneous leading slashes from target. e.g. ":///" becomes "://".
|
Chris@0
|
162 *
|
Chris@0
|
163 * @param string $uri
|
Chris@0
|
164 * String reference containing the URI to normalize.
|
Chris@0
|
165 *
|
Chris@0
|
166 * @return string
|
Chris@0
|
167 * The normalized URI.
|
Chris@0
|
168 */
|
Chris@0
|
169 function file_stream_wrapper_uri_normalize($uri) {
|
Chris@0
|
170 $scheme = \Drupal::service('file_system')->uriScheme($uri);
|
Chris@0
|
171
|
Chris@0
|
172 if (file_stream_wrapper_valid_scheme($scheme)) {
|
Chris@0
|
173 $target = file_uri_target($uri);
|
Chris@0
|
174
|
Chris@0
|
175 if ($target !== FALSE) {
|
Chris@0
|
176 $uri = $scheme . '://' . $target;
|
Chris@0
|
177 }
|
Chris@0
|
178 }
|
Chris@0
|
179
|
Chris@0
|
180 return $uri;
|
Chris@0
|
181 }
|
Chris@0
|
182
|
Chris@0
|
183 /**
|
Chris@0
|
184 * Creates a web-accessible URL for a stream to an external or local file.
|
Chris@0
|
185 *
|
Chris@0
|
186 * Compatibility: normal paths and stream wrappers.
|
Chris@0
|
187 *
|
Chris@0
|
188 * There are two kinds of local files:
|
Chris@0
|
189 * - "managed files", i.e. those stored by a Drupal-compatible stream wrapper.
|
Chris@0
|
190 * These are files that have either been uploaded by users or were generated
|
Chris@0
|
191 * automatically (for example through CSS aggregation).
|
Chris@0
|
192 * - "shipped files", i.e. those outside of the files directory, which ship as
|
Chris@0
|
193 * part of Drupal core or contributed modules or themes.
|
Chris@0
|
194 *
|
Chris@0
|
195 * @param string $uri
|
Chris@0
|
196 * The URI to a file for which we need an external URL, or the path to a
|
Chris@0
|
197 * shipped file.
|
Chris@0
|
198 *
|
Chris@0
|
199 * @return string
|
Chris@0
|
200 * A string containing a URL that may be used to access the file.
|
Chris@0
|
201 * If the provided string already contains a preceding 'http', 'https', or
|
Chris@0
|
202 * '/', nothing is done and the same string is returned. If a stream wrapper
|
Chris@0
|
203 * could not be found to generate an external URL, then FALSE is returned.
|
Chris@0
|
204 *
|
Chris@0
|
205 * @see https://www.drupal.org/node/515192
|
Chris@0
|
206 * @see file_url_transform_relative()
|
Chris@0
|
207 */
|
Chris@0
|
208 function file_create_url($uri) {
|
Chris@0
|
209 // Allow the URI to be altered, e.g. to serve a file from a CDN or static
|
Chris@0
|
210 // file server.
|
Chris@0
|
211 \Drupal::moduleHandler()->alter('file_url', $uri);
|
Chris@0
|
212
|
Chris@0
|
213 $scheme = \Drupal::service('file_system')->uriScheme($uri);
|
Chris@0
|
214
|
Chris@0
|
215 if (!$scheme) {
|
Chris@0
|
216 // Allow for:
|
Chris@0
|
217 // - root-relative URIs (e.g. /foo.jpg in http://example.com/foo.jpg)
|
Chris@0
|
218 // - protocol-relative URIs (e.g. //bar.jpg, which is expanded to
|
Chris@0
|
219 // http://example.com/bar.jpg by the browser when viewing a page over
|
Chris@0
|
220 // HTTP and to https://example.com/bar.jpg when viewing a HTTPS page)
|
Chris@0
|
221 // Both types of relative URIs are characterized by a leading slash, hence
|
Chris@0
|
222 // we can use a single check.
|
Chris@17
|
223 if (mb_substr($uri, 0, 1) == '/') {
|
Chris@0
|
224 return $uri;
|
Chris@0
|
225 }
|
Chris@0
|
226 else {
|
Chris@0
|
227 // If this is not a properly formatted stream, then it is a shipped file.
|
Chris@0
|
228 // Therefore, return the urlencoded URI with the base URL prepended.
|
Chris@0
|
229 $options = UrlHelper::parse($uri);
|
Chris@0
|
230 $path = $GLOBALS['base_url'] . '/' . UrlHelper::encodePath($options['path']);
|
Chris@0
|
231 // Append the query.
|
Chris@0
|
232 if ($options['query']) {
|
Chris@0
|
233 $path .= '?' . UrlHelper::buildQuery($options['query']);
|
Chris@0
|
234 }
|
Chris@0
|
235
|
Chris@0
|
236 // Append fragment.
|
Chris@0
|
237 if ($options['fragment']) {
|
Chris@0
|
238 $path .= '#' . $options['fragment'];
|
Chris@0
|
239 }
|
Chris@0
|
240
|
Chris@0
|
241 return $path;
|
Chris@0
|
242 }
|
Chris@0
|
243 }
|
Chris@0
|
244 elseif ($scheme == 'http' || $scheme == 'https' || $scheme == 'data') {
|
Chris@0
|
245 // Check for HTTP and data URI-encoded URLs so that we don't have to
|
Chris@0
|
246 // implement getExternalUrl() for the HTTP and data schemes.
|
Chris@0
|
247 return $uri;
|
Chris@0
|
248 }
|
Chris@0
|
249 else {
|
Chris@0
|
250 // Attempt to return an external URL using the appropriate wrapper.
|
Chris@0
|
251 if ($wrapper = \Drupal::service('stream_wrapper_manager')->getViaUri($uri)) {
|
Chris@0
|
252 return $wrapper->getExternalUrl();
|
Chris@0
|
253 }
|
Chris@0
|
254 else {
|
Chris@0
|
255 return FALSE;
|
Chris@0
|
256 }
|
Chris@0
|
257 }
|
Chris@0
|
258 }
|
Chris@0
|
259
|
Chris@0
|
260 /**
|
Chris@0
|
261 * Transforms an absolute URL of a local file to a relative URL.
|
Chris@0
|
262 *
|
Chris@0
|
263 * May be useful to prevent problems on multisite set-ups and prevent mixed
|
Chris@0
|
264 * content errors when using HTTPS + HTTP.
|
Chris@0
|
265 *
|
Chris@0
|
266 * @param string $file_url
|
Chris@0
|
267 * A file URL of a local file as generated by file_create_url().
|
Chris@0
|
268 *
|
Chris@0
|
269 * @return string
|
Chris@0
|
270 * If the file URL indeed pointed to a local file and was indeed absolute,
|
Chris@0
|
271 * then the transformed, relative URL to the local file. Otherwise: the
|
Chris@0
|
272 * original value of $file_url.
|
Chris@0
|
273 *
|
Chris@0
|
274 * @see file_create_url()
|
Chris@0
|
275 */
|
Chris@0
|
276 function file_url_transform_relative($file_url) {
|
Chris@0
|
277 // Unfortunately, we pretty much have to duplicate Symfony's
|
Chris@0
|
278 // Request::getHttpHost() method because Request::getPort() may return NULL
|
Chris@0
|
279 // instead of a port number.
|
Chris@0
|
280 $request = \Drupal::request();
|
Chris@0
|
281 $host = $request->getHost();
|
Chris@0
|
282 $scheme = $request->getScheme();
|
Chris@0
|
283 $port = $request->getPort() ?: 80;
|
Chris@0
|
284 if (('http' == $scheme && $port == 80) || ('https' == $scheme && $port == 443)) {
|
Chris@0
|
285 $http_host = $host;
|
Chris@0
|
286 }
|
Chris@0
|
287 else {
|
Chris@0
|
288 $http_host = $host . ':' . $port;
|
Chris@0
|
289 }
|
Chris@0
|
290
|
Chris@16
|
291 return preg_replace('|^https?://' . preg_quote($http_host, '|') . '|', '', $file_url);
|
Chris@0
|
292 }
|
Chris@0
|
293
|
Chris@0
|
294 /**
|
Chris@0
|
295 * Checks that the directory exists and is writable.
|
Chris@0
|
296 *
|
Chris@0
|
297 * Directories need to have execute permissions to be considered a directory by
|
Chris@0
|
298 * FTP servers, etc.
|
Chris@0
|
299 *
|
Chris@0
|
300 * @param $directory
|
Chris@0
|
301 * A string reference containing the name of a directory path or URI. A
|
Chris@0
|
302 * trailing slash will be trimmed from a path.
|
Chris@0
|
303 * @param $options
|
Chris@0
|
304 * A bitmask to indicate if the directory should be created if it does
|
Chris@0
|
305 * not exist (FILE_CREATE_DIRECTORY) or made writable if it is read-only
|
Chris@0
|
306 * (FILE_MODIFY_PERMISSIONS).
|
Chris@0
|
307 *
|
Chris@0
|
308 * @return
|
Chris@0
|
309 * TRUE if the directory exists (or was created) and is writable. FALSE
|
Chris@0
|
310 * otherwise.
|
Chris@18
|
311 *
|
Chris@18
|
312 * @deprecated in Drupal 8.7.0, will be removed before Drupal 9.0.0.
|
Chris@18
|
313 * Use \Drupal\Core\File\FileSystemInterface::prepareDirectory().
|
Chris@0
|
314 */
|
Chris@18
|
315 function file_prepare_directory(&$directory, $options = FileSystemInterface::MODIFY_PERMISSIONS) {
|
Chris@18
|
316 @trigger_error('file_prepare_directory() is deprecated in Drupal 8.7.0 and will be removed before Drupal 9.0.0. Use \Drupal\Core\File\FileSystemInterface::prepareDirectory(). See https://www.drupal.org/node/3006851.', E_USER_DEPRECATED);
|
Chris@18
|
317 return \Drupal::service('file_system')->prepareDirectory($directory, $options);
|
Chris@0
|
318 }
|
Chris@0
|
319
|
Chris@0
|
320 /**
|
Chris@0
|
321 * Creates a .htaccess file in each Drupal files directory if it is missing.
|
Chris@0
|
322 */
|
Chris@0
|
323 function file_ensure_htaccess() {
|
Chris@0
|
324 file_save_htaccess('public://', FALSE);
|
Chris@0
|
325 $private_path = PrivateStream::basePath();
|
Chris@0
|
326 if (!empty($private_path)) {
|
Chris@0
|
327 file_save_htaccess('private://', TRUE);
|
Chris@0
|
328 }
|
Chris@0
|
329 file_save_htaccess('temporary://', TRUE);
|
Chris@0
|
330
|
Chris@0
|
331 // If a staging directory exists then it should contain a .htaccess file.
|
Chris@0
|
332 // @todo https://www.drupal.org/node/2696103 catch a more specific exception
|
Chris@0
|
333 // and simplify this code.
|
Chris@0
|
334 try {
|
Chris@0
|
335 $staging = config_get_config_directory(CONFIG_SYNC_DIRECTORY);
|
Chris@0
|
336 }
|
Chris@0
|
337 catch (\Exception $e) {
|
Chris@0
|
338 $staging = FALSE;
|
Chris@0
|
339 }
|
Chris@0
|
340 if ($staging) {
|
Chris@0
|
341 // Note that we log an error here if we can't write the .htaccess file. This
|
Chris@0
|
342 // can occur if the staging directory is read-only. If it is then it is the
|
Chris@0
|
343 // user's responsibility to create the .htaccess file.
|
Chris@0
|
344 file_save_htaccess($staging, TRUE);
|
Chris@0
|
345 }
|
Chris@0
|
346 }
|
Chris@0
|
347
|
Chris@0
|
348 /**
|
Chris@0
|
349 * Creates a .htaccess file in the given directory.
|
Chris@0
|
350 *
|
Chris@0
|
351 * @param string $directory
|
Chris@0
|
352 * The directory.
|
Chris@0
|
353 * @param bool $private
|
Chris@0
|
354 * (Optional) FALSE indicates that $directory should be a web-accessible
|
Chris@0
|
355 * directory. Defaults to TRUE which indicates a private directory.
|
Chris@0
|
356 * @param bool $force_overwrite
|
Chris@0
|
357 * (Optional) Set to TRUE to attempt to overwrite the existing .htaccess file
|
Chris@0
|
358 * if one is already present. Defaults to FALSE.
|
Chris@0
|
359 */
|
Chris@0
|
360 function file_save_htaccess($directory, $private = TRUE, $force_overwrite = FALSE) {
|
Chris@0
|
361 if (\Drupal::service('file_system')->uriScheme($directory)) {
|
Chris@0
|
362 $htaccess_path = file_stream_wrapper_uri_normalize($directory . '/.htaccess');
|
Chris@0
|
363 }
|
Chris@0
|
364 else {
|
Chris@0
|
365 $directory = rtrim($directory, '/\\');
|
Chris@0
|
366 $htaccess_path = $directory . '/.htaccess';
|
Chris@0
|
367 }
|
Chris@0
|
368
|
Chris@0
|
369 if (file_exists($htaccess_path) && !$force_overwrite) {
|
Chris@0
|
370 // Short circuit if the .htaccess file already exists.
|
Chris@0
|
371 return TRUE;
|
Chris@0
|
372 }
|
Chris@0
|
373 $htaccess_lines = FileStorage::htaccessLines($private);
|
Chris@0
|
374
|
Chris@0
|
375 // Write the .htaccess file.
|
Chris@0
|
376 if (file_exists($directory) && is_writable($directory) && file_put_contents($htaccess_path, $htaccess_lines)) {
|
Chris@18
|
377 return \Drupal::service('file_system')->chmod($htaccess_path, 0444);
|
Chris@0
|
378 }
|
Chris@0
|
379 else {
|
Chris@0
|
380 $variables = ['%directory' => $directory, '@htaccess' => $htaccess_lines];
|
Chris@0
|
381 \Drupal::logger('security')->error("Security warning: Couldn't write .htaccess file. Please create a .htaccess file in your %directory directory which contains the following lines: <pre><code>@htaccess</code></pre>", $variables);
|
Chris@0
|
382 return FALSE;
|
Chris@0
|
383 }
|
Chris@0
|
384 }
|
Chris@0
|
385
|
Chris@0
|
386 /**
|
Chris@0
|
387 * Returns the standard .htaccess lines that Drupal writes to file directories.
|
Chris@0
|
388 *
|
Chris@0
|
389 * @param bool $private
|
Chris@0
|
390 * (Optional) Set to FALSE to return the .htaccess lines for a web-accessible
|
Chris@0
|
391 * public directory. The default is TRUE, which returns the .htaccess lines
|
Chris@0
|
392 * for a private directory that should not be web-accessible.
|
Chris@0
|
393 *
|
Chris@0
|
394 * @return string
|
Chris@0
|
395 * The desired contents of the .htaccess file.
|
Chris@0
|
396 *
|
Chris@0
|
397 * @deprecated in Drupal 8.0.x-dev and will be removed before Drupal 9.0.0.
|
Chris@0
|
398 * Use \Drupal\Component\PhpStorage\FileStorage::htaccessLines().
|
Chris@0
|
399 *
|
Chris@0
|
400 * @see https://www.drupal.org/node/2418133
|
Chris@0
|
401 */
|
Chris@0
|
402 function file_htaccess_lines($private = TRUE) {
|
Chris@0
|
403 return FileStorage::htaccessLines($private);
|
Chris@0
|
404 }
|
Chris@0
|
405
|
Chris@0
|
406 /**
|
Chris@0
|
407 * Determines whether the URI has a valid scheme for file API operations.
|
Chris@0
|
408 *
|
Chris@0
|
409 * There must be a scheme and it must be a Drupal-provided scheme like
|
Chris@0
|
410 * 'public', 'private', 'temporary', or an extension provided with
|
Chris@0
|
411 * hook_stream_wrappers().
|
Chris@0
|
412 *
|
Chris@0
|
413 * @param $uri
|
Chris@0
|
414 * The URI to be tested.
|
Chris@0
|
415 *
|
Chris@0
|
416 * @return
|
Chris@0
|
417 * TRUE if the URI is allowed.
|
Chris@0
|
418 */
|
Chris@0
|
419 function file_valid_uri($uri) {
|
Chris@0
|
420 // Assert that the URI has an allowed scheme. Bare paths are not allowed.
|
Chris@0
|
421 $uri_scheme = \Drupal::service('file_system')->uriScheme($uri);
|
Chris@0
|
422 if (!file_stream_wrapper_valid_scheme($uri_scheme)) {
|
Chris@0
|
423 return FALSE;
|
Chris@0
|
424 }
|
Chris@0
|
425 return TRUE;
|
Chris@0
|
426 }
|
Chris@0
|
427
|
Chris@0
|
428 /**
|
Chris@0
|
429 * Copies a file to a new location without database changes or hook invocation.
|
Chris@0
|
430 *
|
Chris@0
|
431 * This is a powerful function that in many ways performs like an advanced
|
Chris@0
|
432 * version of copy().
|
Chris@0
|
433 * - Checks if $source and $destination are valid and readable/writable.
|
Chris@0
|
434 * - If file already exists in $destination either the call will error out,
|
Chris@0
|
435 * replace the file or rename the file based on the $replace parameter.
|
Chris@0
|
436 * - If the $source and $destination are equal, the behavior depends on the
|
Chris@0
|
437 * $replace parameter. FILE_EXISTS_REPLACE will error out. FILE_EXISTS_RENAME
|
Chris@0
|
438 * will rename the file until the $destination is unique.
|
Chris@0
|
439 * - Works around a PHP bug where copy() does not properly support streams if
|
Chris@0
|
440 * safe_mode or open_basedir are enabled.
|
Chris@0
|
441 * @see https://bugs.php.net/bug.php?id=60456
|
Chris@0
|
442 *
|
Chris@0
|
443 * @param $source
|
Chris@0
|
444 * A string specifying the filepath or URI of the source file.
|
Chris@0
|
445 * @param $destination
|
Chris@0
|
446 * A URI containing the destination that $source should be copied to. The
|
Chris@0
|
447 * URI may be a bare filepath (without a scheme). If this value is omitted,
|
Chris@0
|
448 * Drupal's default files scheme will be used, usually "public://".
|
Chris@0
|
449 * @param $replace
|
Chris@0
|
450 * Replace behavior when the destination file already exists:
|
Chris@0
|
451 * - FILE_EXISTS_REPLACE - Replace the existing file.
|
Chris@0
|
452 * - FILE_EXISTS_RENAME - Append _{incrementing number} until the filename is
|
Chris@0
|
453 * unique.
|
Chris@0
|
454 * - FILE_EXISTS_ERROR - Do nothing and return FALSE.
|
Chris@0
|
455 *
|
Chris@0
|
456 * @return
|
Chris@0
|
457 * The path to the new file, or FALSE in the event of an error.
|
Chris@0
|
458 *
|
Chris@18
|
459 * @deprecated in Drupal 8.7.0, will be removed before Drupal 9.0.0.
|
Chris@18
|
460 * Use \Drupal\Core\File\FileSystemInterface::copy().
|
Chris@18
|
461 *
|
Chris@0
|
462 * @see file_copy()
|
Chris@18
|
463 * @see https://www.drupal.org/node/3006851
|
Chris@0
|
464 */
|
Chris@0
|
465 function file_unmanaged_copy($source, $destination = NULL, $replace = FILE_EXISTS_RENAME) {
|
Chris@18
|
466 @trigger_error('file_unmanaged_copy() is deprecated in Drupal 8.7.0 and will be removed before Drupal 9.0.0. Use \Drupal\Core\File\FileSystemInterface::copy(). See https://www.drupal.org/node/3006851.', E_USER_DEPRECATED);
|
Chris@18
|
467 try {
|
Chris@18
|
468 $file_system = \Drupal::service('file_system');
|
Chris@18
|
469
|
Chris@18
|
470 // Build a destination URI if necessary.
|
Chris@18
|
471 if (!isset($destination)) {
|
Chris@18
|
472 $destination = file_build_uri($file_system->basename($source));
|
Chris@18
|
473 }
|
Chris@18
|
474 return $file_system->copy($source, $destination, $replace);
|
Chris@18
|
475 }
|
Chris@18
|
476 catch (FileException $e) {
|
Chris@0
|
477 return FALSE;
|
Chris@0
|
478 }
|
Chris@0
|
479 }
|
Chris@0
|
480
|
Chris@0
|
481 /**
|
Chris@0
|
482 * Internal function that prepares the destination for a file_unmanaged_copy or
|
Chris@0
|
483 * file_unmanaged_move operation.
|
Chris@0
|
484 *
|
Chris@0
|
485 * - Checks if $source and $destination are valid and readable/writable.
|
Chris@0
|
486 * - Checks that $source is not equal to $destination; if they are an error
|
Chris@0
|
487 * is reported.
|
Chris@0
|
488 * - If file already exists in $destination either the call will error out,
|
Chris@0
|
489 * replace the file or rename the file based on the $replace parameter.
|
Chris@0
|
490 *
|
Chris@0
|
491 * @param $source
|
Chris@0
|
492 * A string specifying the filepath or URI of the source file.
|
Chris@0
|
493 * @param $destination
|
Chris@0
|
494 * A URI containing the destination that $source should be moved/copied to.
|
Chris@0
|
495 * The URI may be a bare filepath (without a scheme) and in that case the
|
Chris@0
|
496 * default scheme (file://) will be used. If this value is omitted, Drupal's
|
Chris@0
|
497 * default files scheme will be used, usually "public://".
|
Chris@0
|
498 * @param $replace
|
Chris@0
|
499 * Replace behavior when the destination file already exists:
|
Chris@0
|
500 * - FILE_EXISTS_REPLACE - Replace the existing file.
|
Chris@0
|
501 * - FILE_EXISTS_RENAME - Append _{incrementing number} until the filename is
|
Chris@0
|
502 * unique.
|
Chris@0
|
503 * - FILE_EXISTS_ERROR - Do nothing and return FALSE.
|
Chris@0
|
504 *
|
Chris@0
|
505 * @return
|
Chris@0
|
506 * TRUE, or FALSE in the event of an error.
|
Chris@0
|
507 *
|
Chris@18
|
508 * @deprecated in Drupal 8.7.0, will be removed before Drupal 9.0.0.
|
Chris@18
|
509 * Use \Drupal\Core\File\FileSystemInterface::getDestinationFilename() instead.
|
Chris@18
|
510 *
|
Chris@0
|
511 * @see file_unmanaged_copy()
|
Chris@0
|
512 * @see file_unmanaged_move()
|
Chris@18
|
513 * @see https://www.drupal.org/node/3006851
|
Chris@0
|
514 */
|
Chris@0
|
515 function file_unmanaged_prepare($source, &$destination = NULL, $replace = FILE_EXISTS_RENAME) {
|
Chris@18
|
516 @trigger_error('file_unmanaged_prepare() is deprecated in Drupal 8.7.0 and will be removed before Drupal 9.0.0. Use \Drupal\Core\File\FileSystemInterface::getDestinationFilename() instead. See https://www.drupal.org/node/3006851.', E_USER_DEPRECATED);
|
Chris@0
|
517 $original_source = $source;
|
Chris@0
|
518 $logger = \Drupal::logger('file');
|
Chris@18
|
519 /** @var \Drupal\Core\File\FileSystemInterface $file_system */
|
Chris@14
|
520 $file_system = \Drupal::service('file_system');
|
Chris@0
|
521
|
Chris@0
|
522 // Assert that the source file actually exists.
|
Chris@0
|
523 if (!file_exists($source)) {
|
Chris@17
|
524 // @todo Replace \Drupal::messenger()->addError() calls with exceptions
|
Chris@17
|
525 // instead.
|
Chris@17
|
526 \Drupal::messenger()->addError(t('The specified file %file could not be moved/copied because no file by that name exists. Please check that you supplied the correct filename.', ['%file' => $original_source]));
|
Chris@14
|
527 if (($realpath = $file_system->realpath($original_source)) !== FALSE) {
|
Chris@0
|
528 $logger->notice('File %file (%realpath) could not be moved/copied because it does not exist.', ['%file' => $original_source, '%realpath' => $realpath]);
|
Chris@0
|
529 }
|
Chris@0
|
530 else {
|
Chris@0
|
531 $logger->notice('File %file could not be moved/copied because it does not exist.', ['%file' => $original_source]);
|
Chris@0
|
532 }
|
Chris@0
|
533 return FALSE;
|
Chris@0
|
534 }
|
Chris@0
|
535
|
Chris@0
|
536 // Build a destination URI if necessary.
|
Chris@0
|
537 if (!isset($destination)) {
|
Chris@18
|
538 $destination = file_build_uri($file_system->basename($source));
|
Chris@0
|
539 }
|
Chris@0
|
540
|
Chris@0
|
541 // Prepare the destination directory.
|
Chris@0
|
542 if (file_prepare_directory($destination)) {
|
Chris@0
|
543 // The destination is already a directory, so append the source basename.
|
Chris@18
|
544 $destination = file_stream_wrapper_uri_normalize($destination . '/' . $file_system->basename($source));
|
Chris@0
|
545 }
|
Chris@0
|
546 else {
|
Chris@0
|
547 // Perhaps $destination is a dir/file?
|
Chris@18
|
548 $dirname = $file_system->dirname($destination);
|
Chris@0
|
549 if (!file_prepare_directory($dirname)) {
|
Chris@0
|
550 // The destination is not valid.
|
Chris@0
|
551 $logger->notice('File %file could not be moved/copied because the destination directory %destination is not configured correctly.', ['%file' => $original_source, '%destination' => $dirname]);
|
Chris@17
|
552 \Drupal::messenger()->addError(t('The specified file %file could not be moved/copied because the destination directory is not properly configured. This may be caused by a problem with file or directory permissions. More information is available in the system log.', ['%file' => $original_source]));
|
Chris@0
|
553 return FALSE;
|
Chris@0
|
554 }
|
Chris@0
|
555 }
|
Chris@0
|
556
|
Chris@0
|
557 // Determine whether we can perform this operation based on overwrite rules.
|
Chris@0
|
558 $destination = file_destination($destination, $replace);
|
Chris@0
|
559 if ($destination === FALSE) {
|
Chris@17
|
560 \Drupal::messenger()->addError(t('The file %file could not be moved/copied because a file by that name already exists in the destination directory.', ['%file' => $original_source]));
|
Chris@0
|
561 $logger->notice('File %file could not be moved/copied because a file by that name already exists in the destination directory (%destination)', ['%file' => $original_source, '%destination' => $destination]);
|
Chris@0
|
562 return FALSE;
|
Chris@0
|
563 }
|
Chris@0
|
564
|
Chris@0
|
565 // Assert that the source and destination filenames are not the same.
|
Chris@14
|
566 $real_source = $file_system->realpath($source);
|
Chris@14
|
567 $real_destination = $file_system->realpath($destination);
|
Chris@0
|
568 if ($source == $destination || ($real_source !== FALSE) && ($real_source == $real_destination)) {
|
Chris@17
|
569 \Drupal::messenger()->addError(t('The specified file %file was not moved/copied because it would overwrite itself.', ['%file' => $source]));
|
Chris@0
|
570 $logger->notice('File %file could not be moved/copied because it would overwrite itself.', ['%file' => $source]);
|
Chris@0
|
571 return FALSE;
|
Chris@0
|
572 }
|
Chris@0
|
573 // Make sure the .htaccess files are present.
|
Chris@0
|
574 file_ensure_htaccess();
|
Chris@0
|
575 return TRUE;
|
Chris@0
|
576 }
|
Chris@0
|
577
|
Chris@0
|
578 /**
|
Chris@0
|
579 * Constructs a URI to Drupal's default files location given a relative path.
|
Chris@0
|
580 */
|
Chris@0
|
581 function file_build_uri($path) {
|
Chris@0
|
582 $uri = file_default_scheme() . '://' . $path;
|
Chris@0
|
583 return file_stream_wrapper_uri_normalize($uri);
|
Chris@0
|
584 }
|
Chris@0
|
585
|
Chris@0
|
586 /**
|
Chris@0
|
587 * Determines the destination path for a file.
|
Chris@0
|
588 *
|
Chris@0
|
589 * @param $destination
|
Chris@0
|
590 * A string specifying the desired final URI or filepath.
|
Chris@0
|
591 * @param $replace
|
Chris@0
|
592 * Replace behavior when the destination file already exists.
|
Chris@0
|
593 * - FILE_EXISTS_REPLACE - Replace the existing file.
|
Chris@0
|
594 * - FILE_EXISTS_RENAME - Append _{incrementing number} until the filename is
|
Chris@0
|
595 * unique.
|
Chris@0
|
596 * - FILE_EXISTS_ERROR - Do nothing and return FALSE.
|
Chris@0
|
597 *
|
Chris@0
|
598 * @return
|
Chris@0
|
599 * The destination filepath, or FALSE if the file already exists
|
Chris@0
|
600 * and FILE_EXISTS_ERROR is specified.
|
Chris@18
|
601 *
|
Chris@18
|
602 * @deprecated in Drupal 8.7.0, will be removed before Drupal 9.0.0.
|
Chris@18
|
603 * Use \Drupal\Core\File\FileSystemInterface::getDestinationFilename().
|
Chris@18
|
604 *
|
Chris@18
|
605 * @see https://www.drupal.org/node/3006851
|
Chris@0
|
606 */
|
Chris@0
|
607 function file_destination($destination, $replace) {
|
Chris@18
|
608 @trigger_error('file_destination() is deprecated in Drupal 8.7.0 and will be removed before Drupal 9.0.0. Use \Drupal\Core\File\FileSystemInterface::getDestinationFilename(). See https://www.drupal.org/node/3006851.', E_USER_DEPRECATED);
|
Chris@18
|
609 return \Drupal::service('file_system')->getDestinationFilename($destination, $replace);
|
Chris@0
|
610 }
|
Chris@0
|
611
|
Chris@0
|
612 /**
|
Chris@0
|
613 * Moves a file to a new location without database changes or hook invocation.
|
Chris@0
|
614 *
|
Chris@0
|
615 * This is a powerful function that in many ways performs like an advanced
|
Chris@0
|
616 * version of rename().
|
Chris@0
|
617 * - Checks if $source and $destination are valid and readable/writable.
|
Chris@0
|
618 * - Checks that $source is not equal to $destination; if they are an error
|
Chris@0
|
619 * is reported.
|
Chris@0
|
620 * - If file already exists in $destination either the call will error out,
|
Chris@0
|
621 * replace the file or rename the file based on the $replace parameter.
|
Chris@0
|
622 * - Works around a PHP bug where rename() does not properly support streams if
|
Chris@0
|
623 * safe_mode or open_basedir are enabled.
|
Chris@0
|
624 * @see https://bugs.php.net/bug.php?id=60456
|
Chris@0
|
625 *
|
Chris@0
|
626 * @param $source
|
Chris@0
|
627 * A string specifying the filepath or URI of the source file.
|
Chris@0
|
628 * @param $destination
|
Chris@0
|
629 * A URI containing the destination that $source should be moved to. The
|
Chris@0
|
630 * URI may be a bare filepath (without a scheme) and in that case the default
|
Chris@0
|
631 * scheme (file://) will be used. If this value is omitted, Drupal's default
|
Chris@0
|
632 * files scheme will be used, usually "public://".
|
Chris@0
|
633 * @param $replace
|
Chris@0
|
634 * Replace behavior when the destination file already exists:
|
Chris@0
|
635 * - FILE_EXISTS_REPLACE - Replace the existing file.
|
Chris@0
|
636 * - FILE_EXISTS_RENAME - Append _{incrementing number} until the filename is
|
Chris@0
|
637 * unique.
|
Chris@0
|
638 * - FILE_EXISTS_ERROR - Do nothing and return FALSE.
|
Chris@0
|
639 *
|
Chris@0
|
640 * @return
|
Chris@0
|
641 * The path to the new file, or FALSE in the event of an error.
|
Chris@0
|
642 *
|
Chris@18
|
643 * @deprecated in Drupal 8.7.0, will be removed before Drupal 9.0.0.
|
Chris@18
|
644 * Use \Drupal\Core\File\FileSystemInterface::move().
|
Chris@18
|
645 *
|
Chris@0
|
646 * @see file_move()
|
Chris@18
|
647 * @see https://www.drupal.org/node/3006851
|
Chris@0
|
648 */
|
Chris@0
|
649 function file_unmanaged_move($source, $destination = NULL, $replace = FILE_EXISTS_RENAME) {
|
Chris@18
|
650 @trigger_error('file_unmanaged_move() is deprecated in Drupal 8.7.0 and will be removed before Drupal 9.0.0. Use \Drupal\Core\File\FileSystemInterface::move(). See https://www.drupal.org/node/3006851.', E_USER_DEPRECATED);
|
Chris@18
|
651 try {
|
Chris@18
|
652 $file_system = \Drupal::service('file_system');
|
Chris@18
|
653
|
Chris@18
|
654 // Build a destination URI if necessary.
|
Chris@18
|
655 if (!isset($destination)) {
|
Chris@18
|
656 $destination = file_build_uri($file_system->basename($source));
|
Chris@18
|
657 }
|
Chris@18
|
658 return $file_system->move($source, $destination, $replace);
|
Chris@18
|
659 }
|
Chris@18
|
660 catch (FileException $e) {
|
Chris@0
|
661 return FALSE;
|
Chris@0
|
662 }
|
Chris@0
|
663 }
|
Chris@0
|
664
|
Chris@0
|
665 /**
|
Chris@0
|
666 * Modifies a filename as needed for security purposes.
|
Chris@0
|
667 *
|
Chris@0
|
668 * Munging a file name prevents unknown file extensions from masking exploit
|
Chris@0
|
669 * files. When web servers such as Apache decide how to process a URL request,
|
Chris@0
|
670 * they use the file extension. If the extension is not recognized, Apache
|
Chris@0
|
671 * skips that extension and uses the previous file extension. For example, if
|
Chris@0
|
672 * the file being requested is exploit.php.pps, and Apache does not recognize
|
Chris@0
|
673 * the '.pps' extension, it treats the file as PHP and executes it. To make
|
Chris@0
|
674 * this file name safe for Apache and prevent it from executing as PHP, the
|
Chris@0
|
675 * .php extension is "munged" into .php_, making the safe file name
|
Chris@0
|
676 * exploit.php_.pps.
|
Chris@0
|
677 *
|
Chris@0
|
678 * Specifically, this function adds an underscore to all extensions that are
|
Chris@0
|
679 * between 2 and 5 characters in length, internal to the file name, and not
|
Chris@0
|
680 * included in $extensions.
|
Chris@0
|
681 *
|
Chris@0
|
682 * Function behavior is also controlled by the configuration
|
Chris@0
|
683 * 'system.file:allow_insecure_uploads'. If it evaluates to TRUE, no alterations
|
Chris@0
|
684 * will be made, if it evaluates to FALSE, the filename is 'munged'. *
|
Chris@0
|
685 * @param $filename
|
Chris@0
|
686 * File name to modify.
|
Chris@0
|
687 * @param $extensions
|
Chris@0
|
688 * A space-separated list of extensions that should not be altered.
|
Chris@0
|
689 * @param $alerts
|
Chris@17
|
690 * If TRUE, \Drupal::messenger()->addStatus() will be called to display
|
Chris@17
|
691 * a message if the file name was changed.
|
Chris@0
|
692 *
|
Chris@0
|
693 * @return string
|
Chris@0
|
694 * The potentially modified $filename.
|
Chris@0
|
695 */
|
Chris@0
|
696 function file_munge_filename($filename, $extensions, $alerts = TRUE) {
|
Chris@0
|
697 $original = $filename;
|
Chris@0
|
698
|
Chris@0
|
699 // Allow potentially insecure uploads for very savvy users and admin
|
Chris@0
|
700 if (!\Drupal::config('system.file')->get('allow_insecure_uploads')) {
|
Chris@0
|
701 // Remove any null bytes. See
|
Chris@0
|
702 // http://php.net/manual/security.filesystem.nullbytes.php
|
Chris@0
|
703 $filename = str_replace(chr(0), '', $filename);
|
Chris@0
|
704
|
Chris@0
|
705 $whitelist = array_unique(explode(' ', strtolower(trim($extensions))));
|
Chris@0
|
706
|
Chris@0
|
707 // Split the filename up by periods. The first part becomes the basename
|
Chris@0
|
708 // the last part the final extension.
|
Chris@0
|
709 $filename_parts = explode('.', $filename);
|
Chris@0
|
710 // Remove file basename.
|
Chris@0
|
711 $new_filename = array_shift($filename_parts);
|
Chris@0
|
712 // Remove final extension.
|
Chris@0
|
713 $final_extension = array_pop($filename_parts);
|
Chris@0
|
714
|
Chris@0
|
715 // Loop through the middle parts of the name and add an underscore to the
|
Chris@0
|
716 // end of each section that could be a file extension but isn't in the list
|
Chris@0
|
717 // of allowed extensions.
|
Chris@0
|
718 foreach ($filename_parts as $filename_part) {
|
Chris@0
|
719 $new_filename .= '.' . $filename_part;
|
Chris@0
|
720 if (!in_array(strtolower($filename_part), $whitelist) && preg_match("/^[a-zA-Z]{2,5}\d?$/", $filename_part)) {
|
Chris@0
|
721 $new_filename .= '_';
|
Chris@0
|
722 }
|
Chris@0
|
723 }
|
Chris@0
|
724 $filename = $new_filename . '.' . $final_extension;
|
Chris@0
|
725
|
Chris@0
|
726 if ($alerts && $original != $filename) {
|
Chris@17
|
727 \Drupal::messenger()->addStatus(t('For security reasons, your upload has been renamed to %filename.', ['%filename' => $filename]));
|
Chris@0
|
728 }
|
Chris@0
|
729 }
|
Chris@0
|
730
|
Chris@0
|
731 return $filename;
|
Chris@0
|
732 }
|
Chris@0
|
733
|
Chris@0
|
734 /**
|
Chris@0
|
735 * Undoes the effect of file_munge_filename().
|
Chris@0
|
736 *
|
Chris@0
|
737 * @param $filename
|
Chris@0
|
738 * String with the filename to be unmunged.
|
Chris@0
|
739 *
|
Chris@0
|
740 * @return
|
Chris@0
|
741 * An unmunged filename string.
|
Chris@0
|
742 */
|
Chris@0
|
743 function file_unmunge_filename($filename) {
|
Chris@0
|
744 return str_replace('_.', '.', $filename);
|
Chris@0
|
745 }
|
Chris@0
|
746
|
Chris@0
|
747 /**
|
Chris@0
|
748 * Creates a full file path from a directory and filename.
|
Chris@0
|
749 *
|
Chris@0
|
750 * If a file with the specified name already exists, an alternative will be
|
Chris@0
|
751 * used.
|
Chris@0
|
752 *
|
Chris@0
|
753 * @param $basename
|
Chris@0
|
754 * String filename
|
Chris@0
|
755 * @param $directory
|
Chris@0
|
756 * String containing the directory or parent URI.
|
Chris@0
|
757 *
|
Chris@0
|
758 * @return
|
Chris@0
|
759 * File path consisting of $directory and a unique filename based off
|
Chris@0
|
760 * of $basename.
|
Chris@18
|
761 *
|
Chris@18
|
762 * @deprecated in Drupal 8.7.0, will be removed before Drupal 9.0.0.
|
Chris@18
|
763 * Use \Drupal\Core\File\FileSystemInterface::createFilename().
|
Chris@18
|
764 *
|
Chris@18
|
765 * @see https://www.drupal.org/node/3006851
|
Chris@0
|
766 */
|
Chris@0
|
767 function file_create_filename($basename, $directory) {
|
Chris@18
|
768 @trigger_error('file_create_filename() is deprecated in Drupal 8.7.0 and will be removed before Drupal 9.0.0. Use \Drupal\Core\File\FileSystemInterface::createFilename(). See https://www.drupal.org/node/3006851.', E_USER_DEPRECATED);
|
Chris@18
|
769 return \Drupal::service('file_system')->createFilename($basename, $directory);
|
Chris@0
|
770 }
|
Chris@0
|
771
|
Chris@0
|
772 /**
|
Chris@0
|
773 * Deletes a file and its database record.
|
Chris@0
|
774 *
|
Chris@0
|
775 * Instead of directly deleting a file, it is strongly recommended to delete
|
Chris@0
|
776 * file usages instead. That will automatically mark the file as temporary and
|
Chris@0
|
777 * remove it during cleanup.
|
Chris@0
|
778 *
|
Chris@0
|
779 * @param $fid
|
Chris@0
|
780 * The file id.
|
Chris@0
|
781 *
|
Chris@18
|
782 * @deprecated in Drupal 8.7.0, will be removed before Drupal 9.0.0.
|
Chris@18
|
783 * Use \Drupal\Core\Entity\EntityStorageInterface::delete() instead.
|
Chris@18
|
784 *
|
Chris@0
|
785 * @see file_unmanaged_delete()
|
Chris@0
|
786 * @see \Drupal\file\FileUsage\FileUsageBase::delete()
|
Chris@18
|
787 * @see \Drupal\Core\Entity\EntityStorageInterface::delete()
|
Chris@18
|
788 * @see https://www.drupal.org/node/3021663
|
Chris@0
|
789 */
|
Chris@0
|
790 function file_delete($fid) {
|
Chris@18
|
791 @trigger_error('file_delete() is deprecated in Drupal 8.7.0 and will be removed before Drupal 9.0.0. Use \Drupal\Core\Entity\EntityStorageInterface::delete() instead. See https://www.drupal.org/node/3021663.', E_USER_DEPRECATED);
|
Chris@0
|
792 return file_delete_multiple([$fid]);
|
Chris@0
|
793 }
|
Chris@0
|
794
|
Chris@0
|
795 /**
|
Chris@0
|
796 * Deletes files.
|
Chris@0
|
797 *
|
Chris@0
|
798 * Instead of directly deleting a file, it is strongly recommended to delete
|
Chris@0
|
799 * file usages instead. That will automatically mark the file as temporary and
|
Chris@0
|
800 * remove it during cleanup.
|
Chris@0
|
801 *
|
Chris@18
|
802 * @param $fids
|
Chris@18
|
803 * An array of file ids.
|
Chris@18
|
804 *
|
Chris@18
|
805 * @deprecated in Drupal 8.7.0, will be removed before Drupal 9.0.0.
|
Chris@18
|
806 * Use \Drupal\Core\Entity\EntityStorageInterface::delete() instead.
|
Chris@0
|
807 *
|
Chris@0
|
808 * @see file_unmanaged_delete()
|
Chris@0
|
809 * @see \Drupal\file\FileUsage\FileUsageBase::delete()
|
Chris@18
|
810 * @see \Drupal\Core\Entity\EntityStorageInterface::delete()
|
Chris@18
|
811 * @see https://www.drupal.org/node/3021663
|
Chris@0
|
812 */
|
Chris@0
|
813 function file_delete_multiple(array $fids) {
|
Chris@18
|
814 @trigger_error('file_delete_multiple() is deprecated in Drupal 8.7.0 and will be removed before Drupal 9.0.0. Use \Drupal\Core\Entity\EntityStorageInterface::delete() instead. See https://www.drupal.org/node/3021663.', E_USER_DEPRECATED);
|
Chris@18
|
815 $storage = \Drupal::entityTypeManager()->getStorage('file');
|
Chris@18
|
816 $entities = $storage->loadMultiple($fids);
|
Chris@18
|
817 $storage->delete($entities);
|
Chris@0
|
818 }
|
Chris@0
|
819
|
Chris@0
|
820 /**
|
Chris@0
|
821 * Deletes a file without database changes or hook invocations.
|
Chris@0
|
822 *
|
Chris@0
|
823 * This function should be used when the file to be deleted does not have an
|
Chris@0
|
824 * entry recorded in the files table.
|
Chris@0
|
825 *
|
Chris@0
|
826 * @param $path
|
Chris@0
|
827 * A string containing a file path or (streamwrapper) URI.
|
Chris@0
|
828 *
|
Chris@0
|
829 * @return
|
Chris@0
|
830 * TRUE for success or path does not exist, or FALSE in the event of an
|
Chris@0
|
831 * error.
|
Chris@0
|
832 *
|
Chris@18
|
833 * @deprecated in Drupal 8.7.0, will be removed before Drupal 9.0.0.
|
Chris@18
|
834 * Use \Drupal\Core\File\FileSystemInterface::delete().
|
Chris@18
|
835 *
|
Chris@0
|
836 * @see file_delete()
|
Chris@0
|
837 * @see file_unmanaged_delete_recursive()
|
Chris@18
|
838 * @see https://www.drupal.org/node/3006851
|
Chris@0
|
839 */
|
Chris@0
|
840 function file_unmanaged_delete($path) {
|
Chris@18
|
841 @trigger_error('file_unmanaged_delete() is deprecated in Drupal 8.7.0 and will be removed before Drupal 9.0.0. Use \Drupal\Core\File\FileSystemInterface::delete(). See https://www.drupal.org/node/3006851.', E_USER_DEPRECATED);
|
Chris@18
|
842 try {
|
Chris@18
|
843 return \Drupal::service('file_system')->delete($path);
|
Chris@0
|
844 }
|
Chris@18
|
845 catch (FileException $e) {
|
Chris@0
|
846 return FALSE;
|
Chris@0
|
847 }
|
Chris@0
|
848 }
|
Chris@0
|
849
|
Chris@0
|
850 /**
|
Chris@0
|
851 * Deletes all files and directories in the specified filepath recursively.
|
Chris@0
|
852 *
|
Chris@0
|
853 * If the specified path is a directory then the function will call itself
|
Chris@0
|
854 * recursively to process the contents. Once the contents have been removed the
|
Chris@0
|
855 * directory will also be removed.
|
Chris@0
|
856 *
|
Chris@0
|
857 * If the specified path is a file then it will be passed to
|
Chris@0
|
858 * file_unmanaged_delete().
|
Chris@0
|
859 *
|
Chris@0
|
860 * Note that this only deletes visible files with write permission.
|
Chris@0
|
861 *
|
Chris@0
|
862 * @param $path
|
Chris@0
|
863 * A string containing either an URI or a file or directory path.
|
Chris@14
|
864 * @param callable $callback
|
Chris@0
|
865 * (optional) Callback function to run on each file prior to deleting it and
|
Chris@0
|
866 * on each directory prior to traversing it. For example, can be used to
|
Chris@0
|
867 * modify permissions.
|
Chris@0
|
868 *
|
Chris@0
|
869 * @return
|
Chris@0
|
870 * TRUE for success or if path does not exist, FALSE in the event of an
|
Chris@0
|
871 * error.
|
Chris@0
|
872 *
|
Chris@18
|
873 * @deprecated in Drupal 8.7.0, will be removed before Drupal 9.0.0.
|
Chris@18
|
874 * Use \Drupal\Core\File\FileSystemInterface::deleteRecursive().
|
Chris@18
|
875 *
|
Chris@0
|
876 * @see file_unmanaged_delete()
|
Chris@18
|
877 * @see https://www.drupal.org/node/3006851
|
Chris@0
|
878 */
|
Chris@0
|
879 function file_unmanaged_delete_recursive($path, $callback = NULL) {
|
Chris@18
|
880 @trigger_error('file_unmanaged_delete_recursive() is deprecated in Drupal 8.7.0 and will be removed before Drupal 9.0.0. Use \Drupal\Core\File\FileSystemInterface::deleteRecursive(). See https://www.drupal.org/node/3006851.', E_USER_DEPRECATED);
|
Chris@18
|
881 $callback = is_callable($callback) ? $callback : NULL;
|
Chris@18
|
882 try {
|
Chris@18
|
883 return \Drupal::service('file_system')->deleteRecursive($path, $callback);
|
Chris@0
|
884 }
|
Chris@18
|
885 catch (FileException $e) {
|
Chris@18
|
886 return FALSE;
|
Chris@0
|
887 }
|
Chris@0
|
888 }
|
Chris@0
|
889
|
Chris@0
|
890 /**
|
Chris@0
|
891 * Moves an uploaded file to a new location.
|
Chris@0
|
892 *
|
Chris@0
|
893 * @deprecated in Drupal 8.0.x-dev, will be removed before Drupal 9.0.0.
|
Chris@0
|
894 * Use \Drupal\Core\File\FileSystem::moveUploadedFile().
|
Chris@0
|
895 *
|
Chris@0
|
896 * @see https://www.drupal.org/node/2418133
|
Chris@0
|
897 */
|
Chris@0
|
898 function drupal_move_uploaded_file($filename, $uri) {
|
Chris@18
|
899 @trigger_error('drupal_move_uploaded_file() is deprecated in Drupal 8.0.x-dev and will be removed before Drupal 9.0.0. Use \Drupal\Core\File\FileSystemInterface::moveUploadedFile(). See https://www.drupal.org/node/2418133.', E_USER_DEPRECATED);
|
Chris@0
|
900 return \Drupal::service('file_system')->moveUploadedFile($filename, $uri);
|
Chris@0
|
901 }
|
Chris@0
|
902
|
Chris@0
|
903 /**
|
Chris@0
|
904 * Saves a file to the specified destination without invoking file API.
|
Chris@0
|
905 *
|
Chris@0
|
906 * This function is identical to file_save_data() except the file will not be
|
Chris@0
|
907 * saved to the {file_managed} table and none of the file_* hooks will be
|
Chris@0
|
908 * called.
|
Chris@0
|
909 *
|
Chris@0
|
910 * @param $data
|
Chris@0
|
911 * A string containing the contents of the file.
|
Chris@0
|
912 * @param $destination
|
Chris@0
|
913 * A string containing the destination location. This must be a stream wrapper
|
Chris@0
|
914 * URI. If no value is provided, a randomized name will be generated and the
|
Chris@0
|
915 * file will be saved using Drupal's default files scheme, usually
|
Chris@0
|
916 * "public://".
|
Chris@0
|
917 * @param $replace
|
Chris@0
|
918 * Replace behavior when the destination file already exists:
|
Chris@0
|
919 * - FILE_EXISTS_REPLACE - Replace the existing file.
|
Chris@0
|
920 * - FILE_EXISTS_RENAME - Append _{incrementing number} until the filename is
|
Chris@0
|
921 * unique.
|
Chris@0
|
922 * - FILE_EXISTS_ERROR - Do nothing and return FALSE.
|
Chris@0
|
923 *
|
Chris@0
|
924 * @return
|
Chris@0
|
925 * A string with the path of the resulting file, or FALSE on error.
|
Chris@0
|
926 *
|
Chris@18
|
927 * @deprecated in Drupal 8.7.0, will be removed before Drupal 9.0.0.
|
Chris@18
|
928 * Use \Drupal\Core\File\FileSystemInterface::saveData().
|
Chris@18
|
929 *
|
Chris@0
|
930 * @see file_save_data()
|
Chris@18
|
931 * @see https://www.drupal.org/node/3006851
|
Chris@0
|
932 */
|
Chris@0
|
933 function file_unmanaged_save_data($data, $destination = NULL, $replace = FILE_EXISTS_RENAME) {
|
Chris@18
|
934 @trigger_error('file_unmanaged_save_data() is deprecated in Drupal 8.7.0 and will be removed before Drupal 9.0.0. Use \Drupal\Core\File\FileSystemInterface::saveData(). See https://www.drupal.org/node/3006851.', E_USER_DEPRECATED);
|
Chris@18
|
935 try {
|
Chris@18
|
936 // Build a destination URI if necessary.
|
Chris@18
|
937 if (!isset($destination)) {
|
Chris@18
|
938 $destination = file_default_scheme() . '://';
|
Chris@18
|
939 }
|
Chris@18
|
940 return \Drupal::service('file_system')->saveData($data, $destination, $replace);
|
Chris@18
|
941 }
|
Chris@18
|
942 catch (FileWriteException $e) {
|
Chris@17
|
943 \Drupal::messenger()->addError(t('The file could not be created.'));
|
Chris@0
|
944 return FALSE;
|
Chris@0
|
945 }
|
Chris@18
|
946 catch (FileException $e) {
|
Chris@18
|
947 return FALSE;
|
Chris@18
|
948 }
|
Chris@0
|
949 }
|
Chris@0
|
950
|
Chris@0
|
951 /**
|
Chris@0
|
952 * Finds all files that match a given mask in a given directory.
|
Chris@0
|
953 *
|
Chris@0
|
954 * Directories and files beginning with a dot are excluded; this prevents
|
Chris@0
|
955 * hidden files and directories (such as SVN working directories) from being
|
Chris@0
|
956 * scanned. Use the umask option to skip configuration directories to
|
Chris@0
|
957 * eliminate the possibility of accidentally exposing configuration
|
Chris@0
|
958 * information. Also, you can use the base directory, recurse, and min_depth
|
Chris@0
|
959 * options to improve performance by limiting how much of the filesystem has
|
Chris@0
|
960 * to be traversed.
|
Chris@0
|
961 *
|
Chris@0
|
962 * @param $dir
|
Chris@0
|
963 * The base directory or URI to scan, without trailing slash.
|
Chris@0
|
964 * @param $mask
|
Chris@0
|
965 * The preg_match() regular expression for files to be included.
|
Chris@0
|
966 * @param $options
|
Chris@0
|
967 * An associative array of additional options, with the following elements:
|
Chris@0
|
968 * - 'nomask': The preg_match() regular expression for files to be excluded.
|
Chris@0
|
969 * Defaults to the 'file_scan_ignore_directories' setting.
|
Chris@0
|
970 * - 'callback': The callback function to call for each match. There is no
|
Chris@0
|
971 * default callback.
|
Chris@0
|
972 * - 'recurse': When TRUE, the directory scan will recurse the entire tree
|
Chris@0
|
973 * starting at the provided directory. Defaults to TRUE.
|
Chris@0
|
974 * - 'key': The key to be used for the returned associative array of files.
|
Chris@0
|
975 * Possible values are 'uri', for the file's URI; 'filename', for the
|
Chris@0
|
976 * basename of the file; and 'name' for the name of the file without the
|
Chris@0
|
977 * extension. Defaults to 'uri'.
|
Chris@0
|
978 * - 'min_depth': Minimum depth of directories to return files from. Defaults
|
Chris@0
|
979 * to 0.
|
Chris@0
|
980 * @param $depth
|
Chris@0
|
981 * The current depth of recursion. This parameter is only used internally and
|
Chris@0
|
982 * should not be passed in.
|
Chris@0
|
983 *
|
Chris@0
|
984 * @return
|
Chris@0
|
985 * An associative array (keyed on the chosen key) of objects with 'uri',
|
Chris@0
|
986 * 'filename', and 'name' properties corresponding to the matched files.
|
Chris@0
|
987 */
|
Chris@0
|
988 function file_scan_directory($dir, $mask, $options = [], $depth = 0) {
|
Chris@0
|
989 // Merge in defaults.
|
Chris@0
|
990 $options += [
|
Chris@0
|
991 'callback' => 0,
|
Chris@0
|
992 'recurse' => TRUE,
|
Chris@0
|
993 'key' => 'uri',
|
Chris@0
|
994 'min_depth' => 0,
|
Chris@0
|
995 ];
|
Chris@0
|
996 // Normalize $dir only once.
|
Chris@0
|
997 if ($depth == 0) {
|
Chris@0
|
998 $dir = file_stream_wrapper_uri_normalize($dir);
|
Chris@0
|
999 $dir_has_slash = (substr($dir, -1) === '/');
|
Chris@0
|
1000 }
|
Chris@0
|
1001
|
Chris@0
|
1002 // Allow directories specified in settings.php to be ignored. You can use this
|
Chris@0
|
1003 // to not check for files in common special-purpose directories. For example,
|
Chris@0
|
1004 // node_modules and bower_components. Ignoring irrelevant directories is a
|
Chris@0
|
1005 // performance boost.
|
Chris@0
|
1006 if (!isset($options['nomask'])) {
|
Chris@0
|
1007 $ignore_directories = Settings::get('file_scan_ignore_directories', []);
|
Chris@0
|
1008 array_walk($ignore_directories, function (&$value) {
|
Chris@0
|
1009 $value = preg_quote($value, '/');
|
Chris@0
|
1010 });
|
Chris@0
|
1011 $default_nomask = '/^' . implode('|', $ignore_directories) . '$/';
|
Chris@0
|
1012 }
|
Chris@0
|
1013
|
Chris@0
|
1014 $options['key'] = in_array($options['key'], ['uri', 'filename', 'name']) ? $options['key'] : 'uri';
|
Chris@0
|
1015 $files = [];
|
Chris@0
|
1016 // Avoid warnings when opendir does not have the permissions to open a
|
Chris@0
|
1017 // directory.
|
Chris@0
|
1018 if (is_dir($dir)) {
|
Chris@0
|
1019 if ($handle = @opendir($dir)) {
|
Chris@0
|
1020 while (FALSE !== ($filename = readdir($handle))) {
|
Chris@0
|
1021 // Skip this file if it matches the nomask or starts with a dot.
|
Chris@0
|
1022 if ($filename[0] != '.'
|
Chris@0
|
1023 && !(isset($options['nomask']) && preg_match($options['nomask'], $filename))
|
Chris@0
|
1024 && !(!empty($default_nomask) && preg_match($default_nomask, $filename))
|
Chris@0
|
1025 ) {
|
Chris@0
|
1026 if ($depth == 0 && $dir_has_slash) {
|
Chris@0
|
1027 $uri = "$dir$filename";
|
Chris@0
|
1028 }
|
Chris@0
|
1029 else {
|
Chris@0
|
1030 $uri = "$dir/$filename";
|
Chris@0
|
1031 }
|
Chris@0
|
1032 if ($options['recurse'] && is_dir($uri)) {
|
Chris@0
|
1033 // Give priority to files in this folder by merging them in after
|
Chris@0
|
1034 // any subdirectory files.
|
Chris@0
|
1035 $files = array_merge(file_scan_directory($uri, $mask, $options, $depth + 1), $files);
|
Chris@0
|
1036 }
|
Chris@0
|
1037 elseif ($depth >= $options['min_depth'] && preg_match($mask, $filename)) {
|
Chris@0
|
1038 // Always use this match over anything already set in $files with
|
Chris@0
|
1039 // the same $options['key'].
|
Chris@0
|
1040 $file = new stdClass();
|
Chris@0
|
1041 $file->uri = $uri;
|
Chris@0
|
1042 $file->filename = $filename;
|
Chris@0
|
1043 $file->name = pathinfo($filename, PATHINFO_FILENAME);
|
Chris@0
|
1044 $key = $options['key'];
|
Chris@0
|
1045 $files[$file->$key] = $file;
|
Chris@0
|
1046 if ($options['callback']) {
|
Chris@0
|
1047 $options['callback']($uri);
|
Chris@0
|
1048 }
|
Chris@0
|
1049 }
|
Chris@0
|
1050 }
|
Chris@0
|
1051 }
|
Chris@0
|
1052
|
Chris@0
|
1053 closedir($handle);
|
Chris@0
|
1054 }
|
Chris@0
|
1055 else {
|
Chris@0
|
1056 \Drupal::logger('file')->error('@dir can not be opened', ['@dir' => $dir]);
|
Chris@0
|
1057 }
|
Chris@0
|
1058 }
|
Chris@0
|
1059
|
Chris@0
|
1060 return $files;
|
Chris@0
|
1061 }
|
Chris@0
|
1062
|
Chris@0
|
1063 /**
|
Chris@0
|
1064 * Determines the maximum file upload size by querying the PHP settings.
|
Chris@0
|
1065 *
|
Chris@0
|
1066 * @return
|
Chris@0
|
1067 * A file size limit in bytes based on the PHP upload_max_filesize and
|
Chris@0
|
1068 * post_max_size
|
Chris@18
|
1069 *
|
Chris@18
|
1070 * @deprecated in Drupal 8.7.0 and will be removed before Drupal 9.0.0.
|
Chris@18
|
1071 * Use \Drupal\Component\Utility\Environment::getUploadMaxSize() instead.
|
Chris@0
|
1072 */
|
Chris@0
|
1073 function file_upload_max_size() {
|
Chris@18
|
1074 @trigger_error('file_upload_max_size() is deprecated in Drupal 8.7.0 and will be removed before Drupal 9.0.0. Use \Drupal\Component\Utility\Environment::getUploadMaxSize() instead. See https://www.drupal.org/node/3000058.', E_USER_DEPRECATED);
|
Chris@18
|
1075 return Environment::getUploadMaxSize();
|
Chris@0
|
1076 }
|
Chris@0
|
1077
|
Chris@0
|
1078 /**
|
Chris@0
|
1079 * Sets the permissions on a file or directory.
|
Chris@0
|
1080 *
|
Chris@18
|
1081 * @deprecated in Drupal 8.0.0, will be removed before Drupal 9.0.0.
|
Chris@0
|
1082 * Use \Drupal\Core\File\FileSystem::chmod().
|
Chris@0
|
1083 *
|
Chris@0
|
1084 * @see https://www.drupal.org/node/2418133
|
Chris@0
|
1085 */
|
Chris@0
|
1086 function drupal_chmod($uri, $mode = NULL) {
|
Chris@18
|
1087 @trigger_error('drupal_chmod() is deprecated in Drupal 8.0.0 and will be removed before Drupal 9.0.0. Use \Drupal\Core\File\FileSystemInterface::chmod(). See https://www.drupal.org/node/2418133.', E_USER_DEPRECATED);
|
Chris@0
|
1088 return \Drupal::service('file_system')->chmod($uri, $mode);
|
Chris@0
|
1089 }
|
Chris@0
|
1090
|
Chris@0
|
1091 /**
|
Chris@0
|
1092 * Deletes a file.
|
Chris@0
|
1093 *
|
Chris@0
|
1094 * @deprecated in Drupal 8.0.x-dev, will be removed before Drupal 9.0.0.
|
Chris@0
|
1095 * Use \Drupal\Core\File\FileSystem::unlink().
|
Chris@0
|
1096 *
|
Chris@0
|
1097 * @see https://www.drupal.org/node/2418133
|
Chris@0
|
1098 */
|
Chris@0
|
1099 function drupal_unlink($uri, $context = NULL) {
|
Chris@0
|
1100 return \Drupal::service('file_system')->unlink($uri, $context);
|
Chris@0
|
1101 }
|
Chris@0
|
1102
|
Chris@0
|
1103 /**
|
Chris@0
|
1104 * Resolves the absolute filepath of a local URI or filepath.
|
Chris@0
|
1105 *
|
Chris@0
|
1106 * @deprecated in Drupal 8.0.x-dev, will be removed before Drupal 9.0.0.
|
Chris@0
|
1107 * Use \Drupal\Core\File\FileSystem::realpath().
|
Chris@0
|
1108 *
|
Chris@0
|
1109 * @see https://www.drupal.org/node/2418133
|
Chris@0
|
1110 */
|
Chris@0
|
1111 function drupal_realpath($uri) {
|
Chris@0
|
1112 return \Drupal::service('file_system')->realpath($uri);
|
Chris@0
|
1113 }
|
Chris@0
|
1114
|
Chris@0
|
1115 /**
|
Chris@0
|
1116 * Gets the name of the directory from a given path.
|
Chris@0
|
1117 *
|
Chris@18
|
1118 * @deprecated in Drupal 8.0.0 and will be removed before Drupal 9.0.0.
|
Chris@0
|
1119 * Use \Drupal\Core\File\FileSystem::dirname().
|
Chris@0
|
1120 *
|
Chris@0
|
1121 * @see https://www.drupal.org/node/2418133
|
Chris@0
|
1122 */
|
Chris@0
|
1123 function drupal_dirname($uri) {
|
Chris@18
|
1124 @trigger_error('drupal_dirname() is deprecated in Drupal 8.0.0 and will be removed before Drupal 9.0.0. Use \Drupal\Core\File\FileSystemInterface::dirname(). See https://www.drupal.org/node/2418133.', E_USER_DEPRECATED);
|
Chris@0
|
1125 return \Drupal::service('file_system')->dirname($uri);
|
Chris@0
|
1126 }
|
Chris@0
|
1127
|
Chris@0
|
1128 /**
|
Chris@0
|
1129 * Gets the filename from a given path.
|
Chris@0
|
1130 *
|
Chris@18
|
1131 * @deprecated in Drupal 8.0.0 and will be removed before Drupal 9.0.0.
|
Chris@0
|
1132 * Use \Drupal\Core\File\FileSystem::basename().
|
Chris@0
|
1133 *
|
Chris@0
|
1134 * @see https://www.drupal.org/node/2418133
|
Chris@0
|
1135 */
|
Chris@0
|
1136 function drupal_basename($uri, $suffix = NULL) {
|
Chris@18
|
1137 @trigger_error('drupal_basename() is deprecated in Drupal 8.0.0 and will be removed before Drupal 9.0.0. Use \Drupal\Core\File\FileSystemInterface::basename(). See https://www.drupal.org/node/2418133.', E_USER_DEPRECATED);
|
Chris@0
|
1138 return \Drupal::service('file_system')->basename($uri, $suffix);
|
Chris@0
|
1139 }
|
Chris@0
|
1140
|
Chris@0
|
1141 /**
|
Chris@0
|
1142 * Creates a directory, optionally creating missing components in the path to
|
Chris@0
|
1143 * the directory.
|
Chris@0
|
1144 *
|
Chris@18
|
1145 * @deprecated in Drupal 8.0.0 and will be removed before Drupal 9.0.0.
|
Chris@0
|
1146 * Use \Drupal\Core\File\FileSystem::mkdir().
|
Chris@0
|
1147 *
|
Chris@0
|
1148 * @see https://www.drupal.org/node/2418133
|
Chris@0
|
1149 */
|
Chris@0
|
1150 function drupal_mkdir($uri, $mode = NULL, $recursive = FALSE, $context = NULL) {
|
Chris@18
|
1151 @trigger_error('drupal_mkdir() is deprecated in Drupal 8.0.0 and will be removed before Drupal 9.0.0. Use \Drupal\Core\File\FileSystemInterface::mkdir(). See https://www.drupal.org/node/2418133.', E_USER_DEPRECATED);
|
Chris@0
|
1152 return \Drupal::service('file_system')->mkdir($uri, $mode, $recursive, $context);
|
Chris@0
|
1153 }
|
Chris@0
|
1154
|
Chris@0
|
1155 /**
|
Chris@0
|
1156 * Removes a directory.
|
Chris@0
|
1157 *
|
Chris@18
|
1158 * @deprecated in Drupal 8.0.0 and will be removed before Drupal 9.0.0.
|
Chris@0
|
1159 * Use \Drupal\Core\File\FileSystem::rmdir().
|
Chris@0
|
1160 *
|
Chris@0
|
1161 * @see https://www.drupal.org/node/2418133
|
Chris@0
|
1162 */
|
Chris@0
|
1163 function drupal_rmdir($uri, $context = NULL) {
|
Chris@18
|
1164 @trigger_error('drupal_rmdir() is deprecated in Drupal 8.0.0 and will be removed before Drupal 9.0.0. Use \Drupal\Core\File\FileSystemInterface::rmdir(). See https://www.drupal.org/node/2418133.', E_USER_DEPRECATED);
|
Chris@0
|
1165 return \Drupal::service('file_system')->rmdir($uri, $context);
|
Chris@0
|
1166 }
|
Chris@0
|
1167
|
Chris@0
|
1168 /**
|
Chris@0
|
1169 * Creates a file with a unique filename in the specified directory.
|
Chris@0
|
1170 *
|
Chris@18
|
1171 * @deprecated in Drupal 8.0.0 and will be removed before Drupal 9.0.0.
|
Chris@0
|
1172 * Use \Drupal\Core\File\FileSystem::tempnam().
|
Chris@0
|
1173 *
|
Chris@0
|
1174 * @see https://www.drupal.org/node/2418133
|
Chris@0
|
1175 */
|
Chris@0
|
1176 function drupal_tempnam($directory, $prefix) {
|
Chris@18
|
1177 @trigger_error('tempnam() is deprecated in Drupal 8.0.0 and will be removed before Drupal 9.0.0. Use \Drupal\Core\File\FileSystemInterface::tempnam(). See https://www.drupal.org/node/2418133.', E_USER_DEPRECATED);
|
Chris@0
|
1178 return \Drupal::service('file_system')->tempnam($directory, $prefix);
|
Chris@0
|
1179 }
|
Chris@0
|
1180
|
Chris@0
|
1181 /**
|
Chris@0
|
1182 * Gets and sets the path of the configured temporary directory.
|
Chris@0
|
1183 *
|
Chris@0
|
1184 * @return mixed|null
|
Chris@0
|
1185 * A string containing the path to the temporary directory.
|
Chris@0
|
1186 */
|
Chris@0
|
1187 function file_directory_temp() {
|
Chris@0
|
1188 $temporary_directory = \Drupal::config('system.file')->get('path.temporary');
|
Chris@0
|
1189 if (empty($temporary_directory)) {
|
Chris@0
|
1190 // Needs set up.
|
Chris@0
|
1191 $config = \Drupal::configFactory()->getEditable('system.file');
|
Chris@0
|
1192 $temporary_directory = ComponentFileSystem::getOsTemporaryDirectory();
|
Chris@0
|
1193
|
Chris@0
|
1194 if (empty($temporary_directory)) {
|
Chris@0
|
1195 // If no directory has been found default to 'files/tmp'.
|
Chris@0
|
1196 $temporary_directory = PublicStream::basePath() . '/tmp';
|
Chris@0
|
1197
|
Chris@0
|
1198 // Windows accepts paths with either slash (/) or backslash (\), but will
|
Chris@0
|
1199 // not accept a path which contains both a slash and a backslash. Since
|
Chris@0
|
1200 // the 'file_public_path' variable may have either format, we sanitize
|
Chris@0
|
1201 // everything to use slash which is supported on all platforms.
|
Chris@0
|
1202 $temporary_directory = str_replace('\\', '/', $temporary_directory);
|
Chris@0
|
1203 }
|
Chris@0
|
1204 // Save the path of the discovered directory. Do not check config schema on
|
Chris@0
|
1205 // save.
|
Chris@0
|
1206 $config->set('path.temporary', (string) $temporary_directory)->save(TRUE);
|
Chris@0
|
1207 }
|
Chris@0
|
1208
|
Chris@0
|
1209 return $temporary_directory;
|
Chris@0
|
1210 }
|
Chris@0
|
1211
|
Chris@0
|
1212 /**
|
Chris@0
|
1213 * Discovers a writable system-appropriate temporary directory.
|
Chris@0
|
1214 *
|
Chris@0
|
1215 * @return mixed
|
Chris@0
|
1216 * A string containing the path to the temporary directory.
|
Chris@0
|
1217 *
|
Chris@0
|
1218 * @deprecated in Drupal 8.3.x-dev, will be removed before Drupal 9.0.0.
|
Chris@0
|
1219 * Use \Drupal\Component\FileSystem\FileSystem::getOsTemporaryDirectory().
|
Chris@0
|
1220 *
|
Chris@0
|
1221 * @see https://www.drupal.org/node/2418133
|
Chris@0
|
1222 */
|
Chris@0
|
1223 function file_directory_os_temp() {
|
Chris@0
|
1224 return ComponentFileSystem::getOsTemporaryDirectory();
|
Chris@0
|
1225 }
|
Chris@0
|
1226
|
Chris@0
|
1227 /**
|
Chris@0
|
1228 * @} End of "defgroup file".
|
Chris@0
|
1229 */
|