How to Get Twitter User Data (Part 2)

by on June 13, 2011

In the first article in this series, we presented background and usage information for A Shortcode To Get Twitter User Data.

Today, we'll present the various PHP functions which make this happen. Be SURE to put ALL of them in your theme's functions.php file. We used separate functions so that you can easily utilize them in your own plugins and other WordPress extensions.

You can also grab the entire collection of functions here.

Our Shortcode Handler

Basically, our shortcode handler merely calls the supporting functions. However, it does do a little post-processing.

Code: PHP (plus WordPress)wcs_tud Shortcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
add_shortcode('wcs_twitter_user_data', 'wcs_twitter_user_data_shortcode_handler');
 
add_shortcode('wcs_tud', 'wcs_twitter_user_data_shortcode_handler');
 
function wcs_twitter_user_data_shortcode_handler($atts)
{
    // extract parameters
    $parms = shortcode_atts(array(
        'user' => 'wordpress',
        'data' => 'status',
        'time_format' => 'F j, Y (g:i a)',
        'conv_lang_name' => 'true',
        'cache_hours' => '1',
        'force_update' => 'false',
        ), $atts);
 
    $user = strtolower($parms['user']);
    $data = strtolower($parms['data']);
    $time_format = $parms['time_format'];
    $conv_lang_name = $parms['conv_lang_name'];
    $cache_hours = intval($parms['cache_hours']);
    $force_update = strtolower($parms['force_update']);
 
    // process t/f options
    $b_conv_lang_name = false;
    if (($conv_lang_name == 'yes') || ($conv_lang_name == 'y') ||
        ($conv_lang_name == 'true') || ($conv_lang_name == '1'))
    {$b_conv_lang_name = true;}
 
    $b_force_update = false;
    if (($force_update == 'yes') || ($force_update == 'y') ||
        ($force_update == 'true') || ($force_update == '1'))
    {$b_force_update = true;}
 
    // prepare to get data
    $transient_name = '_wcs_tud_' . $user;
    $tud = array();
 
    // get the data
    if (($b_force_update == true) || (get_transient($transient_name) === false))
    {
        // fill the array
        $tud = wcs_twitter_get_user_data(
                $user,
                $time_format,
                $b_conv_lang_name);
        // save in the transient cache
        $cache = urlencode(serialize($tud));
        set_transient($transient_name, $cache, 60*60*$cache_hours);
    }
    else
    {
        $cache = get_transient($transient_name);
        $tud = unserialize(urldecode($cache));
    }
 
    // return the data (with some additional processing)
    $output = '';
    switch ($data)
    {
        case 'status': // enable links
            $output = wcs_twitter_make_links($tud[$data]);
            break;
        case 'link': // twitter link
            $output = '<a href="http://twitter.com/' . $user;
            $output .= '" target="_blank" rel="nofollow">';
            $output .= $tud['name'] . '</a>';
            break;
        case 'website_link':
            if ($tud['website'])
            {
                $output = '<a href="' . $tud['website'];
                $output .= '" target="_blank" rel="nofollow">';
                $output .= $tud['website'] . '</a>';
            }
            break;
        case 'image': // profile image display html
            $output = '<img src="' . $tud['image_url'];
            $output .= '" width="48" height="48" class="wcs_tud_image" />';
            break;
        default:
            $output = $tud[$data];
    }
 
    return $output;
}

In lines 8 – 22, we retrieve the user-specified attribute values and set their defaults. In lines 24 – 33, we process the true/false values.

On line 36, we prepare to implement the WordPress Transients API which is used with the subsequent code segments. This is a very convenient way of temporarily storing data in the WP database. When the time expires, the cached data is deleted (essentially).

In lines 40 – 50, we store our array in the database … if it's not already there … or it's cache time limit has expired. Then in lines 51 – 55, we simply extract the array, if it is already stored. In lines 57 – 83, we do some post-processing. And, we return the requested data element in line 85.

Now … let's look at the supporting functions …

Getting the XML File Content

We coded the following function as an alternative to the PHP file_get_contents() function. cURL is more reliable … it's faster … and it offers more options. We specifically coded this function so that it can perform as an exact replacement.

Code: PHP (plus WordPress)wcs_curl_get_contents()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
function wcs_curl_get_contents($url, $fresh_connect=true)
{
    $result = false;
    $url = str_replace(' ', '%20', $url);
    $handle = curl_init($url);
 
    if (is_resource($handle) === true)
    {
        curl_setopt($handle, CURLOPT_FAILONERROR, true);
        curl_setopt($handle, CURLOPT_FOLLOWLOCATION, false);
        curl_setopt($handle, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($handle, CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt($handle, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($handle, CURLOPT_FRESH_CONNECT, $fresh_connect);
 
        $result = curl_exec($handle);
        curl_close($handle);
    }
 
    return $result;
}

You can read about the client URL library here. It's worth noting that setting the CURLOPT_FRESH_CONNECT option to boolean true  forces cURL to not cache the retrieved file. Since we're already caching in the database, we want to make sure we get the latest XML file.

Reading the XML File

Because Twitter's XML file is clean and straightforward, we don't need any special libraries (from PHP or WordPress) to read the file. We can simply extract the data we need by string processing … having already read the XML file into a string.

The following function extracts the content within a specified XML element tag. Then, we merely return that value with our shortcode.

Code: PHP (plus WordPress)wcs_twitter_get_xml_element()

1
2
3
4
5
6
function wcs_twitter_get_xml_element($item_name, $xml)
{
    preg_match("/<$item_name>(.*)</", $xml, $matches);
    $data = $matches[1];
    return $data;
}

Most of the elements in the Twitter XML file are at the root level. But, the status elements are contained within a complete section … they are basically sub-elements of status.

So … this next function extracts an entire section from the XML file contents. Then we utilize the previous function to obtain the value of individual elements of the status section.

Code: PHP (plus WordPress)wcs_twitter_get_xml_section()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function wcs_twitter_get_xml_section($tag, $xml)
{
    // init
    $xml = ' ' . $xml;
    $tag_open = '<' . $tag . '>';
    $tag_close = '</' . $tag . '>';
 
    // process
    $ini = strpos($xml, $tag_open);
    if ($ini == 0) {return '';}
    $ini += strlen($tag_open);
    $len = strpos($xml, $tag_close, $ini) - $ini;
 
    // exit
    return substr($xml, $ini, $len);
}

 

Creating the Status Links

The latest tweet (status) presented with this Twitter XML file is pure text. So … we need to convert any possible URL's to links. At the same time, we also convert #hashtags and @mentions to their appropriate links. You might well find other uses for this function.

Code: PHP (plus WordPress)wcs_twitter_make_links()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function wcs_twitter_make_links($status)
{
    // creates links in text-based twitter status
 
    // convert #hashtags
    $status = preg_replace('/\#([a-z0-9_]+)/i', '<a href="http://twitter.com/search?q=%23$1">#$1</a>', $status);
    // convert @mention
    $status = preg_replace('/\@([a-z0-9_]+)/i', '<a href="http://twitter.com/$1">@$1</a>', $status);
    // normal links
    $status = make_clickable($status);
    // force all links to open in a new tab/window
    $status = popuplinks($status);
 
    // exit
    return $status;
}

In addition to using more of PHP's quite handy string manipulation functions, we also create the links with two built-in (but little-known) WordPress functions. As with all of our source code lists, you can click the function names to view specific usage details.

Converting a Language Code to a Language Name

The XML file includes the native language code for the Twitter account. But, if you display this information, it's more meaningful to your visitor to output 'English' instead of 'en'. That's what the next function accomplishes. You might also find uses for this nifty function in other programming scenarios.

Code: PHP (plus WordPress)wcs_lang_code_to_name()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
function wcs_lang_code_to_name($code)
{
    // init
    $lines = array();
    $line_items = array();
    $language = '';
    $code = strtolower($code);
 
    // strip any possible sub-language
    $pos = strpos($code, '-');
    if ($pos) {$code = substr($code, 0, $pos);}
 
    // get code list from Library of Congress
    // format: five elements per line, separated by |
    // ISO 639-2 Alpha-3 bibliographic code|ISO 639-2 Alpha-3 terminology code|ISO 639-1 Alpha-2 code|English language name(s)|French language name(s)
    $url = 'http://loc.gov/standards/iso639-2/ISO-639-2_utf-8.txt';
    $list = wcs_curl_get_contents($url, false);
 
    if (!$list) {return $language;}
 
    // read the file
    $lines = explode("\n", $list);
    for ($i; $i < sizeof($lines); $i++)
    {
        $line_item = explode("|", $lines[$i]);
        if (($line_item[0] == $code) || ($line_item[1] == $code) || ($line_item[2] == $code))
        {
            $language = $line_item[3];
            break;
        }
    }
 
    // exit
    return $language;
}

These ISO 639 language codes and their translations are stored in a text file at the Library of Congress. You can view that file here.

After opening the file, we parse its contents to locate our language code and then return its corresponding human-readable name.

Getting the User Data from the XML File

This final function, is the primary support for our shortcode. We grab the sundry data from the Twitter XML file … using the other functions … and store these items in an array … which is returned upon exit.

Code: PHP (plus WordPress)wcs_twitter_get_user_data()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
function wcs_twitter_get_user_data($user, $time_format='F j, Y (g:i a)', $conv_lang_name=true)
{
    // returns an array of twitter user data (does not require external PHP libraries)
    // reference: http://apiwiki.twitter.com/w/page/22554755/Twitter-REST-API-Method:-users%C2%A0show
 
    // $time_format codes: http://php.net/manual/en/function.date.php
    // lang iso codes: http://www.w3schools.com/tags/ref_language_codes.asp
 
    // init
    $tud = array();
 
    // get the xml data; return FALSE if no such user
    $url = 'http://twitter.com/users/show.xml?screen_name=';
    $xml = wcs_curl_get_contents($url . $user);
    if (!$xml) {return false;}
 
    // counts
    $tud['followers'] = wcs_twitter_get_xml_element('followers_count', $xml);
    $tud['followers'] = $tud['followers']!=0 ? $tud['followers'] : 0;
    $tud['followers'] = number_format_i18n($tud['followers']);
 
    $tud['following'] = wcs_twitter_get_xml_element('friends_count', $xml);
    $tud['following'] = $tud['following']!=0 ? $tud['following'] : 0;
    $tud['following'] = number_format_i18n($tud['following']);
 
    $tud['tweets'] = wcs_twitter_get_xml_element('statuses_count', $xml);
    $tud['tweets'] = $tud['tweets']!=0 ? $tud['tweets'] : 0;
    $tud['tweets'] = number_format_i18n($tud['tweets']);
 
    $tud['listed'] = wcs_twitter_get_xml_element('listed_count', $xml);
    $tud['listed'] = $tud['listed']!=0 ? $tud['listed'] : 0;
    $tud['listed'] = number_format_i18n($tud['listed']);
 
    $tud['favorites'] = wcs_twitter_get_xml_element('favourites_count', $xml);
    $tud['favorites'] = $tud['favorites']!=0 ? $tud['favorites'] : 0;
    $tud['favorites'] = number_format_i18n($tud['favorites']);
 
    // latest tweet info
    // if the user has tweet_privacy is enabled, there is NO status data
    $status_block = wcs_twitter_get_xml_section('status', $xml);
    $tud['status'] = wcs_twitter_get_xml_element('text', $status_block);
    if ($tud['status'])
    {
        $tud['status_id'] = wcs_twitter_get_xml_element('id', $status_block);
        $tud['status_timestamp'] = wcs_twitter_get_xml_element('created_at', $status_block);
        $tud['status_timestamp_formatted'] = date($time_format, strtotime($tud['status_timestamp']));
        $tud['status_timestamp_ago'] = human_time_diff(time(), strtotime($tud['status_timestamp'])) . ' ago';
        $tud['status_source'] = wcs_twitter_get_xml_element('source', $status_block);
        $tud['status_source'] = strip_tags(html_entity_decode($tud['status_source']));
        if ($tud['status_source'] == 'web') {$tud['status_source'] = 'Twitter';}
        $tud['status_favorited'] = wcs_twitter_get_xml_element('favorited', $status_block);
        $tud['status_retweets'] = wcs_twitter_get_xml_element('retweet_count', $status_block);
        $tud['status_retweets'] = $tud['status_retweets']!=0 ? $tud['status_retweets'] : 0;
    }
 
    // id info
    $tud['id'] = wcs_twitter_get_xml_element('id', $xml);
    $tud['name'] = wcs_twitter_get_xml_element('name', $xml);
    $tud['screen_name'] = wcs_twitter_get_xml_element('screen_name', $xml);
    $tud['description'] = wcs_twitter_get_xml_element('description', $xml);
    $tud['website'] = wcs_twitter_get_xml_element('url', $xml);
    $tud['image_url'] = wcs_twitter_get_xml_element('profile_image_url', $xml);
    $tud['location'] = wcs_twitter_get_xml_element('location', $xml);
 
    // other data
    $tud['created_timestamp'] = wcs_twitter_get_xml_element('created_at', $xml);
    $tud['created_timestamp_formatted'] = date($time_format, strtotime($tud['created_timestamp']));
    $tud['created_timestamp_ago'] = human_time_diff(time(), strtotime($tud['created_timestamp'])) . ' ago';
    $tud['time_zone'] = wcs_twitter_get_xml_element('time_zone', $xml);
    $tud['geo_enabled'] = wcs_twitter_get_xml_element('geo_enabled', $xml);
    $tud['tweet_media'] = wcs_twitter_get_xml_element('show_all_inline_media', $xml);
    $tud['tweet_privacy'] = wcs_twitter_get_xml_element('protected', $xml);
    $tud['language_iso_code'] = wcs_twitter_get_xml_element('lang', $xml);
    if ($conv_lang_name) {$tud['language'] = wcs_lang_code_to_name($tud['language_iso_code']);}
 
    // exit
    return $tud;
}

Be SURE to put ALL of these functions in your theme's functions.php file. You can also grab the entire collection of functions here.

You can view the first article in this series here.

 

Share This Article: “How to Get Twitter User Data (Part 2)”

(Also Available: Press CTRL+D to Bookmark this Page)

Comments

Share Your Thoughts  4 Responses to “How to Get Twitter User Data (Part 2)”
  1. 1
  2. 2
    shannon says:

    Hello,I’m wondering if you could use these functions directly in templates files?Cheers

  3. 3
    تمويل says:

    Hello just wanted to give you a quick heads up. The text in your content seem
    to be running off the screen in Safari. I’m not sure if
    this is a format issue or something to do with web browser compatibility but I thought I’d post to let
    you know. The style and design look great though!
    Hope you get the problem fixed soon. Kudos

Trackbacks

Check out what others are saying about this post...
  1. [...] (ISO code conversion)You can get the source for this shortcode in the next segment of this article: How to Get Twitter User Data (Part 2)   Print PDF Share This Article: “How to Get Twitter User Data (Part 1)”(Also [...]



Share Your Thoughts

(Some editor features are restricted unless you're logged in.)

(When replying to a specific comment, your browser may require Shift+Enter instead of just Enter.)


(get a gravatar)


Notify me of followup comments via e-mail. You can also subscribe without commenting.