Pull merge.
[yaffs-website] / web / core / modules / file / tests / file_test / file_test.module
1 <?php
2
3 /**
4  * @file
5  * Helper module for the file tests.
6  *
7  * The caller is must call file_test_reset() to initializing this module before
8  * calling file_test_get_calls() or file_test_set_return().
9  */
10
11 use Drupal\file\Entity\File;
12
13 const FILE_URL_TEST_CDN_1 = 'http://cdn1.example.com';
14 const FILE_URL_TEST_CDN_2 = 'http://cdn2.example.com';
15
16 /**
17  * Reset/initialize the history of calls to the file_* hooks.
18  *
19  * @see file_test_get_calls()
20  * @see file_test_reset()
21  */
22 function file_test_reset() {
23   // Keep track of calls to these hooks
24   $results = [
25     'load' => [],
26     'validate' => [],
27     'download' => [],
28     'insert' => [],
29     'update' => [],
30     'copy' => [],
31     'move' => [],
32     'delete' => [],
33   ];
34   \Drupal::state()->set('file_test.results', $results);
35
36   // These hooks will return these values, see file_test_set_return().
37   $return = [
38     'validate' => [],
39     'download' => NULL,
40   ];
41   \Drupal::state()->set('file_test.return', $return);
42 }
43
44 /**
45  * Get the arguments passed to invocation of a given hook since
46  * file_test_reset() was last called.
47  *
48  * @param string $op
49  *   One of the hook_file_* operations: 'load', 'validate', 'download',
50  *   'insert', 'update', 'copy', 'move', 'delete'.
51  *
52  * @return array
53  *   Array of the parameters passed to each call.
54  *
55  * @see _file_test_log_call()
56  * @see file_test_reset()
57  */
58 function file_test_get_calls($op) {
59   $results = \Drupal::state()->get('file_test.results') ?: [];
60   return $results[$op];
61 }
62
63 /**
64  * Get an array with the calls for all hooks.
65  *
66  * @return
67  *   An array keyed by hook name ('load', 'validate', 'download', 'insert',
68  *   'update', 'copy', 'move', 'delete') with values being arrays of parameters
69  *   passed to each call.
70  */
71 function file_test_get_all_calls() {
72   return \Drupal::state()->get('file_test.results') ?: [];
73 }
74
75 /**
76  * Store the values passed to a hook invocation.
77  *
78  * @param string $op
79  *   One of the hook_file_* operations: 'load', 'validate', 'download',
80  *   'insert', 'update', 'copy', 'move', 'delete'.
81  * @param array $args
82  *   Values passed to hook.
83  *
84  * @see file_test_get_calls()
85  * @see file_test_reset()
86  */
87 function _file_test_log_call($op, $args) {
88   if (\Drupal::state()->get('file_test.count_hook_invocations', TRUE)) {
89     $results = \Drupal::state()->get('file_test.results') ?: [];
90     $results[$op][] = $args;
91     \Drupal::state()->set('file_test.results', $results);
92   }
93 }
94
95 /**
96  * Load the appropriate return value.
97  *
98  * @param string $op
99  *   One of the hook_file_[validate,download] operations.
100  *
101  * @return mixed
102  *   Value set by file_test_set_return().
103  *
104  * @see file_test_set_return()
105  * @see file_test_reset()
106  */
107 function _file_test_get_return($op) {
108   $return = \Drupal::state()->get('file_test.return') ?: [$op => NULL];
109   return $return[$op];
110 }
111
112 /**
113  * Assign a return value for a given operation.
114  *
115  * @param string $op
116  *   One of the hook_file_[validate,download] operations.
117  * @param mixed $value
118  *   Value for the hook to return.
119  *
120  * @see _file_test_get_return()
121  * @see file_test_reset()
122  */
123 function file_test_set_return($op, $value) {
124   $return = \Drupal::state()->get('file_test.return') ?: [];
125   $return[$op] = $value;
126   \Drupal::state()->set('file_test.return', $return);
127 }
128
129 /**
130  * Implements hook_ENTITY_TYPE_load() for file entities.
131  */
132 function file_test_file_load($files) {
133   foreach ($files as $file) {
134     _file_test_log_call('load', [$file->id()]);
135     // Assign a value on the object so that we can test that the $file is passed
136     // by reference.
137     $file->file_test['loaded'] = TRUE;
138   }
139 }
140
141 /**
142  * Implements hook_file_validate().
143  */
144 function file_test_file_validate(File $file) {
145   _file_test_log_call('validate', [$file->id()]);
146   return _file_test_get_return('validate');
147 }
148
149 /**
150  * Implements hook_file_download().
151  */
152 function file_test_file_download($uri) {
153   if (\Drupal::state()->get('file_test.allow_all', FALSE)) {
154     $files = entity_load_multiple_by_properties('file', ['uri' => $uri]);
155     $file = reset($files);
156     return file_get_content_headers($file);
157   }
158   _file_test_log_call('download', [$uri]);
159   return _file_test_get_return('download');
160 }
161
162 /**
163  * Implements hook_ENTITY_TYPE_insert() for file entities.
164  */
165 function file_test_file_insert(File $file) {
166   _file_test_log_call('insert', [$file->id()]);
167 }
168
169 /**
170  * Implements hook_ENTITY_TYPE_update() for file entities.
171  */
172 function file_test_file_update(File $file) {
173   _file_test_log_call('update', [$file->id()]);
174 }
175
176 /**
177  * Implements hook_file_copy().
178  */
179 function file_test_file_copy(File $file, $source) {
180   _file_test_log_call('copy', [$file->id(), $source->id()]);
181 }
182
183 /**
184  * Implements hook_file_move().
185  */
186 function file_test_file_move(File $file, File $source) {
187   _file_test_log_call('move', [$file->id(), $source->id()]);
188 }
189
190 /**
191  * Implements hook_ENTITY_TYPE_predelete() for file entities.
192  */
193 function file_test_file_predelete(File $file) {
194   _file_test_log_call('delete', [$file->id()]);
195 }
196
197 /**
198  * Implements hook_file_url_alter().
199  */
200 function file_test_file_url_alter(&$uri) {
201   // Only run this hook when this variable is set. Otherwise, we'd have to add
202   // another hidden test module just for this hook.
203   $alter_mode = \Drupal::state()->get('file_test.hook_file_url_alter');
204   if (!$alter_mode) {
205     return;
206   }
207   // Test alteration of file URLs to use a CDN.
208   elseif ($alter_mode == 'cdn') {
209     $cdn_extensions = ['css', 'js', 'gif', 'jpg', 'jpeg', 'png'];
210
211     // Most CDNs don't support private file transfers without a lot of hassle,
212     // so don't support this in the common case.
213     $schemes = ['public'];
214
215     $scheme = file_uri_scheme($uri);
216
217     // Only serve shipped files and public created files from the CDN.
218     if (!$scheme || in_array($scheme, $schemes)) {
219       // Shipped files.
220       if (!$scheme) {
221         $path = $uri;
222       }
223       // Public created files.
224       else {
225         $wrapper = \Drupal::service('stream_wrapper_manager')->getViaScheme($scheme);
226         $path = $wrapper->getDirectoryPath() . '/' . file_uri_target($uri);
227       }
228
229       // Clean up Windows paths.
230       $path = str_replace('\\', '/', $path);
231
232       // Serve files with one of the CDN extensions from CDN 1, all others from
233       // CDN 2.
234       $pathinfo = pathinfo($path);
235       if (array_key_exists('extension', $pathinfo) && in_array($pathinfo['extension'], $cdn_extensions)) {
236         $uri = FILE_URL_TEST_CDN_1 . '/' . $path;
237       }
238       else {
239         $uri = FILE_URL_TEST_CDN_2 . '/' . $path;
240       }
241     }
242   }
243   // Test alteration of file URLs to use root-relative URLs.
244   elseif ($alter_mode == 'root-relative') {
245     // Only serve shipped files and public created files with root-relative
246     // URLs.
247     $scheme = file_uri_scheme($uri);
248     if (!$scheme || $scheme == 'public') {
249       // Shipped files.
250       if (!$scheme) {
251         $path = $uri;
252       }
253       // Public created files.
254       else {
255         $wrapper = \Drupal::service('stream_wrapper_manager')->getViaScheme($scheme);
256         $path = $wrapper->getDirectoryPath() . '/' . file_uri_target($uri);
257       }
258
259       // Clean up Windows paths.
260       $path = str_replace('\\', '/', $path);
261
262       // Generate a root-relative URL.
263       $uri = base_path() . '/' . $path;
264     }
265   }
266   // Test alteration of file URLs to use protocol-relative URLs.
267   elseif ($alter_mode == 'protocol-relative') {
268     // Only serve shipped files and public created files with protocol-relative
269     // URLs.
270     $scheme = file_uri_scheme($uri);
271     if (!$scheme || $scheme == 'public') {
272       // Shipped files.
273       if (!$scheme) {
274         $path = $uri;
275       }
276       // Public created files.
277       else {
278         $wrapper = \Drupal::service('stream_wrapper_manager')->getViaScheme($scheme);
279         $path = $wrapper->getDirectoryPath() . '/' . file_uri_target($uri);
280       }
281
282       // Clean up Windows paths.
283       $path = str_replace('\\', '/', $path);
284
285       // Generate a protocol-relative URL.
286       $uri = '/' . base_path() . '/' . $path;
287     }
288   }
289 }
290
291 /**
292  * Implements hook_file_mimetype_mapping_alter().
293  */
294 function file_test_file_mimetype_mapping_alter(&$mapping) {
295   // Add new mappings.
296   $mapping['mimetypes']['file_test_mimetype_1'] = 'madeup/file_test_1';
297   $mapping['mimetypes']['file_test_mimetype_2'] = 'madeup/file_test_2';
298   $mapping['mimetypes']['file_test_mimetype_3'] = 'madeup/doc';
299   $mapping['extensions']['file_test_1'] = 'file_test_mimetype_1';
300   $mapping['extensions']['file_test_2'] = 'file_test_mimetype_2';
301   $mapping['extensions']['file_test_3'] = 'file_test_mimetype_2';
302   // Override existing mapping.
303   $mapping['extensions']['doc'] = 'file_test_mimetype_3';
304 }
305
306 /**
307  * Helper validator that returns the $errors parameter.
308  */
309 function file_test_validator(File $file, $errors) {
310   return $errors;
311 }
312
313 /**
314  * Helper function for testing file_scan_directory().
315  *
316  * Each time the function is called the file is stored in a static variable.
317  * When the function is called with no $filepath parameter, the results are
318  * returned.
319  *
320  * @param string|null $filepath
321  *   File path
322  * @return array
323  *   If $filepath is NULL, an array of all previous $filepath parameters
324  */
325 function file_test_file_scan_callback($filepath = NULL) {
326   $files = &drupal_static(__FUNCTION__, []);
327   if (isset($filepath)) {
328     $files[] = $filepath;
329   }
330   else {
331     return $files;
332   }
333 }
334
335 /**
336  * Reset static variables used by file_test_file_scan_callback().
337  */
338 function file_test_file_scan_callback_reset() {
339   drupal_static_reset('file_test_file_scan_callback');
340 }
341
342 /**
343  * Implements hook_entity_info_alter().
344  */
345 function file_test_entity_type_alter(&$entity_types) {
346   if (\Drupal::state()->get('file_test_alternate_access_handler', FALSE)) {
347     /** @var $entity_types \Drupal\Core\Entity\EntityTypeInterface[] */
348     $entity_types['file']
349       ->setAccessClass('Drupal\file_test\FileTestAccessControlHandler');
350   }
351 }