file.api.php 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. <?php
  2. /**
  3. * @file
  4. * Hooks related to the File management system.
  5. */
  6. use Drupal\Core\StreamWrapper\StreamWrapperManager;
  7. /**
  8. * @addtogroup hooks
  9. * @{
  10. */
  11. /**
  12. * Control access to private file downloads and specify HTTP headers.
  13. *
  14. * This hook allows modules to enforce permissions on file downloads whenever
  15. * Drupal is handling file download, as opposed to the web server bypassing
  16. * Drupal and returning the file from a public directory. Modules can also
  17. * provide headers to specify information like the file's name or MIME type.
  18. *
  19. * @param $uri
  20. * The URI of the file.
  21. *
  22. * @return
  23. * If the user does not have permission to access the file, return -1. If the
  24. * user has permission, return an array with the appropriate headers. If the
  25. * file is not controlled by the current module, the return value should be
  26. * NULL.
  27. *
  28. * @see \Drupal\system\FileDownloadController::download()
  29. */
  30. function hook_file_download($uri) {
  31. // Check to see if this is a config download.
  32. $scheme = StreamWrapperManager::getScheme($uri);
  33. $target = StreamWrapperManager::getTarget($uri);
  34. if ($scheme == 'temporary' && $target == 'config.tar.gz') {
  35. return [
  36. 'Content-disposition' => 'attachment; filename="config.tar.gz"',
  37. ];
  38. }
  39. }
  40. /**
  41. * Alter the URL to a file.
  42. *
  43. * This hook is called from file_create_url(), and is called fairly
  44. * frequently (10+ times per page), depending on how many files there are in a
  45. * given page.
  46. * If CSS and JS aggregation are disabled, this can become very frequently
  47. * (50+ times per page) so performance is critical.
  48. *
  49. * This function should alter the URI, if it wants to rewrite the file URL.
  50. *
  51. * @param $uri
  52. * The URI to a file for which we need an external URL, or the path to a
  53. * shipped file.
  54. */
  55. function hook_file_url_alter(&$uri) {
  56. $user = \Drupal::currentUser();
  57. // User 1 will always see the local file in this example.
  58. if ($user->id() == 1) {
  59. return;
  60. }
  61. $cdn1 = 'http://cdn1.example.com';
  62. $cdn2 = 'http://cdn2.example.com';
  63. $cdn_extensions = ['css', 'js', 'gif', 'jpg', 'jpeg', 'png'];
  64. // Most CDNs don't support private file transfers without a lot of hassle,
  65. // so don't support this in the common case.
  66. $schemes = ['public'];
  67. /** @var \Drupal\Core\StreamWrapper\StreamWrapperManagerInterface $stream_wrapper_manager */
  68. $stream_wrapper_manager = \Drupal::service('stream_wrapper_manager');
  69. $scheme = $stream_wrapper_manager::getScheme($uri);
  70. // Only serve shipped files and public created files from the CDN.
  71. if (!$scheme || in_array($scheme, $schemes)) {
  72. // Shipped files.
  73. if (!$scheme) {
  74. $path = $uri;
  75. }
  76. // Public created files.
  77. else {
  78. $wrapper = $stream_wrapper_manager->getViaScheme($scheme);
  79. $path = $wrapper->getDirectoryPath() . '/' . $stream_wrapper_manager::getTarget($uri);
  80. }
  81. // Clean up Windows paths.
  82. $path = str_replace('\\', '/', $path);
  83. // Serve files with one of the CDN extensions from CDN 1, all others from
  84. // CDN 2.
  85. $pathinfo = pathinfo($path);
  86. if (isset($pathinfo['extension']) && in_array($pathinfo['extension'], $cdn_extensions)) {
  87. $uri = $cdn1 . '/' . $path;
  88. }
  89. else {
  90. $uri = $cdn2 . '/' . $path;
  91. }
  92. }
  93. }
  94. /**
  95. * Alter MIME type mappings used to determine MIME type from a file extension.
  96. *
  97. * Invoked by \Drupal\Core\File\MimeType\ExtensionMimeTypeGuesser::guess(). It
  98. * is used to allow modules to add to or modify the default mapping from
  99. * \Drupal\Core\File\MimeType\ExtensionMimeTypeGuesser::$defaultMapping.
  100. *
  101. * @param $mapping
  102. * An array of mimetypes correlated to the extensions that relate to them.
  103. * The array has 'mimetypes' and 'extensions' elements, each of which is an
  104. * array.
  105. *
  106. * @see \Drupal\Core\File\MimeType\ExtensionMimeTypeGuesser::guess()
  107. * @see \Drupal\Core\File\MimeType\ExtensionMimeTypeGuesser::$defaultMapping
  108. */
  109. function hook_file_mimetype_mapping_alter(&$mapping) {
  110. // Add new MIME type 'drupal/info'.
  111. $mapping['mimetypes']['example_info'] = 'drupal/info';
  112. // Add new extension '.info.yml' and map it to the 'drupal/info' MIME type.
  113. $mapping['extensions']['info'] = 'example_info';
  114. // Override existing extension mapping for '.ogg' files.
  115. $mapping['extensions']['ogg'] = 189;
  116. }
  117. /**
  118. * Alter archiver information declared by other modules.
  119. *
  120. * See hook_archiver_info() for a description of archivers and the archiver
  121. * information structure.
  122. *
  123. * @param $info
  124. * Archiver information to alter (return values from hook_archiver_info()).
  125. */
  126. function hook_archiver_info_alter(&$info) {
  127. $info['tar']['extensions'][] = 'tgz';
  128. }
  129. /**
  130. * Register information about FileTransfer classes provided by a module.
  131. *
  132. * The FileTransfer class allows transferring files over a specific type of
  133. * connection. Core provides classes for FTP and SSH. Contributed modules are
  134. * free to extend the FileTransfer base class to add other connection types,
  135. * and if these classes are registered via hook_filetransfer_info(), those
  136. * connection types will be available to site administrators using the Update
  137. * manager when they are redirected to the authorize.php script to authorize
  138. * the file operations.
  139. *
  140. * @return array
  141. * Nested array of information about FileTransfer classes. Each key is a
  142. * FileTransfer type (not human readable, used for form elements and
  143. * variable names, etc), and the values are subarrays that define properties
  144. * of that type. The keys in each subarray are:
  145. * - 'title': Required. The human-readable name of the connection type.
  146. * - 'class': Required. The name of the FileTransfer class. The constructor
  147. * will always be passed the full path to the root of the site that should
  148. * be used to restrict where file transfer operations can occur (the $jail)
  149. * and an array of settings values returned by the settings form.
  150. * - 'weight': Optional. Integer weight used for sorting connection types on
  151. * the authorize.php form.
  152. *
  153. * @see \Drupal\Core\FileTransfer\FileTransfer
  154. * @see authorize.php
  155. * @see hook_filetransfer_info_alter()
  156. * @see drupal_get_filetransfer_info()
  157. */
  158. function hook_filetransfer_info() {
  159. $info['sftp'] = [
  160. 'title' => t('SFTP (Secure FTP)'),
  161. 'class' => 'Drupal\Core\FileTransfer\SFTP',
  162. 'weight' => 10,
  163. ];
  164. return $info;
  165. }
  166. /**
  167. * Alter the FileTransfer class registry.
  168. *
  169. * @param array $filetransfer_info
  170. * Reference to a nested array containing information about the FileTransfer
  171. * class registry.
  172. *
  173. * @see hook_filetransfer_info()
  174. */
  175. function hook_filetransfer_info_alter(&$filetransfer_info) {
  176. // Remove the FTP option entirely.
  177. unset($filetransfer_info['ftp']);
  178. // Make sure the SSH option is listed first.
  179. $filetransfer_info['ssh']['weight'] = -10;
  180. }
  181. /**
  182. * @} End of "addtogroup hooks".
  183. */