1
|
<?php
|
2
|
|
3
|
/**
|
4
|
* Implements hook_hook_info().
|
5
|
*/
|
6
|
function media_internet_hook_info() {
|
7
|
$hooks = array(
|
8
|
'media_internet_providers',
|
9
|
);
|
10
|
|
11
|
return array_fill_keys($hooks, array('group' => 'media'));
|
12
|
}
|
13
|
|
14
|
/**
|
15
|
* Implements hook_menu().
|
16
|
*/
|
17
|
function media_internet_menu() {
|
18
|
$items['file/add/web'] = array(
|
19
|
'title' => 'Web',
|
20
|
'description' => 'Add internet files to your media library.',
|
21
|
'page callback' => 'drupal_get_form',
|
22
|
'page arguments' => array('media_internet_add_upload'),
|
23
|
'access callback' => 'media_internet_access',
|
24
|
'type' => MENU_LOCAL_TASK,
|
25
|
'file' => 'file_entity.pages.inc',
|
26
|
'file path' => drupal_get_path('module', 'file_entity'),
|
27
|
);
|
28
|
|
29
|
return $items;
|
30
|
}
|
31
|
|
32
|
/**
|
33
|
* Access callback for the media_internet media browser plugin.
|
34
|
*/
|
35
|
function media_internet_access($account = NULL) {
|
36
|
return user_access('administer files', $account) || user_access('add media from remote sources', $account);
|
37
|
}
|
38
|
|
39
|
/**
|
40
|
* Implement hook_permission().
|
41
|
*/
|
42
|
function media_internet_permission() {
|
43
|
return array(
|
44
|
'add media from remote sources' => array(
|
45
|
'title' => t('Add media from remote services'),
|
46
|
'description' => t('Add media from remote sources such as other websites, YouTube, etc'),
|
47
|
),
|
48
|
);
|
49
|
}
|
50
|
|
51
|
/**
|
52
|
* Implements hook_theme().
|
53
|
*/
|
54
|
function media_internet_theme() {
|
55
|
return array(
|
56
|
// media_internet.pages.inc.
|
57
|
'media_internet_embed_help' => array(
|
58
|
'variables' => array('description' => NULL, 'supported_providers' => NULL),
|
59
|
),
|
60
|
);
|
61
|
}
|
62
|
|
63
|
/**
|
64
|
* Gets the list of Internet media providers.
|
65
|
*
|
66
|
* Each 'Provider' has a title and a class which can handle saving remote files.
|
67
|
* Providers are each given a turn at parsing a user-submitted URL or embed code
|
68
|
* and, if they recognize that it belongs to a service or protocol they support,
|
69
|
* they store a representation of it as a file object in file_managed.
|
70
|
*
|
71
|
* @return array
|
72
|
* An associative array of provider information keyed by provider name.
|
73
|
*/
|
74
|
function media_internet_get_providers() {
|
75
|
$providers = &drupal_static(__FUNCTION__);
|
76
|
|
77
|
if (!isset($providers)) {
|
78
|
foreach (module_implements('media_internet_providers') as $module) {
|
79
|
foreach (module_invoke($module, 'media_internet_providers') as $class => $info) {
|
80
|
$providers[$class] = $info;
|
81
|
|
82
|
// Store the name of the module which declared the provider.
|
83
|
$providers[$class]['module'] = $module;
|
84
|
|
85
|
// Assign a default value to providers which don't specify a weight.
|
86
|
if (!isset($providers[$class]['weight'])) {
|
87
|
$providers[$class]['weight'] = 0;
|
88
|
}
|
89
|
}
|
90
|
}
|
91
|
|
92
|
// Allow modules to alter the list of providers.
|
93
|
drupal_alter('media_internet_providers', $providers);
|
94
|
|
95
|
// Sort the providers by weight.
|
96
|
uasort($providers, 'drupal_sort_weight');
|
97
|
}
|
98
|
|
99
|
return $providers;
|
100
|
}
|
101
|
|
102
|
/**
|
103
|
* Finds the appropriate provider for a given URL or embed_string
|
104
|
*
|
105
|
* Each provider has a claim() method which it uses to tell media_internet
|
106
|
* that it should handle this input. We cycle through all providers to find
|
107
|
* the right one.
|
108
|
*
|
109
|
* @todo: Make this into a normal hook or something because we have to instantiate
|
110
|
* each class to test and that's not right.
|
111
|
*/
|
112
|
function media_internet_get_provider($embed_string) {
|
113
|
foreach (media_internet_get_providers() as $class_name => $nothing) {
|
114
|
$p = new $class_name($embed_string);
|
115
|
if ($p->claim($embed_string)) {
|
116
|
return $p;
|
117
|
}
|
118
|
}
|
119
|
throw new MediaInternetNoHandlerException(t('Unable to handle the provided embed string or URL.'));
|
120
|
}
|
121
|
|
122
|
/**
|
123
|
* Returns HTML for help text based on supported internet media providers.
|
124
|
*
|
125
|
* @param $variables
|
126
|
* An associative array containing:
|
127
|
* - description: The normal description for this field, specified by the
|
128
|
* user.
|
129
|
* - supported_providers: A string of supported providers.
|
130
|
*
|
131
|
* @ingroup themeable
|
132
|
*/
|
133
|
function theme_media_internet_embed_help($variables) {
|
134
|
$description = $variables['description'];
|
135
|
$supported_providers = $variables['supported_providers'];
|
136
|
|
137
|
$descriptions = array();
|
138
|
|
139
|
if (strlen($description)) {
|
140
|
$descriptions[] = $description;
|
141
|
}
|
142
|
if (!empty($supported_providers)) {
|
143
|
$descriptions[] = t('Supported internet media providers: !providers.', array('!providers' => '<strong>' . $supported_providers . '</strong>'));
|
144
|
}
|
145
|
|
146
|
return implode('<br />', $descriptions);
|
147
|
}
|
148
|
|
149
|
/**
|
150
|
* Implements hook_forms().
|
151
|
*/
|
152
|
function media_internet_forms($form_id, $args) {
|
153
|
$forms = array();
|
154
|
|
155
|
// Create a copy of the upload wizard form for internet media.
|
156
|
if ($form_id == 'media_internet_add_upload') {
|
157
|
$forms[$form_id] = array(
|
158
|
'callback' => 'file_entity_add_upload',
|
159
|
);
|
160
|
}
|
161
|
|
162
|
return $forms;
|
163
|
}
|
164
|
|
165
|
/**
|
166
|
* Implements hook_form_FORM_ID_alter().
|
167
|
*/
|
168
|
function media_internet_form_file_entity_add_upload_alter(&$form, &$form_state, $form_id) {
|
169
|
$step = $form['#step'];
|
170
|
$options = $form['#options'];
|
171
|
|
172
|
// Swap the upload field for an embed field when on the first step of the web
|
173
|
// tab.
|
174
|
if ($form_id == 'media_internet_add_upload' && $step == 1) {
|
175
|
unset($form['upload']);
|
176
|
|
177
|
$form['embed_code'] = array(
|
178
|
'#type' => 'textfield',
|
179
|
'#title' => t('File URL'),
|
180
|
'#description' => t('Enter a URL to a file.'),
|
181
|
'#attributes' => array('class' => array('media-add-from-url')),
|
182
|
// There is no standard specifying a maximum length for a URL. Internet
|
183
|
// Explorer supports up to 2083 (http://support.microsoft.com/kb/208427)
|
184
|
// so we assume publicly available media URLs are within this limit.
|
185
|
'#maxlength' => 2083,
|
186
|
'#required' => TRUE,
|
187
|
'#default_value' => isset($form_state['storage']['embed_code']) ? $form_state['storage']['embed_code'] : NULL,
|
188
|
);
|
189
|
|
190
|
// Create an array to hold potential Internet media providers.
|
191
|
$providers = array();
|
192
|
|
193
|
// Determine if there are any visible providers.
|
194
|
foreach (media_internet_get_providers() as $key => $provider) {
|
195
|
if (empty($provider['hidden']) || $provider['hidden'] != TRUE) {
|
196
|
$providers[] = check_plain($provider['title']);
|
197
|
}
|
198
|
}
|
199
|
|
200
|
$form['#providers'] = $providers;
|
201
|
|
202
|
// Notify the user of any available providers.
|
203
|
if ($providers) {
|
204
|
// If any providers are enabled it is assumed that some kind of embed is supported.
|
205
|
$form['embed_code']['#title'] = t('File URL or media resource');
|
206
|
$form['embed_code']['#description'] = t('Enter a URL to a file or media resource. Many media providers also support identifying media via the embed code used to embed the media into external websites.');
|
207
|
|
208
|
$form['embed_code']['#description'] = theme('media_internet_embed_help', array('description' => $form['embed_code']['#description'], 'supported_providers' => implode(', ', $providers)));
|
209
|
}
|
210
|
|
211
|
$form['#validators'] = array();
|
212
|
|
213
|
if (!empty($options['types'])) {
|
214
|
$form['#validators']['media_file_validate_types'] = array($options['types']);
|
215
|
}
|
216
|
|
217
|
// Add validation and submission handlers to the form and ensure that they
|
218
|
// run first.
|
219
|
array_unshift($form['#validate'], 'media_internet_add_validate');
|
220
|
array_unshift($form['#submit'], 'media_internet_add_submit');
|
221
|
}
|
222
|
}
|
223
|
|
224
|
/**
|
225
|
* Allow stream wrappers to have their chance at validation.
|
226
|
*
|
227
|
* Any module that implements hook_media_parse will have an
|
228
|
* opportunity to validate this.
|
229
|
*
|
230
|
* @see media_parse_to_uri()
|
231
|
*/
|
232
|
function media_internet_add_validate($form, &$form_state) {
|
233
|
// Supporting providers can now claim this input. It might be a URL, but it
|
234
|
// might be an embed code as well.
|
235
|
$embed_code = $form_state['values']['embed_code'];
|
236
|
|
237
|
try {
|
238
|
$provider = media_internet_get_provider($embed_code);
|
239
|
$provider->validate();
|
240
|
}
|
241
|
catch (MediaInternetNoHandlerException $e) {
|
242
|
form_set_error('embed_code', $e->getMessage());
|
243
|
return;
|
244
|
}
|
245
|
catch (MediaInternetValidationException $e) {
|
246
|
form_set_error('embed_code', $e->getMessage());
|
247
|
return;
|
248
|
}
|
249
|
|
250
|
$validators = $form['#validators'];
|
251
|
$file = $provider->getFileObject();
|
252
|
|
253
|
if ($validators) {
|
254
|
try {
|
255
|
$file = $provider->getFileObject();
|
256
|
}
|
257
|
catch (Exception $e) {
|
258
|
form_set_error('embed_code', $e->getMessage());
|
259
|
return;
|
260
|
}
|
261
|
|
262
|
// Check for errors. @see media_add_upload_validate calls file_save_upload().
|
263
|
// this code is ripped from file_save_upload because we just want the validation part.
|
264
|
// Call the validation functions specified by this function's caller.
|
265
|
$errors = file_validate($file, $validators);
|
266
|
|
267
|
if (!empty($errors)) {
|
268
|
$message = t('%url could not be added.', array('%url' => $embed_code));
|
269
|
if (count($errors) > 1) {
|
270
|
$message .= theme('item_list', array('items' => $errors));
|
271
|
}
|
272
|
else {
|
273
|
$message .= ' ' . array_pop($errors);
|
274
|
}
|
275
|
form_set_error('embed_code', $message);
|
276
|
return FALSE;
|
277
|
}
|
278
|
}
|
279
|
|
280
|
// @TODO: Validate that if we have no $uri that this is a valid file to
|
281
|
// save. For instance, we may only be interested in images, and it would
|
282
|
// be helpful to let the user know they passed the HTML page containing
|
283
|
// the image accidentally. That would also save us from saving the file
|
284
|
// in the submit step.
|
285
|
|
286
|
// This is kinda a hack of the same.
|
287
|
|
288
|
// This should use the file_validate routines that the upload form users.
|
289
|
// We need to fix the media_parse_to_file routine to allow for a validation.
|
290
|
}
|
291
|
|
292
|
/**
|
293
|
* Upload a file from a URL.
|
294
|
*
|
295
|
* This will copy a file from a remote location and store it locally.
|
296
|
*
|
297
|
* @see media_parse_to_uri()
|
298
|
* @see media_parse_to_file()
|
299
|
*/
|
300
|
function media_internet_add_submit($form, &$form_state) {
|
301
|
$embed_code = $form_state['values']['embed_code'];
|
302
|
|
303
|
try {
|
304
|
// Save the remote file
|
305
|
$provider = media_internet_get_provider($embed_code);
|
306
|
// Providers decide if they need to save locally or somewhere else.
|
307
|
// This method returns a file object
|
308
|
$file = $provider->save();
|
309
|
}
|
310
|
catch (Exception $e) {
|
311
|
form_set_error('embed_code', $e->getMessage());
|
312
|
return;
|
313
|
}
|
314
|
|
315
|
if (!$file->fid) {
|
316
|
form_set_error('embed_code', t('The file %file could not be saved. An unknown error has occurred.', array('%file' => $embed_code)));
|
317
|
return;
|
318
|
}
|
319
|
else {
|
320
|
$form_state['storage']['upload'] = $file->fid;
|
321
|
}
|
322
|
}
|