unitkit / uk-chat-bundle
Simple socket.io chat bundle
v1.1.2
2017-12-19 13:12 UTC
Requires
- php: >=5.3.9
- symfony/symfony: 2.8.*
- wisembly/elephant.io: >=v3.3.1
Requires (Dev)
- phpunit/phpunit: 3.7.*
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>