| 1 |
<?php
|
| 2 |
// $Id: video_cck.module,v 1.22 2007/07/26 14:31:49 aaron Exp $
|
| 3 |
|
| 4 |
define('VIDEO_CCK_DEFAULT_VIDEO_WIDTH', 425);
|
| 5 |
define('VIDEO_CCK_DEFAULT_VIDEO_HEIGHT', 350);
|
| 6 |
define('VIDEO_CCK_DEFAULT_PREVIEW_WIDTH', 425);
|
| 7 |
define('VIDEO_CCK_DEFAULT_PREVIEW_HEIGHT', 350);
|
| 8 |
define('VIDEO_CCK_DEFAULT_THUMBNAIL_WIDTH', 120);
|
| 9 |
define('VIDEO_CCK_DEFAULT_THUMBNAIL_HEIGHT', 90);
|
| 10 |
|
| 11 |
/**
|
| 12 |
* Implement hook_menu
|
| 13 |
*/
|
| 14 |
function video_cck_menu($may_cache) {
|
| 15 |
$items = array();
|
| 16 |
if ($may_cache) {
|
| 17 |
$items[] = array(
|
| 18 |
'path' => 'admin/content/video_cck',
|
| 19 |
'title' => t('Video CCK configuration'),
|
| 20 |
'description' => t('Configure Video CCK: Allow content types to use various 3rd party providers, enter API keys, etc.'),
|
| 21 |
'callback' => 'drupal_get_form',
|
| 22 |
'callback arguments' => 'video_cck_settings',
|
| 23 |
'access' => user_access('administer site configuration'));
|
| 24 |
}
|
| 25 |
return $items;
|
| 26 |
}
|
| 27 |
|
| 28 |
/**
|
| 29 |
* Implement hook_settings
|
| 30 |
*/
|
| 31 |
function video_cck_settings() {
|
| 32 |
$form = array();
|
| 33 |
$providers = video_cck_system_list();
|
| 34 |
$header = array(t('Feature'), t('Supported'), t('Notes'));
|
| 35 |
foreach ($providers as $provider) {
|
| 36 |
$info = video_cck_include_invoke($provider->name, 'info');
|
| 37 |
$form[$provider->name] = array(
|
| 38 |
'#type' => 'fieldset',
|
| 39 |
'#title' => t('@provider configuration', array('@provider' => $info['name'])),
|
| 40 |
'#description' => $info['settings_description'],
|
| 41 |
'#collapsible' => true,
|
| 42 |
'#collapsed' => true,
|
| 43 |
);
|
| 44 |
if (is_array($info['supported_features']) && !empty($info['supported_features'])) {
|
| 45 |
$form[$provider->name]['supported_features'] = array(
|
| 46 |
'#type' => 'fieldset',
|
| 47 |
'#title' => t('Supported features'),
|
| 48 |
'#description' => t('This is a list of the current state of support for the following features by %provider:', array('%provider' => $info['name'])),
|
| 49 |
'#collapsible' => true,
|
| 50 |
'#collapsed' => true,
|
| 51 |
'#weight' => 7,
|
| 52 |
);
|
| 53 |
$form[$provider->name]['supported_features']['features'] = array(
|
| 54 |
'#type' => 'markup',
|
| 55 |
'#value' => theme('table', $header, $info['supported_features']),
|
| 56 |
);
|
| 57 |
}
|
| 58 |
$form[$provider->name]['video_cck_allow_' . $provider->name] = array(
|
| 59 |
'#type' => 'checkbox',
|
| 60 |
'#title' => t('Allow videos from %provider', array('%provider' => $info['name'])),
|
| 61 |
'#description' => t('If checked, then content types may be created that allow video to be provided by %provider.', array('%provider' => $info['name'])),
|
| 62 |
'#weight' => -10,
|
| 63 |
'#default_value' => variable_get('video_cck_allow_' . $provider->name, true),
|
| 64 |
);
|
| 65 |
$form[$provider->name][] = video_cck_include_invoke($provider->name, 'settings');
|
| 66 |
}
|
| 67 |
return system_settings_form($form);
|
| 68 |
}
|
| 69 |
|
| 70 |
/**Implementation of hook_field_info **/
|
| 71 |
|
| 72 |
function video_cck_field_info() {
|
| 73 |
$fields = array(
|
| 74 |
'video_cck' => array('label' => t('Embedded Video')),
|
| 75 |
);
|
| 76 |
return $fields;
|
| 77 |
}
|
| 78 |
|
| 79 |
/** Implementation of hook_field_settings **/
|
| 80 |
|
| 81 |
function video_cck_field_settings($op, $field) {
|
| 82 |
switch ($op) {
|
| 83 |
|
| 84 |
case 'database columns':
|
| 85 |
$columns = array(
|
| 86 |
'embed' => array('type' => 'longtext', 'not null' => TRUE, 'default' => "''", 'sortable' => TRUE),
|
| 87 |
'value' => array('type' => 'varchar', 'length' => 255, 'not null' => TRUE, 'default' => "''", 'sortable' => TRUE),
|
| 88 |
'provider' => array('type' => 'varchar', 'length' => 255, 'not null' => TRUE, 'default' => "''", 'sortable' => TRUE),
|
| 89 |
'data' => array('type' => 'longtext', 'not null' => TRUE, 'default' => "''", 'sortable' => false),
|
| 90 |
);
|
| 91 |
switch ($field['type']) {
|
| 92 |
case 'video_cck':
|
| 93 |
break;
|
| 94 |
}
|
| 95 |
return $columns;
|
| 96 |
}
|
| 97 |
}
|
| 98 |
|
| 99 |
/** Implementation of hook_field **/
|
| 100 |
|
| 101 |
function video_cck_field($op, &$node, $field, &$items, $teaser, $page) {
|
| 102 |
switch ($op) {
|
| 103 |
|
| 104 |
// TODO: nothing to validate at the moment. we need to have different api's have a chance to validate
|
| 105 |
case 'validate':
|
| 106 |
if ($field['multiple']) {
|
| 107 |
foreach ($items as $delta => $item) {
|
| 108 |
$error_field = $field['field_name'].']['.$delta.'][embed';
|
| 109 |
|
| 110 |
_video_cck_field_validate_id($field, $item, $error_field);
|
| 111 |
}
|
| 112 |
}
|
| 113 |
else {
|
| 114 |
$error_field = $field['field_name'];
|
| 115 |
|
| 116 |
_video_cck_field_validate_id($field, $items[0], $error_field);
|
| 117 |
}
|
| 118 |
break;
|
| 119 |
|
| 120 |
case 'submit':
|
| 121 |
if ($field['multiple']) {
|
| 122 |
foreach ($items as $delta => $item) {
|
| 123 |
$list = _video_cck_field_submit_id($field, $item);
|
| 124 |
$items[$delta]['provider'] = $list['provider'];
|
| 125 |
$items[$delta]['value'] = $list['value'];
|
| 126 |
$items[$delta]['data'] = $list['data'];
|
| 127 |
}
|
| 128 |
}
|
| 129 |
else {
|
| 130 |
$list = _video_cck_field_submit_id($field, $items[0]);
|
| 131 |
$items[0]['provider'] = $list['provider'];
|
| 132 |
$items[0]['value'] = $list['value'];
|
| 133 |
$items[0]['data'] = $list['data'];
|
| 134 |
}
|
| 135 |
break;
|
| 136 |
|
| 137 |
case 'insert':
|
| 138 |
case 'update':
|
| 139 |
if ($field['multiple']) {
|
| 140 |
foreach ($items as $delta => $item) {
|
| 141 |
$items[$delta]['data'] = serialize($items[$delta]['data']);
|
| 142 |
}
|
| 143 |
}
|
| 144 |
else {
|
| 145 |
$items[0]['data'] = serialize($items[0]['data']);
|
| 146 |
}
|
| 147 |
break;
|
| 148 |
|
| 149 |
case 'load':
|
| 150 |
$field_name = $field['field_name'];
|
| 151 |
|
| 152 |
if ($field['multiple']) {
|
| 153 |
foreach ($items as $delta => $item) {
|
| 154 |
$data = (array)unserialize($items[$delta]['data']);
|
| 155 |
$items[$delta]['data'] = $data;
|
| 156 |
$node->{$field_name}[$delta]['data'] = $data;
|
| 157 |
}
|
| 158 |
}
|
| 159 |
else {
|
| 160 |
$data = (array)unserialize($items[0]['data']);
|
| 161 |
$items[0]['data'] = $data;
|
| 162 |
$node->{$field_name}[0]['data'] = $data;
|
| 163 |
}
|
| 164 |
$return = array();
|
| 165 |
$return[$field_name] = $items;
|
| 166 |
return $return;
|
| 167 |
break;
|
| 168 |
}
|
| 169 |
}
|
| 170 |
|
| 171 |
/**
|
| 172 |
* return a list of providers allowed for a specific field
|
| 173 |
*/
|
| 174 |
function video_cck_allowed_providers($field) {
|
| 175 |
$allowed_providers = video_cck_system_list();
|
| 176 |
$providers = array();
|
| 177 |
$allow_all = true;
|
| 178 |
foreach ($allowed_providers as $test) {
|
| 179 |
if (!variable_get('video_cck_allow_' . $test->name, true)) {
|
| 180 |
unset($allowed_providers[$test->name]);
|
| 181 |
}
|
| 182 |
else {
|
| 183 |
$allow_all &= !$field['widget']['providers'][$test->name];
|
| 184 |
}
|
| 185 |
}
|
| 186 |
if (!$allow_all) {
|
| 187 |
foreach ($allowed_providers as $test) {
|
| 188 |
if (!$field['widget']['providers'][$test->name]) {
|
| 189 |
unset($allowed_providers[$test->name]);
|
| 190 |
}
|
| 191 |
}
|
| 192 |
}
|
| 193 |
return $allowed_providers;
|
| 194 |
}
|
| 195 |
|
| 196 |
/**
|
| 197 |
* This will parse the url or embedded code pasted by the node submitter.
|
| 198 |
* returns either an empty array (if no match), or an array of provider and value.
|
| 199 |
*/
|
| 200 |
function video_cck_parse_embed($field, $embed = '') {
|
| 201 |
if ($embed) {
|
| 202 |
$providers = video_cck_allowed_providers($field);
|
| 203 |
foreach ($providers as $provider) {
|
| 204 |
$success = video_cck_include_invoke($provider->name, 'extract', $embed);
|
| 205 |
// we've been given an array of regex strings, so let's see if we can find a match
|
| 206 |
if (is_array($success)) {
|
| 207 |
foreach ($success as $regex) {
|
| 208 |
$matches = NULL;
|
| 209 |
if (preg_match($regex, $embed, $matches)) {
|
| 210 |
return array('provider' => $provider->name, 'value' => $matches[1]);
|
| 211 |
}
|
| 212 |
}
|
| 213 |
}
|
| 214 |
// the invoked include module did its own parsing and found a match
|
| 215 |
else if ($success) {
|
| 216 |
return array('provider' => $provider->name, 'value' => $success);
|
| 217 |
}
|
| 218 |
}
|
| 219 |
}
|
| 220 |
// we found no match
|
| 221 |
return array();
|
| 222 |
}
|
| 223 |
|
| 224 |
/**
|
| 225 |
* extract the video id from embedded code or video url
|
| 226 |
*/
|
| 227 |
function _video_cck_field_validate_id($field, $item, $error_field) {
|
| 228 |
// does nothing at this time... TODO: fix this up
|
| 229 |
return _video_cck_field_submit_id($field, $item);
|
| 230 |
}
|
| 231 |
|
| 232 |
/**
|
| 233 |
* replace embedded code with the extracted id. this goes in the field 'value'
|
| 234 |
* also allows you to grab directly from the URL to play the video from field 'provider'
|
| 235 |
*/
|
| 236 |
function _video_cck_field_submit_id($field, $item) {
|
| 237 |
$item = array_merge($item, video_cck_parse_embed($field, $item['embed']));
|
| 238 |
$item['data'] = (array)video_cck_include_invoke($item['provider'], 'data', $field, $item);
|
| 239 |
return $item;
|
| 240 |
}
|
| 241 |
|
| 242 |
/** Implementation of hook_field_formatter_info **/
|
| 243 |
function video_cck_field_formatter_info() {
|
| 244 |
$types = array('video_cck',);
|
| 245 |
$formats = array(
|
| 246 |
'default' => array(
|
| 247 |
'label' => t('Default'),
|
| 248 |
'field types' => $types,
|
| 249 |
),
|
| 250 |
'video_video' => array(
|
| 251 |
'label' => t('Full Size Video'),
|
| 252 |
'field types' => $types,
|
| 253 |
),
|
| 254 |
'video_preview' => array(
|
| 255 |
'label' => t('Preview Video'),
|
| 256 |
'field types' => $types,
|
| 257 |
),
|
| 258 |
'video_thumbnail' => array(
|
| 259 |
'label' => t('Image Thumbnail'),
|
| 260 |
'field types' => $types,
|
| 261 |
),
|
| 262 |
'video_embed' => array(
|
| 263 |
'label' => t('Embed Code'),
|
| 264 |
'field types' => $types,
|
| 265 |
),
|
| 266 |
);
|
| 267 |
return $formats;
|
| 268 |
}
|
| 269 |
|
| 270 |
/** Implementation of hook_field_formatter **/
|
| 271 |
|
| 272 |
function video_cck_field_formatter($field, $item, $formatter, $node) {
|
| 273 |
// if we're coming from a preview, we need to extract our new embedded value...
|
| 274 |
if ($item['in_preview']) {
|
| 275 |
$item = video_cck_parse_embed($field, $item['embed']);
|
| 276 |
}
|
| 277 |
|
| 278 |
// if we have no value, then return an empty string
|
| 279 |
if (!isset($item['value'])) {
|
| 280 |
return '';
|
| 281 |
}
|
| 282 |
|
| 283 |
// unfortunately, when we come from a view, we don't get all the widget fields
|
| 284 |
if (!$node->type) {
|
| 285 |
$type = content_types($field['type_name']);
|
| 286 |
$field['widget'] = $type['fields'][$field['field_name']]['widget'];
|
| 287 |
}
|
| 288 |
|
| 289 |
// and sometimes our data is still unserialized, again from views
|
| 290 |
if (!is_array($item['data'])) {
|
| 291 |
$item['data'] = (array)unserialize($item['data']);
|
| 292 |
}
|
| 293 |
|
| 294 |
switch ($formatter) {
|
| 295 |
case 'video_thumbnail':
|
| 296 |
$output .= theme('video_cck_thumbnail', $field, $item, $formatter, $node);
|
| 297 |
break;
|
| 298 |
case 'video_preview':
|
| 299 |
$output .= theme('video_cck_preview', $field, $item, $formatter, $node);
|
| 300 |
break;
|
| 301 |
case 'video_embed':
|
| 302 |
$output .= theme('video_cck_embed', $field, $item, $formatter, $node);
|
| 303 |
break;
|
| 304 |
case 'video_video':
|
| 305 |
case 'default':
|
| 306 |
default:
|
| 307 |
$output .= theme('video_cck_video', $field, $item, $formatter, $node);
|
| 308 |
break;
|
| 309 |
}
|
| 310 |
return $output;
|
| 311 |
}
|
| 312 |
|
| 313 |
/** Widgets **/
|
| 314 |
|
| 315 |
/** Implementation of hook_widget_info **/
|
| 316 |
function video_cck_widget_info() {
|
| 317 |
return array(
|
| 318 |
'video_cck_textfields' => array(
|
| 319 |
'label' => t('3rd Party Video'),
|
| 320 |
'field types' => array('video_cck',),
|
| 321 |
),
|
| 322 |
);
|
| 323 |
}
|
| 324 |
|
| 325 |
function video_cck_widget_settings($op, $widget) {
|
| 326 |
switch ($op) {
|
| 327 |
case 'form':
|
| 328 |
$form = array();
|
| 329 |
if ($widget['type'] == 'video_cck_textfields') {
|
| 330 |
// retrieve list of allowed providers
|
| 331 |
$options = array();
|
| 332 |
$providers = video_cck_system_list();
|
| 333 |
foreach ($providers as $provider) {
|
| 334 |
if (variable_get('video_cck_allow_' . $provider->name, true)) {
|
| 335 |
$info = video_cck_include_invoke($provider->name, 'info');
|
| 336 |
$options[$provider->name] = $info['name'];
|
| 337 |
}
|
| 338 |
}
|
| 339 |
$form['provider_list'] = array(
|
| 340 |
'#type' => 'fieldset',
|
| 341 |
'#title' => t('Video Providers Supported'),
|
| 342 |
'#description' => t('Select which third party video providers you wish to allow for this content type from the list below. If no checkboxes are checked, then all providers will be supported. When a user submits new content, the URL they enter will be matched to the provider, assuming that provider is allowed here.'),
|
| 343 |
'#collapsible' => true,
|
| 344 |
'#collapsed' => false,
|
| 345 |
);
|
| 346 |
$form['provider_list']['providers'] = array(
|
| 347 |
'#type' => 'checkboxes',
|
| 348 |
'#title' => t('Providers'),
|
| 349 |
'#default_value' => $widget['providers'] ? $widget['providers'] : array(),
|
| 350 |
'#options' => $options,
|
| 351 |
);
|
| 352 |
|
| 353 |
$width = variable_get('video_cck_default_video_width', VIDEO_CCK_DEFAULT_VIDEO_WIDTH);
|
| 354 |
$height = variable_get('video_cck_default_video_height', VIDEO_CCK_DEFAULT_VIDEO_HEIGHT);
|
| 355 |
$form['video'] = array(
|
| 356 |
'#type' => 'fieldset',
|
| 357 |
'#title' => t('Video Display Settings'),
|
| 358 |
'#description' => t('These settings control how this video is displayed in its full size, which defaults to @widthx@height.', array('@width' => $width, '@height' => $height)),
|
| 359 |
'#collapsible' => true,
|
| 360 |
'#collapsed' => false,
|
| 361 |
);
|
| 362 |
$form['video']['video_width'] = array(
|
| 363 |
'#type' => 'textfield',
|
| 364 |
'#title' => t('Video display width'),
|
| 365 |
'#default_value' => $widget['video_width'] ? $widget['video_width'] : $width,
|
| 366 |
'#required' => true,
|
| 367 |
'#description' => t('The width of the video. It defaults to @width.', array('@width' => $width)),
|
| 368 |
);
|
| 369 |
$form['video']['video_height'] = array(
|
| 370 |
'#type' => 'textfield',
|
| 371 |
'#title' => t('Video display height'),
|
| 372 |
'#default_value' => $widget['video_height'] ? $widget['video_height'] : $height,
|
| 373 |
'#required' => true,
|
| 374 |
'#description' => t('The height of the video. It defaults to @height.', array('@height' => $height)),
|
| 375 |
);
|
| 376 |
$form['video']['video_autoplay'] = array(
|
| 377 |
'#type' => 'checkbox',
|
| 378 |
'#title' => t('Autoplay'),
|
| 379 |
'#default_value' => $widget['video_autoplay'] ? $widget['video_autoplay'] : false,
|
| 380 |
'#description' => t('If supported by the provider, checking this box will cause the video to automatically begin after the video loads when in its full size.'),
|
| 381 |
);
|
| 382 |
|
| 383 |
$width = variable_get('video_cck_default_preview_width', VIDEO_CCK_DEFAULT_PREVIEW_WIDTH);
|
| 384 |
$height = variable_get('video_cck_default_preview_height', VIDEO_CCK_DEFAULT_PREVIEW_HEIGHT);
|
| 385 |
$form['preview'] = array(
|
| 386 |
'#type' => 'fieldset',
|
| 387 |
'#title' => t('Video Preview Settings'),
|
| 388 |
'#description' => t('These settings control how this video is displayed in its preview size, which defaults to @widthx@height.', array('@width' => $width, '@height' => $height)),
|
| 389 |
'#collapsible' => true,
|
| 390 |
'#collapsed' => false,
|
| 391 |
);
|
| 392 |
$form['preview']['preview_width'] = array(
|
| 393 |
'#type' => 'textfield',
|
| 394 |
'#title' => t('Video preview width'),
|
| 395 |
'#default_value' => $widget['preview_width'] ? $widget['preview_width'] : variable_get('video_cck_default_preview_width', VIDEO_CCK_DEFAULT_PREVIEW_WIDTH),
|
| 396 |
'#required' => true,
|
| 397 |
'#description' => t('The width of the preview video. It defaults to @width.', array('@width' => $width)),
|
| 398 |
);
|
| 399 |
$form['preview']['preview_height'] = array(
|
| 400 |
'#type' => 'textfield',
|
| 401 |
'#title' => t('Video preview height'),
|
| 402 |
'#default_value' => $widget['preview_height'] ? $widget['preview_height'] : variable_get('video_cck_default_preview_height', VIDEO_CCK_DEFAULT_PREVIEW_HEIGHT),
|
| 403 |
'#required' => true,
|
| 404 |
'#description' => t('The height of the preview video. It defaults to @height.', array('@height' => $height)),
|
| 405 |
);
|
| 406 |
$form['preview']['preview_autoplay'] = array(
|
| 407 |
'#type' => 'checkbox',
|
| 408 |
'#title' => t('Autoplay'),
|
| 409 |
'#default_value' => $widget['preview_autoplay'] ? $widget['preview_autoplay'] : false,
|
| 410 |
'#description' => t('If supported by the provider, checking this box will cause the video to automatically begin after the video loads when in its preview size.'),
|
| 411 |
);
|
| 412 |
|
| 413 |
$width = variable_get('video_cck_default_thumbnail_width', VIDEO_CCK_DEFAULT_THUMBNAIL_WIDTH);
|
| 414 |
$height = variable_get('video_cck_default_thumbnail_height', VIDEO_CCK_DEFAULT_THUMBNAIL_HEIGHT);
|
| 415 |
$form['tn'] = array(
|
| 416 |
'#type' => 'fieldset',
|
| 417 |
'#title' => t('Thumbnail'),
|
| 418 |
'#description' => t('When displayed as a thumbnail, these settings control the image returned. Note that not all 3rd party video content providers offer thumbnails, and others may require an API key or other requirements. More information from the !settings. The default size for thumbnails is @widthx@height.', array('!settings' => l(t('settings page'), 'admin/content/video_cck'), '@width' => $width, '@height' => $height)),
|
| 419 |
'#collapsible' => true,
|
| 420 |
'#collapsed' => false,
|
| 421 |
);
|
| 422 |
$form['tn']['thumbnail_width'] = array(
|
| 423 |
'#type' => 'textfield',
|
| 424 |
'#title' => t('Video width'),
|
| 425 |
'#default_value' => $widget['thumbnail_width'] ? $widget['thumbnail_width'] : variable_get('video_cck_default_thumbnail_width', VIDEO_CCK_DEFAULT_THUMBNAIL_WIDTH),
|
| 426 |
'#required' => true,
|
| 427 |
'#description' => t('The width of the thumbnail. It defaults to @width.', array('@width' => $width)),
|
| 428 |
);
|
| 429 |
$form['tn']['thumbnail_height'] = array(
|
| 430 |
'#type' => 'textfield',
|
| 431 |
'#title' => t('Thumbnail height'),
|
| 432 |
'#default_value' => $widget['thumbnail_height'] ? $widget['thumbnail_height'] : variable_get('video_cck_default_thumbnail_height', VIDEO_CCK_DEFAULT_THUMBNAIL_HEIGHT),
|
| 433 |
'#required' => true,
|
| 434 |
'#description' => t('The height of the thumbnail. It defaults to @height.', array('@height' => $height)),
|
| 435 |
);
|
| 436 |
}
|
| 437 |
return $form;
|
| 438 |
|
| 439 |
case 'validate':
|
| 440 |
if ($widget['type'] == 'video_cck_textfields') {
|
| 441 |
if (!is_numeric($widget['video_width']) || intval($widget['video_width']) != $widget['video_width'] || $widget['video_width'] < 1) {
|
| 442 |
form_set_error('video_width', t('"Video width" must be a positive integer.'));
|
| 443 |
}
|
| 444 |
if (!is_numeric($widget['video_height']) || intval($widget['video_height']) != $widget['video_height'] || $widget['video_height'] < 1) {
|
| 445 |
form_set_error('video_height', t('"Video height" must be a positive integer.'));
|
| 446 |
}
|
| 447 |
if (!is_numeric($widget['preview_width']) || intval($widget['preview_width']) != $widget['preview_width'] || $widget['preview_width'] < 1) {
|
| 448 |
form_set_error('preview_width', t('"Preview width" must be a positive integer.'));
|
| 449 |
}
|
| 450 |
if (!is_numeric($widget['preview_height']) || intval($widget['preview_height']) != $widget['preview_height'] || $widget['preview_height'] < 1) {
|
| 451 |
form_set_error('preview_height', t('"Preview height" must be a positive integer.'));
|
| 452 |
}
|
| 453 |
if (!is_numeric($widget['thumbnail_width']) || intval($widget['thumbnail_width']) != $widget['thumbnail_width'] || $widget['thumbnail_width'] < 1) {
|
| 454 |
form_set_error('thumbnail_width', t('"Thumbnail width" must be a positive integer.'));
|
| 455 |
}
|
| 456 |
if (!is_numeric($widget['thumbnail_height']) || intval($widget['thumbnail_height']) != $widget['thumbnail_height'] || $widget['thumbnail_height'] < 1) {
|
| 457 |
form_set_error('thumbnail_height', t('"Thumbnail height" must be a positive integer.'));
|
| 458 |
}
|
| 459 |
}
|
| 460 |
break;
|
| 461 |
|
| 462 |
case 'save':
|
| 463 |
if ($widget['widget']['type'] == 'video_cck_textfields') {
|
| 464 |
return array('video_width', 'video_height', 'video_autoplay', 'preview_width', 'preview_height', 'preview_autoplay', 'thumbnail_width', 'thumbnail_height', 'providers', );
|
| 465 |
}
|
| 466 |
break;
|
| 467 |
}
|
| 468 |
}
|
| 469 |
|
| 470 |
/** Implementation of hook_widget **/
|
| 471 |
|
| 472 |
function video_cck_widget($op, &$node, $field, &$node_field) {
|
| 473 |
switch ($op) {
|
| 474 |
case 'form':
|
| 475 |
$form = array();
|
| 476 |
|
| 477 |
$form[$field['field_name']] = array('#tree' => TRUE);
|
| 478 |
$textfield = 'embed';
|
| 479 |
$field['required'] = FALSE;
|
| 480 |
$providers = video_cck_allowed_providers($field);
|
| 481 |
$urls = array();
|
| 482 |
foreach ($providers as $provider) {
|
| 483 |
// don't check providers not allowed
|
| 484 |
if (variable_get('video_cck_allow_' . $provider->name, true)) {
|
| 485 |
$info = video_cck_include_invoke($provider->name, 'info');
|
| 486 |
$urls[] = l($info['name'], $info['url'], array('target' => '_blank'));
|
| 487 |
}
|
| 488 |
}
|
| 489 |
$textfield_title = t($field['widget']['label']);
|
| 490 |
$textfield_description = t('Enter the Video\'s URL or Embed Code here. For instance, you might enter the URL from the address bar of a video at Google Videos, or the code from the Embed bar provided by YouTube. The video will be parsed and displayed appropriately from this.');
|
| 491 |
$textfield_description .= '<br />' . t('The following services are provided: !urls', array('!urls' => implode(', ', $urls)));
|
| 492 |
|
| 493 |
if ($field['multiple']) {
|
| 494 |
$form[$field['field_name']]['#type'] = 'fieldset';
|
| 495 |
$form[$field['field_name']]['#title'] = t($field['widget']['label']);
|
| 496 |
$delta = 0;
|
| 497 |
foreach ($node_field as $data) {
|
| 498 |
if (isset($data[$textfield])) {
|
| 499 |
$form[$field['field_name']][$delta][$textfield] = array(
|
| 500 |
'#type' => 'textfield',
|
| 501 |
'#title' => $textfield_title,
|
| 502 |
'#description' => $textfield_description,
|
| 503 |
'#default_value' => $data[$textfield],
|
| 504 |
'#required' => ($delta == 0) ? $field['required'] : FALSE,
|
| 505 |
'#maxlength' => 1024,
|
| 506 |
);
|
| 507 |
$form[$field['field_name']][$delta]['value'] = array(
|
| 508 |
'#type' => 'value',
|
| 509 |
'#value' => $data['value'],
|
| 510 |
);
|
| 511 |
if ($data['value']) {
|
| 512 |
$info = video_cck_include_invoke($data['provider'], 'info');
|
| 513 |
$form[$field['field_name']][$delta]['markup_value'] = array(
|
| 514 |
'#type' => 'item',
|
| 515 |
'#value' => t('(@provider Video ID: !value)', array('@provider' => $info['name'], '!value' => l($data['value'], video_cck_include_invoke($info['provider'], 'video_link', $data['value']), array('target' => '_blank')))),
|
| 516 |
);
|
| 517 |
}
|
| 518 |
$delta++;
|
| 519 |
}
|
| 520 |
}
|
| 521 |
foreach (range($delta, $delta + 2) as $delta) {
|
| 522 |
$form[$field['field_name']][$delta][$textfield] = array(
|
| 523 |
'#type' => 'textfield',
|
| 524 |
'#title' => $textfield_title,
|
| 525 |
'#description' => $textfield_description,
|
| 526 |
'#default_value' => '',
|
| 527 |
'#required' => ($delta == 0) ? $field['required'] : FALSE,
|
| 528 |
'#maxlength' => 1024,
|
| 529 |
);
|
| 530 |
$form[$field['field_name']][$delta]['value'] = array(
|
| 531 |
'#type' => 'value',
|
| 532 |
'#title' => '',
|
| 533 |
);
|
| 534 |
}
|
| 535 |
}
|
| 536 |
else {
|
| 537 |
$form[$field['field_name']][0][$textfield] = array(
|
| 538 |
'#type' => 'textfield',
|
| 539 |
'#title' => $textfield_title, //t($field['widget']['label']),
|
| 540 |
'#description' => $textfield_description,
|
| 541 |
'#default_value' => isset($node_field[0][$textfield]) ? $node_field[0][$textfield] : '',
|
| 542 |
'#required' => $field['required'],
|
| 543 |
'#maxlength' => 1024,
|
| 544 |
);
|
| 545 |
if ($textfield == 'embed') {
|
| 546 |
$value = isset($node_field[0]['value']) ? $node_field[0]['value'] : '';
|
| 547 |
$form[$field['field_name']][0]['value'] = array(
|
| 548 |
'#type' => 'value',
|
| 549 |
'#value' => $value,
|
| 550 |
);
|
| 551 |
if ($value) {
|
| 552 |
$info = video_cck_include_invoke($node_field[0]['provider'], 'info');
|
| 553 |
$form[$field['field_name']][0]['value_markup'] = array(
|
| 554 |
'#type' => 'item',
|
| 555 |
'#value' => t('(@provider Video ID: !value)', array('@provider' => $info['provider'], '!value' => l($value, video_cck_include_invoke($info['provider'], 'video_link', $value), array('target' => '_blank')))),
|
| 556 |
);
|
| 557 |
}
|
| 558 |
}
|
| 559 |
}
|
| 560 |
return $form;
|
| 561 |
default:
|
| 562 |
break;
|
| 563 |
}
|
| 564 |
}
|
| 565 |
|
| 566 |
/**
|
| 567 |
* When an include file requires to read an xml to receive information, such as for thumbnails,
|
| 568 |
* this script can be used to request the xml and return it as an array.
|
| 569 |
* Note that this is a modified function from the flickr.module, made to handle this type of
|
| 570 |
* call more generically. also, i suspect it could be done easier (and more quickly) in php 5.
|
| 571 |
* @param $provider
|
| 572 |
* the string of the third party provider, such as 'youtube' or 'google'
|
| 573 |
* @param $url
|
| 574 |
* the url for the xml request
|
| 575 |
* @param $args
|
| 576 |
* an array of args to pass to the xml url
|
| 577 |
* @param $cacheable
|
| 578 |
* optional; if true, the result of this xml request will be cached. good to play nice w/
|
| 579 |
* the third party folks so they don't stop providing service to your site...
|
| 580 |
* @return
|
| 581 |
* the xml results returned as an array
|
| 582 |
*/
|
| 583 |
function video_cck_request_xml($provider, $url, $args = array(), $cacheable = true) {
|
| 584 |
ksort($args);
|
| 585 |
|
| 586 |
// build an argument hash that we'll use for the cache id and api signing
|
| 587 |
$arghash = $provider . ':';
|
| 588 |
foreach($args as $k => $v){
|
| 589 |
$arghash .= $k . $v;
|
| 590 |
}
|
| 591 |
|
| 592 |
// build the url
|
| 593 |
foreach ($args as $k => $v){
|
| 594 |
$encoded_params[] = urlencode($k).'='.urlencode($v);
|
| 595 |
}
|
| 596 |
if (!empty($encoded_params)) {
|
| 597 |
$url .= '?'. implode('&', $encoded_params);
|
| 598 |
}
|
| 599 |
|
| 600 |
// some providers, such as bliptv, actually change the url, and not just the queries.
|
| 601 |
$arghash .= $url;
|
| 602 |
|
| 603 |
// if it's a cachable request, try to load a cached value
|
| 604 |
if ($cacheable) {
|
| 605 |
if ($cache = cache_get($arghash, 'cache')) {
|
| 606 |
return unserialize($cache->data);
|
| 607 |
}
|
| 608 |
}
|
| 609 |
|
| 610 |
// connect and fetch a value
|
| 611 |
$result = drupal_http_request($url);
|
| 612 |
|
| 613 |
if ($result->code == 200) {
|
| 614 |
$parser = drupal_xml_parser_create($result->data);
|
| 615 |
$vals = array();
|
| 616 |
$index = array();
|
| 617 |
xml_parse_into_struct($parser, $result->data, $vals, $index);
|
| 618 |
xml_parser_free($parser);
|
| 619 |
|
| 620 |
$params = array();
|
| 621 |
$level = array();
|
| 622 |
$start_level = 1;
|
| 623 |
foreach ($vals as $xml_elem) {
|
| 624 |
if ($xml_elem['type'] == 'open') {
|
| 625 |
if (array_key_exists('attributes',$xml_elem)) {
|
| 626 |
list($level[$xml_elem['level']],$extra) = array_values($xml_elem['attributes']);
|
| 627 |
} else {
|
| 628 |
$level[$xml_elem['level']] = $xml_elem['tag'];
|
| 629 |
}
|
| 630 |
}
|
| 631 |
if ($xml_elem['type'] == 'complete') {
|
| 632 |
$php_stmt = '$params';
|
| 633 |
while($start_level < $xml_elem['level']) {
|
| 634 |
$php_stmt .= '[$level['.$start_level.']]';
|
| 635 |
$start_level++;
|
| 636 |
}
|
| 637 |
$php_stmt .= '[$xml_elem[\'tag\']][] = $xml_elem[\'value\'];' . $php_stmt . '[$xml_elem[\'tag\']][] = $xml_elem[\'attributes\'];';
|
| 638 |
eval($php_stmt);
|
| 639 |
$start_level--;
|
| 640 |
}
|
| 641 |
}
|
| 642 |
|
| 643 |
// save a cacheable result for future use
|
| 644 |
if ($cacheable) {
|
| 645 |
cache_set($arghash, 'cache', serialize($params), time() + 3600);
|
| 646 |
}
|
| 647 |
return $params;
|
| 648 |
}
|
| 649 |
return array();
|
| 650 |
}
|
| 651 |
|
| 652 |
/**
|
| 653 |
* Return an array of installed .inc files and/or loads them upon request.
|
| 654 |
* This routine is modeled after drupal_system_listing() (and also depends on it).
|
| 655 |
* It's major difference, however, is that it loads .inc files by default.
|
| 656 |
*
|
| 657 |
* @param $provider
|
| 658 |
* Optional; name of the passed $provider to find (e.g. "youtube", "google", etc.).
|
| 659 |
* @param $load
|
| 660 |
* Defaults to true; whether to include matching files into memory.
|
| 661 |
* @return
|
| 662 |
* An array of file objects optionally matching $provider.
|
| 663 |
*/
|
| 664 |
function video_cck_system_list($provider = NULL, $load = true) {
|
| 665 |
$files = drupal_system_listing("$provider\.inc", drupal_get_path('module', 'video_cck')."/providers", 'name', 0);
|
| 666 |
|
| 667 |
ksort($files);
|
| 668 |
|
| 669 |
if ($load) {
|
| 670 |
foreach ($files as $file) {
|
| 671 |
video_cck_include_list($file);
|
| 672 |
}
|
| 673 |
}
|
| 674 |
|
| 675 |
return $files;
|
| 676 |
}
|
| 677 |
|
| 678 |
/**
|
| 679 |
* Maintains a list of all loaded include files.
|
| 680 |
*
|
| 681 |
* @param $file
|
| 682 |
* Optional; a file object (from video_cck_system_list()) to be included.
|
| 683 |
* @return
|
| 684 |
* An array of all loaded includes (without the .inc extension).
|
| 685 |
*/
|
| 686 |
function video_cck_include_list($file = NULL) {
|
| 687 |
static $list = array();
|
| 688 |
|
| 689 |
// if (!$list) { $list = array(); }
|
| 690 |
|
| 691 |
if ($file && !isset($list[$file->name])) {
|
| 692 |
include_once('./'.$file->filename);
|
| 693 |
$list[$file->name] = $file->name;
|
| 694 |
}
|
| 695 |
|
| 696 |
return $list;
|
| 697 |
}
|
| 698 |
|
| 699 |
/**
|
| 700 |
* Determine whether an include implements a hook, cf. module_hook.
|
| 701 |
*
|
| 702 |
* @param $provider
|
| 703 |
* The name of the provider file (without the .inc extension), such as 'youtube' or 'google'.
|
| 704 |
* @param $hook
|
| 705 |
* The name of the hook (e.g. "thumbnail", "settings", etc.).
|
| 706 |
* @return
|
| 707 |
* TRUE if the provider is loaded and the hook is implemented.
|
| 708 |
*/
|
| 709 |
function video_cck_include_hook($provider, $hook) {
|
| 710 |
return function_exists('video_cck_' . $provider .'_'. $hook);
|
| 711 |
}
|
| 712 |
|
| 713 |
/**
|
| 714 |
* Invoke hook in a particular include. If the include does not implement
|
| 715 |
* the hook, a default value is returned.
|
| 716 |
*
|
| 717 |
* @param $provider
|
| 718 |
* The name of the provider (without the .inc extension).
|
| 719 |
* @param $hook
|
| 720 |
* The name of the hook (e.g. "settings", "thumbnail", etc.).
|
| 721 |
* @param ...
|
| 722 |
* Arguments to pass to the hook implementation.
|
| 723 |
* @return
|
| 724 |
* The return value of the hook implementation.
|
| 725 |
*/
|
| 726 |
function video_cck_include_invoke() {
|
| 727 |
$args = func_get_args();
|
| 728 |
$provider = array_shift($args);
|
| 729 |
$hook = array_shift($args);
|
| 730 |
$function = 'video_cck_' . $provider . '_' . $hook;
|
| 731 |
video_cck_system_list($provider);
|
| 732 |
return video_cck_include_hook($provider, $hook) ? call_user_func_array($function, $args) : NULL;
|
| 733 |
}
|
| 734 |
|
| 735 |
function video_cck_embed_form($field, $item, $formatter, $node) {
|
| 736 |
$embed = $item['value'];
|
| 737 |
$width = $field['widget']['video_width'];
|
| 738 |
$height = $field['widget']['video_height'];
|
| 739 |
$autoplay = $field['widget']['video_autoplay'];
|
| 740 |
$text = video_cck_include_invoke($item['provider'], 'video', $embed, $width, $height, $field, $item, $autoplay);
|
| 741 |
$form = array();
|
| 742 |
$form['video_cck_embed'] = array(
|
| 743 |
'#type' => 'textarea',
|
| 744 |
'#title' => t('Embed Code'),
|
| 745 |
'#description' => t('To embed this video on your own site, simply copy and paste the html code from this text area.'),
|
| 746 |
'#default_value' => $text,
|
| 747 |
);
|
| 748 |
return $form;
|
| 749 |
}
|
| 750 |
|
| 751 |
function theme_video_cck_embed($field, $item, $formatter, $node) {
|
| 752 |
if ($item['value'] && $item['provider']) {
|
| 753 |
$output = drupal_get_form('video_cck_embed_form', $field, $item, $formatter, $node);
|
| 754 |
}
|
| 755 |
return $output;
|
| 756 |
}
|
| 757 |
|
| 758 |
function theme_video_cck_thumbnail($field, $item, $formatter, $node) {
|
| 759 |
if ($item['value'] && $item['provider']) {
|
| 760 |
$width = $field['widget']['thumbnail_width'] ? $field['widget']['thumbnail_width'] : variable_get('video_cck_default_thumbnail_width', VIDEO_CCK_DEFAULT_THUMBNAIL_WIDTH);
|
| 761 |
$height = $field['widget']['thumbnail_height'] ? $field['widget']['thumbnail_height'] : variable_get('video_cck_default_thumbnail_height', VIDEO_CCK_DEFAULT_THUMBNAIL_HEIGHT);
|
| 762 |
$thumbnail_url = video_cck_include_invoke($item['provider'], 'thumbnail', $field, $item, $formatter, $node, $width, $height);
|
| 763 |
if ($thumbnail_url) {
|
| 764 |
$output = l('<img src="' . $thumbnail_url . '" width="' . $width . '" height="' . $height . '" alt="' . t('See Video') . '" title="' . t('See Video') . '" />', 'node/' . $node->nid, array(), NULL, NULL, false, true);
|
| 765 |
}
|
| 766 |
else {
|
| 767 |
$output .= l(t('See Video'), 'node/' . $node->nid);
|
| 768 |
}
|
| 769 |
}
|
| 770 |
return $output;
|
| 771 |
}
|
| 772 |
|
| 773 |
function theme_video_cck_video($field, $item, $formatter, $node) {
|
| 774 |
if ($item['value'] && $item['provider']) {
|
| 775 |
$embed = $item['value'];
|
| 776 |
$width = $field['widget']['video_width'] ? $field['widget']['video_width'] : variable_get('video_cck_default_video_width', VIDEO_CCK_DEFAULT_VIDEO_WIDTH);;
|
| 777 |
$height = $field['widget']['video_height'] ? $field['widget']['video_height'] : variable_get('video_cck_default_video_height', VIDEO_CCK_DEFAULT_VIDEO_HEIGHT);;
|
| 778 |
$autoplay = $field['widget']['video_autoplay'];
|
| 779 |
$output = video_cck_include_invoke($item['provider'], 'video', $embed, $width, $height, $field, $item, $autoplay);
|
| 780 |
}
|
| 781 |
return $output;
|
| 782 |
}
|
| 783 |
|
| 784 |
function theme_video_cck_preview($field, $item, $formatter, $node) {
|
| 785 |
if ($item['value'] && $item['provider']) {
|
| 786 |
$embed = $item['value'];
|
| 787 |
$width = $field['widget']['preview_width'] ? $field['widget']['preview_width'] : variable_get('video_cck_default_preview_width', VIDEO_CCK_DEFAULT_PREVIEW_WIDTH);;
|
| 788 |
$height = $field['widget']['preview_height'] ? $field['widget']['preview_height'] : variable_get('video_cck_default_preview_height', VIDEO_CCK_DEFAULT_PREVIEW_HEIGHT);;
|
| 789 |
$autoplay = $field['widget']['preview_autoplay'];
|
| 790 |
$output = video_cck_include_invoke($item['provider'], 'preview', $embed, $width, $height, $field, $item, $autoplay);
|
| 791 |
}
|
| 792 |
return $output;
|
| 793 |
}
|