| 1 |
<?php
|
| 2 |
|
| 3 |
// $Id: video_upload_widget.inc,v 1.4.2.8 2009/09/04 20:51:16 jhedstrom Exp $
|
| 4 |
|
| 5 |
/**
|
| 6 |
* @file
|
| 7 |
* Video_Upload widget hooks and callbacks.
|
| 8 |
*
|
| 9 |
* This file is loaded by fileifeld.module and the callbacks it contains are
|
| 10 |
* invoked by filefield.module. This happens because video_upload delegates it's
|
| 11 |
* CCK hooks and callbacks to filefield in video_upload.module.
|
| 12 |
*/
|
| 13 |
|
| 14 |
|
| 15 |
/**
|
| 16 |
* @defgroup "FileField widget settings callbacks."
|
| 17 |
* @{
|
| 18 |
*
|
| 19 |
* These callbacks are invoked by filefield_widget_settings. Their return
|
| 20 |
* values are merged with and will override filefields' widget settings
|
| 21 |
* callback's return values.
|
| 22 |
*
|
| 23 |
* @fixme
|
| 24 |
* allow for more token types other than users
|
| 25 |
*/
|
| 26 |
function video_upload_widget_settings_form($widget) {
|
| 27 |
video_upload_initialize_provider();
|
| 28 |
$form = module_invoke('filefield', 'widget_settings', 'form', $widget);
|
| 29 |
|
| 30 |
// Allowed file extensions.
|
| 31 |
$form['file_extensions'] = array(
|
| 32 |
'#type' => 'textfield',
|
| 33 |
'#title' => t('Allowed upload file extensions.'),
|
| 34 |
'#default_value' => is_string($widget['file_extensions']) ? $widget['file_extensions'] : 'mov avi mp4 mpa mpe mpg mpeg qt wmv',
|
| 35 |
'#size' => 64,
|
| 36 |
'#description' => t('Video filename extenstions allowed by the video provider. Seperate extensions with a space and do not include the leading dot.'),
|
| 37 |
);
|
| 38 |
|
| 39 |
$form['use_browser_upload_method'] = array(
|
| 40 |
'#type' => 'hidden',
|
| 41 |
'#value' => FALSE,
|
| 42 |
|
| 43 |
// @todo once the browser upload method is working, this option
|
| 44 |
// should be enabled.
|
| 45 |
// '#type' => 'checkbox',
|
| 46 |
// '#title' => t('Use Browser Upload Method'),
|
| 47 |
// '#default_value' => isset($widget['use_browser_upload_method']) ? $widget['use_browser_upload_method'] : true,
|
| 48 |
// '#description' => t('The <a href="!url">Browser Upload Method</a> sends video files directly to YouTube, instead of touching the Drupal server. This saves on storage and bandwidth', array('!url' => url('http://code.google.com/apis/youtube/developers_guide_php.html#BrowserUpload'))),
|
| 49 |
);
|
| 50 |
|
| 51 |
// Maintenance.
|
| 52 |
$form['auto_delete_rejected_videos'] = array(
|
| 53 |
'#type' => 'checkbox',
|
| 54 |
'#title' => t('Auto-delete rejected videos from account'),
|
| 55 |
'#description' => t('When videos are rejected, use cron to automatically remove them from the video provider.'),
|
| 56 |
'#default_value' => isset($widget['auto_delete_rejected_videos']) ? $widget['auto_delete_rejected_videos'] : FALSE,
|
| 57 |
);
|
| 58 |
$form['remove_deleted_videos'] = array(
|
| 59 |
'#type' => 'checkbox',
|
| 60 |
'#title' => t('Remove videos from provider if node is deleted, or video is changed'),
|
| 61 |
'#description' => t("When a node is deleted, or a video is changed/updated the original video will be removed from the provider. If left un-checked, videos will remain on the 3rd-party provider's site."),
|
| 62 |
'#default_value' => isset($widget['remove_deleted_videos']) ? $widget['remove_deleted_videos'] : FALSE,
|
| 63 |
);
|
| 64 |
|
| 65 |
// Width and height.
|
| 66 |
$form['display'] = array(
|
| 67 |
'#type' => 'fieldset',
|
| 68 |
'#title' => t('Display Options'),
|
| 69 |
'#tree' => TRUE,
|
| 70 |
'#collapsible' => TRUE,
|
| 71 |
);
|
| 72 |
$form['display']['default_width'] = array(
|
| 73 |
'#type' => 'textfield',
|
| 74 |
'#title' => t('Default/Large Width'),
|
| 75 |
'#required' => TRUE,
|
| 76 |
'#default_value' => $widget['display']['default_width'] ? $widget['display']['default_width'] : '480',
|
| 77 |
'#description' => t('The width for the default (large) player'),
|
| 78 |
);
|
| 79 |
$form['display']['default_height'] = array(
|
| 80 |
'#type' => 'textfield',
|
| 81 |
'#title' => t('Default/Large Height'),
|
| 82 |
'#required' => TRUE,
|
| 83 |
'#default_value' => $widget['display']['default_height'] ? $widget['display']['default_height'] : '295',
|
| 84 |
'#description' => t('The height for the default (large) player'),
|
| 85 |
);
|
| 86 |
$form['display']['small_width'] = array(
|
| 87 |
'#type' => 'textfield',
|
| 88 |
'#title' => t('Small Width'),
|
| 89 |
'#required' => TRUE,
|
| 90 |
'#default_value' => $widget['display']['small_width'] ? $widget['display']['small_width'] : '240',
|
| 91 |
'#description' => t('The width for the small player'),
|
| 92 |
);
|
| 93 |
$form['display']['small_height'] = array(
|
| 94 |
'#type' => 'textfield',
|
| 95 |
'#title' => t('Small Height'),
|
| 96 |
'#required' => TRUE,
|
| 97 |
'#default_value' => $widget['display']['small_height'] ? $widget['display']['small_height'] : '148',
|
| 98 |
'#description' => t('The height for the small player'),
|
| 99 |
);
|
| 100 |
$form['display']['thumb_width'] = array(
|
| 101 |
'#type' => 'textfield',
|
| 102 |
'#title' => t('Thumbnail Width'),
|
| 103 |
'#default_value' => $widget['display']['thumb_width'] ? $widget['display']['thumb_width'] : '128',
|
| 104 |
);
|
| 105 |
$form['display']['thumb_height'] = array(
|
| 106 |
'#type' => 'textfield',
|
| 107 |
'#title' => t('Thumbnail Height'),
|
| 108 |
'#default_value' => $widget['display']['thumb_height'] ? $widget['display']['thumb_height'] : '72',
|
| 109 |
);
|
| 110 |
// @TODO abstract out youtube. The options below are (mostly)
|
| 111 |
// YouTube-specific, and should be added via a provider hook.
|
| 112 |
$form['display']['related_videos'] = array(
|
| 113 |
'#type' => 'checkbox',
|
| 114 |
'#title' => t('Show related videos'),
|
| 115 |
'#default_value' => $widget['display']['related_videos'],
|
| 116 |
'#description' => t('Show related videos in the player after the video has finished.'),
|
| 117 |
);
|
| 118 |
$form['display']['autoplay'] = array(
|
| 119 |
'#type' => 'checkbox',
|
| 120 |
'#title' => t('Auto-play video on page load'),
|
| 121 |
'#default_value' => $widget['display']['autoplay'],
|
| 122 |
);
|
| 123 |
$form['display']['fullscreen'] = array(
|
| 124 |
'#type' => 'checkbox',
|
| 125 |
'#title' => t('Enable Fullscreen'),
|
| 126 |
'#description' => t('Show a <em>fullscreen</em> button on the embedded player.'),
|
| 127 |
'#default_value' => isset($widget['display']['fullscreen']) ? $widget['display']['fullscreen'] : TRUE,
|
| 128 |
);
|
| 129 |
|
| 130 |
// Default title pattern.
|
| 131 |
$form['default_title'] = array(
|
| 132 |
'#type' => 'textfield',
|
| 133 |
'#title' => t('Default Video Title'),
|
| 134 |
'#default_value' => $widget['default_title'],
|
| 135 |
'#size' => 64,
|
| 136 |
'#maxlength' => 255,
|
| 137 |
'#description' => t('Since the videos are initially uploaded prior to node creation, they must contain a default title. This title will only be visible on the provider site, and will be updated once the node is saved, and the video has been processed.'),
|
| 138 |
);
|
| 139 |
if (module_exists('token')) {
|
| 140 |
$form['default_title']['#description'] .= ' '. t('<br />The following tokens can be used in the default title');
|
| 141 |
$form['default_title']['#suffix'] = theme('fieldset', array('#children' => theme('token_help', 'user'), '#collapsed' => TRUE, '#collapsible' => TRUE, '#title' => t('Tokens')));
|
| 142 |
}
|
| 143 |
|
| 144 |
// Default title synchronization.
|
| 145 |
$form['default_title_sync'] = array(
|
| 146 |
'#type' => 'radios',
|
| 147 |
'#title' => t('Default Video Title Synchronization'),
|
| 148 |
'#description' => t('The <em>Video Upload module</em> will attempt to synchronize data with the provider, these options determine the extent of such synchronization'),
|
| 149 |
'#options' => array(
|
| 150 |
VIDEO_UPLOAD_SYNC => t('Synchronize (overwrite default)'),
|
| 151 |
VIDEO_UPLOAD_SYNC_NONE => t('Don\'t Synchronize (keep default)'),
|
| 152 |
VIDEO_UPLOAD_SYNC_APPEND => t('Append node title to default'),
|
| 153 |
),
|
| 154 |
'#default_value' => isset($widget['default_title_sync']) ? $widget['default_title_sync'] : VIDEO_UPLOAD_SYNC,
|
| 155 |
'#required' => TRUE,
|
| 156 |
);
|
| 157 |
|
| 158 |
// Default description.
|
| 159 |
$form['default_description'] = array(
|
| 160 |
'#type' => 'textarea',
|
| 161 |
'#title' => t('Default video description'),
|
| 162 |
'#default_value' => $widget['default_description'],
|
| 163 |
'#description' => t('Since the videos are initially uploaded prior to node creation, they can contain a default description. This description will only be visible on the provider site, and will be updated with the node teaser once the node is saved and the video has been processed.'),
|
| 164 |
'#element_validate' => array('_video_upload_widget_validate_strip_tags'),
|
| 165 |
);
|
| 166 |
if (module_exists('token')) {
|
| 167 |
$form['default_description']['#description'] .= t('<br />The following tokens can be used in the default description');
|
| 168 |
$form['default_description']['#suffix'] = theme('fieldset', array('#children' => theme('token_help'), '#collapsed' => TRUE, '#collapsible' => TRUE, '#title' => t('Tokens')));
|
| 169 |
}
|
| 170 |
|
| 171 |
// Default description synchronization.
|
| 172 |
$form['default_description_sync'] = array(
|
| 173 |
'#type' => 'radios',
|
| 174 |
'#title' => t('Default Video Description Synchronization'),
|
| 175 |
'#description' => t('The <em>Video Upload module</em> will attempt to synchronize data with the provider, these options determine the extent of such synchronization'),
|
| 176 |
'#options' => array(
|
| 177 |
VIDEO_UPLOAD_SYNC => t('Synchronize (overwrite default)'),
|
| 178 |
VIDEO_UPLOAD_SYNC_NONE => t('Don\'t Synchronize (keep default)'),
|
| 179 |
VIDEO_UPLOAD_SYNC_APPEND => t('Append Description to default')
|
| 180 |
),
|
| 181 |
'#default_value' => isset($widget['default_description_sync']) ? $widget['default_description_sync'] : VIDEO_UPLOAD_SYNC_APPEND,
|
| 182 |
'#required' => TRUE,
|
| 183 |
);
|
| 184 |
|
| 185 |
// Keywords.
|
| 186 |
// @todo - some input validation
|
| 187 |
$form['default_keywords'] = array(
|
| 188 |
'#type' => 'textfield',
|
| 189 |
'#title' => t('Default keywords'),
|
| 190 |
'#required' => TRUE,
|
| 191 |
'#description' => t('Comma-separated list of keywords (no white space allowed in keywords).<br /><br />Since the videos are initially uploaded prior to node creation, they must contain a default set of keywords. These keywords will only be visible on the provider site, and will be updated with taxonomy terms (if in use on this content type) once the node is saved and the video has been processed.'),
|
| 192 |
'#default_value' => $widget['default_keywords'],
|
| 193 |
'#element_validate' => array('_video_upload_widget_validate_default_keywords'),
|
| 194 |
);
|
| 195 |
// default keyword synchronization
|
| 196 |
$form['default_keyword_sync'] = array(
|
| 197 |
'#type' => 'radios',
|
| 198 |
'#title' => t('Default Video Keyword Synchronization'),
|
| 199 |
'#description' => t('The <em>Video Upload module</em> will attempt to synchronize data with the provider site. These options determine the extent of such synchronization'),
|
| 200 |
'#options' => array(
|
| 201 |
VIDEO_UPLOAD_SYNC => t('Synchronize (overwrite default)'),
|
| 202 |
VIDEO_UPLOAD_SYNC_NONE => t("Don't Synchronize (keep default)"),
|
| 203 |
VIDEO_UPLOAD_SYNC_APPEND => t('Append Taxonomy (if applicable) to default keywords')
|
| 204 |
),
|
| 205 |
'#default_value' => isset($widget['default_keyword_sync']) ? $widget['default_keyword_sync'] : VIDEO_UPLOAD_SYNC_APPEND,
|
| 206 |
'#required' => TRUE,
|
| 207 |
);
|
| 208 |
|
| 209 |
// Developer tags.
|
| 210 |
$form['developer_tags'] = array(
|
| 211 |
'#type' => 'textfield',
|
| 212 |
'#title' => t('Developer Tags'),
|
| 213 |
'#default_value' => $widget['developer_tags'],
|
| 214 |
'#description' => t('Videos uploaded to the video provider can have hidden tags associated with them for later organization and tracking. Separate tags with a comma.'),
|
| 215 |
);
|
| 216 |
if (module_exists('token')) {
|
| 217 |
$form['developer_tags']['#description'] .= t('<br />The following tokens can be used in <em>Developer Tags</em>');
|
| 218 |
$form['developer_tags']['#suffix'] = theme('fieldset', array('#children' => theme('token_help', 'user'), '#collapsed' => TRUE, '#collapsible' => TRUE, '#title' => t('Tokens')));
|
| 219 |
}
|
| 220 |
|
| 221 |
// Video category (this is a fixed list from YouTube).
|
| 222 |
// @todo abstract out YouTube
|
| 223 |
$form['video_category'] = array(
|
| 224 |
'#type' => 'select',
|
| 225 |
'#title' => t('Video Category'),
|
| 226 |
'#options' => _video_upload_youtube_available_categories(),
|
| 227 |
'#default_value' => $widget['video_category'],
|
| 228 |
'#required' => TRUE,
|
| 229 |
'#description' => t('The video provider requires that videos be placed into one of these categories'),
|
| 230 |
);
|
| 231 |
|
| 232 |
return $form;
|
| 233 |
}
|
| 234 |
|
| 235 |
/**
|
| 236 |
* An array of variables as defined above.
|
| 237 |
*/
|
| 238 |
function video_upload_widget_settings_save($widget) {
|
| 239 |
$filefield_settings = module_invoke('filefield', 'widget_settings', 'save', $widget);
|
| 240 |
$video_upload_settings = array(
|
| 241 |
'video_category',
|
| 242 |
'auto_delete_rejected_videos',
|
| 243 |
'remove_deleted_videos',
|
| 244 |
'file_extensions',
|
| 245 |
'use_browser_upload_method',
|
| 246 |
'default_title',
|
| 247 |
'default_description',
|
| 248 |
'default_keywords',
|
| 249 |
'developer_tags',
|
| 250 |
'display',
|
| 251 |
'default_title_sync',
|
| 252 |
'default_description_sync',
|
| 253 |
'default_keyword_sync',
|
| 254 |
);
|
| 255 |
return array_merge($filefield_settings, $video_upload_settings);
|
| 256 |
}
|
| 257 |
|
| 258 |
/**
|
| 259 |
* Validate default keywords setting.
|
| 260 |
*/
|
| 261 |
function _video_upload_widget_validate_default_keywords($element, &$form_state) {
|
| 262 |
if ($form_state['values']['default_keywords']) {
|
| 263 |
// @todo abstract out YouTube. This should simply call a provider callback
|
| 264 |
// instead of enforcing a YouTube-specific keyword format.
|
| 265 |
// Keywords can't have spaces in them.
|
| 266 |
$check = explode(',', $form_state['values']['default_keywords']);
|
| 267 |
foreach ($check as $keyword) {
|
| 268 |
$keyword = trim($keyword);
|
| 269 |
if (strpos($keyword, ' ') !== FALSE) {
|
| 270 |
form_error($element, t("No spaces are allowed in keywords."));
|
| 271 |
return;
|
| 272 |
}
|
| 273 |
$keywords[] = $keyword;
|
| 274 |
}
|
| 275 |
form_set_value($element, implode(',', $keywords), $form_state);
|
| 276 |
}
|
| 277 |
}
|
| 278 |
|
| 279 |
/**
|
| 280 |
* Strip all tags out of description fields.
|
| 281 |
*/
|
| 282 |
function _video_upload_widget_validate_strip_tags($element, &$form_state) {
|
| 283 |
$field = $form_state['values'][$element['#name']];
|
| 284 |
form_set_value($element, strip_tags($field), $form_state);
|
| 285 |
}
|
| 286 |
|
| 287 |
/**
|
| 288 |
* @} End defgroup "Filefield widget settings callbacks."
|
| 289 |
*/
|
| 290 |
|
| 291 |
/**
|
| 292 |
* @defgroup "FileField widget element callbacks.
|
| 293 |
* @{
|
| 294 |
*
|
| 295 |
* The call backs are called by form elements that leverage the
|
| 296 |
* filefield_widget_value and filefield_widget_process callbacks. They will
|
| 297 |
* be called after the filefield callbacks and their return values will be
|
| 298 |
* merged with the filefield callback's.
|
| 299 |
*/
|
| 300 |
function video_upload_widget_value($element, $edit = FALSE) {
|
| 301 |
$item = filefield_widget_value($element, $edit);
|
| 302 |
if ($edit) {
|
| 303 |
$item['video_status'] = isset($edit['video_status']) ? $edit['video_status'] : VIDEO_UPLOAD_STATUS_UPLOAD_PENDING;
|
| 304 |
$item['video_status_ts'] = isset($edit['video_status_ts']) ? $edit['video_status_ts'] : $_SERVER['REQUEST_TIME'];
|
| 305 |
}
|
| 306 |
else {
|
| 307 |
$item['video_status'] = VIDEO_UPLOAD_STATUS_UPLOAD_PENDING;
|
| 308 |
$item['video_status_ts'] = $_SERVER['REQUEST_TIME'];
|
| 309 |
}
|
| 310 |
|
| 311 |
return $item;
|
| 312 |
}
|
| 313 |
|
| 314 |
function video_upload_widget_process($element, $edit, &$form_state, $form) {
|
| 315 |
$file = $element['#value'];
|
| 316 |
|
| 317 |
$field = content_fields($element['#field_name'], $element['#type_name']);
|
| 318 |
|
| 319 |
$element['video_status'] = array(
|
| 320 |
'#type' => 'hidden',
|
| 321 |
'#default_value' => $element['#default_value']['video_status'],
|
| 322 |
);
|
| 323 |
$element['video_status_ts'] = array(
|
| 324 |
'#type' => 'hidden',
|
| 325 |
'#default_value' => $element['#default_value']['video_status_ts'],
|
| 326 |
);
|
| 327 |
$element['video_id'] = array(
|
| 328 |
'#type' => 'hidden',
|
| 329 |
'#default_value' => $element['#default_value']['video_id'],
|
| 330 |
);
|
| 331 |
|
| 332 |
return $element;
|
| 333 |
}
|
| 334 |
|
| 335 |
/**
|
| 336 |
* An #element_validate callback for the video_upload_widget field.
|
| 337 |
*
|
| 338 |
* This is mostly a copy of FileField's widget validate callback.
|
| 339 |
*/
|
| 340 |
function video_upload_widget_validate(&$element, &$form_state) {
|
| 341 |
// If referencing an existing file, only allow if there are existing
|
| 342 |
// references. This prevents unmanaged files (outside of FileField) from
|
| 343 |
// being deleted if this node were to be deleted.
|
| 344 |
if (!empty($element['fid']['#value'])) {
|
| 345 |
$field = content_fields($element['#field_name'], $element['#type_name']);
|
| 346 |
if ($file = field_file_load($element['fid']['#value'])) {
|
| 347 |
$file = (object) $file;
|
| 348 |
if ($file->status == FILE_STATUS_PERMANENT) {
|
| 349 |
// TODO: We could use field_file_references() here to reference any file
|
| 350 |
// but hook_file_delete() needs to be implemented first.
|
| 351 |
$references = module_invoke('video_upload', 'file_references', $file);
|
| 352 |
if ($references['video_upload'] == 0) {
|
| 353 |
form_error($element, t('Referencing to the file used in the %field field is not allowed.', array('%field' => $element['#title'])));
|
| 354 |
}
|
| 355 |
}
|
| 356 |
}
|
| 357 |
else {
|
| 358 |
form_error($element, t('The file referenced by the %field field does not exist.', array('%field' => $element['#title'])));
|
| 359 |
}
|
| 360 |
}
|
| 361 |
}
|
| 362 |
|
| 363 |
/**
|
| 364 |
* @} End defgroup "FileField widget element callbacks."
|
| 365 |
*/
|
| 366 |
|
| 367 |
/**
|
| 368 |
* @defgroup "CCK/Filefield widget theme functions."
|
| 369 |
* @{
|
| 370 |
* FormAPI theme function. Theme the output of an image field.
|
| 371 |
*/
|
| 372 |
function theme_video_upload_widget(&$element) {
|
| 373 |
return theme('form_element', $element, $element['#children']);
|
| 374 |
}
|
| 375 |
|
| 376 |
function theme_video_upload_widget_preview($item = NULL) {
|
| 377 |
$message = theme('video_upload_status_text', $item['video_status']);
|
| 378 |
return '<div class="messages">' . $message . '</div>' . theme('video_upload_video', $items['id']);
|
| 379 |
}
|
| 380 |
|
| 381 |
/**
|
| 382 |
* @} End defgroup "CCK/Filefield widget theme functions."
|
| 383 |
*/
|
| 384 |
|