Write a chat application with HTML5 WebSockets and Node.js

The traditional web was not designed for bidirectional communication. It was mostly designed as request/response paradigm where a client can only make a request to server and server can only respond to that request. To make things easy and faster, HTML5 introduced amazing WebSocket.

HTML5 WebSockets

WebSocket is a low latency bi-directional persistent connection between server and client where both server and client can send messages to each other.

With help of WebSocket, we can easily write a chat application in Node.js by ws library. Make sure Node.JS is installed.

Node.js

First, create a directory for our chat application and cd to the directory. (e.g my-chat)
mkdir my-chat
cd my-chat

Then create a file named package.json inside the directory with the following content

{
"name": "websocket-chat",
"version": "0.0.1",
"description": "Chat application using websocket",
"dependencies": {}
}

For our project, we are going to use two dependencies. One is ws and another is express web framework. To populate dependencies run following command on your terminal.
npm install --save express
npm install --save ws

Now create a file named index.js and populate with following content

  1. var express = require('express'),
  2. app = express(),
  3. http = require('http').Server(app),
  4. WebSocketServer = require('ws').Server,
  5. wss = new WebSocketServer({
  6. port: 8080
  7. });
  8.  
  9. app.use(express.static('public'));
  10.  
  11. app.get('/', function(req, res) {
  12. res.sendFile(__dirname + '/index.html');
  13. });
  14.  
  15. wss.broadcast = function broadcast(data) {
  16. wss.clients.forEach(function each(client) {
  17. client.send(data);
  18. });
  19. };
  20.  
  21. wss.on('connection', function(ws) {
  22. ws.on('message', function(msg) {
  23. data = JSON.parse(msg);
  24. if (data.message) wss.broadcast('<strong>' + data.name + '</strong>: ' + data.message);
  25. });
  26. });
  27.  
  28. http.listen(3000, function() {
  29. console.log('listening on *:3000');
  30. });
  31.  

On above codes, first we declare some variable and initiate express and WebSocketServer on port 8080. Then declare public directory to serve css file. Then we wrote code for routing. After that, we declare wss.broadcast to send message to all connected clients. By wss.on we bind events for WebSocket connection and message event. At the end by http.listen our application can listen to port 3000.

As we can see, our routing will call index.html to serve html file, now we need to create index.html file. Write our html code to index.html with following content

  1. <!doctype html>
  2. <html>
  3.  
  4. <head>
  5. <title>WebSocket Chat</title>
  6. <link rel="stylesheet" type="text/css" href="style.css">
  7. <script src="http://code.jquery.com/jquery-3.0.0.slim.min.js"></script>
  8. </head>
  9.  
  10. <body>
  11. <form>
  12. <div id="name-div">
  13. <input id="name" name="name" autocomplete="off" autofocus placeholder="Enter your nickname" />
  14. <button>Submit</button>
  15. </div>
  16. <div id="welcome"></div>
  17. <ul id="messages"></ul>
  18. <div id="input-div">
  19. <input id="message" name="message" autocomplete="off" placeholder="Type your message here" />
  20. <button>Send</button>
  21. </div>
  22. </form>
  23.  
  24. <script>
  25. websocket = new WebSocket("ws://localhost:8080/");
  26. $('form').submit(function() {
  27. name = $('#name').val() ? $('#name').val() : 'Anonymous';
  28. $('#name-div').hide();
  29. $('#welcome').text('Hello ' + name);
  30. websocket.send(JSON.stringify({
  31. name: name,
  32. message: $('#message').val()
  33. }));
  34. $('#message').focus();
  35. $('#message').val('');
  36. return false;
  37. });
  38.  
  39. websocket.onmessage = function(evt) {
  40. $('#messages').append($('<li>').html(evt.data));
  41. };
  42.  
  43. websocket.onerror = function(evt) {
  44. $('#messages').append($('<li>').text('<span style="color: red;">ERROR:</span> ' + evt.data));
  45. };
  46. </script>
  47. </body>
  48.  
  49. </html>
  50.  

In HTML part, we use some form elements to post nickname and message to the server. Inside script tag, we use HTML5 WebSocket connection and their methods.

Lets add some css to make our chat looks beautiful. Create a public directory and a file named style.css inside public directory.

  1. * {
  2. margin: 0;
  3. padding: 0;
  4. box-sizing: border-box;
  5. }
  6. body {
  7. font: 13px Helvetica, Arial;
  8. }
  9. form input {
  10. border: 0;
  11. padding: 10px;
  12. width: 90%;
  13. margin-right: .5%;
  14. }
  15. form button {
  16. width: 9%;
  17. background: rgb(130, 224, 255);
  18. border: none;
  19. padding: 10px;
  20. }
  21. #name-div, #welcome {
  22. background: #AAA;
  23. padding: 10px;
  24. width: 100%;
  25. }
  26. #input-div {
  27. background: #000;
  28. padding: 3px;
  29. position: fixed;
  30. bottom: 0;
  31. width: 100%;
  32. }
  33. #messages {
  34. list-style-type: none;
  35. margin: 0;
  36. padding: 0;
  37. }
  38. #messages li {
  39. padding: 5px 10px;
  40. }
  41. #messages li:nth-child(odd) {
  42. background: #eee;
  43. }
  44.  

Let’s run our application. Write following command to terminal/console

node index.js

Then go to your browser and visit http://localhost:3000

For full application check my GitHub repository.

N.B: Style was copyed from  chat application in socket.io

Using Vagrant box for WordPress development

Setting up development environment is a tedious processes. Vagrant makes it easier to create and configure lightweight, reproducible, and portable development environments.

vagrant

We can use vagrant box to create our WordPress development environment, where nginx, php, MySQL, WordPress and other necessary softwares were pre-installed.

I wrote a solution for that, named WordPress-Vagrant.

Laravel framework offers a nice vagrant box named Homestead, that already contains almost everything that we need. So, instead of creating a new box from scratch, I did use homestead as base box and added WordPress on it.

Once you clone the repository and setup according to instructions, you shall get a virtual machine with following softwares pre-installed.

  • Ubuntu 14.04
  • PHP 5.6
  • HHVM
  • Nginx
  • MySQL
  • Postgres
  • Node (With PM2, Bower, Grunt, and Gulp)
  • Redis
  • Memcached (PHP 5.x Only)
  • Beanstalkd
  • WP-CLI
  • PHPUnit
  • Composer
  • Running WordPress instance

Newly created WordPress instance can be accessable by visiting http://wordpress.app

All WordPress files serve from a directory named wordpress, inside your project directory on your local machine. So, you can use your favourite IDE for writing your codes.

Initially wordpress directory contains no files. When you run vagrant up, it will dump all WordPress files for you.

Visit WordPress-Vagrant and feel free to fork.

SSH Connection from local machine to Amazon(aws) EC2 ubuntu instance with new user and keys

ec2

In Amazon Elastic Cloud Compute(EC2), a key needs to assign when creating an instance. ssh connection can be establish by using that key.

ssh -i your_private_key.pem username@hostname

If you have a ubuntu instance the username may be ubuntu

Now, we need to allow another user from another local machine to connect your remote server via ssh.

1. Generating key pairs for your local machine:
Open your terminal(Ctrl+Alt+t on windows), in your local machine, write
ssh-keygen -t rsa

It will create two files id_rsa and id_rsa.pub in .ssh directory under your home directory, where id_rsa is your private key and id_rsa.pub is your public key.

2. Configure remote server

Create a new user on remote server:
adduser testuser

Login with newly created user:
sudo su testuser

Creating authorized_keys file:

cd $HOME
mkdir .ssh
chmod 700 .ssh
vi .ssh/authorized_keys

Press i for insert mode, copy id_rsa.pub content and paste here. Press ESC, then type :wq save your changes.

Changing file permissions and owner:

chmod 600 .ssh/authorized_keys
chown testuser:testuser .ssh
chown testuser:testuser .ssh/ authorized_keys

Now you can able to connect with your remote server from local machine without locating .pem file:
ssh testuser@hostname

WordPress Error handling with WP_Error class

WordPress has WP_Error class for checking WordPress errors and error messages since version 2.1.0. WordPress uses object of WP_Error class for reporting errors from several WP functions. However, we can use this object in plugin or theme to handle error within WordPress. This class containing various useful method for managing error.

wp

Constructor of WP_Error allows three parameters: $code, $message and $data
Syntex is:

$error = new WP_Error( $code, $message, $data );

here, $code containing error code. it may be string or integer, $message containing error message and $data containing error data. however all parameter are optional.

Suppose, we want to report new error, so we can use:

$error = new WP_Error( 'not_found', 'Page Not Found', 'Page Data' );

Here, we consider not_found as error code, ‘Page Not Found’ as error message and ‘Page Data’ as error data.

After creating error object we can check error by is_wp_error function.

PHPUnit test with Yii application

Unit tests are written to provide the developer with verification that the code is doing the right things.
This tests focus on the smallest units within a software application. In an object-oriented application, (such as a Yii web application) the smallest units are the public methods that make up the interfaces to classes. Unit tests should focus on one single class, and not require other classes or objects to run. Their purpose is to validate that a single unit of code is working as expected.

phpunit

Basic conventions and steps for writing tests with PHPUnit:
1. The tests for a class Abc go into a class AbcTest.
2. AbcTest inherits (most of the time) from PHPUnit_Framework_TestCase.
3. The tests are public methods that are named test*.
4. Inside the test methods, assertion methods such as assertEquals() are used to assert that an actual value matches an expected value.

yii

Writing Tests for PHPUnit in Yii:
A unit test in Yii is written as a PHP class that extends from the framework class, CTestCase. The conventions prescribe it be named AbcTest where Abc is replaced by the name of the class being tested. For example,
if we were to test MyClass, we would name the test class MyClassTest. This class is saved in a file called MyClassTest.php under the folder protected/tests/unit/. The test class primarily has a set of test methods named testXyz where Xyz is often the same as the method name the test is built for in the class being tested. Continuing with the MyClassTest example, if we were testing our Helloworld() method, we would name the corresponding test method in our MyClassTest class, testHelloworld().

For those testing, Create the new file, protected/tests/unit/MyClassTest.php and add to it the following code:

class MyClassTest extends CTestCase {
 	public function testHelloworld() {
        $this->assertTrue(true);
	}
}

Run phpunit tests in Command-Line:
The PHPUnit command-line test runner can be invoked through the phpunit command.
Now we can navigate to our tests folder and execute the command to run this test:

%cd /WebRoot/demo/protected/tests
%phpunit unit/MyClassTest.php

Test Result:
[khaled@folsom tests]$ phpunit unit/MyClassTest.php
PHPUnit 3.5.12 by Sebastian Bergmann.

.

Time: 0 seconds, Memory: 4.00Mb

OK (1 test, 1 assertion)

For each test run, the PHPUnit command-line tool prints one character to indicate progress:
. Printed when the test succeeds.
F Printed when an assertion fails while running the test method.
E Printed when an error occurs while running the test method.
S Printed when the test has been skipped.
I Printed when the test is marked as being incomplete or not yet implemented.

PHPUnit distinguishes between failures and errors. A failure is a violated PHPUnit assertion such as a failing assertEquals() call. An error is an unexpected exception or a PHP error. Sometimes this distinction proves useful since errors tend to be easier to fix than failures. If we have a big list of problems, it is best to tackle the errors first and see if we have any failures left when they are all fixed.

More help on phpunit can be found by typing ‘phpunit –help’ on command line.

Fixtures:
One of the most time-consuming parts of writing tests is writing the code to set the world up in a known state and then return it to its original state when the test is complete. This known state is called the fixture of the test.
PHPUnit supports sharing the setup code. Before a test method is run, a template method called setUp() is invoked. setUp() is where we create the objects against which we will test. Once the test method has finished running, whether it succeeded or failed, another template method called tearDown() is invoked. tearDown() is where we clean up the objects against which we tested.

Setting Fixture in Yii:
A test fixture is a system state or context in which tests are run. We want to run our tests a multiple number of times, and each time they run, we want to be able to have them return repeatable results. A fixture is intended to provide a well-known and fixed environment in which to run our tests. Typically, a fixture’s job is to ensure that all of the objects involved in the testing are consistently initialized to a particular state. One typical example of a fixture is the loading of a database table with a fixed and known set of data. Fixtures in yii are PHP files that return an array specifying the initial data configuration. They are typically named the same as the database table they represent, and are located under the protected/tests/fixtures/ folder.

Configuring the fixture manager:
Was actually already done for us when we created the initial application. If we open up the application configuration file specific to testing, protected/config/test.php, we will see the following application component defined:
'fixture'=>array( 'class'=>'system.test.CDbFixtureManager', ),
So the application has already been configured to use this fixture manager. We need to separate our development database from our testing database so that our testing will not continue to interfere with
our development.

return CMap::mergeArray(

    require(dirname(__FILE__) . "/main.php"), array("components" => array(
        
			"fixture" => array(
				"class" => "system.test.CDbFixtureManager"
			),

			"db" => array(
				"connectionString" => "mysql:host=localhost;dbname=eventapp_test",
				"emulatePrepare" => true,
				"username" => "test_username",
				"password" => "test_password",
				"charset"  => "utf8'
			),
		),
	)
);

We still need to tell our unit tests to actually use this fixture we just created. We do this in the unit test file. In this case, we will need to add our fixture declaration to the top of our test file protected/tests/unit/EventsTest.php as such:

public $fixtures = array('events' => 'Events');

Using jQuery with Yii

Yii is a high performance PHP framework, which has all sort of weapon to build up your efficient web application. Most popular javascript library jQuery are already included with the core of this framework, so for using jQuery no one need to included it.

For register jQuery as core of your application just need to add one line code in main view file.

clientScript->registerCoreScript('jquery'); ?>

With yii default settings, this file can be found in ‘protectedviewslayouts’ directory. Under this directory find main.php and put those code into HEAD section.

Normally we use jquery in a script tag like that:

$(document).ready(function(){
	alert('hello world');
});

In Yii we can use jquery within our php code. like that:

<?php
Yii::app()->clientScript->registerScript('testscript',"
		alert('hello world');
	",CClientScript::POS_READY);
?>

Here, ‘testscript’ parameter are nothing just a name of your script which need to be unique in a view file. POS_READY is identical to $(document).ready(). You can use POS_HEAD to put your script in head section. This way of using jquery will automatically prevent conflict of several javascript in your application

Add FTP info to your wordpress site

Sometimes WordPress asking you for ftp details when you are going to add new plugins or themes or going to upgrade. In that case it also restrict you to edit your file or .htaccess file. This problem occur while your WordPress don’t have sufficient or wrong FTP info for accessing your files in server.

To overcome this problem, let your wordpress know about your FTP account by adding those lines in wp-config.php file.

define('FTP_HOST', 'ftp.sitename.com');
define('FTP_USER', 'FTP_Username');
define('FTP_PASS', 'FTP_password');
//*For using SSL Connection set this to true*
define('FTP_SSL', true);