t('YouTube'),
);
return $info;
}
/**
* Implements hook_stream_wrappers().
*/
function media_youtube_stream_wrappers() {
return array(
'youtube' => array(
'name' => t('YouTube videos'),
'class' => 'MediaYouTubeStreamWrapper',
'description' => t('Videos provided by YouTube.'),
'type' => STREAM_WRAPPERS_READ_VISIBLE,
),
);
}
/**
* Implements hook_theme().
*/
function media_youtube_theme($existing, $type, $theme, $path) {
return array(
'media_youtube_video' => array(
'variables' => array('uri' => NULL, 'options' => array()),
'file' => 'media_youtube.theme.inc',
'path' => $path . '/themes',
'template' => 'media-youtube-video',
),
);
}
/**
* Implements hook_media_parse().
*
* @todo This hook should be deprecated. Refactor Media module to not call it
* any more, since media_internet should be able to automatically route to the
* appropriate handler.
*/
function media_youtube_media_parse($embed_code) {
$handler = new MediaInternetYouTubeHandler($embed_code);
return $handler->parse($embed_code);
}
/**
* Implements hook_file_mimetype_mapping_alter().
*
* Register the video/youtube mimetype.
*/
function media_youtube_file_mimetype_mapping_alter(&$mapping) {
$mapping['mimetypes'][] = 'video/youtube';
}
/**
* YouTube search tab for the Media browser.
*/
/**
* Implements hook_media_browser_plugin_info().
*
* Commented out for release versions, active in dev versions. To enable the
* YouTube media browser tab, uncomment this function.
*/
function media_youtube_media_browser_plugin_info() {
$info['youtube'] = array(
'title' => t('YouTube'),
'class' => 'MediaYouTubeBrowser',
);
return $info;
}
/**
* Provides a form for adding media items from YouTube search.
*/
function media_youtube_add($form, &$form_state = array()) {
module_load_include('inc', 'media', 'includes/media.browser');
// Our search term can come from the form, or from the pager.
$term = isset($form_state['input']['search']) ? $form_state['input']['search'] : (isset($_GET['search']) ? $_GET['search'] : '');
$form['search'] = array(
'#type' => 'textfield',
'#title' => t('Search'),
'#description' => t('Input a phrase or tags to search.'),
'#default_value' => $term,
);
$form['apply'] = array(
'#type' => 'button',
'#value' => t('Apply'),
);
// This is our half-assed pager.
$page = isset($_GET['page-yt']) ? $_GET['page-yt'] : 0;
if (isset($form_state['input']['search'])) {
// Reset the pager when we press apply.
$page = 0;
}
if (!empty($term)) {
$search = media_youtube_video_search(array('q' => $term, 'max-results' => 12, 'start-index' => $page * 12 + 1));
}
$form['videos']['#prefix'] = '
';
$empty = FALSE;
$files = array();
if (!isset($search['entry'])) {
$empty = TRUE;
}
else {
foreach ($search['entry'] as $video) {
try {
$uri = media_parse_to_uri($video['link'][0]['@attributes']['href']);
}
catch (Exception $e) {
// Ignore invalid videos.
continue;
}
// Create a temporary file object for our retrieved video.
$file = file_uri_to_object($uri);
$file->type = 'video';
if (!isset($file->fid)) {
$file->fid = 0;
}
media_browser_build_media_item($file);
$file->preview = l($file->preview, 'media/browser', array(
'html' => TRUE,
'attributes' => array(
'data-uri' => $uri,
),
'query' => array('render' => 'media-popup', 'uri' => $uri),
));
$form['videos'][$uri] = array(
'#markup' => $file->preview,
'#prefix' => '',
'#suffix' => '',
);
$files[$uri] = $file;
}
}
if (!count($files)) {
$empty= TRUE;
}
if ($empty) {
$form['empty'] = array(
'#markup' => '' . t('No videos match your search criteria. Please try again.') . '
',
);
}
$query = $_GET;
if ($term !== '') {
$query['search'] = $term;
}
$dest = $query['q'];
unset($query['q']);
$prev = $next = '';
if ($page) {
$query['page-yt'] = $page - 1;
$prev = l(t('previous'), $dest, array('query' => $query));
}
$query['page-yt'] = $page + 1;
if (!$empty) {
$next = l(t('next'), $dest, array('query' => $query));
}
$form['pager']= array(
'#markup' => $prev . ' ' . $next,
);
$form['submitted-video'] = array(
'#type' => 'hidden',
'#default_value' => FALSE,
);
// Add the files to JS so that they are accessible inside the browser
drupal_add_js(array('media' => array('files' => $files)), 'setting');
// Add media browser javascript and CSS.
drupal_add_js(drupal_get_path('module', 'media_youtube') . '/js/media-youtube.browser.js');
// @TODO: Remove deprecated library js and css. They're removed in Media,
// so let's comment out for now.
// drupal_add_js(drupal_get_path('module', 'media') . '/js/plugins/media.library.js');
// drupal_add_css(drupal_get_path('module', 'media') . '/js/plugins/media.library.css');
$form['actions'] = array('#type' => 'actions');
$form['actions']['submit'] = array(
'#type' => 'submit',
'#value' => t('Submit'),
);
return $form;
}
/**
* Allow stream wrappers to have their chance at validation.
*
* Any module that implements hook_media_parse will have an
* opportunity to validate this.
*
* @see media_parse_to_uri()
*/
function media_youtube_add_validate($form, &$form_state) {
if ($form_state['values']['op'] == t('Apply')) {
return;
}
$uri = $form_state['values']['submitted-video'];
try {
$file = file_uri_to_object($uri, TRUE);
}
catch (Exception $e) {
form_set_error('url', $e->getMessage());
return;
}
if (!$file->uri) {
form_set_error('url', t('Please select a video.'));
return;
}
$validators = $form['#validators'];
if ($validators) {
// Check for errors. @see media_add_upload_validate calls file_save_upload().
// this code is ripped from file_save_upload because we just want the validation part.
// Call the validation functions specified by this function's caller.
$errors = file_validate($file, $validators);
if (!empty($errors)) {
$message = t('%uri could not be added.', array('%uri' => $uri));
if (count($errors) > 1) {
$message .= theme('item_list', array('items' => $errors));
}
else {
$message .= ' ' . array_pop($errors);
}
form_set_error('url', $message);
return FALSE;
}
}
// @TODO: Validate that if we have no $uri that this is a valid file to
// save. For instance, we may only be interested in images, and it would
// be helpful to let the user know they passed the HTML page containing
// the image accidentally. That would also save us from saving the file
// in the submit step.
// This is kinda a hack of the same.
// This should use the file_validate routines that the upload form users.
// We need to fix the media_parse_to_file routine to allow for a validation.
}
/**
* @TODO: Document this function.
*/
function media_youtube_add_submit($form, &$form_state) {
$uri = $form_state['values']['submitted-video'];
try {
// Save the remote file
$file = file_uri_to_object($uri, TRUE);
file_save($file);
}
catch (Exception $e) {
form_set_error('url', $e->getMessage());
return;
}
if (!$file->fid) {
form_set_error('url', t('The file %file could not be saved. An unknown error has occurred.', array('%file' => $uri)));
return;
}
else {
$form_state['file'] = $file;
}
// Redirect to the file edit page after submission.
// @TODO: media_access() is a wrapper for file_entity_access(). Switch to the
// new function when Media 1.x is deprecated.
if (media_access('update', $file)) {
$destination = array('destination' => 'admin/content/file');
if (isset($_GET['destination'])) {
$destination = drupal_get_destination();
unset($_GET['destination']);
}
$form_state['redirect'] = array('file/' . $file->fid . '/edit', array('query' => $destination));
}
else {
$form_state['redirect'] = 'admin/content/file';
}
}
/**
* @TODO: Document this function.
*/
function media_youtube_video_search($options = array()) {
$options['v'] = 2;
$request = drupal_http_request(url(MEDIA_YOUTUBE_REST_API, array('query' => $options)));
if (!isset($request->error)) {
$entry = simplexml_load_string($request->data);
}
else {
throw new Exception("Error Processing Request. (Error: {$request->code}, {$request->error})");
//if request wasn't successful, create object for return to avoid errors
$entry = new SimpleXMLElement();
}
return media_youtube_unserialize_xml($entry);
}
/**
* Recursively converts a SimpleXMLElement object into an array.
*
* @param object $xml
* The original XML object.
*/
function media_youtube_unserialize_xml($xml) {
if ($xml instanceof SimpleXMLElement) {
$xml = (array) $xml;
}
if (is_array($xml)) {
foreach ($xml as $key => $item) {
$xml[$key] = media_youtube_unserialize_xml($item);
}
}
return $xml;
}
/**
* Check to ensure that a given id is valid.
*
* @param string $id
* The YouTube video id.
* @param boolean $refresh
* (Defaults to FALSE) If TRUE, then reset the value from the cache.
* @return boolean
* Returns TRUE if the video is valid.
*
* @TODO: How does this compare to MediaInternetYouTubeHandler's validId
* method, and can we refactor the code to rely on only one of them?
*/
function media_youtube_valid_id($id, $refresh = FALSE) {
$ids = &drupal_static(__FUNCTION__, array());
// Return our cached id if allowed, and it exists.
if (!$refresh && isset($ids[$id])) {
return $ids[$id];
}
elseif (!$refresh && !isset($ids[$id])) {
return $id;
}
elseif (!$refresh && $cache = cache_get('media_youtube:id:' . $id, 'cache_media_xml')) {
$ids[$id] = $cache->data;
return $ids[$id];
}
$url = url(MEDIA_YOUTUBE_REST_API . '/' . $id);
$response = drupal_http_request($url, array('method' => 'HEAD'));
$ids[$id] = ($response->code == 200);
cache_set('media_youtube:id:' . $id, $ids[$id], 'cache_media_xml', media_variable_get('xml_cache_expire', 3600));
return $ids[$id];
}