More fun with the Basecamp PHP Wrapper

First The Wrapper, Introduction, Part 1

So jumping right in . . .

I’ve been working on a little application using the Basecamp Wrapper, and basically just fooling around with the UI now. Just because I’m dicking around, doesn’t mean you should have to suffer. So here are some nuggets.

The idea for the app was that I wanted a big simple todo list that combined all the todos I had from all the different projects in a meaningful and useful order. So first and foremost its collecting all the todos in a single array and then making use of them.

In my Customcamp class:

function find_all_uncomplete_todos($in_project = false) {
    if ($in_project) {
        $projects[] = $in_project;
    } else {
        $projects = $this->projects();
    $to_dos = array();
    foreach ($projects as $project) {
        $lists = $this->lists($project->id);
        $lists = ($lists->id)?array($lists):$lists;
        foreach ($lists as $list) {
            $list_data = $this->list_items($list->id);
            if ($list_data && $list_data->{"todo-items"}->{"todo-item"}) {
                foreach ($list_data->{"todo-items"}->{"todo-item"} as $todo) {
                    if ($todo->completed == "false") {
                        $todo->in_project = $project;
                        $todo->in_list = $list;
                        $to_dos[] = $todo;
    return $to_dos;
Thats just a seemingly complicated function that does a pretty simple thing. Just a lot of nested loops is all. It fetches all the projects. Then for each project it fetches all the lists. Then for each list it fetches all the incomplete items for the list. Then it puts each of those todo items in one big array of every incomplete todo. As a convenience it also stores the list and project meta data for each todo in in_project and in_list respectively. This is useful because it allows us, in an HTML page for example, to iterate over the array of todos and print the meta data as well. Now this is all fine and dandy, but why is this function different from the todo views in Basecamp itself? You’re right. Its not. Thats why we’ve got to add the magic ingredient, which in this case is a simple ranking algorithm. For my purposes, I wanted the list to be ordered with the most pressing items at top. So I came up with this simple ranking algorithm based on the list positions within the Basecamp account.
todo->position * list->position * (now - time_the_project_was_last_modified)
Though a todo’s position is scoped to the list that its on, this creates a number that can be used as a rank for scope of your entire account. So to apply this to the function:
// calculate rank
$todo->rank = $list->position * $todo->position * 
                (time(+1) - 
//this is just so they all have unique keys
$todo->rank += (rand(0,50) * .000001);
$to_dos["$todo->rank"] = $todo;

By adding a minuscule random number to the rank we can use the rank as keys for a humongoid array of all our todos. Then to get them in order all we have to do is:


I have a very good use for this function, but even if you don’t I hope this was informative. Grab the full code here.

8 Responses to “More fun with the Basecamp PHP Wrapper”

Paul Forsyth Says: #

Thanks for this wrapper!

I’ve been able to pick it up this morning and have a quick play. Very easy 🙂

AQ Says: #

If you write anything cool or useful, please share. I’m really interested in what other people are doing with the wrapper/api.

Paul Forsyth Says: #

I will do. Im using this in context with a CMS system so much of my usage is domain specific.

I would like to add some wrapper functions to help with requests construction. For example, adding in names/descriptions for new todo lists is currently performed by including an array which i didnt realise at first.

AQ Says: #

Awesome, If you make any changes to the actual wrapper, please let me know. I’ll test them and see about adding them to the code-base. Would you rather send PHP objects instead of arrays?

Andy Says: #

Had a 404 trying to download customcamp.php.

Looking for sample code to understand your class.

AQ Says: #

I dont think I ever posted the actual full file. I assumed that readers could take the couple posts that I had here and cut and paste the sample code that they needed.

matt Says: #

I had an issue with the find_all_uncomplete_todos function when there was a to-do list item only one item (it didn’t matter if it was umcomplete or complete).

The issue is that todo-item does not contain an array, but rather just the single item.

My workaround. Tests the count = 1 and then if so, creates an array with one item and stores that in the {“todo-item”}

First and last line are the same as the original script and used for an insertion reference.

if ($list_data && $list_data->{“todo-items”}->{“todo-item”}) {
//start array hack here
if (count($list_data->{“todo-items”}->{“todo-item”}) == 1){
$tmp = $list_data->{“todo-items”}->{“todo-item”};
$list_data->{“todo-items”}->{“todo-item”} = array($tmp);
//end array hack here

foreach ($list_data->{“todo-items”}->{“todo-item”} as $todo) {

AQ Says: #

Thanks, Matt,

I’m looking to finally make a real release of this in the next couple weeks and i’ll include this bit and give you full credit.


QuirkeyBlog is Aaron Quint's perspective on the ongoing adventure of Code, Life, Work and the Web.




QuirkeyBlog is proudly powered by WordPress