You are here

function tweet_feed_save_tweet in Tweet Feed 7.3

Same name and namespace in other branches
  1. 7.2 tweet_feed.module \tweet_feed_save_tweet()

Save The Tweet (and profile)

Save our tweet data and (optionally) profile if site is configured to do so.

2 calls to tweet_feed_save_tweet()
tweet_feed_cron in ./tweet_feed.module
Implements hook_cron().
tweet_feed_process_tweets in ./tweet_feed.module
Process each tweet
1 string reference to 'tweet_feed_save_tweet'
tweet_feed_run_import in ./tweet_feed_admin.inc
Run the Import

File

./tweet_feed.module, line 734

Code

function tweet_feed_save_tweet($tweet, $feed, $update_node_id = 0, $hash = NULL, $cron = FALSE) {

  // Get the creation time of the tweet and store it.
  $creation_timestamp = strtotime($tweet->created_at);

  // Add our hash tags to the hashtag taxonomy. If it already exists, then get the tid
  // for that term. Returns an array of tid's for hashtags used.
  $hashtags = tweet_feed_process_taxonomy($tweet->entities->hashtags, 'hashtag_terms');

  // If hashtags comes back as false, then we have a problem and need to quit.
  // Using our custom bail function since this could be a drush command or a web
  // interface call and we need to be able to handle accordingly.
  if ($hashtags === FALSE) {
    tweet_feed_bail();
  }

  // Add our user mentions to it's relative taxonomy. Handled just like hashtags
  $user_mentions = tweet_feed_process_taxonomy($tweet->entities->user_mentions, 'user_mention_terms');

  // If user_mentions comes back as false, then we have a problem and need to quit.
  if ($user_mentions === FALSE) {
    tweet_feed_bail();
  }

  // Lists have a different object than timelines or searches. Nice twitter.
  if (!empty($tweet->retweeted_status)) {
    $tweet_text = 'RT @' . $tweet->retweeted_status->user->screen_name . ': ' . $tweet->retweeted_status->full_text;
  }
  else {
    if ($feed->query_type == QUERY_LIST) {
      $tweet_text = $tweet->text;
    }
    else {
      $tweet_text = $tweet->full_text;
    }
  }

  // Process the tweet. This linkes our twitter names, hash tags and converts any
  // URL's into HTML.
  $tweet_html = tweet_feed_format_output($tweet_text, $feed->new_window, $feed->hash_taxonomy, $hashtags);

  // Populate our node object with the data we will need to save
  $node = new stdClass();
  $node->created = $creation_timestamp;

  // If we are being passed a node id for updating, then set it here so we update that
  // node. (might be an edge case)
  if ($update_node_id > 0) {
    $node->nid = $update_node_id;
    node_load($node->nid);
  }

  // Because we modify the tweet to get source images, we need to get the hash before
  // we do any of our processing
  $tweet_hash = md5(serialize($tweet_text));

  // If we are being provided a hash, we compare against this hash and if they are equal
  // then there is nothing to do
  if ($tweet_hash == $hash) {
    return NULL;
  }

  // Get started with our node data structure
  $node->type = 'twitter_tweet_feed';
  $node->uid = 1;

  // We need to respect the default state of the content type for tweets. If set to
  // unpublished, then we need to set the status to zero not one.
  $node_type = variable_get('node_options_twitter_tweet_feed', array());

  // If the node type has not been updated, assume published.
  if (empty($node_type)) {
    $node_type = [
      'status',
    ];
  }
  $node->status = in_array('status', $node_type);
  $node->comment = 0;
  $node->promote = in_array('promote', $node_type);
  $node->moderate = 0;
  $node->sticky = in_array('sticky', $node_type);
  $node->language = LANGUAGE_NONE;

  // Check to see if utf8mb4 is available and configured.
  $connection = Database::getConnection();
  $utf8mb4_configurable = $connection
    ->utf8mb4IsConfigurable();
  $utf8mb4_active = $connection
    ->utf8mb4IsActive();
  $utf8mb4_supported = $connection
    ->utf8mb4IsSupported();
  $utf8 = $utf8mb4_configurable && $utf8mb4_active && $utf8mb4_supported ? TRUE : FALSE;

  // NOTE: Support for non Multibyte-extended UTF-8 tables is deprecated. Support for them is likely to go away
  // sooner rather than later.
  if ($utf8 === TRUE) {
    $node->title = mb_substr(check_plain($tweet->user->screen_name) . ': ' . check_plain($tweet_text), 0, 255);

    // The tweet itself goes into the tweet contents field
    $node->field_tweet_contents[$node->language][0] = array(
      'value' => $tweet_html,
      'format' => 'full_html',
    );

    // Save the name of the user to the tweet.
    $node->field_tweet_author_name[$node->language][0]['value'] = $tweet->user->name;
  }
  else {

    // Filter it cleanly since it is going into the title field and remove iconv.
    $node->title = mb_substr(check_plain(tweet_feed_filter_iconv_text(tweet_feed_filter_smart_quotes($tweet->user->screen_name)) . ': ' . tweet_feed_filter_iconv_text(tweet_feed_filter_smart_quotes($tweet_text))), 0, 255);

    // The tweet itself goes into the tweet contents field
    $node->field_tweet_contents[$node->language][0] = array(
      'value' => htmlspecialchars_decode(utf8_encode(tweet_feed_filter_smart_quotes($tweet_html))),
      'format' => 'full_html',
    );

    // Save the name of the user to the tweet.
    $node->field_tweet_author_name[$node->language][0]['value'] = tweet_feed_filter_iconv_text(tweet_feed_filter_smart_quotes($tweet->user->name));
  }

  // Set our verified field
  $node->field_tweet_author_verified[$node->language][0]['value'] = (int) $tweet->user->verified;

  // Save the feed ID for this tweet
  $node->field_tweet_feed_id[$node->language][0]['value'] = $feed->fid;

  // Geographic Information if it exist
  if (!empty($tweet->place) && is_object($tweet->place)) {
    $bb = json_encode($tweet->place->bounding_box->coordinates[0]);
    $node->field_geographic_coordinates[$node->language][0] = array(
      'value' => $bb,
      'safe_value' => $bb,
    );
  }

  // Handle user mentions (our custom field defined by the module). Also places them in
  // the user mentions taxonomy.
  if (!empty($tweet->entities->media) && is_array($tweet->entities->media) && variable_get('tweet_feed_fetch_images', 1)) {
    foreach ($tweet->entities->media as $key => $media) {
      if (is_object($media)) {
        $image = file_get_contents($media->media_url . ':large');
        if (!empty($image)) {
          tweet_feed_check_path('public://tweet-feed-tweet-images');
          $file_temp = file_save_data($image, 'public://tweet-feed-tweet-images/' . $tweet->id_str . '.jpg', FILE_EXISTS_REPLACE);
          if (is_object($file_temp)) {
            $file = array();
            $file[$node->language][0] = array(
              'fid' => $file_temp->fid,
              'filename' => $file_temp->filename,
              'filemime' => $file_temp->filemime,
              'uid' => 1,
              'uri' => $file_temp->uri,
              'status' => 1,
            );
            $node->field_tweet_linked_images = $file;
          }
          unset($file);
          unset($file_temp);
          unset($image);
        }
      }
    }
  }

  // If we have a place, then assign it based on which components we have available
  // to us.
  if (!empty($tweet->place->full_name)) {
    $node->field_geographic_place[$node->language][0] = array(
      'value' => $tweet->place->full_name,
      'safe_value' => $tweet->place->full_name,
    );
    if (!empty($tweet->place->country)) {
      $node->field_geographic_place[$node->language][0]['value'] .= ', ' . $tweet->place->country;
      $node->field_geographic_place[$node->language][0]['safe_value'] .= ', ' . $tweet->place->country;
    }
  }
  if ($utf8 === TRUE) {

    // Handle the author name
    $node->field_tweet_author[$node->language][0] = array(
      'value' => $tweet->user->screen_name,
      'safe_value' => $tweet->user->screen_name,
    );
  }
  else {
    $node->field_tweet_author[$node->language][0] = array(
      'value' => tweet_feed_filter_iconv_text(tweet_feed_filter_smart_quotes($tweet->user->screen_name)),
      'safe_value' => tweet_feed_filter_iconv_text(tweet_feed_filter_smart_quotes($tweet->user->screen_name)),
    );
  }

  // Handle the author id
  $node->field_tweet_author_id[$node->language][0] = array(
    'value' => $tweet->user->id,
    'safe_value' => $tweet->user->id,
  );

  // Handle the tweet creation date
  $created_dt = DateTime::createFromFormat('D M d H:i:s O Y', $tweet->created_at);
  $node->field_tweet_creation_date[$node->language][0] = array(
    'value' => $created_dt
      ->format('Y-m-d H:i:s'),
    'timezone' => 'UTC/GMT',
    'timezone_db' => 'UTC/GMT',
    'datatype' => 'datetime',
  );

  // Handle the tweet id
  $node->field_tweet_id[$node->language][0] = array(
    'value' => $tweet->id_str,
    'safe_value' => $tweet->id_str,
  );

  // Handle the favorite count for this tweet
  $node->field_twitter_favorite_count[$node->language][0]['value'] = $tweet->favorite_count;

  // Handle the hashtags
  foreach ($hashtags as $hashtag) {
    $node->field_twitter_hashtags[$node->language][] = array(
      'target_id' => $hashtag,
    );
  }

  // Handle the re-tweet count
  $node->field_twitter_retweet_count[$node->language][0]['value'] = $tweet->retweet_count;

  // Handle the tweet source
  $node->field_tweet_source[$node->language][0] = array(
    'value' => $tweet->source,
    'safe_value' => strip_tags($tweet->source),
  );

  // Create a direct link to this tweet
  $node->field_link_to_tweet[$node->language][0]['value'] = 'https://twitter.com/' . $tweet->user->screen_name . '/status/' . $tweet->id_str;

  // Handle user mentions (our custom field defined by the module). Also places them in
  // the user mentions taxonomy.
  if (!empty($tweet->entities->user_mentions) && is_array($tweet->entities->user_mentions)) {
    foreach ($tweet->entities->user_mentions as $key => $mention) {
      if ($utf8 == TRUE) {
        $node->field_tweet_user_mentions[$node->language][$key] = array(
          'tweet_feed_mention_name' => $mention->name,
          'tweet_feed_mention_screen_name' => $mention->screen_name,
          'tweet_feed_mention_id' => $mention->id,
        );
      }
      else {
        $node->field_tweet_user_mentions[$node->language][$key] = array(
          'tweet_feed_mention_name' => tweet_feed_filter_iconv_text(tweet_feed_filter_smart_quotes($mention->name)),
          'tweet_feed_mention_screen_name' => tweet_feed_filter_iconv_text(tweet_feed_filter_smart_quotes($mention->screen_name)),
          'tweet_feed_mention_id' => $mention->id,
        );
      }
    }
    foreach ($user_mentions as $mention) {
      $node->field_twitter_mentions_in_tweet[$node->language][] = array(
        'target_id' => $mention,
      );
    }
  }

  // Not sure about this method of getting the big twitter profile image, but we're
  // going to roll with it for now.
  $tweet->user->profile_image_url = str_replace('_normal', '', $tweet->user->profile_image_url);

  // Handle the profile image obtained from twitter.com
  $file = tweet_feed_process_twitter_image($tweet->user->profile_image_url, 'tweet-feed-profile-image', $tweet->id_str);
  if ($file !== NULL) {
    $node->field_profile_image[$node->language][0] = (array) $file;
  }

  /// Allow other modules to alter the node about to be saved
  drupal_alter('tweet_feed_tweet_save', $node, $tweet);
  if (empty($node)) {
    return;
  }

  // Save the node
  node_save($node);
  $nid = $node->nid;

  // Make sure the hash in our tweet_hashes table is right by deleting what is there
  // for this node and updating
  db_delete('tweet_hashes')
    ->condition('nid', $node->nid)
    ->execute();
  $hash_insert = array(
    'tid' => $tweet->id_str,
    'nid' => $node->nid,
    'hash' => $tweet_hash,
  );
  db_insert('tweet_hashes')
    ->fields($hash_insert)
    ->execute();

  // Unset the node variable so we can re-use it
  unset($node);

  // If we are creating a user profile for the person who made this tweet, then we need
  // to either create it or update it here. To determine create/update we need to check
  // the hash of the profile id and see if it matches our data.
  if (variable_get('tweet_feed_get_tweeter_profiles', FALSE) == TRUE) {
    $user_hash = md5(serialize($tweet->user));

    // See if we have a profile for the author if this tweet. If we do not then we do not
    // need to do the rest of the checks
    $query = new EntityFieldQuery();
    $result = $query
      ->entityCondition('entity_type', 'node')
      ->entityCondition('bundle', 'twitter_user_profile')
      ->fieldCondition('field_twitter_user_id', 'value', $tweet->user->id, '=')
      ->execute();

    // If we have a result, then we have a profile! Then we need to check to see if the hash
    // of the profile is the same as the hash of the user data. If so, then update. If not,
    // then skip and on to the next
    if (isset($result['node'])) {
      $result = db_select('tweet_user_hashes', 'h')
        ->fields('h', array(
        'nid',
        'tuid',
        'hash',
      ))
        ->condition('h.tuid', $tweet->user->id)
        ->execute();
      if ($result
        ->rowCount() > 0) {
        $tdata = $result
          ->fetchObject();

        // If our hashes are equal, we have nothing to update and can move along
        if ($user_hash == $tdata->hash) {
          return;
        }
        else {
          $update_node_id = $tdata->nid;
        }
      }
    }

    // Populate our node object with the data we will need to save
    $node = new stdClass();

    // If we are being passed a node id for updating, then set it here so we update that
    // node. (might be an edge case)
    if ($update_node_id > 0) {
      $node->nid = $update_node_id;
    }

    // Initialize the standard parts of our tweeting node.
    $node->type = 'twitter_user_profile';
    $node->uid = 1;
    $node->created = $creation_timestamp;
    $node->status = 1;
    $node->comment = 0;
    $node->promote = 0;
    $node->moderate = 0;
    $node->sticky = 0;
    $node->language = LANGUAGE_NONE;
    $node->field_twitter_user_id[$node->language][0]['value'] = $tweet->user->id_str;
    $node->title = $tweet->user->name;
    if ($utf8 == TRUE) {
      $node->body[$node->language][0]['value'] = $tweet->user->description;
      $node->field_twitter_a_screen_name[$node->language][0]['value'] = $tweet->user->screen_name;
    }
    else {
      $node->body[$node->language][0]['value'] = tweet_feed_filter_iconv_text(tweet_feed_filter_smart_quotes($tweet->user->description));
      $node->field_twitter_a_screen_name[$node->language][0]['value'] = tweet_feed_filter_iconv_text(tweet_feed_filter_smart_quotes($tweet->user->screen_name));
    }
    $node->field_twitter_location[$node->language][0]['value'] = $tweet->user->location;
    $node->field_twitter_a_profile_url[$node->language][0]['value'] = $tweet->user->entities->url->urls[0]->url;
    $node->field_twitter_profile_url[$node->language][0]['value'] = $tweet->user->entities->url->urls[0]->display_url;
    $node->field_twitter_followers[$node->language][0]['value'] = $tweet->user->followers_count;
    $node->field_twitter_following[$node->language][0]['value'] = $tweet->user->friends_count;
    $node->field_twitter_favorites_count[$node->language][0]['value'] = $tweet->user->favourites_count;
    $node->field_twitter_tweet_count[$node->language][0]['value'] = $tweet->user->statuses_count;
    $node->field_tweet_author_verified[$node->language][0]['value'] = (int) $tweet->user->verified;

    // Handle the profile background image obtained from twitter.com
    $file = tweet_feed_process_twitter_image($tweet->user->profile_background_image_url, 'tweet-feed-profile-background-image', $tweet->user->id_str);
    if ($file !== NULL) {
      $node->field_background_image[$node->language][0] = (array) $file;
    }

    // Handle the user profile image obtained from twitter.com
    $file = tweet_feed_process_twitter_image($tweet->user->profile_image_url, 'tweet-feed-profile-user-profile-image', $tweet->user->id_str);
    if ($file !== NULL) {
      $node->field_profile_image[$node->language][0] = (array) $file;
    }

    // Handle the user profile banner image obtained from twitter.com
    $file = tweet_feed_process_twitter_image($tweet->user->profile_banner_url, 'tweet-feed-profile-banner-image', $tweet->user->id_str);
    if ($file !== NULL) {
      $node->field_banner_image[$node->language][0] = (array) $file;
    }
    $node->field_background_color[$node->language][0]['value'] = $tweet->user->profile_background_color;
    $node->field_profile_text_color[$node->language][0]['value'] = $tweet->user->profile_text_color;
    $node->field_link_color[$node->language][0]['value'] = $tweet->user->profile_link_color;
    $node->field_sidebar_border_color[$node->language][0]['value'] = $tweet->user->profile_sidebar_border_color;
    $node->field_sidebar_fill_color[$node->language][0]['value'] = $tweet->user->profile_sidebar_fill_color;
    node_save($node);

    // Make sure the hash in our tweet_hashes table is right by deleting what is there
    // for this node and updating
    db_delete('tweet_user_hashes')
      ->condition('nid', $node->nid)
      ->execute();
    $hash_insert = array(
      'tuid' => $tweet->user->id_str,
      'nid' => $node->nid,
      'hash' => $user_hash,
    );
    db_insert('tweet_user_hashes')
      ->fields($hash_insert)
      ->execute();
  }
}