youtube.inc in YouTube Field 7
YouTube field helper functions.
File
youtube.incView source
<?php
/**
* @file
* YouTube field helper functions.
*/
/**
* Extracts the video_id from the submitted field value.
*
* @param string $input
* The input submitted to the field.
*
* @return string|bool
* Returns the video_id if available, or FALSE if not.
*/
function youtube_get_video_id($input) {
// See README.txt for accepted URL formats.
preg_match("/^(?:http(?:s)?:\\/\\/)?(?:www\\.)?(?:youtu\\.be\\/|youtube\\.com\\/(?:(?:watch)?\\?(?:.*&)?v(?:i)?=|(?:embed|v|vi|user)\\/))([^\\?&\"'<> #]+)/", $input, $matches);
if (!empty($matches[1])) {
$video_id = $matches[1];
return $video_id;
}
return FALSE;
}
/**
* Returns a list of YouTube video size options.
*
* @return array
* An array of options, keyed by machine name with human readable values.
*/
function youtube_size_options() {
return array(
'420x315' => '450px by 315px',
'480x360' => '480px by 360px',
'640x480' => '640px by 480px',
'960x720' => '960px by 720px',
'responsive' => 'responsive (full-width of container)',
'custom' => 'custom',
);
}
/**
* Returns a list of thumbnail link types.
*
* @return array
* An array of link types, keyed by machine name with human readable values.
*/
function youtube_thumbnail_link_types() {
$link_types = array(
'content' => t('Content'),
'youtube' => t('YouTube'),
);
// Allow other modules to add link types.
drupal_alter('youtube_thumbnail_link_types', $link_types);
return $link_types;
}
/**
* Determines the height and width when given a player size.
*
* @param string $size
* (optional) The machine name of the size from youtube_size_options().
* @param string $width
* (optional) The width input for custom dimensions.
* @param string $height
* (optional) The height input for custom dimensions.
*
* @return array
* An array keyed by 'width' and 'height' with the values to use when theming
* the video player.
*/
function youtube_get_dimensions($size = NULL, $width = NULL, $height = NULL) {
$dimensions = array();
if ($size == 'responsive') {
$dimensions['width'] = '100%';
$dimensions['height'] = '100%';
}
elseif ($size == 'custom') {
$dimensions['width'] = strstr($width, '%') ? (int) $width . '%' : (int) $width;
$dimensions['height'] = strstr($height, '%') ? (int) $height . '%' : (int) $height;
}
else {
// Locate the 'x'.
$strpos = strpos($size, 'x');
// Width is the first dimension.
$dimensions['width'] = substr($size, 0, $strpos);
// Height is the second dimension.
$dimensions['height'] = substr($size, $strpos + 1, strlen($size));
}
return $dimensions;
}
/**
* Builds the URI to a given thumbnail or the module's thumbnail directory.
*
* @param string $video_id
* (optional) The video ID to build the thumbnail URI for.
*
* @return string
* If a $video_id was supplied, the URI to that video's thumbnail. Otherwise
* the URI to the module's thumbnail directory.
*/
function youtube_build_thumbnail_uri($video_id = NULL) {
$scheme = file_default_scheme();
$youtube_thumb_dir = variable_get('youtube_thumb_dir', 'youtube');
$youtube_thumb_uri = $scheme . '://' . $youtube_thumb_dir;
if ($video_id) {
return $youtube_thumb_uri . '/' . $video_id . '.jpg';
}
return $youtube_thumb_uri;
}
/**
* Retrieves the thumbnail image for a given video from YouTube.
*
* @param int|null $video_id
* The video ID of the particular YouTube video.
* @param bool $force_small
* (optional) When TRUE, this function should return the standard size image
* regardless of what the youtube_thumb_hires variable is set to. This is used
* should the high resolution image be found to not exist for a particular
* video.
*
* @return bool|object
* Either the Drupal $file object of saved image, or FALSE if the save failed.
*/
function youtube_get_remote_image($video_id = NULL, $force_small = FALSE) {
// This variable is TRUE when higher resolution thumbnails should be saved.
// The only thumbnail resolution higher than the standard 480 is
// 'maxresdefault'. This resolution image is not guaranteed to exist. If
// there's an error retrieving the hi-res image, we try again for small.
$youtube_thumb_hires = variable_get('youtube_thumb_hires', FALSE);
// This boolean is TRUE if we're obtaining a hi-res thumbnail.
$get_hires = $youtube_thumb_hires && !$force_small;
if ($get_hires) {
$src = youtube_build_remote_image_path($video_id, 'maxresdefault');
}
else {
$src = youtube_build_remote_image_path($video_id);
}
// Download file and save it as managed Drupal file.
$image = drupal_http_request($src);
if ($image->code != 200) {
// Silently retry for small image if hi-res did not exist, otherwise log an
// error and return FALSE.
if ($get_hires) {
return youtube_get_remote_image($video_id, TRUE);
}
watchdog('youtube', 'HTTP request for video ID %id failed (error code: %err).', array(
'%id' => $video_id,
'%err' => $image->code,
), WATCHDOG_ERROR);
return FALSE;
}
// Set the path to thumbnails, and make sure it's usable.
$youtube_thumb_uri = youtube_build_thumbnail_uri();
if (!file_prepare_directory($youtube_thumb_uri, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS)) {
watchdog('youtube', 'Failed to create YouTube thumbnail directory: %dir', array(
'%dir' => $youtube_thumb_uri,
), WATCHDOG_ERROR);
return FALSE;
}
$destination = youtube_build_thumbnail_uri($video_id);
// Save the thumbnail and add to Drupal managed files.
$file = file_save_data($image->data, $destination, FILE_EXISTS_REPLACE);
if (!$file) {
watchdog('youtube', 'Unable to save youtube thumbnail to filesystem for video %id', array(
'%id' => $video_id,
), WATCHDOG_ERROR);
}
return $file;
}
/**
* Submit callback; delete all existing thumbnail image files.
*
* @see youtube_settings_form()
*/
function youtube_thumb_delete_all($form, &$form_state) {
$youtube_thumb_uri = youtube_build_thumbnail_uri();
if (!file_prepare_directory($youtube_thumb_uri)) {
return drupal_set_message(t('No files deleted.'));
}
$files = file_scan_directory($youtube_thumb_uri, '/^.*\\.(jpg|png)$/');
$legacy_files = FALSE;
foreach ($files as $raw_file) {
// Check if file is being managed by Drupal.
$uri = $youtube_thumb_uri . '/' . $raw_file->filename;
$managed_file = db_select('file_managed', 'fm')
->fields('fm')
->condition('uri', '%' . $uri, 'LIKE')
->execute()
->fetchAssoc();
if (!$managed_file) {
// Old files exist before module used managed files, notify user.
$legacy_files = file_unmanaged_delete($raw_file->uri);
}
else {
$file = file_load($managed_file['fid']);
// file_delete() invokes hooks to refresh associated image files.
file_delete($file);
}
}
if ($legacy_files) {
drupal_set_message(t('Note: Some unmanaged files from an older version of the module were deleted. Their associated image style derivatives were not deleted. <a href="@imagestyleflush">Image style flush</a> or `drush image-flush` can be used for that. New thumbnails will be managed files and will not have this issue.', array(
'@imagestyleflush' => 'https://www.drupal.org/project/imagestyleflush',
)));
}
}
/**
* Get YouTube image path by building correctly formed URL.
*
* @param string|null $video_id
* (optional) The ID of the video to grab the thumbnail from.
* @param string|null $version
* (optional) Which version of the thumbnail to grab.
*
* @return string|null
* The youtube.com image path to the specified version/video.
*/
function youtube_build_remote_image_path($video_id = NULL, $version = '0') {
// The different versions of the image made available by YouTube.
// http://stackoverflow.com/questions/2068344/how-to-get-thumbnail-of-youtube-video-link-using-youtube-api
$versions = array(
'0',
'hqdefault',
'mqdefault',
'maxresdefault',
'default',
'1',
'2',
'3',
);
if (!$video_id || !in_array($version, $versions)) {
return;
}
$version_path = 'http://img.youtube.com/vi/' . $video_id . '/' . $version . '.jpg';
return url($version_path);
}
/**
* Implements hook_feeds_processor_targets_alter().
*
* Adds a target option for YouTube fields to Feeds mapping options.
*/
function youtube_feeds_processor_targets_alter(&$targets, $entity_type, $bundle_name) {
foreach (field_info_instances($entity_type, $bundle_name) as $name => $instance) {
$info = field_info_field($name);
if (in_array($info['type'], array(
'youtube',
))) {
$targets[$name] = array(
'name' => check_plain($instance['label']),
'callback' => 'youtube_set_target',
'description' => t('The @label field of the node.', array(
'@label' => $instance['label'],
)),
);
}
}
}
/**
* Callback to set the Feeds target for a YouTube field.
*
* @param FeedsSource $source
* Field mapper source settings.
* @param object $entity
* An entity object, for instance a node object.
* @param string $target
* A string identifying the target on the node.
* @param string|array $value
* The value to populate the target with.
* @param array $mapping
* Associative array of the mapping settings from the per mapping
* configuration form.
*/
function youtube_set_target(FeedsSource $source, $entity, $target, $value, array $mapping) {
if (empty($value)) {
return;
}
if (!is_array($value)) {
$value = array(
$value,
);
}
$info = field_info_field($target);
$field = isset($entity->{$target}) ? $entity->{$target} : array(
LANGUAGE_NONE => array(),
);
// Allow for mappings to a multi-value field on the same target.
$delta = count($field[LANGUAGE_NONE]);
foreach ($value as $v) {
if ($info['cardinality'] == $delta) {
break;
}
if (is_object($v) && $v instanceof FeedsElement) {
$v = $v
->getValue();
}
if (is_scalar($v)) {
$video_id = youtube_get_video_id($v);
if ($video_id) {
$entity->{$target}[LANGUAGE_NONE][$delta] = array(
'input' => $v,
'video_id' => $video_id,
);
$delta++;
}
}
}
}
/**
* Implements hook_token_info_alter().
*
* Alters and adds tokens for each youtube field.
*/
function youtube_token_info_alter(&$data) {
// Get all youtube fields. Gather entity_type and bundle information.
$fields = field_info_fields();
$youtube_fields = array();
foreach ($fields as $name => $field) {
if ($field['type'] == 'youtube') {
foreach ($field['bundles'] as $type => $entity_type) {
foreach ($entity_type as $bundle) {
$youtube_fields[] = array(
'entity_type' => $type,
'bundle' => $bundle,
'field_name' => $name,
);
}
}
}
}
foreach ($youtube_fields as $field) {
$field_info = field_info_instance($field['entity_type'], $field['field_name'], $field['bundle']);
$field_label = $field_info['label'];
// Modify the default field token.
$data['tokens'][$field['entity_type']][$field['field_name']] = array(
'name' => $field_label . t(": Default"),
'description' => t("The YouTube video field value's Default (or Token if exists) view mode output."),
);
// Add two new tokens.
$data['tokens'][$field['entity_type']][$field['field_name'] . '__youtube_video_url'] = array(
'name' => $field_label . t(": Video URL"),
'description' => t("The YouTube video field value's youtube.com URL."),
);
$data['tokens'][$field['entity_type']][$field['field_name'] . '__youtube_image_url'] = array(
'name' => $field_label . t(": Image URL"),
'description' => t("The YouTube video field value's local image URL."),
);
}
}
/**
* Implements hook_tokens().
*
* @see youtube_tokens_info_alter()
*/
function youtube_tokens($type, $tokens, array $data = array(), array $options = array()) {
global $base_url;
global $base_path;
$url_options = array(
'absolute' => TRUE,
);
if (isset($options['language'])) {
$url_options['language'] = $options['language'];
$language_code = $options['language']->language;
}
else {
$language_code = NULL;
}
$sanitize = !empty($options['sanitize']);
$replacements = array();
if ($type == 'node' && !empty($data['node'])) {
$node = $data['node'];
foreach ($tokens as $name => $original) {
if (!strpos($name, '__youtube_')) {
// This isn't a YouTube Field token!
continue;
}
$token_pieces = explode('__', $name);
if (count($token_pieces) != 2) {
continue;
}
$field_name = $token_pieces[0];
$token_name = $token_pieces[1];
switch ($token_name) {
case 'youtube_video_url':
$replacements[$original] = '';
if ($field_value = field_get_items('node', $node, $field_name)) {
$replacements[$original] = 'http://www.youtube.com/watch?v=' . $field_value[0]['video_id'];
}
break;
case 'youtube_image_url':
$replacements[$original] = '';
if ($field_value = field_get_items('node', $node, $field_name)) {
$video_id = $field_value[0]['video_id'];
$file_uri = youtube_build_thumbnail_uri($video_id);
$file_url = file_create_url($file_uri);
if (file_exists($file_uri) || youtube_get_remote_image($video_id)) {
$replacements[$original] = $file_url;
if ($style_name = variable_get('youtube_thumb_token_image_style', NULL)) {
$derivative_uri = image_style_path($style_name, $file_uri);
if (!file_exists($derivative_uri)) {
$image_style = image_style_load($style_name);
image_style_create_derivative($image_style, $file_uri, $derivative_uri);
}
$replacements[$original] = file_create_url($derivative_uri);
}
}
}
break;
}
}
}
return $replacements;
}
Functions
Name | Description |
---|---|
youtube_build_remote_image_path | Get YouTube image path by building correctly formed URL. |
youtube_build_thumbnail_uri | Builds the URI to a given thumbnail or the module's thumbnail directory. |
youtube_feeds_processor_targets_alter | Implements hook_feeds_processor_targets_alter(). |
youtube_get_dimensions | Determines the height and width when given a player size. |
youtube_get_remote_image | Retrieves the thumbnail image for a given video from YouTube. |
youtube_get_video_id | Extracts the video_id from the submitted field value. |
youtube_set_target | Callback to set the Feeds target for a YouTube field. |
youtube_size_options | Returns a list of YouTube video size options. |
youtube_thumbnail_link_types | Returns a list of thumbnail link types. |
youtube_thumb_delete_all | Submit callback; delete all existing thumbnail image files. |
youtube_tokens | Implements hook_tokens(). |
youtube_token_info_alter | Implements hook_token_info_alter(). |