Selecting Specific Data with the JSON Selector Generator

The JSON Selector Generator at work!

Last post of the year, I promise! Something I forgot to mention in yesterday’s post: I found a great tool for finding the correct JSON selector!

The JSON Selector Generator allows you to put in a JSON string, and it parses it such that you can then select which block or item you wish to reference in your code. When your JSON string is small and well-formatted, it’s easy to see what selector to use without a tool like this. However, if an API returns a JSON string that fills your screen, eyeballing it is not likely to get you anywhere quickly.

Processing the long JSON string returned by the call to my Duolingo profile takes only a few seconds with this great tool.

The JSON Selector Generator at work!
The JSON Selector Generator at work!

Using the Duolingo API with PHP to Get Profile Data

Duolingo logo

For those who are interested in learning a new language, Duolingo is a great place to start. It’s free, and some recent studies suggest that it’s more effective than Rosetta Stone (which is not free).

I’ve been using Duolingo for the past few months and decided to do something similar with my Duolingo profile as I did with my Code School profile – put it on the sidebar of this blog.

However, I soon discovered that I could not do that, as Duolingo’s terms of service banned Web scraping. Fortunately, I discovered that an API is available!

Using this API, I was able to write a PHP script that I host which will pull a user’s data, then filter out only language information that is pertinent (to this particular task).

Source for duolingo.php:

<?php

    function file_get_contents_curl($url){

       $ch = curl_init();
       curl_setopt($ch, CURLOPT_URL, $url);
       curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
       curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
       curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
       $data = curl_exec($ch);
       curl_close($ch);
       flush();
       return $data;
    }

    /* gets username from querystring */
    $username = $_GET['nick'];

    /* builds profile URL on Duolingo */
    $profile_url =  'https://www.duolingo.com/api/1/users/show?username=' . $username;

    /* get JSON from Duolingo API */
    $json = file_get_contents_curl($profile_url);  

    /* decode JSON into associative array */
    $results = json_decode($json,true);

    /* get nested array "languages" */
    $languages = $results['languages'];
    //var_dump($languages);

    /* create inner div */
    $html = '<div id="duolingo_inner">';

    /* add anchor tag to user's profile */
    $html = $html . '<a href="https://www.duolingo.com/' . $username . '" target="_blank">';

    /* add Duolingo logo from Internet */
    $html = $html . '<img src="https://i.imgur.com/mF9aokL.png" alt="' . $username . '\'s Duolingo profile" />';

    /* loop through languages to get only active ones */
    foreach ($languages as $language){
    	$temp_html = "
<table>\n";
    	$include = 0;
    	//var_dump($language);
    	foreach($language as $attribute=>$value){
    		if ($attribute == 'points' && $value > 0) {
    			$include = 1;
    		}
    		if ($attribute == 'language_string') {
    			$temp_html = $temp_html . "<tr><th colspan='2'><h2>$value</h2></th></tr>\n";
    		}
    		if ($attribute == 'points') {
    			$temp_html = $temp_html . "<tr><td class='tdleft'>Points: </td><td class='tdright'>$value</td></tr>\n";
    		}
    		if ($attribute == 'level') {
    			$temp_html = $temp_html . "<tr><td class='tdleft'>Level: </td><td class='tdright'>$value</td></tr>\n";
    		}
    		if ($attribute == 'to_next_level') {
    			$temp_html = $temp_html . "<tr><td class='tdleft'>Points to Next Level: </td><td class='tdright'>$value</td></tr>\n";
    		}
    		//echo $attribute . ' ' . $value . "
\n";
    	}
    	if ($include == 1) {
    		$temp_html = $temp_html . "</table>\n";
    		$html = $html . $temp_html;
    	}
    }

    /* close anchor tag and inner div */
    $html = $html . "</a></div>";
    
    /* return the html */
    echo $html;

    /* uncommenting below will show full contents of JSON from languages section */
    //$languages_json = json_encode($languages);
    //echo $languages_json;
?>

If you want to put this on WordPress, create a Text widget and insert the following code. This assumes that you are hosting duolingo.php in the root directory. Also, change the username in the querystring as appropriate.

<style scoped="">
#duolingo_inner {
   border: 1px solid white;
   text-align: center;
   vertical-align: middle;
   display:block;
   margin-left: auto;
   margin-right: auto;
   margin-bottom: 10px;
}
.tdleft {
 text-align: left;
}
.tdright {
 text-align: right;
}
#duolingo_inner table {
   margin-left: auto;
   margin-right: auto;
}
#duolingo_inner img {
   display:block !important;
   margin-left: auto;
   margin-right: auto;
   width: 50%;
}
</style>
<div id="duolingo_outer">
</div>
<script>
(function($) {
$("#duolingo_outer").load("/duolingo.php?nick=deepinthecode");
})(jQuery);
</script>

And that’s it! You will likely need to change the CSS if you don’t like how it looks on your browser as my widget inherits from my WP theme.

Performance and Availability Issues when Using Linux Hosting for WordPress on GoDaddy

Change Domain on cPanel Hosting page

I have used GoDaddy for hosting this blog for several years now, and I can say that I have not always been happy about it. I have used a free service called Monitor.Us to let me know when the website was down, and until recently, it was down quite a lot more than I thought it should be. Also, it seemed slower than I thought it should be much of the time.

I began looking at other possibilities for hosting, partially because GoDaddy doesn’t have the greatest reputation for WordPress website performance, despite their generally positive reviews regarding domain registration. I looked at BlueHost and HostGator, both of whom get better reviews than GoDaddy for WordPress hosting.

I wondered about the difficulty of moving my site when I realized I had another option: using cPanel at GoDaddy. This is the standard for Linux Web Hosting there now – I think the “classic” hosting I had been using is not even available any longer for new websites.

I had heard good things about cPanel; in fact, one of my friends here in Houston works there and had told me about their implementation at GoDaddy. I called GoDaddy support, and the person I talked to set up a new cPanel site for me. Given a few simple instructions, I was able to import my old WordPress site into the cPanel site.

If you’re using the base domain as I am (like example.com), you will set up a subdomain like new.example.com, and import your old WP site into the new site using the import screen shown below. Use your old domain name, choose the FTP option, and your FTP username and password on the next screen to import from your old account. Note: You may want to first log into the admin section of your old WP site to make sure you are on the newest version of WP.

import existing WP install
Select WordPress from the cPanel Hosting screen to get here.

If you need allow_url_fopen in your site, this will need to be added to your php.ini file. It worked automatically in the old hosting environment.

allow_url_fopen = on

After you’re sure that your new site works properly, you will delete the old site through the GoDaddy hosting interface.

Once that’s complete, you can change your new subdomain back to the base domain in the Preferences section of the cPanel Hosting page.

Change Domain on cPanel Hosting page
Change Domain in Preferences section on cPanel Hosting page

Any URL references to your site may need to be manually corrected in the Widgets section of your WP site to point at the correct domain.

If media in your existing posts aren’t showing up, a SQL script similar to the one below should be run against the MySQL database that your site uses.
For further details, look at the source where I found this gem. (If you’ve changed the “wp_” prefix on your tables, adjust accordingly.)

UPDATE wp_options SET option_value = replace(option_value, 'http://www.oldurl', 'http://www.newurl') WHERE option_name = 'home' OR option_name = 'siteurl';
UPDATE wp_posts SET guid = replace(guid, 'http://www.oldurl','http://www.newurl');
UPDATE wp_posts SET post_content = replace(post_content, 'http://www.oldurl', 'http://www.newurl');
UPDATE wp_postmeta SET meta_value = replace(meta_value,'http://www.oldurl','http://www.newurl');

Inside the WordPress admin Dashboard, you can correct any broken links using the Broken Link Checker plugin.

And that’s it. I’ve found that for the same price I was paying before, I get better performance, more uptime (no downtime since the migration yet!), and a better hosting interface.

TL;DR: If you’re already using GoDaddy for Linux Web hosting, instead of going elsewhere, first consider switching to cPanel at GoDaddy for better performance and availability!