Shared posts

13 Dec 14:06

Making Accessibility Simpler, With Ally.js

by Rodney Rehm
sotiris.katsaniotis

accessibility


  

I’ve been a web developer for 15 years, but I’d never looked into accessibility. I didn’t know enough people with (serious) disabilities to properly understand the need for accessible applications and no customer has ever required me to know what ARIA is. But I got involved with accessibility anyway – and that’s the story I’d like to share with you today.

Making Accessibility Simpler

At the Fronteers Conference in October 2014 I saw Heydon Pickering give a talk called “Getting nowhere with CSS best practices”. Among other things, he made a case for using WAI-ARIA attributes like aria-disabled="true" instead of classes like .is-disabled to express application state. It struck me then and there that I was missing out on a few well-prepared standards, simply because ARIA belongs to that accessibility space that I had no idea of.

The post Making Accessibility Simpler, With Ally.js appeared first on Smashing Magazine.

17 Oct 09:29

Exploring Social Design Patterns For the Web

by Chris Bank


Although many people are designing mobile products that are social in nature, few understand what that really means, how it works, or why it’s important.

While social features are becoming increasingly important for many reasons, they require careful thinking about the identities and respective communities impacted by them, and how the nature of the product changes with this kind of user interaction. For example, every social network you could possibly link to (i.e. for sharing purposes) is different and serves a different purpose for the users involved. And some information may be really sensitive (i.e. bank information, personally identifiable information, or users may want privacy so they can’t be viewed or contacted by certain people or anyone. These are just some considerations, but the list is virtually endless as mobile applications incorporate more designs around who we are as unique and social people.

In this article, we dive deep into 10 different UI patterns for social design. We’ve also previously delved into the importance of navigation design patterns, you should check that out as well.

An Overview of The Patterns

Here’s an overview of the design patterns we’ve detailed in this article:

  1. Achievements & Badges.
  2. Auto-Sharing.
  3. Activity Feeds.
  4. Friend Lists.
  5. Follow.
  6. Vote to Promote.
  7. Pay To Promote.
  8. Direct Messaging.
  9. Like.
  10. Find & Invite Friends.

1. Achievements & Badges

Codecademy

Example: Codecademy, Stackoverflow

Problem: The user wants incremental encouragement and a general sense of progress

Solution: Build gamification into the user’s interactions with the website. Apart from the regular user interactions like listening to a song or posting an update on a social network, many sites also want to encourage users to complete their profile information or interact more frequently with the app. In these cases it makes sense to provide some incentive to the user so that this extra step appeals to them.

Gamification is one of the most popular ways of doing this as it can be a great way of increasing user engagement. Gamification applies the mechanics that hook gamers in order to make the users more engaged on the site. A gamified app is characterized by rewards the user receives as they move through different stages of the “game”. For example users of Codecademy receive points and badges as they complete different tutorials. Stackoverflow and Quora implement the same and provide users with points that can be used to unlock additional features like asking targeted questions or contributing to protected questions.

2. Auto-Sharing

Quora

Example: Quora, Vimeo

Problem: The user wants to easily share their activity with their social networks.

Solution: Build an option that lets users automatically share particular interactions with their social networks. A lot of web apps like Tumblr, Spotify and Vimeo are building granular sharing settings which allow users to automatically post updates to their networks based on their activity. These updates can be posted within the app or even shared with external social channels like Facebook or Twitter.

Not only does this help the user engage with their friends and family in everyday activities like listening to a song or reading an article on an external website, its also a great way to build awareness and engagement with the app itself. For interactions like uploading a photo to Carousel or a video to Vimeo, this pattern makes it even easier for users by eliminating an extra step in the process which they are most likely going to take regardless.

3. Activity Feeds

Medium

Example: Medium, Vimeo

Problem: The user wants to keep up with what’s happening around them and get quick updates on recent activity.

Solution: Show recent activity that’s relevant to the user within the app. Aside from the obvious Facebook or Twitter news feeds, other web apps that contain an element of social interaction, like Quora or Medium have implemented activity feeds that provide users with an overview of recent activity from their friends or people they follow.

The activity stream can be used to aggregate recent actions by an individual user, commonly used on profile pages; more commonly however, activity feeds are used to aggregate multiple users from the perspective of one user. These feeds are extremely useful in demonstrating different features of the UI by showing how other users are interacting with it, and this also plays a great word-of-mouth role.

4. Friend Lists

Goodreads, Spotify

Example: Goodreads

Problem: The user wants to keep track of and engage a subset of their friends on the site.

Solution: Show all the user’s connections or friends in a list. Spotify and Airbnb are part of the growing number of web apps that give you friend lists which can be used to help users engage with the app in a better way by keeping up with how people they know are using the app. Combined with the Follow pattern, which we discuss next, a friend list gives users an easy way to keep track of this information, which comes in handy to give some social proof to content that the users are interacting with.

Friend lists also come in handy when the users want to control who they share with. Whether it’s one-on-one communication or keeping track of someone’s tastes and preferences, the way users explore their blossoming friend groups will become increasingly contextual, requiring friends to become a more integral part of the content-consumption experience.

5. Follow

Google+

Example: Google+, Pinterest

Problem: The user wants to track and keep up to date with activity on topics or themes, not just people.

Solution: Let users select items that they want to stay up to date with. Aside from the purely social web apps like Twitter, Pinterest and Spotify, they let you select friends, channels or artists that you want to keep track of, and updates are shown in the user’s newsfeed. Whether you have friends or not, there’s endless user-generated content to keep you busy.

Users can gain access to a lot of varied content by “following” the activities and recommendations of other users and this pattern allows them to do so without having to worry about how many of their actual friends are using the app. Content shared with followers on sites like Google+ and Pinterest makes the content curation community possible and users can choose to follow topics, events, themes or even people to get fresh content built by and around the channel being followed. For the same reason friend lists will become an increasingly important UI design pattern, so will following.

6. Vote to Promote

Medium

Example: Medium, Reddit

Problem: The user wants to endorse and share content they like.

Solution: Let users participate in content curation by designing a voting system, where content they like can be promoted. The idea of crowd-sourced content curation was popularized by the likes of Digg and Reddit, and today we see almost every app that has user generated content integrate this pattern to bring up the best from the rest. On Reddit, Stackoverflow and Quora, users can vote on content created by other users. Not only does this create a history of what the user has upvoted or downvoted, it also gives users a way of popularizing content and publicly associate themselves with something they enjoyed.

7. Pay To Promote

OKCupid

Example: Quora, OKCupid

Problem: The user wants to highlight certain content above the regular content feed.

Solution: Let users pay to to promote their content. On sites like Quora and Facebook, users can give their posts a boost by paying a certain amount that gives them greater visibility in the content feed above the regular non-paid content. OKCupid allows users to give their profile a boost in views and LinkedIn does the same albeit as part of the paid membership plan rather than by individual content like in Facebook. As discussed in the e-book Web UI Design Patterns 2014, this form of native advertising can be a great way of allowing users to gain traction and greater visibility while maintaining the user’s experience in the platform.

8. Direct Messaging

Spotify

Example: Spotify, Twitter

Problem: The user wants to send private messages to their friends from within the system.

Solution: Allow users to interact with each other in private messages alongside their other interactions. Instagram and many other web apps offer chat or direct messaging as an integral part of their experience. Private chat UI design patterns will continue to blossom across many web apps, not just traditional “social networks” now that users are finally comfortable sharing more private things online and they have substantial breadth in the content they’re generating online.

9. Like

YouTube

Example: YouTube, Pinterest

Problem: The user wants to rate content in a simple way without having to worry about the degrees to which they like it.

Solution: Simplify rating controls by making them binary choices – the user either likes it or dislikes it. Eliminating the fine-grain of stars and rating scores, this makes rating things easier for users as well as interpreting them. If I liked a video, should I rate it 4 stars or go all the way with 5 stars? YouTube and almost every application lets you like (or even dislike) everything in a binary way instead. A lot of web apps provide a way of showing appreciation by simply “liking” or “hearting” content.

10. Find & Invite Friends

Airbnb

Example: Pinterest, Airbnb

Problem: The user wants to experience the application with their friends.

Solution: Make the invitation process simple and easy to complete. Since word-of-mouth and referrals are a huge driver of growth especially in consumer applications, you’ll see this UI design pattern proliferate and evolve even more. Providing users with a way of connecting with and sharing the app with friends also gives them a better, more immersive experience even if just in terms of more content. The invite feature can be built into the onboarding pattern or even as the empty state design, both of which we’ve covered earlier.

Let The User Socialize

Keep track of where your users might want or need to socialize, whether they ever view those features, how often they use them, where they’re coming from and going to in the application (i.e. the user flow) and so on. Keep rearranging, re-sequencing, re-sizing, and tweaking those controls until you get more of the desired actions. And, of course, think deeply about how the user is actually using your mobile application when they’re trying to socialize – make sure you’re not missing something obvious.

For a deeper look at how some of the hottest companies are implementing new and existing social design patterns as well as 50+ other patterns, feel free to check out the e-book Web UI Design Patterns 2014. Use what you need and scrap the rest – but make sure to tailor them to solve your own problems and, most importantly, those of your users.


The post Exploring Social Design Patterns For the Web appeared first on Speckyboy Web Design Magazine.

27 May 12:33

Photo

sotiris.katsaniotis

I don't quite get it....













06 Nov 11:51

Geeks in Stores

by Oliver Widder
sotiris.katsaniotis

I don't get it.

geek-store.jpg
25 Sep 16:51

masterperegrin: boromir’s in too deep

by aishiterushit












masterperegrin:

boromir’s in too deep

25 Sep 16:49

Photo

sotiris.katsaniotis

I can almost feel it...



24 Sep 14:43

The.Addams.Family.1991.720p.BluRay.X264-AMIABLE

by zyber

The Addams step out of Charles Addams’ cartoons. They live with all of the trappings of the macabre (including a detached hand for a servant) and are quite wealthy. Added to this mix is a crooked accountant and his loan shark and a plot to slip in the shark’s son into the family as their long lost Uncle Fester. Can the false Fester find his way into the vault before he is discovered?

Uploaded
http://ul.to/jomow68k/taf1991.720p.BluRay.X264-AMIABLE.mkv

Filecloud (1GB Links)
http://filecloud.io/nsvoymhj/taf1991.720p.BluRay.X264-AMIABLE.1000.part1.rar
http://filecloud.io/vliyms2f/taf1991.720p.BluRay.X264-AMIABLE.1000.part2.rar
http://filecloud.io/njvp1609/taf1991.720p.BluRay.X264-AMIABLE.1000.part3.rar
http://filecloud.io/zq32grd4/taf1991.720p.BluRay.X264-AMIABLE.1000.part4.rar
http://filecloud.io/zh5jwx01/taf1991.720p.BluRay.X264-AMIABLE.1000.part5.rar

Netload (Interchangeable)
http://netload.in/dateisRi8pBAiEY/taf1991.720p.BluRay.X264-AMIABLE.1000.part1.rar.htm
http://netload.in/dateilSgz2AW96f/taf1991.720p.BluRay.X264-AMIABLE.1000.part2.rar.htm
http://netload.in/datei7YkUJlNwlc/taf1991.720p.BluRay.X264-AMIABLE.1000.part3.rar.htm
http://netload.in/dateifpDXdUyZ3Y/taf1991.720p.BluRay.X264-AMIABLE.1000.part4.rar.htm
http://netload.in/dateia1Cffn2OXS/taf1991.720p.BluRay.X264-AMIABLE.1000.part5.rar.htm

Uploaded (Interchangeable)
http://ul.to/u9au5chh/taf1991.720p.BluRay.X264-AMIABLE.1000.part1.rar
http://ul.to/pq6z2ms1/taf1991.720p.BluRay.X264-AMIABLE.1000.part2.rar
http://ul.to/0g1uao3r/taf1991.720p.BluRay.X264-AMIABLE.1000.part3.rar
http://ul.to/jx1q7h0w/taf1991.720p.BluRay.X264-AMIABLE.1000.part4.rar
http://ul.to/c5afbby3/taf1991.720p.BluRay.X264-AMIABLE.1000.part5.rar

Putlocker (Interchangeable)
http://www.putlocker.com/file/649151F54DF667FB
http://www.putlocker.com/file/9EDBAD7CBB67FF55
http://www.putlocker.com/file/4E4C66BAAAE99611
http://www.putlocker.com/file/ADC8E72315BA0807
http://www.putlocker.com/file/C652A35420F3374B

Multiupload (Interchangeable) (Direct Download, Turbobit)
http://www.multiupload.nl/P14JM9EAGL
http://www.multiupload.nl/HU5B5UA92J
http://www.multiupload.nl/C523IINP62
http://www.multiupload.nl/LW3V7CC6R4
http://www.multiupload.nl/LN3IG50D4T

Rapidgator (Interchangeable)
http://rapidgator.net/file/8f3ca2c24039cf1c7e9d8c475d3b9e29/taf1991.720p.BluRay.X264-AMIABLE.1000.part1.rar.html
http://rapidgator.net/file/3615907a48bc7076f80759bd135ecf35/taf1991.720p.BluRay.X264-AMIABLE.1000.part2.rar.html
http://rapidgator.net/file/24bd731284c1ffc2c8c0ab660dc9a412/taf1991.720p.BluRay.X264-AMIABLE.1000.part3.rar.html
http://rapidgator.net/file/bc343a6856320f2548e784c0db2eac39/taf1991.720p.BluRay.X264-AMIABLE.1000.part4.rar.html
http://rapidgator.net/file/893b0cbbb40617491caa8b7b104863f3/taf1991.720p.BluRay.X264-AMIABLE.1000.part5.rar.html

27 Aug 06:17

Building a CodeIgniter Web Application From Scratch – Part 1

by Carlos Cessa
sotiris.katsaniotis

to be read in detail

In this series we’re going to build a web billboard application from scratch, we’re going to use CodeIgniter to handle the back-end service and BackboneJS for the web client. In the first two parts of the series we’ll create the back-end service and then the client application in the last two.


Application Description

The application we are creating will be a simple billboard, where users can register, post tasks, and offer a reward for its completion. Other users can see the existing tasks, assign the task to themselves, and get the offered reward.

The tasks will have basic data like a title, description and reward (as required parameters) and an optional due date and notes. The user profile will simply consist of the user’s name, email and website. So let’s get started.


Database Setup

First off, for the app data we’re going to use MongoDB as the database server. MongoDB is a document oriented database and the leading NoSQL database out there. It’s really scalable and fast, which makes it great to manage huge amounts of data.

MongoDB is a document oriented database and the leading NoSQL database.

In order to use MongoDB in this application, I’m going to use a MongoDB CodeIgniter driver that I wrote some time ago, it’s just a wrapper of the MongoDB PHP driver to mimic the framework’s SQL ActiveRecord. You can find the source files for this driver in my public repository. For this driver to work properly, make sure that you have the PHP’s MongoDB driver installed, if you don’t, follow these steps to get it working.

Please note that explaining the drivers in CodeIgniter and such is out of the scope of this tutorial, refer to the documentation if you have any doubts. You just need to move the "mongo_db.php" in the "config" folder to the "config" folder of your application and the "Mongo_db" folder in the "libraries" folder to the "libraries" folder in your application.

Database Configuration

The only file we need to edit at this point is the "mongo_db.php" file under the "config" folder, since my mongo installation has all the default parameters, I’m just going to edit line 40 and give it the name of the database that I want to use:

$config['mongo_db'] = 'billboard';

That’s it for the database, one of the many advantages of MongoDB is that the documents have no predefined structure, so it works without us needing to set anything up before using it, our database doesn’t even have to exist, MongoDB will create it on the fly when we need it.


Global Configuration

Other than your regular configuration options, that should include the base_url and the index_page if any, we need to set the string and date helpers to autoload. I’m not going to walk you through this, since we have much more to cover, when in doubt refer to the documentation.

Other than the helpers, we need to set up the encryption class since we’re going to use it for our app.


URL Handling

This is going to be a RESTful service and we need a way to take the requests coming to the server and handle them accordingly. We could use an existing library (which is great by the way) but for the purposes of this demonstration, I’m going to create the functionality I need using CodeIgniter’s core features.

Handling RESTful Requests

In particular, we’re going to use the ability to extend the core classes. We will start with the Controller, for the main part of this extension we’re using the "_remap" method in the base controller so all the controllers of our app can use it. Start by creating a MY_Controller.php file inside the "core" folder in the "application" folder, we create this just like any other CodeIgniter controller, as follows:

<?php
if( !defined( 'BASEPATH' ) ) exit( 'No direct script access allowed' );

class MY_Controller extends CI_Controller {

}

Now in this controller we’re going to use the CodeIgniter _remap method to preprocess every request made to the server. Inside the class we just created, add the following method:

public function _remap( $param ) {
    $request = $_SERVER['REQUEST_METHOD'];

    switch( strtoupper( $request ) ) {
        case 'GET':
            $method = 'read';
            break;
        case 'POST':
            $method = 'save';
            break;
        case 'PUT':
            $method = 'update';
            break;
        case 'DELETE':
            $method = 'remove';
            break;
        case 'OPTIONS':
            $method = '_options';
            break;
    }

    $this->$method( $id );
}

A couple of things to note here, first off, there are some REST verbs that we are ignoring (like PATCH), since I’m demonstrating building a REST app, I don’t want to add things that may make this more complex than it needs to be. Secondly, we’re not taking into account the case where a controller doesn’t implement a particular method, which is very likely that this could happen. Now, we could add a default method to handle such requests, but so that we don’t add too much complexity, let’s leave it like this. Third, we’re receiving a param variable in the method declaration, let’s address that, and then I’ll explain the OPTIONS request. Above the switch statement, add the following code:

if ( preg_match( "/^(?=.*[a-zA-Z])(?=.*[0-9])/", $param ) ) {
    $id = $param;
} else {
    $id = null;
}

This regular expression matches any string consisting of uppercase and lowercase letters and any numbers. This is used to check if a MongoDB _id string is being given as a parameter, again, this is not the safest way nor the most thorough check, but for the sake of simplicity, we’ll keep it as is.

OPTIONS Request

Since we’re building a web service and a client application as separate parts, it makes sense that both are going to be hosted on different domains, so we will enable CORS in the back-end and this means, among other things, that our app will respond properly to OPTIONS requests.

When a web app created with BackboneJS (and some other frameworks) tries to make an asynchronous request to a remote server, it sends an OPTIONS request before sending the actual request it’s supposed to send. Among other things, the client tells the server from where it is sending the request, what type of request it is about to send, and the content that it’s expecting. After that, it is up to the server to send the client a response where it acknowledges the request or rejects it.

Since our back-end service, no matter which controller is called, is going to receive this OPTIONS request, it makes sense to implement the method to respond to it in our base controller. Add the following method below (or above) the _remap method in our controller.

private function _options() {
    $this->output->set_header( 'Access-Control-Allow-Origin: *' );
    $this->output->set_header( "Access-Control-Allow-Methods: POST, GET, PUT, DELETE, OPTIONS" );
    $this->output->set_header( 'Access-Control-Allow-Headers: content-type' );
    $this->output->set_content_type( 'application/json' );
    $this->output->set_output( "*" );
}

Ideally, we would only allow some domains to make requests to us, we would check the request_headers header to see if we accept it and we would check for the expected content type, by the client to see if we support it, but again, this is a not-so-complex app and we are skipping these edge cases.


Managing Output

To finish our base controller, let’s create a method that every controller will use to send its results back to the client. In the base controller class, add the following method:

protected function _format_output( $output = null ) {
    $this->output->set_header( 'Access-Control-Allow-Origin: *' );

    if( isset( $output->status ) && $output->status == 'error' ) {
        $this->output->set_status_header( 409, $output->desc );
    }
    $this->_parse_data( $output );

    $this->output->set_content_type( 'application/json' );
    $this->output->set_output( json_encode( $output ) );
}

Again, in order for BackboneJS to process the server response it has to know that its host is accepted by the server, hence the Allow-Origin header, then, if the result is a faulty one, we set a status header indicating this. This status will become more clear when we create the back-end models. Next we use the parse_data helper, which will be a private method (that we will write in a moment) but let me skip that for the time being, then we set the content type as JSON and finally we encode the response as a JSON object. Again, here we could (and should) support other output formats (like XML).

Now let’s create the parse_data helper method (and I’ll explain it afterwards), add the following code to the base controller:

private function _parse_data( &$data ) {
    if ( ! is_array( $data ) && ! is_object( $data ) )
        return $data;

    foreach ( $data as $key => $value ) {
        if ( is_object( $value ) || is_array( $value ) ) {
            if( is_object( $data ) ) {
                $data->{$key} = $this->_parse_data( $value );
            } else {
                $data[ $key ] = $this->_parse_data( $value );
            }
        }

        if ( isset( $value->sec ) ) {
            if( is_object( $data ) ) {
                $data->{$key} = date( 'd.m.Y', $value->sec );
            } else {
                $data[ $key ] = date( 'd.m.Y', $value->sec );
            }
        }

        if ( is_object( $value ) && isset( $value->{'$id'} ) ) {
            if( is_object( $data ) ) {
                $data->{$key} = $value->__toString();
            } else {
                $data[ $key ] = $value->__toString();
            }
        }
    }

    return $data;
}

First off, note that we only parse the data for arrays and objects, and we’re doing it recursively. This pre-parsing has to do with the fact that MongoDB uses dates and IDs as objects, but our clients don’t need this information. Now for the case of IDs, we just need its string value, hence the toString method call, then the value has an ‘$id’ property. Afterwards we are converting the dates to a day.month.year format, this is being done for convenience in the design of the client application, again, not the most flexible approach but it works for this example.


Handling Input

Since we’re sending JSON back to the client application, it is only logical that we accept data in JSON format as well. CodeIgniter doesn’t support this by default like Laravel does, as a matter of fact, CodeIgniter doesn’t even support put and delete params. This is mainly because the framework is not intended for a RESTful service, however the effort that it takes to adapt it is minimal compared to the benefits, at least from my point of view.

So we will start by supporting the JSON data that BackboneJS sends. Create a new file inside the "core" folder, this time it is going to be named "MY_Input.php" and it will have the following basic structure:

<?php
if( !defined( 'BASEPATH' ) ) exit( 'No direct script access allowed' );

class MY_Input extends CI_Input {

}

Now every time we use $this->input in our application we’ll be referring to this class, we will create some new methods and override a few existing ones. First off, we are going to add the support for JSON data, add the following method to the new class.

public function json() {
    if ( !self::$request_params ) {
        $payload    = file_get_contents( 'php://input' );

        if ( is_array( $payload ) ) {
            self::$request_params   = $payload;
        } else if ( ( substr( $payload, 0, 1 ) == "{" ) && ( substr( $payload, ( strlen( $payload ) - 1 ), 1 ) == "}" ) ) {
            self::$request_params   = json_decode( $payload );
        } else {
            parse_str( $payload, self::$request_params );
        }
    }

    return (object) self::$request_params;
}

$request_params is a static variable used to store the request string/data sent by the client. It is static in order to make it object independent so that we can access it from any controller at any given time. The data is obtained from the php://input stream rather than the $_POST global. This is done in order to obtain the data sent in via PUT and DELETE requests as well. Finally, the obtained payload is inspected to check if it’s an array, a JSON encoded object, or a query string, and it’s processed accordingly. The result is then returned as an object.

For this method to work, we need to create the static $request_params variable, add its declaration to the top of the class.

private static $request_params  = null;

Handling Regular Requests

Next, we need to override the post method of the regular input class to use the new JSON payload instead of the $_POST global, add the following method to the new Input class.

public function post( $index = NULL, $xss_clean = FALSE ) {
    $request_vars   = ( array ) $this->json();
    if ( $index === NULL && !empty( $request_vars ) ) {
        $post       = array();
        foreach( array_keys( $request_vars ) as $key ) {
            $post[$key]  = $this->_fetch_from_array( $request_vars, $key, $xss_clean );
        }
        return $post;
    }
    return $this->_fetch_from_array( $request_vars, $index, $xss_clean );
}

This is almost the same as the post method from the original CI_Input class, with the difference being that it uses our new JSON method instead of the $_POST global to retrieve the post data. Now let’s do the same for the the PUT method.

public function put( $index = NULL, $xss_clean = FALSE ) {
    $request_vars   = ( array ) $this->json();
    if ( $index === NULL && !empty( $request_vars ) ) {
        $put = array();
        foreach( array_keys( $request_vars ) as $key ) {
            $put[$key]   = $this->_fetch_from_array( $request_vars, $key, $xss_clean );
        }
        return $put;
    }
    return $this->_fetch_from_array( $request_vars, $index, $xss_clean );
}

And then we also need the DELETE method:

public function delete( $index = NULL, $xss_clean = FALSE ) {
    $request_vars   = ( array ) $this->json();
    if ( $index === NULL && !empty( $request_vars ) ) {
        $delete = array();
        foreach( array_keys( $request_vars ) as $key ) {
            $delete[$key]   = $this->_fetch_from_array( $request_vars, $key, $xss_clean );
        }
        return $delete;
    }
    return $this->_fetch_from_array( $request_vars, $index, $xss_clean );
}

Now technically, there’s really no need for these additional methods, since the post method can handle the params in the PUT and DELETE requests, but semantically it’s better (in my opinion).

This is all we need for our custom Input class. Again we’re ignoring edge cases here, like multipart requests, even though it’s not very hard to handle those and still maintain the functionality obtained here, but, for the sake of simplicity we’ll keep it just the way it is.


Base Model

To end the extension of the core classes, let’s create a base model that every model in the app will extend upon, this is just to avoid repetition of common tasks for every model. Like any other core class extension, here’s our barebones base model:

<?php
if( !defined( 'BASEPATH' ) ) exit( 'No direct script access allowed' );

class MY_Model extends CI_Model {

}

This base model will only serve the purpose of setting and retrieving errors. Add the following method to set a model error:

protected function _set_error( $desc, $data = null ) {
    $this->_error           = new stdClass();
    $this->_error->status   = 'error';
    $this->_error->desc     = $desc;
    if ( isset( $data ) ) {
        $this->_error->data = $data;
    }
}

As you can see, this method uses an instance variable $error, so let’s add its declaration to the top of our base model class.

protected $_error;

Finally, to keep it structured, let’s create the getter method for this property.

public function get_error() {
    return $this->_error;
}

Handling Sessions

Session Controller

For the last part of this tutorial, we will create the controller and model to handle user sessions.

The controller for our session is going to respond to any POST request made to our Session resource, since the session can’t be retrieved after creation, nor updated directly, this controller will only respond to POST and DELETE requests. Please note that sending any other request to the resource will result in a server error, we’re not dealing with edge cases here but this could be easily avoided by checking if the method that’s called exists in our MY_Controller file and setting a default method name if the resource doesn’t support the request.

Below you’ll find the structure for our Session controller:

<?php
if ( !defined( 'BASEPATH' ) ) exit( 'No direct script access allowed' );

class Session extends MY_Controller {

    public function __construct() {}

    public function save() {}

    public function remove( $id = null ) {}
}

Note that this controller is extending the MY_Controller class instead of the regular CI_Controller class, we do this in order to use the _remap method and other functionality that we created earlier. OK, so now let’s start with the constructor.

public function __construct() {
    parent::__construct();

    $this->load->model( 'session_model', 'model' );
}

This simple constructor just calls its parent constructor (as every controller in CodeIgniter must do) and then loads the controller’s model. The code for the save method is as follows.

public function save() {
    $result = $this->model->create();
    if ( !$result ) {
        $result = $this->model->get_error();
    }
    $this->_format_output( $result );
}

And then the code for the remove method:

public function remove( $id = null ) {
    $result = $this->model->destroy( $id );
    if ( !$result ) {
        $result = $this->model->get_error();
    }
    $this->_format_output( $result );
}

Both methods simply delegate the task at hand to the model, which handles the actual data manipulation. In a real world application, the necessary data validation and session checking would be done in the controller, and the common tasks such as session checking should be implemented in the base controller.

Session Model

Now let’s move on to the session model. Here is its basic structure:

<?php
if ( !defined( 'BASEPATH' ) ) exit( 'No direct script access allowed' );

class Session_Model extends MY_Model {

    public function __construct() {}

    public function create() {}

    public function destroy( $id ) {}
}

Like the controller, this model extends the MY_Model class instead of the regular CI_Model class, this is being done in order to use the common methods that we’ve created earlier. Again, let’s start with the constructor.

public function __construct() {
    $this->load->driver( 'mongo_db' );
}

In this case, we just load the Mongo_db driver, that we discussed earlier. Now we’ll continue with the method in charge of destroying the session.

public function destroy( $id ) {
    $filters    = array( '_id' => $this->mongo_db->gen_id( $id ) );

    $query     = $this->mongo_db->get_where( 'sessions', $filters );
    if ( $query->num_rows() == 0 ) {
        $this->_set_error( 'INVALID_CREDENTIALS' );
        return false;
    }

    $this->mongo_db->remove( 'sessions', $filters );
    return 'SESSION_TERMINATED';
}

In this method we check if there’s a session for the given session_id, and if so we attempt to remove it, sending a success message if everything goes OK, or setting an error and returning false if something goes wrong. Note that when using the session_id we use the special method $this->mongo_db->gen_id, this is because like I mentioned earlier, IDs in MongoDB are objects, so we use the id string to create it.

Finally, let’s write the create method which will wrap up part one of this tutorial series.

public function create() {
    $query      = $this->mongo_db->get_where( 'users', array( 'email' => $this->input->post( 'email' ) ) );
    if ( $query->num_rows() != 1 ) {
        $this->_set_error( 'INVALID_CREDENTIALS' );
        return false;
    }

    $this->load->library( 'encrypt' );
    $user   = $query->row();
    $salt   = $this->encrypt->decode( $user->salt );
    if ( $user->pass != sha1( $this->input->post( 'pass' ) . $salt ) ) {
        $this->_set_error( 'INVALID_CREDENTIALS' );
        return false;
    }

    $this->mongo_db->remove( 'sessions', array( 'user_id' => $user->_id->__toString() ) );

    $session    = array(
        'timestamp'     => now(),
        'user_id'       => $user->_id->__toString(),
        'persistent'    => $this->input->post( 'persistent' )
    );

    if ( !$this->mongo_db->insert( 'sessions', $session ) ) {
        $this->_set_error( 'ERROR_REGISTERING_SESSION' );
        return false;
    }

    $result                 = new stdClass();
    $result->id             = $this->mongo_db->insert_id();
    $result->user_id        = $user->_id->__toString();

    return $result;
}

First of all, we check that there’s a user associated with the given email. Then we decode the user’s associated salt (which I’ll explain in the second part of this series when we cover user registration) and check that the given password matches the user’s stored password.

We then remove any previous session associated with the user and create a new session object. If we were checking the session thoroughly, we would add things like the user_agent, ip_address, last_activity field and so on to this object. Finally, we send back to the client the session and user IDs for the new session.


Conclusion

This has been a rather long tutorial, we covered a lot of topics, and we have even more to cover yet. Hopefully by now you have a better understanding of RESTful or stateless services and how to create such a service with CodeIgniter, and possibly, you may have also picked up some new ideas that you can give to the framework’s core functionality.

In the next part we will finish the back-end service and in parts three and four we’ll cover the BackboneJS client application. If you have any doubts/suggestions or anything to say, please do so in the comments section below.