Projet

Général

Profil

Paste
Télécharger (9,81 ko) Statistiques
| Branche: | Révision:

root / drupal7 / sites / all / modules / remote_stream_wrapper / remote_stream_wrapper.module @ 8dc4e7e8

1
<?php
2

    
3
/**
4
 * @file
5
 * Provides a remote stream wrapper and file field integration.
6
 *
7
 * @todo Add a 'Remote URL' file field widget.
8
 */
9

    
10
/**
11
 * Stream wrapper type flag -- visible and readable using remote files that act like local files.
12
 */
13
define('STREAM_WRAPPERS_REMOTE', STREAM_WRAPPERS_LOCAL | STREAM_WRAPPERS_READ | STREAM_WRAPPERS_VISIBLE);
14

    
15
/**
16
 * Implements hook_menu().
17
 */
18
function remote_stream_wrapper_menu() {
19
  $items = array();
20

    
21
  $items['file/add/remote'] = array(
22
    'title' => 'Remote',
23
    'page callback' => 'drupal_get_form',
24
    'page arguments' => array('remote_stream_wrapper_file_add_form'),
25
    'access callback' => 'remote_stream_wrapper_media_browser_plugin_access',
26
    'type' => MENU_LOCAL_TASK,
27
  );
28

    
29
  // Add image style generation paths for external URLs.
30
  if (module_exists('image')) {
31
    $wrappers = file_get_remote_stream_wrappers();
32
    $directory_path = file_stream_wrapper_get_instance_by_scheme(file_default_scheme())->getDirectoryPath();
33
    $pos = count(explode('/', $directory_path)) + 1;
34
    $item = array(
35
      'page callback' => 'remote_stream_wrapper_image_style_deliver',
36
      'page arguments' => array($pos, $pos + 1),
37
      'access callback' => TRUE,
38
      'type' => MENU_CALLBACK,
39
      'file' => 'remote_stream_wrapper.image.inc',
40
    );
41
    foreach (array_keys($wrappers) as $scheme) {
42
      $items[$directory_path . '/styles/%image_style/' . $scheme] = $item;
43
    }
44
  }
45

    
46
  return $items;
47
}
48

    
49
/**
50
 * Implements hook_permission().
51
 */
52
function remote_stream_wrapper_permission() {
53
  $permission = array();
54

    
55
  if (module_exists('media')) {
56
    $permission['add media from remote urls'] = array(
57
      'title' => t('Add media from remote URLs'),
58
      'description' => t('Add media from remote URLs.'),
59
    );
60
  }
61

    
62
  return $permission;
63
}
64

    
65
/**
66
 * Implements hook_stream_wrappers().
67
 */
68
function remote_stream_wrapper_stream_wrappers() {
69
  $info['http'] = array(
70
    'name' => t('HTTP URLs'),
71
    'class' => 'DrupalRemoteStreamWrapper',
72
    'description' => t('Remote files.'),
73
    'type' => STREAM_WRAPPERS_REMOTE,
74
    'remote' => TRUE,
75
  );
76
  $info['https'] = $info['http'];
77
  $info['https']['name'] = t('HTTPS URLs');
78
  $info['feed'] = $info['http'];
79
  $info['feed']['name'] = t('Feed URLs');
80

    
81
  return $info;
82
}
83

    
84
/**
85
 * Return a list of remote stream wrappers.
86
 */
87
function file_get_remote_stream_wrappers() {
88
  $wrappers = &drupal_static(__FUNCTION__);
89
  if (!isset($wrappers)) {
90
    $wrappers = file_get_stream_wrappers(STREAM_WRAPPERS_REMOTE);
91
    foreach ($wrappers as $scheme => $wrapper) {
92
      if (empty($wrapper['remote'])) {
93
        unset($wrappers[$scheme]);
94
      }
95
    }
96
    //$wrappers = array_diff_key($wrappers, file_get_stream_wrappers(STREAM_WRAPPERS_LOCAL_NORMAL
97
  }
98
  return $wrappers;
99
}
100

    
101
/**
102
 * Check if a stream wrapper scheme is a remote stream wrapper.
103
 */
104
function file_is_scheme_remote($scheme) {
105
  $wrappers = file_get_remote_stream_wrappers();
106
  return isset($wrappers[$scheme]);
107
}
108

    
109
/**
110
 * Implements hook_file_url_alter().
111
 */
112
function remote_stream_wrapper_file_url_alter(&$uri) {
113
  $scheme = file_uri_scheme($uri);
114
  if ($scheme && file_is_scheme_remote($scheme) && strpos($uri, "$scheme://styles/") === 0) {
115
    $uri = file_default_scheme() . '://' . file_uri_target($uri);
116
    if (!variable_get('clean_url') && file_uri_scheme($uri) == 'public' && !file_exists($uri)) {
117
      $directory_path = file_stream_wrapper_get_instance_by_uri($uri)->getDirectoryPath();
118
      $uri = url($directory_path . '/' . file_uri_target($uri), array('absolute' => TRUE));
119
    }
120
  }
121
}
122

    
123
/**
124
 * Copy of image_style_path() for use with remote images.
125
 *
126
 * When image_style_path() is give a file like 'http://example.com/image.png'
127
 * it is converted into 'http://styles/stylename/http/example.com/image.png'
128
 * which will fail image_style_deliver().
129
 */
130
function remote_stream_wrapper_image_style_path($style_name, $uri) {
131
  // Force the image style to be returned with the default file scheme, but
132
  // with the file's original scheme in the path.
133
  return file_default_scheme() . '://styles/' . $style_name . '/' . file_uri_scheme($uri) . '/' . file_uri_target($uri);
134
}
135

    
136
/**
137
 * Implements hook_form_FORM_ID_alter().
138
 *
139
 * Manually add support for the remote stream wrapper in file fields since
140
 * it is read-only.
141
 */
142
function remote_stream_wrapper_form_field_ui_field_edit_form_alter(&$form, &$form_state) {
143
  if ($form['#field']['type'] == 'file' || $form['#field']['type'] == 'image') {
144
    $form['field']['settings']['uri_scheme']['#description'] .= ' ' . t('This only applies to uploaded files and not remote files.');
145
  }
146
}
147

    
148
/**
149
 * Validation callback for remote URLs.
150
 */
151
function remote_stream_wrapper_validate_url($element, &$form_state) {
152
  $value = trim($element['#value']);
153
  if ($value != '' && !valid_url($value, TRUE)) {
154
    form_error($element, t('Invalid URL %url.', array('%url' => $value)));
155
  }
156
  elseif (!file_stream_wrapper_valid_scheme(file_uri_scheme($value))) {
157
    // Check that the scheme is supported.
158
    form_error($element, t('Remote URLs with the %scheme scheme are not supported.', array('%scheme' => file_uri_scheme($value))));
159
  }
160
  else {
161
    // Check that the file exists.
162
    $request = drupal_http_request($value, array('method' => 'HEAD'));
163
    if (!empty($request->error)) {
164
      form_error($element, t('Unable to fetch file from URL %url (error @code: %error).', array('%url' => $value, '@code' => $request->code, '%error' => $request->error)));
165
    }
166
  }
167
}
168

    
169
/**
170
 * Load a file object by URI.
171
 *
172
 * @param string $uri
173
 *   A string containing the URI, path, or filename.
174
 *
175
 * @return
176
 *   A file object, or FALSE if not found.
177
 */
178
function remote_stream_wrapper_file_load_by_uri($uri) {
179
  $uri = file_stream_wrapper_uri_normalize($uri);
180
  $files = entity_load('file', FALSE, array('uri' => $uri));
181
  return !empty($files) ? reset($files) : FALSE;
182
}
183

    
184
/**
185
 * Helper functon to assemble a new file entity object by URI.
186
 *
187
 * @param string $uri
188
 *   A string containing the URI, path, or filename.
189
 */
190
function remote_stream_wrapper_file_create_by_uri($uri) {
191
  $uri = file_stream_wrapper_uri_normalize($uri);
192

    
193
  $file = new stdClass();
194
  $file->fid = NULL;
195
  $file->uri = $uri;
196
  $file->filename = basename($file->uri);
197
  $file->filemime = file_get_mimetype($file->uri);
198
  $file->uid = $GLOBALS['user']->uid;
199
  $file->status = FILE_STATUS_PERMANENT;
200
  return $file;
201
}
202

    
203
/**
204
 * Implements hook_media_browser_plugin_info().
205
 */
206
function remote_stream_wrapper_media_browser_plugin_info() {
207
  $plugins['remote_file'] = array(
208
    'title' => t('Remote URL'),
209
    'class' => 'RemoteStreamWrapperMediaBrowser',
210
    // Support for Media 1.x browser plugin API.
211
    '#title' => t('Remote URL'),
212
    'access callback' => 'remote_stream_wrapper_media_browser_plugin_access',
213
  );
214
  return $plugins;
215
}
216

    
217
/**
218
 * Media 1.x browser plugin access callback.
219
 *
220
 * Duplicate of RemoteStreamWrapperMediaBrowser::access().
221
 */
222
function remote_stream_wrapper_media_browser_plugin_access() {
223
  return user_access('administer files') || user_access('add media from remote urls');
224
}
225

    
226
/**
227
 * Implements hook_media_browser_plugin_view().
228
 */
229
function remote_stream_wrapper_media_browser_plugin_view($plugin_name, $params) {
230
  if ($plugin_name == 'remote_file') {
231
    if (remote_stream_wrapper_media_browser_plugin_access()) {
232
      $params += array('types' => array());
233
      $form = drupal_get_form('remote_stream_wrapper_file_add_form', $params);
234
      return array(
235
        '#title' => t('Remote URL'),
236
        'form' => array($form),
237
      );
238
    }
239
  }
240
}
241

    
242
/**
243
 * Provides a form for adding media items from remote URLs.
244
 *
245
 * @see remote_stream_wrapper_media_browser_form_submit()
246
 */
247
function remote_stream_wrapper_file_add_form($form, &$form_state, array $options = array()) {
248
  $form['url'] = array(
249
    '#type' => 'textfield',
250
    '#title' => 'URL',
251
    '#attributes' => array('class' => array('media-add-from-remote-url')),
252
    '#maxlength' => 255, // Maximum length of {file_managed}.uri
253
    '#element_validate' => array('remote_stream_wrapper_validate_url'),
254
    '#required' => TRUE,
255
  );
256

    
257
  // @todo Validate against file field allowed types.
258
  $form['#validators'] = array();
259

    
260
  $form['actions'] = array('#type' => 'actions');
261
  $form['actions']['submit'] = array(
262
    '#type' => 'submit',
263
    '#value' => t('Submit'),
264
  );
265
  return $form;
266
}
267

    
268
/**
269
 * Save a file record based on a remote URL.
270
 *
271
 * @see remote_stream_wrapper_media_browser_form()
272
 * @see file_save()
273
 * @see DrupalRemoteStreamWrapper
274
 */
275
function remote_stream_wrapper_file_add_form_submit($form, &$form_state) {
276
  $uri = $url = trim($form_state['values']['url']);
277

    
278
  try {
279
    $file = remote_stream_wrapper_file_load_by_uri($uri);
280
    if (!$file) {
281
      $file = remote_stream_wrapper_file_create_by_uri($uri);
282
      file_save($file);
283
    }
284
  }
285
  catch (Exception $e) {
286
    form_set_error('url', $e->getMessage());
287
    return;
288
  }
289

    
290
  if (empty($file->fid)) {
291
    form_set_error('url', t('Unable to add file from URL %file.', array('%file' => $url)));
292
    return;
293
  }
294
  else {
295
    $form_state['file'] = $file;
296
  }
297

    
298
  if (drupal_valid_path('file/' . $file->fid . '/edit')) {
299
    $destination = array('destination' => 'admin/content/file');
300
    if (isset($_GET['destination'])) {
301
      $destination = drupal_get_destination();
302
      unset($_GET['destination']);
303
    }
304
    $form_state['redirect'] = array('file/' . $file->fid . '/edit', array('query' => $destination));
305
  }
306
  else {
307
    $form_state['redirect'] = 'admin/content/file';
308
  }
309
}
310

    
311
/**
312
 * Implements hook_file_delete().
313
 */
314
function remote_stream_wrapper_file_delete($file) {
315
  $scheme = file_uri_scheme($file->uri);
316
  if ($scheme && file_is_scheme_remote($scheme)) {
317
    remote_stream_wrapper_image_path_flush($file->uri);
318
  }
319
}
320

    
321
function remote_stream_wrapper_image_path_flush($path) {
322
  $styles = image_styles();
323
  foreach ($styles as $style) {
324
    $image_path = remote_stream_wrapper_image_style_path($style['name'], $path);
325
    if (file_exists($image_path)) {
326
      file_unmanaged_delete($image_path);
327
    }
328
  }
329
}