You are here

scald_youtube.module in Scald YouTube 7

Defines a YouTube provider for Scald.

File

scald_youtube.module
View source
<?php

/**
 * @file
 * Defines a YouTube provider for Scald.
 */
define('SCALD_YOUTUBE_WEB', 'https://www.youtube.com/watch');
define('SCALD_YOUTUBE_EMBED', 'https://www.youtube.com/embed/');
define('SCALD_YOUTUBE_NOCOOKIE_EMBED', 'https://www.youtube-nocookie.com/embed/');
define('SCALD_YOUTUBE_ID_REGEXP', '/^[a-zA-Z0-9\\-_]+$/');
define('SCALD_YOUTUBE_WEB_REGEXP', '/(?:https?:\\/\\/)?(?:www\\.)?(?:youtu\\.be\\/|youtube\\.com\\/(?:embed\\/|v\\/|watch\\?v=|watch\\?.+(?:&|&#38;);v=))((?:\\w|-|_){11})(?:(?:\\?|&|&#38;)index=((?:\\d){1,3}))?(?:(?:\\?|&|&#38;)list=((?:\\w|-|_){12,}))?(?:\\S+)?/');
define('SCALD_YOUTUBE_API', 'https://www.googleapis.com/youtube/v3');

/**
 * Implements hook_scald_atom_providers().
 *
 * Tell Scald that we'll be providing some video atoms.
 */
function scald_youtube_scald_atom_providers() {
  return array(
    'video' => 'Video hosted on YouTube',
  );

  /*
   * This code will never be hit, but is necessary to mark the string
   * for translation on localize.d.o
   * @codingStandardsIgnoreStart
   */
  t('Video hosted on YouTube');

  // @codingStandardsIgnoreEnd
}

/**
 * Implements hook_scald_add_form().
 */
function scald_youtube_scald_add_form(&$form, &$form_state) {
  $form['identifier'] = array(
    '#type' => 'textfield',
    '#title' => t('YouTube video identifier or URL'),
    '#element_validate' => array(
      'scald_youtube_validate_id',
    ),
    '#required' => TRUE,
    '#default_value' => '',
  );
  $api_key = variable_get('scald_youtube_api_key', '');
  if (!empty($api_key)) {
    $form['search'] = array(
      '#type' => 'fieldset',
      '#title' => t('Search on YouTube'),
      '#weight' => 5,
      '#collapsible' => TRUE,
      '#collapsed' => TRUE,
    );
    $form['search']['search_text'] = array(
      '#type' => 'textfield',
      '#default_value' => '',
      '#size' => 60,
      '#maxlength' => 128,
    );
    $form['search']['search_button'] = array(
      '#type' => 'submit',
      '#value' => t('Search'),
      '#weight' => 19,
      '#submit' => array(
        'scald_youtube_search_submit',
      ),
      '#limit_validation_errors' => array(
        array(
          'search_text',
        ),
      ),
      '#ajax' => array(
        'callback' => 'scald_youtube_search_callback',
        'wrapper' => 'search-results-wrapper',
        'method' => 'replace',
        'effect' => 'fade',
      ),
      '#attributes' => array(
        'class' => array(
          'search-button',
        ),
      ),
    );
    $form['search']['search_results_wrapper'] = array(
      '#tree' => FALSE,
      '#weight' => 20,
      '#prefix' => '<div id="search-results-wrapper">',
      '#suffix' => '</div>',
    );
    $form['search']['search_results_wrapper']['results'] = array(
      '#theme' => 'scald_youtube_search',
      '#videos' => array(),
      '#attached' => array(
        'js' => array(
          drupal_get_path('module', 'scald_youtube') . '/js/scald_youtube_search.js',
        ),
        'css' => array(
          drupal_get_path('module', 'scald_youtube') . '/css/scald_youtube_search.css',
        ),
      ),
    );
    $form['buttons']['next']['#attributes']['class'][] = 'continue-button';
  }
}

/**
 * Submit callback for the YouTube Search.
 */
function scald_youtube_search_submit($form, &$form_state) {

  // A submit function is required for the limit validation errors to work.
}

/**
 * Callback to perform the YouTube Search.
 */
function scald_youtube_search_callback($form, $form_state) {
  $api_key = variable_get('scald_youtube_api_key', '');
  if (empty($api_key)) {
    return '';
  }
  $q = urlencode(check_plain($form_state['values']['search_text']));
  $url = SCALD_YOUTUBE_API . '/search?key=' . $api_key . '&q=' . $q . '&part=snippet&order=rating&type=video,playlist';
  $response = drupal_http_request($url);
  if ($response->code >= 200 && $response->code < 400 && !empty($response->data)) {
    $json = json_decode($response->data);
    $form['search']['search_results_wrapper']['results']['#videos'] = $json->items;
    return $form['search']['search_results_wrapper'];
  }
  return '';
}

/**
 * Implements hook_scald_add_form_fill().
 */
function scald_youtube_scald_add_form_fill(&$atom, $form, $form_state) {

  // Get the identifier.
  $identifier = scald_youtube_parse_id($form_state['values']['identifier'], FALSE);

  // Get video info.
  $infos = scald_youtube_video($identifier['id']);
  $atom->base_id = $identifier['id'];
  if (!isset($atom->data)) {
    $atom->data = array();
  }
  if (isset($identifier['list'])) {
    $atom->data['list'] = $identifier['list'];
  }
  $atom->title = $infos->title;

  // Prefill the author.
  if (isset($infos->author)) {
    $langcode = field_language('scald_atom', $atom, 'scald_authors');
    $atom->scald_authors[$langcode][0] = array(
      'tid' => 0,
      'taxonomy_term' => (object) array(
        'name' => $infos->author,
      ),
    );
  }

  // Prefill tags.
  if (isset($infos->tags)) {
    $langcode = field_language('scald_atom', $atom, 'scald_tags');
    foreach ($infos->tags as $index => $tag) {

      // Beware, this is not a real tid, it's just an index.
      $atom->scald_tags[$langcode][$index] = array(
        'tid' => $index,
        'taxonomy_term' => (object) array(
          'name' => $tag,
        ),
      );
    }
  }

  // Save video width and height.
  $atom->data['video_width'] = $infos->width;
  $atom->data['video_height'] = $infos->height;

  // Download a copy of the video thumbnail. This makes it possible
  // to do interesting manipulation with image styles presets.
  $thumb = drupal_http_request($infos->thumbnail['src']);
  if ($thumb->code == 200 && ($directory = ScaldAtomController::getThumbnailPath('video'))) {
    $dest = $directory . '/youtube-' . $infos->id . '.jpg';
    $file = file_save_data($thumb->data, $dest);
    if ($file) {

      // Set the file status to temporary.
      db_update('file_managed')
        ->condition('fid', $file->fid)
        ->fields(array(
        'status' => 0,
      ))
        ->execute();
      $langcode = field_language('scald_atom', $atom, 'scald_thumbnail');
      $atom->scald_thumbnail[$langcode][0] = (array) $file;
    }
  }
}

/**
 * Implements hook_form_FORM_ID_alter().
 */
function scald_youtube_form_scald_atom_add_form_options_alter(&$form, &$form_state, $form_id) {
  $scald = $form_state['scald'];
  if (isset($scald['type'])) {
    $source = $scald['source'];
  }
  else {
    $source = $scald['atoms'][0]->provider;
  }
  if ($source != 'scald_youtube') {
    return;
  }
  foreach ($form as $key => $data) {
    if (strpos($key, 'atom') === 0) {
      $index = intval(substr($key, 4));
      $scald_youtube_show_related = variable_get('scald_youtube_show_related', TRUE);
      if (isset($scald['atoms'][$index]->data['show_related'])) {
        $scald_youtube_show_related = $scald['atoms'][$index]->data['show_related'];
      }
      $form[$key]['scald_youtube_show_related'] = array(
        '#type' => 'checkbox',
        '#default_value' => $scald_youtube_show_related,
        '#title' => t('Show related videos'),
        '#description' => t('If checked the related videos will be visible at the end of the video.'),
        '#weight' => $form[$key]['scald_thumbnail']['#weight'] + 0.5,
        '#tree' => TRUE,
        '#parents' => array(
          $key,
          'scald_youtube_show_related',
        ),
      );
      $scald_youtube_autoplay = variable_get('scald_youtube_autoplay', FALSE);
      if (isset($scald['atoms'][$index]->data['youtube_autoplay'])) {
        $scald_youtube_autoplay = $scald['atoms'][$index]->data['youtube_autoplay'];
      }
      $form[$key]['scald_youtube_autoplay'] = array(
        '#type' => 'checkbox',
        '#default_value' => $scald_youtube_autoplay,
        '#title' => t('Autoplay the video'),
        '#description' => t('If checked, the video will be automatically started.'),
        '#weight' => $form[$key]['scald_thumbnail']['#weight'] + 0.7,
        '#tree' => TRUE,
        '#parents' => array(
          $key,
          'scald_youtube_autoplay',
        ),
      );
      $scald_youtube_mute = FALSE;
      if (isset($scald['atoms'][$index]->data['youtube_mute'])) {
        $scald_youtube_mute = $scald['atoms'][$index]->data['youtube_mute'];
      }
      $form[$key]['scald_youtube_mute'] = array(
        '#type' => 'checkbox',
        '#default_value' => $scald_youtube_mute,
        '#title' => t('Mute the video'),
        '#description' => t('If checked, the video will be muted.'),
        '#weight' => $form[$key]['scald_thumbnail']['#weight'] + 0.8,
        '#tree' => TRUE,
        '#parents' => array(
          $key,
          'scald_youtube_mute',
        ),
      );
    }
  }
  array_unshift($form['#submit'], 'scald_youtube_extra_options_save_handler');
}

/**
 * Handler to store any extra options in the atom Entity.
 */
function scald_youtube_extra_options_save_handler(&$form, &$form_state) {
  foreach ($form as $key => $data) {
    if (strpos($key, 'atom') === 0) {
      $index = intval(substr($key, 4));
      $form_state['scald']['atoms'][$index]->data['show_related'] = $form_state['values'][$key]['scald_youtube_show_related'];
      $form_state['scald']['atoms'][$index]->data['youtube_autoplay'] = $form_state['values'][$key]['scald_youtube_autoplay'];
      $form_state['scald']['atoms'][$index]->data['youtube_mute'] = $form_state['values'][$key]['scald_youtube_mute'];
    }
  }
}

/**
 * Implements hook_scald_fetch().
 */
function scald_youtube_scald_fetch($atom, $type) {
  $items = field_get_items('scald_atom', $atom, 'scald_thumbnail');
  if ($items && file_exists($items[0]['uri'])) {
    $atom->file_source = $atom->thumbnail_source = $items[0]['uri'];
  }
}

/**
 * Implements hook_scald_prerender().
 */
function scald_youtube_scald_prerender($atom, $context, $options, $mode) {
  if ($mode == 'atom') {

    // Load context configuration to retrieve dimension data if present.
    $context_config = scald_context_config_load($context);
    $video_width = !empty($atom->data['video_width']) ? $atom->data['video_width'] : 480;
    $video_height = !empty($atom->data['video_height']) ? $atom->data['video_height'] : 365;

    // Allow context configuration to override video dimension variables.
    if (!empty($context_config->data['width'])) {
      $video_width = $context_config->data['width'];
    }
    if (!empty($context_config->data['height'])) {
      $video_height = $context_config->data['height'];
    }
    $query = array();
    if (!empty($atom->data['list'])) {
      $query['list'] = $atom->data['list'];
    }
    if (isset($atom->data['show_related']) && empty($atom->data['show_related'])) {
      $query['rel'] = '0';
    }

    // Don't apply the autoplay on admin page.
    if (isset($atom->data['youtube_autoplay']) && !empty($atom->data['youtube_autoplay']) && !path_is_admin(current_path())) {
      $query['autoplay'] = '1';
    }
    if (isset($atom->data['youtube_mute']) && !empty($atom->data['youtube_mute'])) {
      $query['mute'] = '1';
    }
    $youtube_domain = SCALD_YOUTUBE_EMBED;
    $attached_files = array(
      'css' => array(
        drupal_get_path('module', 'scald_youtube') . '/css/scald_youtube_iframe.css',
      ),
    );
    $defer_enable = variable_get('scald_youtube_defer_videos', FALSE);
    $consent_enable = variable_get('scald_youtube_consent_enable', FALSE);
    $consent_text = variable_get('scald_youtube_consent_text', '');
    $consent_button = variable_get('scald_youtube_consent_button', 'Accept');
    if ($consent_enable) {
      $defer_enable = TRUE;
    }
    $delayed_cookie = variable_get('scald_youtube_delayed_cookie', FALSE);
    if ($delayed_cookie) {
      $youtube_domain = SCALD_YOUTUBE_NOCOOKIE_EMBED;
    }
    if ($defer_enable) {
      $attached_files['js'] = array(
        drupal_get_path('module', 'scald_youtube') . '/js/scald_youtube_defer_library.js',
        drupal_get_path('module', 'scald_youtube') . '/js/scald_youtube_defer.js',
      );
    }
    $video_url = url($youtube_domain . $atom->base_id, array(
      'query' => $query,
    ));
    $atom->rendered->player = array(
      '#theme' => 'scald_youtube_player',
      '#vars' => array(
        'video_id' => $atom->base_id,
        'video_width' => $video_width,
        'video_height' => $video_height,
        'video_url' => $video_url,
        'thumbnail' => $atom->rendered->thumbnail_source_url,
        'title' => check_plain($atom->title),
        'enable_defer' => $defer_enable,
        'enable_consent' => $consent_enable,
        'consent_text' => t($consent_text),
        'consent_button' => !empty($consent_button) ? t($consent_button) : FALSE,
      ),
      '#atom' => $atom,
      '#attached' => $attached_files,
    );
  }
}

/**
 * Implements hook_theme().
 */
function scald_youtube_theme() {
  return array(
    'scald_youtube_player' => array(
      'variables' => array(
        'vars' => NULL,
        'atom' => NULL,
      ),
      'template' => 'templates/scald_youtube_player',
    ),
    'scald_youtube_search' => array(
      'variables' => array(
        'videos' => NULL,
      ),
      'template' => 'templates/scald_youtube_search',
    ),
  );
}

/**
 * Scald_youtube_register.
 *
 * Creates an atom based on a video ID or an object containing
 * the video informations.
 *
 * @param mixed $video
 *   Unique identifier of the video on YouTube, or object
 *   returned by scald_youtube_video.
 *
 * @return int
 *   Unique identifier of the new atom.
 */
function scald_youtube_register($video) {

  // Fetch the needed informations from YouTube.
  if (is_object($video)) {
    $infos = $video;
  }
  else {
    $infos = scald_youtube_video($video);
  }

  // Check if the video has already been imported to prevent duplicate.
  $old = scald_youtube_already_imported($infos->id);
  if ($old) {
    return FALSE;
  }

  // Download a copy of the video thumbnail. This makes it possible
  // to do interesting manipulation with image styles presets.
  $thumb = drupal_http_request($infos->thumbnail['src']);
  $dir = 'public://youtube';
  if ($thumb->code == 200 && file_prepare_directory($dir, FILE_CREATE_DIRECTORY)) {
    $dest = $dir . '/' . $infos->id . '.jpg';
    $file = file_save_data($thumb->data, $dest);
  }

  // Create an atom.
  $atom = new ScaldAtom('video', 'scald_youtube', array(
    'base_id' => $infos->id,
    'title' => $infos->title,
  ));

  // Save video width and height.
  if (!isset($atom->data)) {
    $atom->data = array();
  }
  $atom->data['video_width'] = $infos->width;
  $atom->data['video_height'] = $infos->height;

  // Set file.
  if ($file) {
    db_update('file_managed')
      ->condition('fid', $file->fid)
      ->fields(array(
      'status' => 0,
    ))
      ->execute();
    $langcode = field_language('scald_atom', $atom, 'scald_thumbnail');
    $atom->scald_thumbnail[$langcode][0] = (array) $file;
  }

  // And save it.
  $atom_sid = scald_atom_save($atom);

  // Finally, return this id.
  return $atom_sid;
}

/**
 * Analyze a YouTube RSS feed to extract videos information.
 *
 * @param string $id
 *   Identifier or string associated with the type. For example, user name,
 *   video id or tag.
 *
 * @return array
 *   An array of object, each one containing an analyzed video.
 */
function scald_youtube_feed($id) {
  $item = scald_youtube_video_get_info($id);
  $api_key = variable_get('scald_youtube_api_key', '');
  if (empty($api_key)) {
    if (empty($item)) {
      return array();
    }
  }
  else {
    if (empty($item)) {
      $item = scald_youtube_create_default_info($id);
    }
    $url = SCALD_YOUTUBE_API . '/videos?id=' . $id . '&key=' . $api_key . '&part=snippet';
    $response = drupal_http_request($url);
    if ($response->code >= 200 && $response->code < 400 && !empty($response->data)) {
      $json = json_decode($response->data);
      $data = $json->items[0];
      $thumb_size = variable_get('scald_youtube_thumb_size', 'default');
      $item->thumbnail = array(
        'src' => $data->snippet->thumbnails->{$thumb_size}->url,
      );
      $item->title = $data->snippet->title;
      $item->author = $data->snippet->channelTitle;
    }
    else {
      return array();
    }
  }
  return $item;
}

/**
 * Analyze the youtube feed for a specific video.
 */
function scald_youtube_video($id) {
  $item = scald_youtube_feed($id);
  return $item;
}

/**
 * Analyze OEmbed response for a given video ID.
 *
 * @deprecated
 *
 * @see scald_youtube_video_get_info()
 */
function scald_youtube_video_oembed($id) {
  return scald_youtube_video_get_info($id);
}

/**
 * Create a default info object.
 */
function scald_youtube_create_default_info($id) {
  $info = new stdClass();
  $info->id = $id;
  $info->license = 'YT';
  $info->width = $info->video_width = 480;
  $info->height = $info->video_height = 365;
  return $info;
}

/**
 * Returns meta data on a YouTube video that are not found on the v3 API.
 *
 * Unfortunately the YouTube API doesn't provide original video dimensions
 * see: http://code.google.com/p/gdata-issues/issues/detail?id=1083
 * We need both oembed data and parsing the web page to have author information
 * and video dimensions.
 */
function scald_youtube_video_get_info($id) {
  static $cache = array();
  if (isset($cache[$id])) {
    return $cache[$id];
  }
  $info = array();
  $url = SCALD_YOUTUBE_WEB . '?v=' . $id;
  $options = array(
    'headers' => array(
      'User-Agent' => NULL,
    ),
  );
  $response = drupal_http_request($url, $options);
  if ($response->code >= 200 && $response->code < 400 && !empty($response->data)) {

    // Initialize default values.
    $info = scald_youtube_create_default_info($id);
    $data = $response->data;

    // DOMDocument does not work well with UTF-8, we need to use HTML entities
    // to be safe.
    if (function_exists('mb_convert_encoding')) {
      $data = mb_convert_encoding($data, 'HTML-ENTITIES', 'UTF-8');
    }
    $dom = new DOMDocument();
    $dom->preserveWhiteSpace = FALSE;
    @$dom
      ->loadHTML($data);
    foreach ($dom
      ->getElementsByTagName('meta') as $meta) {
      $content = $meta
        ->getAttribute('content');
      switch ($meta
        ->getAttribute('name')) {
        case 'keywords':
          $info->tags = explode(', ', $content);
          break;
        case 'title':
          $info->title = $content;
          break;
      }
      switch ($meta
        ->getAttribute('property')) {
        case 'og:image':
          $info->thumbnail = array(
            'src' => $content,
          );
          break;
        case 'og:video:width':
          $info->width = $content;
          $info->video_width = $content;
          break;
        case 'og:video:height':
          $info->height = $content;
          $info->video_height = $content;
          break;
      }
    }
    if (empty($info->title)) {
      $info = array();
    }
  }
  $cache[$id] = $info;
  return $info;
}

/**
 * Implements hook_form_FORM_ID_alter().
 */
function scald_youtube_form_scald_admin_type_form_alter(&$form, &$form_state, $form_id) {
  if ($form['atom_type']['#value'] === 'video') {
    $form['defaults']['scald_youtube'] = array(
      '#type' => 'fieldset',
      '#title' => t('Scald YouTube Configuration'),
      '#collapsible' => TRUE,
      '#collapsed' => TRUE,
    );
    $form['defaults']['scald_youtube']['scald_youtube_api_key'] = array(
      '#type' => 'textfield',
      '#title' => t('YouTube API Key'),
      '#element_validate' => array(
        'scald_youtube_validate_api_key',
      ),
      '#default_value' => variable_get('scald_youtube_api_key', ''),
      '#description' => t('The API Key can be requested on the Google Developer Console. Without it the YouTube Search and some of the video information will not be accessible.'),
    );
    $form['defaults']['scald_youtube']['scald_youtube_show_related'] = array(
      '#type' => 'checkbox',
      '#default_value' => variable_get('scald_youtube_show_related', TRUE),
      '#title' => t('Show related videos by default'),
      '#description' => t('If checked the related videos will be visible at the end of the video by default for new Atoms.'),
    );
    $form['defaults']['scald_youtube']['scald_youtube_autoplay'] = array(
      '#type' => 'checkbox',
      '#default_value' => variable_get('scald_youtube_autoplay', FALSE),
      '#title' => t('Autoplay the video'),
      '#description' => t('If checked, the video will be set to automatically start by default for new Atoms.'),
    );
    $form['defaults']['scald_youtube']['scald_youtube_delayed_cookie'] = array(
      '#type' => 'checkbox',
      '#default_value' => variable_get('scald_youtube_delayed_cookie', FALSE),
      '#title' => t('Use the "delayed cookie" privacy feature'),
      '#description' => t("If this checkbox is checked, the nocookie.com domain will be used for embedding. The cache has to be cleared for the changes to take effect."),
    );
    $form['defaults']['scald_youtube']['scald_youtube_defer_videos'] = array(
      '#type' => 'checkbox',
      '#default_value' => variable_get('scald_youtube_defer_videos', FALSE),
      '#title' => t('Defer the Youtube videos'),
      '#description' => t("If this checkbox is checked, the loading of the Scald Youtube videos will be deferred to the end. The cache has to be cleared for the changes to take effect. If you use the WYSIWYG module, you must enable the 'Defer Youtube videos' plugin in your WYSIWYG profile."),
    );
    $form['defaults']['scald_youtube']['scald_youtube_consent_enable'] = array(
      '#type' => 'checkbox',
      '#default_value' => variable_get('scald_youtube_consent_enable', FALSE),
      '#title' => t('Ask user consent before displaying videos'),
      '#description' => t("If this checkbox is checked, the configured message below with a button will be displayed instead of the video in order to receive user consent. When the user agrees, the video will be shown. The cache has to be cleared for the changes to take effect. This will enable the defer option."),
    );
    $form['defaults']['scald_youtube']['scald_youtube_consent_text'] = array(
      '#type' => 'textfield',
      '#default_value' => variable_get('scald_youtube_consent_text', ''),
      '#title' => t('Consent text'),
      '#description' => t("This text will be displayed instead of the video until the user gives his consent."),
    );
    $form['defaults']['scald_youtube']['scald_youtube_consent_button'] = array(
      '#type' => 'textfield',
      '#default_value' => variable_get('scald_youtube_consent_button', 'Accept'),
      '#title' => t('Consent button'),
      '#description' => t("This text will be used as the button label in order to get the user consent."),
    );
    $form['defaults']['scald_youtube']['scald_youtube_thumb_size'] = array(
      '#type' => 'select',
      '#title' => t('Size of thumbnails'),
      '#default_value' => variable_get('scald_youtube_thumb_size', 'default'),
      '#options' => array(
        'default' => t('Default resolution'),
        'medium' => t('Medium resolution'),
        'high' => t('High resolution'),
        'standard' => t('Standard resolution'),
        'maxres' => t('Max resolution'),
      ),
      '#description' => t('Choose the size of thumbnails that is used to save to the local file system'),
    );
    $form['#submit'][] = 'scald_youtube_configuration_submit';
  }
}

/**
 * Checks if a video has already been imported, based on its video ID.
 *
 * @param string $id
 *   The video identifier.
 *
 * @return mixed
 *   FALSE if the video was never imported, the scald identifier of
 *   the video otherwise.
 */
function scald_youtube_already_imported($id) {
  $query = array(
    'provider' => 'scald_youtube',
    'base_id' => $id,
  );
  return scald_search($query, FALSE, TRUE);
}

/**
 * Form element validation handler for YouTube API key.
 */
function scald_youtube_validate_api_key($element, &$form_state) {
  if (!empty($form_state['values']['scald_youtube_api_key']) && !preg_match('/^[a-zA-Z0-9_\\-]+$/', $form_state['values']['scald_youtube_api_key'])) {
    form_error($element, t('Invalid YouTube API Key.'));
  }
}

/**
 * Submit function to save the YouTube Configuration.
 */
function scald_youtube_configuration_submit($form_id, &$form_state) {
  variable_set('scald_youtube_api_key', $form_state['values']['scald_youtube_api_key']);
  variable_set('scald_youtube_show_related', $form_state['values']['scald_youtube_show_related']);
  variable_set('scald_youtube_autoplay', $form_state['values']['scald_youtube_autoplay']);
  variable_set('scald_youtube_delayed_cookie', $form_state['values']['scald_youtube_delayed_cookie']);
  variable_set('scald_youtube_defer_videos', $form_state['values']['scald_youtube_defer_videos']);
  variable_set('scald_youtube_consent_enable', $form_state['values']['scald_youtube_consent_enable']);
  variable_set('scald_youtube_consent_text', $form_state['values']['scald_youtube_consent_text']);
  variable_set('scald_youtube_consent_button', $form_state['values']['scald_youtube_consent_button']);
  variable_set('scald_youtube_thumb_size', $form_state['values']['scald_youtube_thumb_size']);
}

/**
 * Form element validation handler for YouTube identifier.
 */
function scald_youtube_validate_id($element, &$form_state) {
  $identifier = scald_youtube_parse_id($form_state['values']['identifier'], TRUE);
  if (empty($identifier['id'])) {
    form_error($element, t('Invalid YouTube video identifier.'));
  }
  elseif (scald_youtube_already_imported($identifier['id'])) {
    form_error($element, t('YouTube video already imported.'));
  }
}

/**
 * Parse a YouTube ID and check validity.
 */
function scald_youtube_parse_id($string, $check) {
  $identifier = NULL;
  $string = trim($string);
  if (!preg_match(SCALD_YOUTUBE_ID_REGEXP, $string)) {

    // The string ID is not easy to parse, let's try to analyze it.
    if (preg_match(SCALD_YOUTUBE_WEB_REGEXP, $string, $m)) {

      // This string is a full YouTube URL.
      $identifier['id'] = $m[1];
      if (!empty($m[3])) {
        $identifier['list'] = $m[3];
      }
    }
    elseif (preg_match("/^http/", $string)) {

      // This string is a URL, most likely a shortened one.
      // For example (http://dai.ly, http://bit.ly, etc...).
      $response = drupal_http_request($string);
      if ($response->code == 200 && isset($response->redirect_code) && ($response->redirect_code == 301 || $response->redirect_code == 302)) {
        return scald_youtube_parse_id($response->redirect_url, $check);
      }
    }
  }
  else {
    $identifier['id'] = $string;
  }
  if (!empty($identifier) && $check) {

    // Last check to confirm this video really exists on YouTube.
    $info = scald_youtube_video($identifier['id']);
    if (empty($info)) {
      $identifier['id'] = FALSE;
    }
  }
  return $identifier;
}

/**
 * Implements hook_wysiwyg_plugin().
 */
function scald_youtube_wysiwyg_plugin($editor, $version) {
  switch ($editor) {
    case 'ckeditor':
      return array(
        'scald_youtube_defer_plugin' => array(
          'path' => drupal_get_path('module', 'scald_youtube') . '/scald_youtube_defer_plugin/',
          'buttons' => array(
            'scald_youtube_defer_button' => t('Defer Youtube videos'),
          ),
          'load' => TRUE,
        ),
      );
  }
}

/**
 * Implements hook_element_info_alter().
 */
function scald_youtube_element_info_alter(&$types) {
  $defer_enable = variable_get('scald_youtube_defer_videos', FALSE);
  if ($defer_enable) {

    // Add the path of the script.
    $types['text_format']['#pre_render'][] = 'scald_youtube_add_defer_video_plugin_js';
  }
}

/**
 * A function in order to pass the JS file to the ckeditor plugin.
 *
 * @param array $element
 *   The element array.
 *
 * @return array
 *   Return the text format element with a settings in order to add the JS file.
 */
function scald_youtube_add_defer_video_plugin_js($element) {
  global $base_url, $base_path;
  $element['#attached']['js'][] = array(
    'type' => 'setting',
    'data' => array(
      'defer_youtube_video_js_library' => $base_url . $base_path . drupal_get_path('module', 'scald_youtube') . '/js/scald_youtube_defer_library.js',
    ),
  );
  return $element;
}

Functions

Namesort descending Description
scald_youtube_add_defer_video_plugin_js A function in order to pass the JS file to the ckeditor plugin.
scald_youtube_already_imported Checks if a video has already been imported, based on its video ID.
scald_youtube_configuration_submit Submit function to save the YouTube Configuration.
scald_youtube_create_default_info Create a default info object.
scald_youtube_element_info_alter Implements hook_element_info_alter().
scald_youtube_extra_options_save_handler Handler to store any extra options in the atom Entity.
scald_youtube_feed Analyze a YouTube RSS feed to extract videos information.
scald_youtube_form_scald_admin_type_form_alter Implements hook_form_FORM_ID_alter().
scald_youtube_form_scald_atom_add_form_options_alter Implements hook_form_FORM_ID_alter().
scald_youtube_parse_id Parse a YouTube ID and check validity.
scald_youtube_register Scald_youtube_register.
scald_youtube_scald_add_form Implements hook_scald_add_form().
scald_youtube_scald_add_form_fill Implements hook_scald_add_form_fill().
scald_youtube_scald_atom_providers Implements hook_scald_atom_providers().
scald_youtube_scald_fetch Implements hook_scald_fetch().
scald_youtube_scald_prerender Implements hook_scald_prerender().
scald_youtube_search_callback Callback to perform the YouTube Search.
scald_youtube_search_submit Submit callback for the YouTube Search.
scald_youtube_theme Implements hook_theme().
scald_youtube_validate_api_key Form element validation handler for YouTube API key.
scald_youtube_validate_id Form element validation handler for YouTube identifier.
scald_youtube_video Analyze the youtube feed for a specific video.
scald_youtube_video_get_info Returns meta data on a YouTube video that are not found on the v3 API.
scald_youtube_video_oembed Analyze OEmbed response for a given video ID.
scald_youtube_wysiwyg_plugin Implements hook_wysiwyg_plugin().

Constants