/**
  * If user doesn't exist in the datastore, fetch details from instagram API and insert into the datastore.
  * If $reload_from_instagram is true, update existing user details in store with data from instagram API.
  * @param int $user_id instagram user ID
  * @param str $found_in Where the user was found
  * @param str $username
  * @param str $full_name
  * @param str $avatar
  * @param bool $reload_from_instagram Defaults to false; if true will query instagram API and update existing user
  * @return User
  */
 public function fetchUser($user_id, $found_in, $username, $full_name, $avatar, $force_reload_from_instagram = false)
 {
     $this->logger->logInfo("Start fetching user " . $username, __METHOD__ . ',' . __LINE__);
     //assume all users except the instance user is a instagram profile, not a page
     $network = $user_id == $this->instance->network_user_id ? $this->instance->network : 'instagram';
     $user_dao = DAOFactory::getDAO('UserDAO');
     $user_object = null;
     if ($force_reload_from_instagram || !$user_dao->isUserInDB($user_id, $network)) {
         // Get user details and save them to DB
         $user_details = null;
         try {
             $user_details = $this->api_accessor->apiRequest('user', array('user_id' => $user_id));
             $this->logger->logSuccess("Successfully fetched " . $user_id . " " . $network . "'s details from Instagram", __METHOD__ . ',' . __LINE__);
             $user_details->network = $network;
             $user = $this->parseUserDetails($user_details);
         } catch (APICallPermissionDeniedException $e) {
             $user = array();
             $user["user_name"] = $username;
             $user["full_name"] = $full_name;
             $user["user_id"] = $user_id;
             $user["avatar"] = $avatar;
             $user['url'] = '';
             $user["location"] = '';
             $user["description"] = '';
             $user["is_protected"] = 1;
             $user["joined"] = '';
             //Column 'joined' cannot be null
             $user["network"] = 'instagram';
             $this->logger->logInfo("Private user " . $username . " with limited details", __METHOD__ . ',' . __LINE__);
         } catch (APIErrorException $e) {
             $this->logger->logInfo(get_class($e) . " fetching " . $user_id . " " . $network . "'s details from Instagram API, error was " . $e->getMessage(), __METHOD__ . ',' . __LINE__);
         }
         if (isset($user)) {
             $user_object = new User($user, $found_in);
             $updated_user = $user_dao->updateUser($user_object);
             if ($updated_user > 0) {
                 $this->logger->logInfo("Updated user successfully", __METHOD__ . ',' . __LINE__);
             } else {
                 $this->logger->logInfo("No changes to user " . $username, __METHOD__ . ',' . __LINE__);
             }
         } else {
             $this->logger->logInfo("Error parsing user details " . Utils::varDumpToString($user_details), __METHOD__ . ',' . __LINE__);
         }
     } else {
         $this->logger->logInfo("No need to update user ", __METHOD__ . ',' . __LINE__);
     }
     return $user_object;
 }
 /**
  * Check the validity of foursquares OAuth token by requesting the instance user's details.
  * Fetch details from foursquares API for the current instance user and insert into the datastore.
  * @param str $access_token
  * @param str $owner_id
  * @return User
  */
 public function initializeInstanceUser($access_token, $owner_id)
 {
     // Set the network to foursquare
     $network = 'foursquare';
     // Get a new UserDAO
     $user_dao = DAOFactory::getDAO('UserDAO');
     // Set the user object to null as we need to run an isset() on it later to check our code updates it
     $user_object = null;
     // Query the API for the users details
     $user_details = $this->api_accessor->apiRequest('users/self', $this->access_token);
     /* Set the network to foursquare so when we create our user object we know which network the details
      * correspond to
      */
     $user_details->network = $network;
     // Put the JSON details we got back from foursquare into an array
     $user = $this->parseUserDetails($user_details);
     // If this attempt succeed
     if (isset($user)) {
         // Create a new user Object with these details
         $user_object = new User($user, 'Owner initialization');
         // Insert them into the database
         $user_dao->updateUser($user_object);
     }
     if (isset($user_object)) {
         // If the attempt to create a user object succeed put a note in the log
         $this->logger->logSuccess("Successfully fetched " . $user_object->username . " " . $user_object->network . "'s details from foursquare", __METHOD__ . ',' . __LINE__);
     } else {
         // If something went wrong note this in the log
         $this->logger->logInfo("Error fetching " . $owner_id . " " . $network . "'s details from the foursquare API, " . "response was " . Utils::varDumpToString($user_details), __METHOD__ . ',' . __LINE__);
     }
     // Return the user object
     return $user_object;
 }
Example #3
0
 /**
  * For a given post, extract URLs and store them, including image_src if that's from a known source like Twitpic,
  * Twitgoo, Yfrog, Instagr.am.
  * @param str $post_text
  * @param int $post_id
  * @param str $network
  * @param Logger $logger
  * @param arr $urls Array of URLs, optionally set, defaults to null
  */
 public static function processPostURLs($post_text, $post_id, $network, $logger, $urls = null)
 {
     if (!$urls) {
         $urls = Post::extractURLs($post_text);
     }
     if ($urls) {
         $link_dao = DAOFactory::getDAO('LinkDAO');
         $post_dao = DAOFactory::getDAO('PostDAO');
         $post = $post_dao->getPost($post_id, $network);
         if (isset($post->id)) {
             foreach ($urls as $url) {
                 $logger->logInfo("Processing URL {$url}", __METHOD__ . ',' . __LINE__);
                 $image_src = self::getImageSource($url);
                 //if we have an image_src, the URL is a known image source not in need of expansion
                 $expanded_url = $image_src !== '' ? $url : '';
                 $link_array = array('url' => $url, 'expanded_url' => $expanded_url, "image_src" => $image_src, 'post_key' => $post->id);
                 $link = new Link($link_array);
                 try {
                     $link_dao->insert($link);
                     $logger->logSuccess("Inserted " . $url . " " . ($image_src == '' ? '' : "(thumbnail " . $image_src . ") ") . "into links table", __METHOD__ . ',' . __LINE__);
                 } catch (DuplicateLinkException $e) {
                     $logger->logInfo($url . " " . ($image_src == '' ? '' : "(thumbnail " . $image_src . ") ") . " already exists in links table", __METHOD__ . ',' . __LINE__);
                 } catch (DataExceedsColumnWidthException $e) {
                     $logger->logInfo($url . " " . ($image_src == '' ? '' : "(thumbnail " . $image_src . ") ") . " data exceeds table column width", __METHOD__ . ',' . __LINE__);
                 }
             }
         }
     }
 }
 /**
  * If user doesn't exist in the datastore, fetch details from Facebook API and insert into the datastore.
  * If $reload_from_facebook is true, update existing user details in store with data from Facebook API.
  * @param int $user_id Facebook user ID
  * @param str $found_in Where the user was found
  * @param bool $reload_from_facebook Defaults to false; if true will query Facebook API and update existing user
  * @return User
  */
 public function fetchUser($user_id, $found_in, $force_reload_from_facebook = false)
 {
     //assume all users except the instance user is a facebook profile, not a page
     //@TODO: Start supporting users of type 'facebook page'
     $network = $user_id == $this->instance->network_user_id ? $this->instance->network : 'facebook';
     $user_dao = DAOFactory::getDAO('UserDAO');
     $user_object = null;
     if ($force_reload_from_facebook || !$user_dao->isUserInDB($user_id, $network)) {
         // Get owner user details and save them to DB
         $fields = $network != 'facebook page' ? 'id,name,about,location,website' : '';
         $user_details = FacebookGraphAPIAccessor::apiRequest('/' . $user_id, $this->access_token, $fields);
         $user_details->network = $network;
         $user = $this->parseUserDetails($user_details);
         if (isset($user)) {
             $user_object = new User($user, $found_in);
             $user_dao->updateUser($user_object);
         }
         // Record the current number of page likes in follower count table
         if ($network == 'facebook page' && isset($user_details->likes) && !$this->page_like_count_set) {
             $follower_count_dao = DAOFactory::getDAO('FollowerCountDAO');
             $follower_count_dao->insert($this->instance->network_user_id, 'facebook page', $user_details->likes);
             $this->page_like_count_set = true;
         }
         if (isset($user_object)) {
             $this->logger->logSuccess("Successfully fetched " . $user_id . " " . $network . "'s details from Facebook", __METHOD__ . ',' . __LINE__);
         } else {
             //@TODO: Most of these errors occur because TU doesn't yet support users of type 'facebook page'
             //We just assume every user is a vanilla FB user. However, we can't retrieve page details using
             //a vanilla user call here
             $this->logger->logInfo("Error fetching " . $user_id . " " . $network . "'s details from Facebook API, " . "response was " . Utils::varDumpToString($user_details), __METHOD__ . ',' . __LINE__);
         }
     }
     return $user_object;
 }
Example #5
0
 /**
  * If user doesn't exist in the datastore, fetch details from instagram API and insert into the datastore.
  * If $reload_from_instagram is true, update existing user details in store with data from instagram API.
  * @param int $user_id instagram user ID
  * @param str $found_in Where the user was found
  * @param bool $reload_from_instagram Defaults to false; if true will query instagram API and update existing user
  * @return User
  */
 public function fetchUser($user_id, $found_in, $force_reload_from_instagram = false)
 {
     //assume all users except the instance user is a instagram profile, not a page
     $network = $user_id == $this->instance->network_user_id ? $this->instance->network : 'instagram';
     $user_dao = DAOFactory::getDAO('UserDAO');
     $user_object = null;
     if ($force_reload_from_instagram || !$user_dao->isUserInDB($user_id, $network)) {
         // Get owner user details and save them to DB
         $user_details = null;
         try {
             $user_details = InstagramAPIaccessor::apiRequest('user', $user_id, $this->access_token);
         } catch (Instagram\Core\ApiException $e) {
             $this->logger->logInfo("Error fetching " . $user_id . " " . $network . "'s details from Instagram API, " . "error was " . $e->getMessage(), __METHOD__ . ',' . __LINE__);
         }
         if (isset($user_details)) {
             $user_details->network = $network;
             $user = $this->parseUserDetails($user_details);
             if (isset($user)) {
                 $user_object = new User($user, $found_in);
                 $user_dao->updateUser($user_object);
             }
             if (isset($user_object)) {
                 $this->logger->logSuccess("Successfully fetched " . $user_id . " " . $network . "'s details from Instagram", __METHOD__ . ',' . __LINE__);
             } else {
                 $this->logger->logInfo("Error fetching " . $user_id . " " . $network . "'s details from Instagram API, " . "response was " . Utils::varDumpToString($user_details), __METHOD__ . ',' . __LINE__);
             }
         }
     }
     return $user_object;
 }
Example #6
0
 /**
  * For fetching details about a user who does not have a Gooogle Plus ID
  * If user doesn't exist in the datastore, fetch details from YouTube API and insert into the datastore.
  * If $reload_from_youtube is true, update existing user details in store with data from YouTube API.
  * @param int $user_id YouTube user ID
  * @param str $found_in Where the user was found
  * @param bool $reload_from_youtube Defaults to false; if true will query YouTube API and update existing user
  * @return User
  */
 public function fetchUserFromYouTube($user_id, $found_in, $force_reload_from_youtube = false)
 {
     $network = 'youtube';
     $user_dao = DAOFactory::getDAO('UserDAO');
     $user_object = null;
     if ($force_reload_from_youtube || !$user_dao->isUserInDB($user_id, $network)) {
         // Get owner user details and save them to DB
         $fields = array('alt' => 'json');
         if (isset($this->developer_key)) {
             $fields['key'] = $this->developer_key;
         }
         $user_details = $this->youtube_api_v2_accessor->apiRequest('users/' . $user_id_string[sizeof($user_id_string) - 1], $fields);
         $user = $this->parseYouTubeUserDetails($user_details->entry);
         if (isset($user)) {
             $user_object = new User($user, $found_in);
             $user_dao->updateUser($user_object);
         }
         if (isset($user_object)) {
             $this->logger->logSuccess("Successfully fetched " . $user_id . " " . $network . "'s details from YouTube", __METHOD__ . ',' . __LINE__);
         } else {
             $this->logger->logInfo("Error fetching " . $user_id . " " . $network . "'s details from the YouTube API, " . "response was " . Utils::varDumpToString($user_details), __METHOD__ . ',' . __LINE__);
         }
     }
     return $user_object;
 }
 /**
  * Check the validity of G+'s OAuth token by requestig the instance user's details.
  * Fetch details from Google+ API for the current instance user and insert into the datastore.
  * @param str $client_id
  * @param str $client_secret
  * @param str $access_token
  * @param str $refresh_token
  * @param str $owner_id
  * @return User
  */
 public function initializeInstanceUser($client_id, $client_secret, $access_token, $refresh_token, $owner_id)
 {
     $network = 'google+';
     $user_dao = DAOFactory::getDAO('UserDAO');
     $user_object = null;
     // Get owner user details and save them to DB
     $fields = array('fields' => 'displayName,id,image,tagline');
     $user_details = $this->api_accessor->apiRequest('people/me', $this->access_token, $fields);
     if (isset($user_details->error->code) && $user_details->error->code == '401') {
         //Token has expired, fetch and save a new one
         $tokens = self::getOAuthTokens($client_id, $client_secret, $refresh_token, 'refresh_token');
         $owner_instance_dao = DAOFactory::getDAO('OwnerInstanceDAO');
         $owner_instance_dao->updateTokens($owner_id, $this->instance->id, $access_token, $refresh_token);
         $this->access_token = $tokens->access_token;
         //try again
         $user_details = $this->api_accessor->apiRequest('people/me', $this->access_token, $fields);
     }
     $user_details->network = $network;
     $user = $this->parseUserDetails($user_details);
     if (isset($user)) {
         $user_object = new User($user, 'Owner initialization');
         $user_dao->updateUser($user_object);
     }
     if (isset($user_object)) {
         $this->logger->logSuccess("Successfully fetched " . $user_object->username . " " . $user_object->network . "'s details from Google+", __METHOD__ . ',' . __LINE__);
     } else {
         $this->logger->logInfo("Error fetching " . $user_id . " " . $network . "'s details from the Google+ API, " . "response was " . Utils::varDumpToString($user_details), __METHOD__ . ',' . __LINE__);
     }
     return $user_object;
 }
 /**
  * If link is an image (Twitpic/Twitgoo/Yfrog/Flickr for now), insert direct path to thumb as expanded url.
  * @TODO Move image thumbnail processng to Expand URLs plugin.
  * @param Logger $logger
  * @param str $tweet
  * @param Array $urls
  */
 public static function processTweetURLs($logger, $tweet, $urls = null)
 {
     $link_dao = DAOFactory::getDAO('LinkDAO');
     if (!$urls) {
         $urls = Post::extractURLs($tweet['post_text']);
     }
     foreach ($urls as $u) {
         $logger->logInfo("processing url: {$u}", __METHOD__ . ',' . __LINE__);
         $is_image = 0;
         $title = '';
         $eurl = '';
         if (substr($u, 0, strlen('http://twitpic.com/')) == 'http://twitpic.com/') {
             $eurl = 'http://twitpic.com/show/thumb/' . substr($u, strlen('http://twitpic.com/'));
             $is_image = 1;
         } elseif (substr($u, 0, strlen('http://yfrog.com/')) == 'http://yfrog.com/') {
             $eurl = $u . '.th.jpg';
             $is_image = 1;
         } elseif (substr($u, 0, strlen('http://twitgoo.com/')) == 'http://twitgoo.com/') {
             $eurl = 'http://twitgoo.com/show/thumb/' . substr($u, strlen('http://twitgoo.com/'));
             $is_image = 1;
         } elseif (substr($u, 0, strlen('http://picplz.com/')) == 'http://picplz.com/') {
             $eurl = $u . '/thumb/';
             $is_image = 1;
         } elseif (substr($u, 0, strlen('http://flic.kr/')) == 'http://flic.kr/') {
             $is_image = 1;
         } elseif (substr($u, 0, strlen('http://instagr.am/')) == 'http://instagr.am/') {
             $is_image = 1;
         }
         if ($link_dao->insert($u, $eurl, $title, $tweet['post_id'], 'twitter', $is_image)) {
             $logger->logSuccess("Inserted " . $u . " (" . $eurl . ", " . $is_image . "), into links table", __METHOD__ . ',' . __LINE__);
         } else {
             $logger->logError("Did NOT insert " . $u . " (" . $eurl . ") into links table", __METHOD__ . ',' . __LINE__);
         }
     }
 }
Example #9
0
    /**
     * Fetch a save the posts and replies on a Facebook page.
     * @param int $pid Page ID
     */
    public function fetchPagePostsAndReplies($pid) {
        $stream = FacebookGraphAPIAccessor::apiRequest('/'.$pid.'/posts', $this->access_token);

        if (isset($stream->data) && is_array($stream->data) && sizeof($stream->data > 0)) {
            $this->logger->logSuccess(sizeof($stream->data)." Facebook posts found for page ID $pid.",
            __METHOD__.','.__LINE__);

            $thinkup_data = $this->parseStream($stream, 'facebook page');
            $posts = $thinkup_data["posts"];

            $post_dao = DAOFactory::getDAO('PostDAO');
            $added_posts = 0;
            foreach ($posts as $post) {
                if ($post['author_username']== "" && isset($post['author_user_id'])) {
                    $commenter_object = $this->fetchUserInfo($post['author_user_id'], 'facebook',
                    'Facebook page comments');
                    if (isset($commenter_object)) {
                        $post["author_username"] = $commenter_object->full_name;
                        $post["author_fullname"] = $commenter_object->full_name;
                        $post["author_avatar"] = $commenter_object->avatar;
                    }
                }

                $added_posts = $added_posts + $post_dao->addPost($post);
                $this->logger->logInfo("Added post ID ".$post["post_id"]." on ".$post["network"].
                " for ".$post["author_username"].":".$post["post_text"], __METHOD__.','.__LINE__);
            }

            $added_users = 0;
            $users = $thinkup_data["users"];
            if (count($users) > 0) {
                foreach ($users as $user) {
                    $user["post_count"] = $post_dao->getTotalPostsByUser($user['user_id'], $user['network']);
                    $found_in = 'Facebook page stream';
                    $user_object = new User($user, $found_in);
                    $user_dao = DAOFactory::getDAO('UserDAO');
                    $user_dao->updateUser($user_object);
                    $added_users = $added_users + 1;
                }
            }
            if ($added_posts > 0 || $added_users > 0) {
                $this->logger->logUserSuccess($added_posts." post(s) added; ".$added_users." user(s) updated.",
                __METHOD__.','.__LINE__);
            } else {
                $this->logger->logUserInfo("No new page posts found.", __METHOD__.','.__LINE__);
            }
        } else {
            $this->logger->logInfo("No Facebook posts found for page ID $pid", __METHOD__.','.__LINE__);
        }
    }
 /**
  * If link is an image (Twitpic/Twitgoo/Yfrog/Flickr for now), insert direct path to thumb as expanded url.
  * @TODO Move image thumbnail processng to Expand URLs plugin.
  * @param Logger $logger
  * @param str $tweet
  * @param Array $urls
  */
 public static function processTweetURLs($logger, $tweet, $urls = null)
 {
     $link_dao = DAOFactory::getDAO('LinkDAO');
     if (!$urls) {
         $urls = Post::extractURLs($tweet['post_text']);
     }
     foreach ($urls as $u) {
         $logger->logInfo("processing url: {$u}", __METHOD__ . ',' . __LINE__);
         $is_image = 0;
         $title = '';
         $eurl = '';
         if (substr($u, 0, strlen('http://twitpic.com/')) == 'http://twitpic.com/') {
             $eurl = 'http://twitpic.com/show/thumb/' . substr($u, strlen('http://twitpic.com/'));
             $is_image = 1;
         } elseif (substr($u, 0, strlen('http://yfrog.com/')) == 'http://yfrog.com/') {
             $eurl = $u . '.th.jpg';
             $is_image = 1;
         } elseif (substr($u, 0, strlen('http://twitgoo.com/')) == 'http://twitgoo.com/') {
             $eurl = 'http://twitgoo.com/show/thumb/' . substr($u, strlen('http://twitgoo.com/'));
             $is_image = 1;
         } elseif (substr($u, 0, strlen('http://picplz.com/')) == 'http://picplz.com/') {
             $eurl = $u . '/thumb/';
             $is_image = 1;
         } elseif (substr($u, 0, strlen('http://flic.kr/')) == 'http://flic.kr/') {
             $is_image = 1;
         } elseif (substr($u, 0, strlen('http://instagr.am/')) == 'http://instagr.am/') {
             // see: http://instagr.am/developer/embedding/ for reference
             // the following does a redirect to the actual jpg
             // make a check for an end slash in the url -- if it is there (likely) then adding a second
             // slash prior to the 'media' string will break the expanded url
             if ($u[strlen($u) - 1] == '/') {
                 $eurl = $u . 'media/';
             } else {
                 $eurl = $u . '/media/';
             }
             $logger->logDebug("expanded instagram URL to: " . $eurl, __METHOD__ . ',' . __LINE__);
             $is_image = 1;
         }
         if ($link_dao->insert($u, $eurl, $title, $tweet['post_id'], 'twitter', $is_image)) {
             $logger->logSuccess("Inserted " . $u . " (" . $eurl . ", " . $is_image . "), into links table", __METHOD__ . ',' . __LINE__);
         } else {
             $logger->logError("Did NOT insert " . $u . " (" . $eurl . ") into links table", __METHOD__ . ',' . __LINE__);
         }
     }
 }
Example #11
0
 /**
  * For a given post, extract URLs and store them, including image_src if that's from a known source like Twitpic,
  * Twitgoo, Yfrog, Instagr.am.
  * @param str $post_text
  * @param int $post_id
  * @param str $network
  * @param Logger $logger
  * @param arr $urls Array of URLs, optionally set, defaults to null
  */
 public static function processPostURLs($post_text, $post_id, $network, $logger, $urls = null)
 {
     if (!$urls) {
         $urls = Post::extractURLs($post_text);
     }
     if ($urls) {
         $link_dao = DAOFactory::getDAO('LinkDAO');
         foreach ($urls as $url) {
             $logger->logInfo("Processing URL: {$url}", __METHOD__ . ',' . __LINE__);
             $image_src = self::getImageSource($url);
             //if we have an image_src, the URL is a known image source not in need of expansion
             $expanded_url = isset($image_src) ? $url : '';
             $link_array = array('url' => $url, 'expanded_url' => $expanded_url, "image_src" => $image_src, 'post_id' => $post_id, 'network' => $network);
             $link = new Link($link_array);
             if ($link_dao->insert($link)) {
                 $logger->logSuccess("Inserted " . $url . " (thumbnail " . $image_src . "), into links table", __METHOD__ . ',' . __LINE__);
             } else {
                 $logger->logError("Did NOT insert " . $url . " (thumbnail " . $image_src . ") into links table", __METHOD__ . ',' . __LINE__);
             }
         }
     }
 }
 /**
  * Fetch the instance user's friends' tweets.
  */
 public function fetchInstanceUserFriends()
 {
     if (!isset($this->user)) {
         $this->fetchInstanceUserInfo();
     }
     if (isset($this->user)) {
         $fd = DAOFactory::getDAO('FollowDAO');
         $this->instance->total_friends_in_system = $fd->countTotalFriends($this->instance->network_user_id, 'twitter');
         if ($this->instance->total_friends_in_system < $this->user->friend_count) {
             $this->instance->is_archive_loaded_friends = false;
             $this->logger->logUserInfo($this->instance->total_friends_in_system . " friends in system, " . $this->user->friend_count . " friends according to Twitter; Friend archive is not loaded", __METHOD__ . ',' . __LINE__);
         } else {
             $this->instance->is_archive_loaded_friends = true;
             $this->logger->logInfo("Friend archive loaded", __METHOD__ . ',' . __LINE__);
         }
         $status_message = "";
         // Fetch friend pages
         $continue_fetching = true;
         $updated_follow_count = 0;
         $inserted_follow_count = 0;
         while ($this->api->available && $this->api->available_api_calls_for_crawler > 0 && $continue_fetching && !$this->instance->is_archive_loaded_friends) {
             $friend_ids = $this->api->cURL_source['following'];
             $args = array();
             if (!isset($next_cursor)) {
                 $next_cursor = -1;
             }
             $args['cursor'] = strval($next_cursor);
             try {
                 list($cURL_status, $twitter_data) = $this->api->apiRequest($friend_ids, $args);
             } catch (APICallLimitExceededException $e) {
                 break;
             }
             if ($cURL_status > 200) {
                 $continue_fetching = false;
             } else {
                 $status_message = "Parsing XML. ";
                 $status_message .= "Cursor " . $next_cursor . ":";
                 $users = $this->api->parseXML($twitter_data);
                 $next_cursor = $this->api->getNextCursor();
                 $status_message .= count($users) . " friends queued to update. ";
                 $this->logger->logInfo($status_message, __METHOD__ . ',' . __LINE__);
                 $status_message = "";
                 if (count($users) == 0) {
                     $this->instance->is_archive_loaded_friends = true;
                 }
                 foreach ($users as $u) {
                     $utu = new User($u, 'Friends');
                     $this->user_dao->updateUser($utu);
                     // add/update follow relationship
                     if ($fd->followExists($utu->user_id, $this->instance->network_user_id, 'twitter')) {
                         //update it
                         if ($fd->update($utu->user_id, $this->instance->network_user_id, 'twitter', Utils::getURLWithParams($friend_ids, $args))) {
                             $updated_follow_count++;
                         }
                     } else {
                         //insert it
                         if ($fd->insert($utu->user_id, $this->instance->network_user_id, 'twitter', Utils::getURLWithParams($friend_ids, $args))) {
                             $inserted_follow_count++;
                         }
                     }
                 }
                 $this->logger->logSuccess("Cursor at " . strval($next_cursor), __METHOD__ . ',' . __LINE__);
             }
         }
         if ($updated_follow_count > 0 || $inserted_follow_count > 0) {
             $status_message = $updated_follow_count . " people " . $this->instance->network_username . " follows updated; " . $inserted_follow_count . " new follow(s) inserted.";
             $this->logger->logUserSuccess($status_message, __METHOD__ . ',' . __LINE__);
         }
     }
 }
 /**
  * Fetch the instance user's friends.
  */
 public function fetchInstanceUserFriends()
 {
     if (!isset($this->user)) {
         $this->fetchInstanceUserInfo();
     }
     if (isset($this->user)) {
         $follow_dao = DAOFactory::getDAO('FollowDAO');
         $this->instance->total_friends_in_system = $follow_dao->countTotalFriends($this->instance->network_user_id, 'twitter');
         $this->logger->logUserInfo($this->instance->total_friends_in_system . " friends in system, " . $this->user->friend_count . " friends according to Twitter", __METHOD__ . ',' . __LINE__);
         if ($this->instance->total_friends_in_system < $this->user->friend_count) {
             $this->instance->is_archive_loaded_friends = false;
         } elseif ($this->instance->total_friends_in_system > $this->user->friend_count) {
             $this->instance->is_archive_loaded_friends = true;
             $this->cleanUpFollows($friends_only = true);
         } else {
             $this->instance->is_archive_loaded_friends = true;
             $this->logger->logInfo("Friend archive loaded", __METHOD__ . ',' . __LINE__);
         }
         $status_message = "";
         // Fetch friend pages
         $continue_fetching = true;
         $updated_follow_count = 0;
         $inserted_follow_count = 0;
         while ($continue_fetching && !$this->instance->is_archive_loaded_friends) {
             $endpoint = $this->api->endpoints['following'];
             $args = array();
             if (!isset($next_cursor)) {
                 $next_cursor = -1;
             }
             $args['cursor'] = strval($next_cursor);
             $args['skip_status'] = 'true';
             $args['include_user_entities'] = 'false';
             try {
                 list($http_status, $payload) = $this->api->apiRequest($endpoint, $args);
             } catch (APICallLimitExceededException $e) {
                 $this->logger->logInfo($e->getMessage(), __METHOD__ . ',' . __LINE__);
                 break;
             }
             if ($http_status > 200) {
                 $continue_fetching = false;
             } else {
                 $status_message = "Parsing JSON. ";
                 $status_message .= "Cursor " . $next_cursor . ":";
                 $users = $this->api->parseJSONUsers($payload);
                 $next_cursor = $this->api->getNextCursor();
                 $status_message .= count($users) . " friends queued to update. ";
                 $this->logger->logInfo($status_message, __METHOD__ . ',' . __LINE__);
                 $status_message = "";
                 if (count($users) == 0) {
                     $this->instance->is_archive_loaded_friends = true;
                 }
                 foreach ($users as $u) {
                     $user_to_update = new User($u, 'Friends');
                     $this->user_dao->updateUser($user_to_update);
                     // add/update follow relationship
                     $does_follow_exist = $follow_dao->followExists($user_to_update->user_id, $this->instance->network_user_id, 'twitter');
                     if ($does_follow_exist) {
                         //update it
                         if ($follow_dao->update($user_to_update->user_id, $this->instance->network_user_id, 'twitter')) {
                             $updated_follow_count++;
                         }
                     } else {
                         //insert it
                         if ($follow_dao->insert($user_to_update->user_id, $this->instance->network_user_id, 'twitter')) {
                             $inserted_follow_count++;
                         }
                     }
                 }
                 $this->logger->logSuccess("Cursor at " . strval($next_cursor), __METHOD__ . ',' . __LINE__);
             }
         }
         if ($updated_follow_count > 0 || $inserted_follow_count > 0) {
             $status_message = $updated_follow_count . " people " . $this->instance->network_username . " follows updated; " . $inserted_follow_count . " new follow(s) inserted.";
             $this->logger->logUserSuccess($status_message, __METHOD__ . ',' . __LINE__);
         }
     }
 }