unitkit/uk-chat-bundle

Simple socket.io chat bundle

v1.1.2 2017-12-19 13:12 UTC

This package is auto-updated.

Last update: 2020-07-22 05:34:35 UTC


README

Simple socket.io chat bundle

Requires

  • php: >=5.3.9
  • symfony/symfony: 2.8.*
  • wisembly/elephant.io: >=v3.3.1

Install

Composer

#!console

# install bundle from composer
> composer require unitkit/uk-chat-bundle

# go to bunde assets for install node dependencies
> cd web/bundles/ukchat

# install dependencies
> npm link socket.io
> npm link winston
> npm link socketio-jwt

Setup

app/AppKernel.php

#!php
<?php

use Symfony\Component\HttpKernel\Kernel;
use Symfony\Component\Config\Loader\LoaderInterface;

class AppKernel extends Kernel
{
   public function registerBundles()
   {
       $bundles = array(           
           new UnitKit\Chat\UkChatBundle()
       );
       return $bundles;
   }
}

?>

Usage

Run socket.js

#!console

> node web/bundles/ukchat/socket.js

routing.yml

#!yaml

userChatSend:
  path: /messages/send/{id}{slug}
  defaults: { _controller: AppBundle:Chat:chatSend, slug:'/' }
  requirements: {'slug': '\/?', 'id': '\d+'}

Controller and Model example

#!php
<?php

class ChatController extends Controller
{

    /**
     * Page for chat message send
     * @param \Symfony\Component\HttpFoundation\Request $request
     * @param integer $id chat identity
     */
    public function chatSendAction (Request $request, $id)
    {
        $chatModel = $this->getModel('chatModel');
        $chat = $chatModel->getChatById($id);

        $user = $this->getUser();
        $users = $chatModel->getUsersByChat($id);

        if(!in_array($user, $users)){
            new JsonResponse(array('error' => 'Chat not found'));
        }
        $chatModel->setChatReadTime($chat, $user);
        $socket = $this->get('uk.socket.client');
        $response = $chatModel->sendChatMessage($socket, $chat, $user, $request->request->get('message', ''));        
        if(isset($response['error'])){            
            return new JsonResponse(array('error' => $response['error']));
        }
        return new JsonResponse($response);
    }
}


class ChatModel
{

    /**
     * Send messages by socket and save message in database
     * @param \UnitKit\Chat\Socket\UkClient $socket service for using socket
     * @param \AppBundle\Entity\Chat $chat chat-room to send message
     * @param \AppBundle\Entity\User $user user who send message
     * @param string $text message
     * @return array return array form json response
     */
    public function sendChatMessage(\UnitKit\Chat\Socket\UkClient $socket, Chat $chat, User $user, $text){
        $message = $this->saveChatMessage($chat, $user, $text);
        $result = array(
            'user' => $user->getId(),
            'date' => $message->getCreatedAt()->format('d.m.Y'),
            'time' => $message->getCreatedAt()->format('H:i'),
            'text' => $text,
            'success' => true
        );
        $socket->emit('chat', 'room', array('room' => $chat->getId()));                
        $socket->emit(
            'chat', 
            'send', 
            array('message' => $result)
        );
        return $result;
    }
    
    /**
     * Create, fill and flush message entity
     * @param \AppBundle\Entity\Chat $chat chat-room to send message
     * @param \AppBundle\Entity\User $user user who send message
     * @param string $text message
     * @return \AppBundle\Entity\Message
     */
    protected function saveChatMessage(Chat $chat, User $user, $text){
        $message = new Message();
        $message->setChat($chat);
        $message->setText($text);
        $message->setUser($user);
        $this->em->persist($message);
        $this->em->flush();
        return $message;
    }

}

?>

Twig template example

#!twig

<div uk-chat-output>

    {# block for show posted messages #}
    {% if chat.messages %}
        {% for message in chat.messages %}
            {% if message.user == app.user %}
                <div>
                    <p>{{ message.text }}</p>
                    <div><div>{{ message.createdAt|date('d.m.Y') }}</div><div>{{ message.createdAt|date('H:i') }}</div></div>
                </div>
            {% else %}
                <div>
                    <p>{{ message.text }}</p>
                    <div><div>{{ message.createdAt|date('d.m.Y') }}</div><div>{{ message.createdAt|date('H:i') }}</div></div>
                </div>
            {% endif %}
        {% endfor %}
    {% endif %}

    {# prototype for posting messages on sender side #}
    <div uk-chat-prototype style="display:none;">
        <p uk-chat-text></p>
        <div uk-chat-date><div uk-chat-message-date></div><div uk-chat-message-time></div></div>
    </div>

    {# prototype for posting messages on reciever side #}
    <div uk-chat-prototype-broadcast style="display:none;">
        <p uk-chat-text></p>
        <div uk-chat-date><div uk-chat-message-date></div><div uk-chat-message-time></div></div>
    </div>

    {# prototype for posting sending fail messages #}
    <div uk-chat-prototype-fail style="display:none;">
        <p uk-chat-text>Message delivery error.</p>
    </div>
</div>

<div>
    {# block for answer form #}
    <form action="" id="uk-socket-chat">
        <div>Write answer</div>
        <div class="form-group">
            <div class="fg-line">
                <div class="fg">
                    <textarea uk-chat-input name="message" placeholder="message..."></textarea>
                </div>
            </div>
        </div>
        <button class="btn btn-green" type="submit">Send</button>
    </form>
</div>

<!-- Latest compiled and minified JQuery and Bootstrap -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
<!-- Socket and UkChat libraries -->
<script type="text/javascript" src="{{asset('web/public/node_modules/socket.io-client/dist/socket.io.js')}}"></script>
<script type="text/javascript" src="{{asset('web/bundles/ukchat/client.js')}}"></script>
<!-- App JavaScript -->
<script type="text/javascript">
    $(document).ready(function(){
        ukChat.init(
            $('#uk-socket-chat'), 
            '{{path('userChatSend', {'id': chat.id})}}', 
            parseInt('{{chat.id | default(0)}}'),
            // callback
            function(data){
                if(data.success){
                    $('[uk-chat-input]').val('');
                }else{
                    var $prototype = $('[uk-chat-prototype-fail]').clone();
                    $prototype.removeAttr('uk-chat-prototype-fail');
                    $('uk-chat-output').append($prototype);
                    $prototype.find('[uk-chat-text]').text(data.text);
                    $prototype.show();
                }
            },
            // fail callback
            function(data){
                var $prototype = $('[uk-chat-prototype-fail]').clone();
                $prototype.removeAttr('uk-chat-prototype-fail');
                $('uk-chat-output').append($prototype);
                $prototype.find('[uk-chat-text]').text(data.text);
                $prototype.show();
            }
        );
        ukChat.listen(
            '{{app.request.getSchemeAndHttpHost()~':1337/chat'}}', 
            parseInt({{chat.id | default(0)}}),
            // callback
            function(data){
                if(data === null){
                    return;
                }
                var $prototype = null;
                if(data.user == '{{app.user.id}}'){
                    $prototype = $('[uk-chat-prototype]').clone();
                    $prototype.removeAttr('uk-chat-prototype');
                }else{
                    $prototype = $('[uk-chat-prototype-broadcast]').clone();
                    $prototype.removeAttr('uk-chat-prototype-broadcast');
                } 
                $('[uk-chat-output]').append($prototype);
                $prototype.find('[uk-chat-message-date]').text(data.date);
                $prototype.find('[uk-chat-message-time]').text(data.time);
                $prototype.find('[uk-chat-text]').text(data.text);
                $prototype.show();
            }
        );
    });
</script>