Tuesday, January 24, 2017

Calendar as a Service in PHP? Easy, with Google Calendar API!

In this article, you'll learn how to work with the Google Calendar API in PHP. You'll do it by building a calendar app that allows users to add new calendars, add events, and sync calendars to Google Calendar. If you want to follow along, I recommend you to set up Homestead so you can easily get an environment for running the app.

Calendar image

Setting up a Google Console Project

The first thing that you need to do is to create a new project in the Google Developers Console.

new project

Once the project is created, click on the enable and manage APIs link on the dashboard.

dashboard

On the google APIs page, select and enable the Calendar API and Google+ API.

google apis

Once enabled, go back to the Google APIs page and click the Credentials link, then the add credentials button and select OAuth 2.0 client ID.

add credentials

This will ask you to configure the consent screen. Click the configure consent screen to do so.

Select your preferred email address, add the product name, then click save.

oauth consent screen

Create a Web Application.

create client ID

This will give you the client ID and client secret

Building the App

We'll use Laravel via Composer.

Installing Dependencies

composer create-project --prefer-dist laravel/laravel kalendaryo

This will create a new folder named kalendaryo which will serve as your project's directory.

Let's install some other dependencies:

composer require nesbot/carbon google/apiclient

You will be using the Google Client for talking with the Google+ API for the sign in process, and the Google Calendar API for working with Google Calendar.

Configuring the App

Open the .env file at the root of the project directory and supply the lacking details, like so:

APP_ENV=local
APP_DEBUG=true
APP_KEY=base64:iZ9uWJVHemk5wa8disC8JZ8YRVWeGNyDiUygtmHGXp0=
APP_URL=http://localhost

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=kalendaryo
DB_USERNAME=root
DB_PASSWORD=secret

SESSION_DRIVER=file

APP_TITLE=Kalendaryo
APP_TIMEZONE="Asia/Manila"

GOOGLE_CLIENT_ID="YOUR GOOGLE CLIENT ID"
GOOGLE_CLIENT_SECRET="YOUR GOOGLE CLIENT SECRET"
GOOGLE_REDIRECT_URL="http://ift.tt/2jO1I71"
GOOGLE_SCOPES="email,profile,http://ift.tt/16kSG6F"
GOOGLE_APPROVAL_PROMPT="force"
GOOGLE_ACCESS_TYPE="offline"

The configuration values that you need to add are DB_DATABASE, DB_USERNAME, DB_PASSWORD, APP_TIMEZONE, GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET, and GOOGLE_REDIRECT_URL.

For APP_TIMEZONE, you can use any value from the PHP timezones page.

For the database details, create a new MySQL database and use the database name as value for DB_DATABASE. DB_USERNAME and DB_PASSWORD are the login credentials for that database. If on Homestead Improved, you can just use the pre-created DB homestead with the credentials homestead / secret.

For the Google config, replace the value for the GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET and GOOGLE_REDIRECT_URL with the credentials that you got from Google console earlier. GOOGLE_SCOPES are the permissions that your app is going to need. What you put in there will show up in the consent screen. The user has to agree in order for the app to have access to the specific data that you're asking for.

If you're wondering where I got those, you can check out oauthplayground and select the Google+ API and Google Calendar API. The URLs that show up in the dropdown are basically the permissions. email and profile are just shorthand for http://ift.tt/AjNHPk and http://ift.tt/y4qatF. Each permission is separated by a comma because you will be converting it into an array later on.

Creating a Service Container for the Google Client

Next, take a look at the service container for the Google client. Create an app/Googl.php file and add the following:

<?php
namespace App;

class Googl 
{    
    public function client()
    {
        $client = new \Google_Client();
        $client->setClientId(env('GOOGLE_CLIENT_ID'));
        $client->setClientSecret(env('GOOGLE_CLIENT_SECRET'));
        $client->setRedirectUri(env('GOOGLE_REDIRECT_URL'));
        $client->setScopes(explode(',', env('GOOGLE_SCOPES')));
        $client->setApprovalPrompt(env('GOOGLE_APPROVAL_PROMPT'));
        $client->setAccessType(env('GOOGLE_ACCESS_TYPE'));
        return $client;
    }
}

In the above code, you set the client ID, client secret, redirect URL, scopes (permissions), approval prompt and access type. You are loading all those values from the .env file that you created earlier. Once everything is set, return the new instance. Later on, you'll just call the client method to initialize the Google client.

Routes

Open the app/Http/routes.php file then add the routes for the different pages in the app:

Route::group(
    ['middleware' => ['admin']],
    function(){

        Route::get('/dashboard', 'AdminController@index');

        Route::get('/calendar/create', 'AdminController@createCalendar');
        Route::post('/calendar/create', 'AdminController@doCreateCalendar');

        Route::get('/event/create', 'AdminController@createEvent');
        Route::post('/event/create', 'AdminController@doCreateEvent');

        Route::get('/calendar/sync', 'AdminController@syncCalendar');
        Route::post('/calendar/sync', 'AdminController@doSyncCalendar');

        Route::get('/events', 'AdminController@listEvents');

        Route::get('/logout', 'AdminController@logout');
});

Route::get('/', 'HomeController@index');
Route::get('/login', 'HomeController@login');

In the above code, you're using a custom route middleware called admin. You'll be creating it shortly. Using middleware in a route group means that it's going to be activated for every route in the group.

Route::group(
    ['middleware' => ['admin']],
    function(){
        ...
    }
);

Inside the callback function, you have the different routes that belong to the group. They're all self-explanatory. The route that respond to POST requests are used to perform write operations, while GET routes are read-only.

Route::get('/dashboard', 'AdminController@index');

Route::get('/calendar/create', 'AdminController@createCalendar');
Route::post('/calendar/create', 'AdminController@doCreateCalendar');

Route::get('/event/create', 'AdminController@createEvent');
Route::post('/event/create', 'AdminController@doCreateEvent');

Route::get('/calendar/sync', 'AdminController@syncCalendar');
Route::post('/calendar/sync', 'AdminController@doSyncCalendar');

Route::get('/events', 'AdminController@listEvents');

Route::get('/logout', 'AdminController@logout');

Admin Route Middleware

As mentioned earlier, route middlewares is used to execute code when a specific route is accessed. In the case of the admin middleware, it is used to check whether or not a user is currently logged in.

Create the admin middleware at app/Http/Middleware/AdminMiddleware.php and add the following:

<?php
namespace App\Http\Middleware;

use Closure;

class AdminMiddleware
{
    public function handle($request, Closure $next)
    {
        if ($request->session()->has('user')) {
            return $next($request);
        }

        return redirect('/')
            ->with(
                'message',
                ['type' => 'danger', 'text' => 'You need to login']
            );
    }
}

Most route middleware has one thing in common: they have a handle method used for handling the request. This is executed before any method for responding to a route. Inside the method, you check if a user has been set in the current session. If it has, proceed with processing the request.

if ($request->session()->has('user')) {
    return $next($request);
}

Otherwise, redirect the user to the home page and pass on a message to the session saying that they need to login.

return redirect('/')
            ->with(
                'message',
                ['type' => 'danger', 'text' => 'You need to login']
            );

Make the middleware available for use by adding it to the app/Http/Kernel.php file under the $routeMiddleware array:

'admin' => \App\Http\Middleware\AdminMiddleware::class

Database

The app uses three tables: user, calendar and event. To save time, you can just grab the migrations from the repository, and paste them into the same path in your own project. Execute php artisan migrate in the root of your project to actually create the tables in the database.

After that, copy the contents of User.php, Calendar.php, and Event.php into the app directory. These files are the models that you will use later on to talk to the database.

Continue reading %Calendar as a Service in PHP? Easy, with Google Calendar API!%


by Wern Ancheta via SitePoint

No comments:

Post a Comment