Index: youtube_api.module =================================================================== RCS file: /cvs/drupal-contrib/contributions/modules/youtube_api/youtube_api.module,v retrieving revision 1.11 diff -u -r1.11 youtube_api.module --- youtube_api.module 3 Jul 2008 16:55:58 -0000 1.11 +++ youtube_api.module 12 Jul 2008 03:55:11 -0000 @@ -181,13 +181,14 @@ watchdog('video_upload', t("Read file from %filepath.", array('%filepath' => $filepath)), WATCHDOG_NOTICE); $data .= "\r\n--". $boundary ."--"; - $headers = array('Authorization' => "GoogleLogin auth=". $_SESSION['youtube_api_token'], - 'X-GData-Key' => "key=". variable_get('youtube_api_key', ''), - 'X-GData-Client' => variable_get('youtube_api_client_id', ''), - 'Slug' => $filename, - 'Content-Type' => 'multipart/related; boundary="'. $boundary .'"', - 'Connection' => 'close', - ); + $headers = array( + 'Authorization' => "GoogleLogin auth=". $_SESSION['youtube_api_token'], + 'X-GData-Key' => "key=". variable_get('youtube_api_key', ''), + 'X-GData-Client' => variable_get('youtube_api_client_id', ''), + 'Slug' => $filename, + 'Content-Type' => 'multipart/related; boundary="'. $boundary .'"', + 'Connection' => 'close', + ); $location = 'http://uploads.gdata.youtube.com/feeds/api/users/default/uploads'; watchdog('video_upload', t("Sending payload to youtube..."), WATCHDOG_NOTICE); @@ -480,7 +481,7 @@ // get video player URL $attrs = $media->group->player->attributes(); if ($media->group->player) { - $video->media['player'] = $attrs['url']; + $video->media['player'] = (string) $attrs['url']; } //parse the thumbnails $video->media['thumbnails'] = array(); @@ -771,8 +772,7 @@ */ function youtube_api_rate_video($video_id, $rating, $min = 1, $max = 5) { //Do some basic sanity checking. - if (!($min <= $rating && $rating <= $max)) - { + if (!($min <= $rating && $rating <= $max)) { watchdog('youtube_api', "Rating of video {$video_id} failed checked of {$min} <= {$rating} <= {$max}", WATCHDOG_NOTICE); return FALSE; } @@ -869,6 +869,308 @@ return FALSE; } } +/** + * Implementation of a feedapi parser. + * + * @param $op + * The operation to perform on the feed. + */ +function youtube_api_feedapi_feed($op) { + $args = func_get_args(); + // Validate the URL, if it is not basically valid, why send to simplepie object + $url_parts = parse_url(is_string($args[1]) ? $args[1] : $args[1]->url); + + switch ($op) { + case 'type': + return array("YouTube feed"); + case 'compatible': + if (strstr(strtolower($args[1]->url), 'gdata.youtube.com/feeds/')) { + return TRUE; + } + return false; + case 'parse': + $feed = is_object($args[1]) ? $args[1] : FALSE; + $auth = $args[1]->settings['processors']['youtube_api']['authentication']; + $headers = array(); + if ($auth['requires_authentication'] == 1) { + if ($auth['user'] && $auth['password']) { + if (youtube_api_login($auth['user'], $auth['password'])) { + $headers['Authorization'] = "GoogleLogin auth=". $_SESSION['youtube_api_token']; + } + else { + watchdog("youtube_api", t("Could not fetch feed %feed. The user was not able to be logged into YouTube", array('%feed' => $feed->url)), WATCHDOG_NOTICE); + } + } + } + $num_items = $args[1]->settings['processors']['youtube_api']['num_items'] ? $args[1]->settings['processors']['youtube_api']['num_items'] : 25; + $result = youtube_api_get_feed($feed->url, 1, $num_items, $headers); + $items = youtube_api_process_feed($result); + $parsed_source = new stdClass(); + $parsed_source->items = $items; + // Detect the title + $parsed_source->title = isset($feed_XML->title) ? "{$feed_XML->title}" : ""; + // Detect the description + $parsed_source->description = isset($feed_XML->subtitle) ? "{$feed_XML->subtitle}" : ""; + $parsed_source->options = new stdClass(); + // Detect the link + $parsed_source->options->link = ""; + if (count($feed_XML->link) > 0) { + $link = $feed_XML->link; + $link = $link->attributes(); + $parsed_source->options->link = isset($link["href"]) ? "{$link["href"]}" : ""; + } + return $parsed_source; + } +} + +/** + * Provides a feedapi specific settings form. + * + * @param $type + * The type of form options are being added to. + */ +function youtube_api_feedapi_settings_form($type) { + switch ($type) { + case 'processors': + $ct_types = node_get_types(); + $ct_options = array(); + if (is_array($ct_types)) { + foreach ($ct_types as $key => $data) { + $ct_options[$key] = $data->name; + } + } + + $form['content_type'] = array( + '#type' => 'select', + '#title' => t('Node type of feed items'), + '#default_value' => 'story', + '#options' => $ct_options, + '#description' => t('Choose the node type for feed item nodes created by this feed. If this node type has an attached emfield, the module will detect and use that field for video storage.'), + ); + + $filters = filter_formats(); + $filter_options = array(); + foreach ($filters as $filter) { + $filter_options[$filter->format] = $filter->name; + } + + $form['input_filter'] = array( + '#type' => 'select', + '#title' => t('Input Filter to use'), + '#default_value' => '3', + '#options' => $filter_options, + '#description' => t('The input filter to use for the node body. This filter must allow div, object, and embed tags for the video to properly embed.'), + ); + + $form['node_date'] = array( + '#type' => 'radios', + '#title' => t('Created date of item nodes'), + '#options' => array('feed' => t('Retrieve from feed'), 'current' => t('Use time of download')), + '#default_value' => 'feed', + ); + + $form['promote'] = array( + '#type' => 'textfield', + '#title' => t('Promoted items'), + '#description' => t('The newest N items per feed will be promoted to front page. Leave empty and FeedAPI does not alter the promote property of the feed items.'), + '#default_value' => 3, + ); + + + $form['num_items'] = array( + '#type' => 'textfield', + '#title' => t('Number of items to fetch at a time'), + '#description' => t('The maximum number of items to get from the feed on any refresh. Large numbers may cause a significant decrease in performance.'), + '#default_value' => 25, + ); + + + $form['authentication'] = array( + '#type' => 'fieldset', + '#title' => t('Authentication Settings'), + '#collapsible' => TRUE, + '#collapsed' => TRUE, + ); + + $form['authentication']['requires_authentication'] = array( + '#type' => 'radios', + '#title' => t('Feed Requires Authentication'), + '#description' => t('Enable if this feed requires a YouTube user to be logged in.'), + '#options' => array('No', 'Yes'), + ); + + $form['authentication']['user'] = array( + '#type' => 'textfield', + '#title' => t('YouTube Login'), + '#description' => t('The YouTube login to use. Only applicable when authentication is required'), + ); + + $form['authentication']['password'] = array( + '#type' => 'textfield', + '#title' => t('YouTube Password'), + '#description' => t('The YouTube password to use. Only applicable when authentication is required'), + ); + + $form['x_dedupe'] = array( + '#type' => 'radios', + '#title' => t('Duplicates'), + '#description' => t('If you choose "check for duplicates on all feeds", a feed item will not be created if it already exists on *ANY* feed. Instead, the existing feed item will be linked to the feed. If you are not sure, choose the first option.'), + '#options' => array(0 => t('Check for duplicates only within feed'), 1 => t('Check for duplicates on all feeds')), + '#default_value' => 0, + ); + + break; + } + return $form; +} + +/** + * Implimentation of a feedapi processor. + * + * @param $op + * The operation being performed. + */ +function youtube_api_feedapi_item($op) { + switch ($op) { + case 'type': + return array("YouTube feed"); + default: + if (function_exists('_youtube_api_feedapi_node_'. $op)) { + $args = array_slice(func_get_args(), 1); + return call_user_func_array('_youtube_api_feedapi_node_'. $op, $args); + } + else if (function_exists('_feedapi_node_'. $op)) { + $args = array_slice(func_get_args(), 1); + return call_user_func_array('_feedapi_node_'. $op, $args); + } + } +} + +function _youtube_api_feedapi_node_update($feed_item, $feed_nid, $settings = array()) { + // Determine which node is assigned to this item + if ($feed_item->options->guid) { + $node = db_fetch_object(db_query("SELECT nid FROM {feedapi_node_item} WHERE guid = '%s'", $feed_item->video_id)); + } + + $feed_item->nid = $node->nid; + _youtube_api_feedapi_save($feed_item, $feed_nid, $settings); + return $feed_item; +} + + +function _youtube_api_feedapi_node_save($feed_item, $feed_nid, $settings = array()) { + // Don't save anything if neither url nor guid given. + if (!$feed_item->video_id) { + return false; + } + + $node_type = !empty($settings['content_type']) ? $settings['content_type'] : variable_get('feedapi_node_type', 'story'); + + //we must know if we are using emfield ahead of time. from what I can tell emfield only checks meta data on the initial save of an item, + //otherwise it assumes it already has the metadata for the field. not doing this results in emfield metadata being lost. + $use_emfield = FALSE; + if ($emfield = db_fetch_object(db_query("select field_name, widget_settings from {node_field_instance} where type_name = '%s' and widget_type = '%s'", $node_type, 'video_cck_textfields'))) { + $emfield->widget_settings = unserialize($emfield->widget_settings); + if ($emfield->widget_settings['providers']['youtube']) { + $use_emfield = TRUE; + } + } + + // Construct the node object + if (isset($feed_item->nid) && $use_emfield) { + $node = node_load($feed_item->nid); + } + else { + $node = new stdClass(); + $node->nid = $feed_item->nid; + } + + $node->type = $node_type; + + // Get the default options from the cont + $options = variable_get('node_options_'. $node->type, FALSE); + if (is_array($options)) { + $node->status = in_array('status', $options) ? 1 : 0; + $node->promote = in_array('promote', $options) ? 1 : 0; + $node->sticky = in_array('sticky', $options) ? 1 : 0; + } + else { + $node->status = 1; + } + + $feed_node = node_load($feed_nid); + $node->title = $feed_item->title; + $node->uid = $feed_node->uid; + $node->created = $feed_item->published ? strtotime($feed_item->published) : mktime(); + if ($use_emfield) { + $node->{$emfield->field_name}[0]['embed'] = $feed_item->media['player']; + $node->body = $feed_item->content; + } + else { + $node->body = theme('youtube_api_embed', $feed_item, $feed_item->media['content'][0]); + $node->teaser = node_teaser($feed_item->content); + } + $node->format = $settings['input_filter']; + + // Stick feed item on node so that add on modules can act on it. + // A feed item can come in from more than one feed. + $node->feedapi_node->feed_nids[$feed_nid] = $feed_nid; + $node->feedapi_node->feed_item = $feed_item; + // For backwards compatibility - todo: move to using feedapi_node->feed_nids and feedapi_node->feed_item. + $node->feedapi->feed_nid = $feed_nid; + $node->feedapi->feed_item = $feed_item; + node_object_prepare($node); + + // If there are dupes on other feeds, don't create new feed item, but link this feed + // to existing feed item. + // Heads up: if there is a duplicate on the SAME feed, + // _feedapi_node_save() won't even be called. + if (isset($feed_item->feedapi_node->duplicates)) { + foreach ($feed_item->feedapi_node->duplicates as $fi_nid => $f_nids) { + $feed_item_node = node_load($fi_nid); + $feed_item_node->feedapi_node->feed_nids[$feed_nid] = $feed_nid; + node_object_prepare($feed_item_node); + node_save($feed_item_node); + } + } + else { + node_save($node); + } + + /*if ($feed_item->nid) { + db_query("update {youtube_api_node_cache} set video_id = '%s', video_object = '%s' where nid = %d", $feed_item->video_id, serialize($feed_item), $node->nid); + } + else { + db_query('insert into {youtube_api_node_cache} (nid, video_id, video_object) values (%d, "%s", "%s")', $node->nid, $feed_item->video_id, serialize($feed_item)); + }*/ + + return $feed_item; +} + +function _youtube_api_feedapi_node_unique($feed_item) { + if (isset($feed_item->video_id)) { + $count = db_result(db_query("SELECT fni.nid FROM {feedapi_node_item} fni JOIN {feedapi_node_item_feed} ff ON ff.feed_item_nid = fni.nid WHERE fni.url = '%s' AND ff.feed_nid = %d", $feed_item->video_id, $feed_nid)); + if ($count) { + return FALSE; + } + } + + if ($settings['x_dedupe']) { + if (isset($feed_item->video_id)) { + $result = db_query("SELECT fni.nid, ff.feed_nid FROM {feedapi_node_item} fni JOIN {feedapi_node_item_feed} ff ON ff.feed_item_nid = fni.nid WHERE ff.feed_nid <> %d AND fni.url = '%s'", $feed_nid, $feed_item->video_id); + $i = 0; + while ($existing_feed_item = db_fetch_object($result)) { + $feed_item->feedapi_node->duplicates[$existing_feed_item->nid][] = $existing_feed_item->feed_nid; + } + } + } + + if (isset($feed_item->video_id)) { + return TRUE; + } + return FALSE; +} + /** * Create a video response request. @@ -961,12 +1263,11 @@ function theme_youtube_api_embed($meta, $video, $width = 350, $height = 250, $print_comments = FALSE) { $out = "
". $meta->content ."
"; - $out .= ""; + $out .= ""; + + if ($print_comments) { $comments = youtube_api_get_comments($meta->comments['href'], 1, 5);