Google API + WordPress: A Problem, an Inconvienience and a Killer

I started off planning on using Google Calanders to store my clockin information. I was doing this for one main reason: Its important that how I store the information is standardized in case I attempt to export my plugin to node.js or another platform. But there is a problem I ran into that I realized may turn very annoying or worse.

Refresh Tokens are not unlimited

this will create an awkward situation once the refresh tokens run out and the website owner is forced to login and authorize again

And as a minor inconvienience

Google Authorization Doesn’t allow Get parameters in the url

Perhaps this is a problem on WordPress side more than googles in the way they setup their admin. Essentially I’m forced to create a plugin url that is independent from the direct flow. Making either the user Leave the admin interface conpletely or doing it through a popup. Then Instead of storing it in WordPress Options, we’d be storing it in a seperated SQL table to avoid loading wp-load.php. These are definitely managable, though not entirely preferable. If I’m using a content management system, I’d rather feel as though I can do everything in a very sexy and clean manner. Rather than go through hoops.

nonetheless I will continue to make the plugin as is simply for experience sake. Though I recognize this is definitely not final version

Update: What Killed using Google API as a web service was the fact that I am forced to use give my webserver an key file. This will not make future installations happy for random people. As a Result, I’m going to drop google calander from the design spec and move onto something else. This isn’t necessarilly Google Calanders Fault, but rather a design philosophy Flaw. I wanted to Use Google Calanders as My database, but I didn’t want to have to make installation a hassle. as a result, I gotta move on.

I’ll go with what is important

  1. Start DateTime
  2. Duration in seconds
  3. Github User
  4. Github Project

Clockin WordPress Integration: Million ways to get it, choose one. pt1

So at this point we can….
1) Retrieve a Github info
2) Retrieve google calender info

But one thing we have yet to do is provide a place where we can actually clock in and clock out. Now we can do this in a variety of ways….

  • Custom Post Types to define Projects and Users
    -they would literally just be place holders to avoid storing tons of duplicant data
    -Would be based off any user that enters our website and allows our app to access their github profile

    • Pros
      -We don’t need javascript to display data
      -Pretty URLs will be enforced
      -Good for SEO
      -Can Be Placed in a Plugin
    • Cons
      -Whats the point of creating a reference?
  • Query Based Multiple Page Service
    -We would create a page that is based off a template we created
    -In the template we would get the queries and give the appropiate data back

    • Pros
      -clean and neat
      -Can make it SEO Freindly
    • Cons
      -Would have to define an archive and various link tags to make it SEO freindly
      -Ugly Urls
  • Single Page Service
    -Using Ajax, we would do everything right from the one page

    • Pros
      -Clean and Neat
      -Pretty Url… Well theres only one….
      -Can be stored in a plugin
      -Nothing is stored
    • Cons
      -Requires Javascript
      -Will need to deal with the data in the browser
      -No SEO

So here’s our choices, I’ll assume you assumed which I’m going with… And if you didn’t assume, I’ll give you a hint “Type Post Custom”. WordPress is wonderful in that it gives you pretty URLS, it gives you proper SEO in a variety of ways, makes your URLs beautful and on top of that you can avoid alot of the struggles you would enter into with your own Content Management System,  such as creating a proper PHP class to interact with sql.

We really want to make sure this is a plugin also to allow ourselves some breathing room in terms of installation.

So Lets begin by creating our plugin

Now Things we will have to include are….

  1.  Creating a Custom Post Type for Users and associating it to a User
  2. Creating a Custom Post Type for Projects
  3.  Giving people the opportunity to choose their Calender
  4.  Auto Load on new sites to old calanders

So lets prepare in the Init, we’re going to leave out the auto load for now

add_action( 'init', 'initialize_clockin' );
function initialize_clockin() {
 register_post_type( 'clockin_dev',
  array(
   'labels' => array(
    'name' => __( 'Developers' ),
    'singular_name' => __( 'Developer' )
   ),
   'description' => 'The user object associated with the wordpress user. stores the guthub username as well',
   'public' => true,
   'has_archive' => true,
   'show_ui' => false,
   'show_in_menu' => false,
   'supports' => false
  )
 );
 register_post_type( 'clockin_project',
  array(
   'labels' => array(
   'name' => __( 'Github Projects' ),
   'singular_name' => __( 'Github Project' )
),
   'description' => 'Associated to Github Project',
   'public' => true,
   'has_archive' => true,
   'show_in_menu' => false,
   'supports' => false
  )
 );
 add_option("Calander ID", null);
}

Now lets create our admin page

This is the code I came up with. I preferred the object oriented approach so that I can store it in a different file

<?php
class clock_in_admin {
 public $options;
public function __construct(){
 add_action( 'admin_menu', array( $this, 'add_to_menu' ) );
 add_action( 'admin_init', array( $this, 'page_init' ) );
 }
 public function add_to_menu(){
 add_options_page( "Clock In Settings", "Clockin", "manage_options", "clock-in-admin", array($this, "admin_page"));
 }
 public function admin_page(){
 $this->options = get_option( 'clock-in' );
?>
 <div class="wrap">
 <?php screen_icon(); ?>
 <h2>Clock In Settings</h2>
 <form method="post" action="options.php"> 
 <?php 
settings_fields( 'clock_in_fields' );
 do_settings_sections( 'clock-in-admin' );
 ?>
<?php submit_button(); ?>
 </form>
 </div>
<?php
 }
 public function page_init(){
 register_setting('clock_in_fields', 'clock-in', array( $this, 'sanitize' ) );
 add_settings_section('clock-in-cal', 'Google Calender Setting', array( $this, 'print_section_info' ),'clock-in-admin');
 add_settings_field('calender-id','Calander ID',array( $this, 'calander_id_input' ),'clock-in-admin','clock-in-cal');
 }
 public function print_section_info()
 {
 echo 'Enter your settings below:';
 }
 public function sanitize( $input ){
 if( isset( $input['calender-id'] ) ){
 //need to check if the calender exists and we can't view and edit it
 //if we can't edit it, we need to ask for permission
 $this->options['calender-id'] = $input['calender-id'];
 }
return $this->options;
 }
 public function calander_id_input()
 { ?>
 <input id='calender-id' name='clock-in[calender-id]' size='40' type='text' value='<?php echo $this->options['calender-id'] ?>' />
<?php
 }
}
?>

 

Hello World: Google Calanders

So, the second main technology I’d like to use is google calenders
Lets have a look at their API 🙂

Now to start out, just looking at the google calender we can see that we can add an event to a previous date as well as edit previous actions. This looks good so far

In all We’re going to be looking for
1) Ability to add an event
2) Ability to edit an event
3) Ability to store Arbitrary Data about what we’re working on
4) Ability to specify a user either based on email address or even better a generic name

Our calander is going to be dependent on the company that uses it as a result we’ll be interested in using

https://www.googleapis.com/calendar/v3/calendars/{your calander id}/events/{the event id}?parameters

as our main Rest Query

To find the calender id

  1. add a new calender
    google calander
  2. go to calender settings
    calander settings
  3. Find the ID at the very bottom
    calander id

 

So Here is the basics of how we’re going to do this…

  1.  We create a new event storing…
    1. User
    2. Project
    3. The Start Time as the Event Start, Stop Time = Start Time
  2. On Clock Out We find
    1. All events that have the Github User (Sorted by startdate, descending)
    2. Get The Last one
      1. (Start time == Stop Time)?Set Stop Time = Date.Now():This user can’t clock out;

Looks good
So First we want to be able to Create events on our calander

Attendee[].email = github email
Attendee[].displayname = github username
summery = github project name
start = date.now()
end = date.now()

(One thing I love about google api’s is they make it real easy for you to try something out)

now Originally, I planned to store the information in attendees and title. But as it turns out, you can’t query attendees nor title… So……
Extended Properties it is!

POST https://www.googleapis.com/calendar/v3/calendars/{your calander ID}/events?key={Your Api Key}

{
 "end":{"dateTime":"2014-1-7T13:31:00-08:00"},
 "start:{"dateTime":"2014-1-7T13:31:00-08:00"},
 "extendedProperties":{
  "shared" : {
   "user":"github-username",
   "project":"github-repo"
  }
 },
 "summary": "git-username worked on github-repo"
}

Next we want to request

Important to note we want singleEvents to be true in order for us to be able to sort properly and we want to sort by startTime

GET https://www.googleapis.com/calendar/v3/calendars/{google calander id}/events?orderBy=startTime&amp;sharedExtendedProperty=User%3DGU&amp;singleEvents=true&amp;sortorder=descending&amp;key={your api key}

Success, but there’s one problem, the sort order…
currently its ascending which means we’ll get the very first clock in that’s ever be done is the first we’ll receive. When we have 50+ clockins this will be an issue since we’ll have to go through the pages to find the very last clockin.  However, a little research shows we can set the sort order to be descending

Next Thing We Want to do is update on clock out, this will be an update to change its end time
Using the first item (root.items[0]) we’ll grab its ID and make an update, after taking a look at the update though we see we are forced to supply the start time and the end time. Thats more information than we truelly desire to redeliver, as a result we can instead use patch

PATCH https://www.googleapis.com/calendar/v3/calendars/{your calander id}/events/{the event id}?key={your api key}

{
 "end": {
  "dateTime": "2014-1-7T15:03:00-08:00"
 }
}

And We have it! Clocking in and Clocking out!
There’s other ways we could have done this, for example we could have stored the ID after clockin locally. However if the user changes computers or etc, then we run into an issue. that being said, we can always change that later