Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

General Discussion

Is there a way to embed all your achievements from treehouse into an html page?

i know they have a plugin for wordpress to display all achievements.

6 Answers

Robert Bojor
PLUS
Robert Bojor
Courses Plus Student 29,439 Points

Hi Sergio,

I have a PHP script displaying the badges that you can use. Not as fancy as the Wordpress plugin but it's a start if you feel like improving it. Let me know if you want it.

Hi Robert! yes that'll be great! how can i get that from you?

John MacDonald
John MacDonald
8,593 Points

Would there be a way for you to use JSON?

Samuel Webb
Samuel Webb
25,370 Points

Robert,

That sounds like it would make a good GitHub repository.

I haven't started studying JSON but if I can do it with the good old copy n paste code, yes!Lol

Robert Bojor
PLUS
Robert Bojor
Courses Plus Student 29,439 Points

Here's a version of the code, with some config values at the top. The code I'm using on my site is split into two files, variables load separately and the module that displays the badges loads on selected screens.

I've added a $_SESSION variable in order to cache the JSON coming from Treehouse - I don't like to pest other websites with too many requests. I would recommend using your own caching method for the badge images, but you can feel free to use the function pasted below this code.

The display part was done using an unstyled UL and LI tags. You can use the thBadges class to style is as you wish per your page.

<?php
session_start();
$username = 'robertbojor';
// When going to your profile page the username is in the address bar

$sortDirection = -1; // Last badges first
// $sortDirection = 1; // Order of earning

$badgeLimit = 10;
// $badgeLimit = 0; // All badges

if (!isset($_SESSION['badges'])) {
    $url = 'http://teamtreehouse.com/'.$username.'.json';
    $jsonData = file_get_contents($url);
    $_SESSION['badges'] = json_decode($jsonData, true);
}

if (isset($_SESSION['badges']['points'])) {
    $totalPoints = intval($_SESSION['badges']['points']['total'])
}

if (isset($_SESSION['badges']['badges']) && count($_SESSION['badges']['badges']) > 0) {
    if ($sortDirection == -1) {
        $badges = array_reverse($_SESSION['badges']['badges']);
    } else {
        $badges = $_SESSION['badges']['badges'];
    }
    $badgeCount = 1;
    echo '
<ul class="thBadges">';
    foreach($badges as $k => $v) {
        if ($badgeCount <= $badgeLimit && $badgeLimit > 0) {
            echo '
    <li><img src="'.$v['icon_url'].'"></li>';
            $badgeCount++;
        } else if ($badgeLimit == 0) {
            echo '
    <li><img src="'.$v['icon_url'].'"></li>';
        } else {
            break;
        }
    }
    echo '
</ul>';
}

For caching and resizing images you can use the following function. It wasn't written by me, frankly I would love to give credit to the author, but I do not remember where I got it from...

In order for the function to work you will need to have ImageMagick installed on the server ( it doesn't use GD ) and you will also need to have a folder called cache in the root of your website and another folder called remote inside the cache folder. Both folders should have permissions so the webserver can save and read from them.

$serverFiles = '/var/www/robertbojor.com/';
function resize($imagePath,$opts=null){
        global $serverFiles;
    $imagePath = urldecode($imagePath);
    $cacheFolder = $serverFiles.'cache/';
    $remoteFolder = $cacheFolder.'remote/';

    $defaults = array(
        'crop' => false,
        'scale' => false,
        'thumbnail' => false,
        'maxOnly' => false, 
        'canvas-color' => '#ffffff',
        'output-filename' => false,
        'cacheFolder' => $cacheFolder,
        'remoteFolder' => $remoteFolder,
        'quality' => 90,
        'cache_http_days' => 365
    );

    $opts = array_merge($defaults, $opts);    

    $cacheFolder = $opts['cacheFolder'];
    $remoteFolder = $opts['remoteFolder'];

    $path_to_convert = '/usr/bin/convert'; # this could be something like /usr/bin/convert or /opt/local/share/bin/convert

    ## you shouldn't need to configure anything else beyond this point

    $purl = parse_url($imagePath);
    $finfo = pathinfo($imagePath);
    $ext = $finfo['extension'];

    # check for remote image..
    if(isset($purl['scheme']) && ($purl['scheme'] == 'http' || $purl['scheme'] == 'https')):
        # grab the image, and cache it so we have something to work with..
        list($filename) = explode('?',$finfo['basename']);
        $local_filepath = $remoteFolder.$filename;
        $download_image = true;
        if(file_exists($local_filepath)):
            if(filemtime($local_filepath) < strtotime('+'.$opts['cache_http_days'].' days')):
                $download_image = false;
            endif;
        endif;
        if($download_image == true):
            $img = file_get_contents($imagePath);
            file_put_contents($local_filepath,$img);
        endif;
        $imagePath = $local_filepath;
    endif;

    if(file_exists($imagePath) == false):
        $imagePath = $_SERVER['DOCUMENT_ROOT'].$imagePath;
        if(file_exists($imagePath) == false):
            return 'image not found';
        endif;
    endif;

    if(isset($opts['w'])): $w = $opts['w']; endif;
    if(isset($opts['h'])): $h = $opts['h']; endif;

    $filename = md5_file($imagePath);

    // If the user has requested an explicit output-filename, do not use the cache directory.
    if(false !== $opts['output-filename']) :
        $newPath = $opts['output-filename'];
    else:
        if(!empty($w) and !empty($h)):
            $newPath = $cacheFolder.$filename.'_w'.$w.'_h'.$h.(isset($opts['crop']) && $opts['crop'] == true ? "_cp" : "").(isset($opts['scale']) && $opts['scale'] == true ? "_sc" : "").'.'.$ext;
        elseif(!empty($w)):
            $newPath = $cacheFolder.$filename.'_w'.$w.'.'.$ext; 
        elseif(!empty($h)):
            $newPath = $cacheFolder.$filename.'_h'.$h.'.'.$ext;
        else:
            return false;
        endif;
    endif;

    $create = true;

    if(file_exists($newPath) == true):
        $create = false;
        $origFileTime = date("YmdHis",filemtime($imagePath));
        $newFileTime = date("YmdHis",filemtime($newPath));
        if($newFileTime < $origFileTime): # Not using $opts['expire-time'] ??
            $create = true;
        endif;
    endif;

    if($create == true):
        if(!empty($w) and !empty($h)):

            list($width,$height) = getimagesize($imagePath);
            $resize = $w;

            if($width > $height):
                $resize = $w;
                if(true === $opts['crop']):
                    $resize = "x".$h;               
                endif;
            else:
                $resize = "x".$h;
                if(true === $opts['crop']):
                    $resize = $w;
                endif;
            endif;

            if(true === $opts['scale']):
                $cmd = $path_to_convert ." ". escapeshellarg($imagePath) ." -resize ". escapeshellarg($resize) . 
                " -quality ". escapeshellarg($opts['quality']) . " " . escapeshellarg($newPath);
            else:
                $cmd = $path_to_convert." ". escapeshellarg($imagePath) ." -resize ". escapeshellarg($resize) . 
                " -size ". escapeshellarg($w ."x". $h) . 
                " xc:". escapeshellarg($opts['canvas-color']) .
                " +swap -gravity center -composite -quality ". escapeshellarg($opts['quality'])." ".escapeshellarg($newPath);
            endif;

        else:
            $cmd = $path_to_convert." " . escapeshellarg($imagePath) . 
            " -thumbnail ". (!empty($h) ? 'x':'') . $w ."". 
            (isset($opts['maxOnly']) && $opts['maxOnly'] == true ? "\>" : "") . 
            " -quality ". escapeshellarg($opts['quality']) ." ". escapeshellarg($newPath);
        endif;

        $c = exec($cmd, $output, $return_code);
        if($return_code != 0) {
            error_log("Tried to execute : $cmd, return code: $return_code, output: " . print_r($output, true));
            return false;
        }
    endif;

    # return cache file path
    return str_replace($_SERVER['DOCUMENT_ROOT'],'',$newPath);

}

The usage in PHP is the following:

echo resize('https://wac.A8B5.edgecastcdn.net/80A8B5/achievement-images/badges_iOS_SpriteKit_Stage5.png', array('w'=>250, 'h'=>250));
/*
This would echo out a path towards the resized image similar to: cache/resized_image_name.png
The resized_image_name is constructed based on the options sent to the function.

Valid options to send to the function:

'w' => Integer // The desired width of the resized image. You can specify only the width and the height will be auto calculated.
'h' => Integer // The desired height of the resized image. You can specify only the height and the width will be auto calculated
'crop' => Bool // Will crop the image in the center. Default value: false
'scale' => Bool // Will scale the image is it is smaller than required dimensions. Default value: false
'canvas-color' => '#ffffff' // Background of the new canvas where the resized image will be placed.
'quality' => 90 // Quality of the new image
'cache_http_days' => 365 // Cache time in days

Have fun and don't hesitate to ask questions if you need any help.