diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..7a73a41 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,2 @@ +{ +} \ No newline at end of file diff --git a/.whitesource b/.whitesource new file mode 100644 index 0000000..f340c5d --- /dev/null +++ b/.whitesource @@ -0,0 +1,8 @@ +########################################################## +#### WhiteSource Integration configuration file #### +########################################################## + +# Configuration # +#---------------# +ws.repo.scan=true +vulnerable.check.run.conclusion.level=failure diff --git a/README.md b/README.md index 2599fb3..8e43e72 100644 --- a/README.md +++ b/README.md @@ -1,19 +1,16 @@ # Laravel-Talk -[![Awesome Laravel](https://img.shields.io/badge/Awesome-Laravel-brightgreen.svg)](https://github.com/nahid/talk) -[![GitHub license](https://img.shields.io/badge/license-CC0-blue.svg)](https://raw.githubusercontent.com/nahid/talk/master/LICENSE) -[![Build Status](https://travis-ci.org/nahid/talk.svg?branch=master)](https://travis-ci.org/nahid/talk) +[![Awesome Laravel](https://img.shields.io/badge/Awesome-Laravel-brightgreen.svg)](https://github.com/nahid/talk) [![GitHub license](https://img.shields.io/badge/license-CC0-blue.svg)](https://raw.githubusercontent.com/nahid/talk/master/LICENSE) [![Build Status](https://travis-ci.org/nahid/talk.svg?branch=master)](https://travis-ci.org/nahid/talk) -Talk is a Laravel 5 based user conversation (inbox) system with realtime messaging. You can easily integrate this package with any Laravel based project. It helps you to develop a messaging system in just few minutes. Here is a project screenshot that was developed by Talk. - -Talk v2.1.0 supports realtime messaging. Learn more about [Talk Live Messaging](https://github.com/nahid/talk#realtime-messaging) +Talk is a Laravel 5 based user conversation (inbox) system with realtime messaging. You can easily integrate this package with any Laravel based project. It helps you to develop a messaging system in just few minutes. Here is a project screenshot that was developed by Talk. +Talk v2.1.0 supports realtime messaging. Learn more about [Talk Live Messaging](https://github.com/nahid/talk#realtime-messaging) #### Feedback -If you already used Talk, please share your experience with us. It will make the project better. +If you already used Talk, please share your experience with us. It will make the project better. -[Give us your feedback](https://github.com/nahid/talk/issues/43) +[Give us your feedback](https://github.com/nahid/talk/issues/43) #### Built with Talk @@ -21,11 +18,10 @@ If you are using Talk in your project please share your project URL or project n See which project was [Built with Talk](https://github.com/nahid/talk/issues/42). -## Caution +## Caution > Do not migrate 1.1.7 from its higher version directly. Please try our [sample project](https://github.com/nahid/talk-example) first and then apply it on your project. - ![Talk-Example Screenshot](http://i.imgur.com/uQ7sgmI.png "Talk-Example Project") You may try [Talk-Example](https://github.com/nahid/talk-example) project. @@ -33,27 +29,27 @@ You may try [Talk-Example](https://github.com/nahid/talk-example) project. Or you can try live [Demo](http://portal.inilabs.net/baseapp/v1.0/admin/message/inbox) by using this credentials: ``` -username: admin +username: admin password: admin ``` - - So let's start your tour :) ### Features -* Head to head messaging -* Realtime messaging -* Creating new conversation -* Message threads with latest one -* View conversations by user id or conversation id -* Support pagination in threads and messages -* Delete (soft delete) message from both end. Sender and receiver can delete their message from their end -* Permanent delete message -* Mark message as seen -* Only participant can view or access there message or message threads -* Inline url render using oembed specifications +- Head to head messaging +- Realtime messaging +- Creating new conversation with titles +- Adding [tags](https://github.com/nahid/talk#tags) to conversations +- Message threads (i.e. conversations) with latest messages +- View conversations by user id or conversation id +- Support pagination in threads and messages +- Delete (soft delete) message from both end. Sender and receiver can delete their message from their end +- Permanent delete message +- Mark message as seen +- Mark message as read +- Only participant can view or access there message or message threads +- Inline url render using oembed specifications ### Installation @@ -85,6 +81,12 @@ Now run this command in your terminal to publish this package resources: php artisan vendor:publish --provider="Nahid\Talk\TalkServiceProvider" ``` +Note that you can publish only the migrations with the command below: + +``` +php artisan vendor:publish --provider="Nahid\Talk\TalkServiceProvider" --tag=migrations +``` + After running this command, all necessary file will be included in your project. This package has two default migrations. So you have to run migrate command like this. (But make sure your database configuration is configured correctly.) ```shell @@ -121,36 +123,42 @@ return [ ]; ``` - ### Usage -Its very easy to use. If you want to set authenticate user id globally then you have to set a middleware first. Go to `app/Http/Kernel.php` and set it in `$routeMiddleware` array: +It is very easy to use. If you want to set authenticate user id globally then you have to set a middleware first. Go to `app/Http/Kernel.php` and set it in `$routeMiddleware` array: - ```php - 'talk' => \Nahid\Talk\Middleware\TalkMiddleware::class, - ``` +```php +'talk' => \Nahid\Talk\Middleware\TalkMiddleware::class, +``` - And now you can use it from anywhere with middleware. Suppose you have a Controller and you want to set authenticate user id globally then write this in controller constructor: +And now you can use it from anywhere with middleware. Suppose you have a Controller and you want to set authenticate user id globally then write this in controller constructor: - - ```php - $this->middleware('talk'); - ``` - -But instead of set id globally you can use these procedure from any method in controller: +```php +$this->middleware('talk'); +``` +But instead of set id globally you can use these procedure from any method in controller: ```php Talk::setAuthUserId(auth()->user()->id); ``` - Now you may use any method what you need. But if want pass authentic id instantly, this method may help you: ```php Talk::user(auth()->user()->id)->anyMethodHere(); ``` -Please see the API Doc. + +### Tags + +With Talk, you can "tag" conversations. This makes it possible for your users to uniquely identify conversations and categorized them. This is usually a very useful and invaluable tool when you want your users to add labels to their conversations. When creating tags, you can mark a tag as being "special". Special tags are tags that do not belong to any user. Hence, only one copy of a special tag can exist. With this, Talk can effectively replace the default [Laravel notification system](https://laravel.com/docs/6.x/notifications), because you can simply send a Talk message to the concerned user and labelling the conversation with a special tag (e.g. "SYSTEM_NOTIFICATION"). Then in your frontend, you can simply fetch all conversations with that label and you've got yourself a system notification! The applications of Talk tags are limitless! + + +Please note that you can quickly get tags that are not special tags by using the `withoutSpecialTags()` [scope of the Tag Eloquent model](https://laravel.com/docs/6.x/eloquent#local-scopes). + + +#### Please see the API Doc. + ### API List @@ -161,16 +169,21 @@ Please see the API Doc. - [isAuthenticUser](https://github.com/nahid/talk#isauthenticuser) - [sendMessage](https://github.com/nahid/talk#sendmessage) - [sendMessageByUserId](https://github.com/nahid/talk#sendmessagebyuserid) +- [sendNotificationToUser](https://github.com/nahid/talk#sendnotificationtouser) - [getInbox](https://github.com/nahid/talk#getinbox) - [getInboxAll](https://github.com/nahid/talk#getinboxAll) - [threads](https://github.com/nahid/talk#threads) - [threadsAll](https://github.com/nahid/talk#threadsall) +- [addTagToConversation](https://github.com/nahid/talk#addtagtoconversation) +- [getUserTags](https://github.com/nahid/talk#getusertags) - [getConversationsById](https://github.com/nahid/talk#getconversationbyid) +- [getConversationsByTagId](https://github.com/nahid/talk#getconversationsbytagid) - [getConversationsAllById](https://github.com/nahid/talk#getconversationallbyid) - [getConversationsByUserId](https://github.com/nahid/talk#getconversationbyuserid) - [getConversationsAllByUserId](https://github.com/nahid/talk#getconversationallbyuserid) - [getMessages](https://github.com/nahid/talk#getmessages) - [getMessagesByUserId](https://github.com/nahid/talk#getmessagesbyuserid) +- [getMessagesByTagId](https://github.com/nahid/talk#getMessagesByTagId) - [getMessagesAll](https://github.com/nahid/talk#getmessagesall) - [getMessagesAllByUserId](https://github.com/nahid/talk#getmessagesallbyuserid) - [readMessage](https://github.com/nahid/talk#readmessage) @@ -180,7 +193,6 @@ Please see the API Doc. - [deleteForever](https://github.com/nahid/talk#deleteforever) - [deleteConversations](https://github.com/nahid/talk#deleteconversations) - ### setAuthUserId `setAuthUserId` method sets the currently loggedin user id, which you pass through parameter. If you pass `null` or `empty` value then it returns false. @@ -193,7 +205,7 @@ void setAuthUserId($userid) **Example** -Constructor of a Controller is the best place to write this method. +Constructor of a Controller is the best place to write this method. ```php function __construct() @@ -207,13 +219,14 @@ When you pass logged in user ID, Talk will know who is currently authenticated f ### user You may use this method instead of `setAuthUserId()` method. When you have to instantly access users conversations then you may use it. + **Syntax** ```php object user($id) ``` -**Example** -When you haven't set authenticated user id globally, then you just use this method directly with others method. + +**Example** When you haven't set authenticated user id globally, then you just use this method directly with others method. ```php $inboxes = Talk::user(auth()->user()->id)->threads(); @@ -235,12 +248,12 @@ int|false isConversationExists($userid) ```php if ($conversationId = Talk::isConversationExists($userId)) { Talk::sendMessage($conversationId, $message); -} +} ``` ### isAuthenticUser -isAuthenticUser checks if the given user exists in given conversation. +isAuthenticUser checks if the given user exists in given conversation. **Syntax** @@ -253,7 +266,7 @@ boolean isAuthenticUser($conversationId, $userId) ```php if (Talk::isAuthenticUser($conversationId, $userId)) { Talk::sendMessage($conversationId, $message); -} +} ``` ### sendMessage @@ -282,12 +295,23 @@ You can send message via receiver id by using this method. If the message is suc **Syntax** ```php -object|false sendMessageByUserId($userId, $message) +object|false sendMessageByUserId($receiverId, $message) +``` + +### sendNotificationToUser + +This allows you to quickly send notification to a user. + +**Syntax** + +```php +object|false sendNotificationToUser($receiverId, $message, $title = null, $customNotificationTag = null, \$optionalSenderId = null) + ``` ### getInbox -If you want to get all the inboxes except soft deleted message , this method may help you. This method gets all the inboxes via previously assigned authenticated user id. It returns collections of message thread with latest message. +If you want to get all the inboxes except soft deleted message , this method may help you. This method gets all the inboxes via previously assigned authenticated user id. It returns collections of message threads with latest messages in each of the returned threads. Specifically, it retrieves all message threads (i.e. conversations) for the authenticated user without soft deleted message, including latest messages, sender and receiver user model. This method differs from the `getInboxAll()` method in that each conversation returned contains a lot more data (each conversation contains the conversation model itself, the messages in the conversation, a collection of only unread messages in the conversation, the corresponding user, etc.) **Syntax** @@ -295,7 +319,6 @@ If you want to get all the inboxes except soft deleted message , this method may array getInbox([$order = 'desc'[,$offset = 0[, $take = 20]]]) ``` - **Example** ```php @@ -307,19 +330,19 @@ return view('message.threads', compact('inboxes')); ```html ``` ### getInboxAll -Its similar as `getInbox()` method. If you want to get all the inboxes with soft deleted messages, this method may help you. This method gets all the inboxes via given user id. +It is similar as `getInbox()` method. If you want to get all the inboxes with soft deleted messages, this method may help you. This method gets all the inboxes for the authenticated user. Specifically, it retrieves all message threads (i.e. conversations) for the authenticated user with the latest message and the corresponding user model. This method defers from the `getInbox()` method in that it is more light-weight and thus more efficient, because it only includes just a handful of information for each conversation (each conversation only contains the first message in the conversation and the corresponding user). **Syntax** @@ -337,7 +360,6 @@ This method is an alias of `getInbox()` method. array threads([$order = 'desc'[,$offset = 0[, $take = 20]]]) ``` - ### threadsAll This method is an alias of `getInboxAll()` method. @@ -348,8 +370,27 @@ This method is an alias of `getInboxAll()` method. array threadsAll([$order = 'desc'[,$offset = 0[, $take = 20]]]) ``` -### getConversationsById +### addTagToConversation + +This method adds a tag to a conversation. This is useful when you need to label a conversation. There is also an included `starThisConversation()` function to help you "star" a conversation. Internally, the method simply assigns a special tag to the conversation. + +**Syntax** + +```php +bool addTagToConversation($conversationId, string $tagName, bool $makeItASpecialTag = null) +``` + +### getUserTags + +Get all the tags that belongs to the currently authenticated user (i.e. the tags that the user created) + +**Syntax** +```php +bool getUserTags() +``` + +### getConversationsById When you want to get all the conversations using your desire conversation id, you can try this method. This method returns all the conversations (except soft deleted) with `sender` and `withUser` objects @@ -369,6 +410,7 @@ $withUser = $conversations->withUser; return view('messages.conversations', compact('messages', 'withUser')); ``` + This method returns two objects `messages` and `withUser`. `messages` object contains messages collection and `withUser` object contains participant User collections. Let's see how to use it with your views @@ -376,28 +418,29 @@ Let's see how to use it with your views ```html
-

Chat with {{$withUser->name}}

- @foreach ($messages as $msg) -
-

{{$msg->sender->name}}

- {{$msg->humans_time}} -

- {{$msg->message}} -

-
- @endforeach +

Chat with {{$withUser->name}}

+ @foreach ($messages as $msg) +
+

{{$msg->sender->name}}

+ {{$msg->humans_time}} +

+ {{$msg->message}} +

+
+ @endforeach
``` ### getConversationsAllById -This method is similar as `getConversationsById()`. The only difference between this method is its return all messages with soft deleted items. +This method is similar as `getConversationsById()`. The only difference is that this method returns all messages with soft deleted items. **Syntax** ```php array getConversationsAllById($conversationId[, $offset = 0[, $take = 20]]) ``` + ### getConversationsByUserId When you want to get all the conversations using your desire receiver id, you can try this method. This method returns all the conversations (except soft deleted message) with user's objects @@ -410,7 +453,7 @@ object getConversationsByUserId($receiverId [, $offset = 0[, $take = 20]]) ### getConversationsAllByUserId -This method is similar as `getConversationsByUserId()`. The only difference between this method is it returns all messages with soft deleted items. +This method is similar as `getConversationsByUserId()`. The only difference is that this method returns all messages with soft deleted items. **Syntax** @@ -418,9 +461,13 @@ This method is similar as `getConversationsByUserId()`. The only difference betw array getConversationsAllByUserId($receiverId[, $offset = 0[, $take = 20]]) ``` +### getConversationsByTagId + +This method is similar to `getMessagesByTagId()` + ### getMessages -This is a alias of `getConversationsById()` method. +This is a alias of `getConversationsById()` method. **Syntax** @@ -430,7 +477,7 @@ array messages($conversationId[, $offset = 0[, $take = 20]]) ### getMessagesAll -This is a alias of `getConversationsAllById()` method. +This is a alias of `getConversationsAllById()` method. **Syntax** @@ -440,7 +487,7 @@ array messagesAll($conversationId[, $offset = 0[, $take = 20]]) ### getMessagesByUserId -This is a alias of `getConversationsByUserId()` method. +This is a alias of `getConversationsByUserId()` method. **Syntax** @@ -448,10 +495,19 @@ This is a alias of `getConversationsByUserId()` method. array messagesByUserId($receiverId[, $offset = 0[, $take = 20]]) ``` +### getMessagesByTagId + +Gets the conversations that has the specified tag id. + +**Syntax** + +```php +Collection getMessagesByTagId($tagId) +``` ### getMessagesAllByUserId -This is a alias of `getConversationsAllByUserId()` method. +This is a alias of `getConversationsAllByUserId()` method. **Syntax** @@ -471,7 +527,7 @@ array readMessage($messageId) ### getReceiverInfo -This method returns all the information about message receiver. +This method returns all the information about message receiver. > This method is deprecated from version 2.0.0 and it will be removed from version 2.0.2 @@ -546,17 +602,13 @@ return [ ]; ``` -in this new version broadcast section was added with talk config. Here broadcast is disabled by default. -If you want to enable live (realtime) messaging then you have to enable it first. Then add pusher credentials to your .env file and you must add a new line called PUSHER_APP_NAME in the .env file to specify your application pusher name. Thats it. Everytime -when you send message then talk will automatically fire two event, one for specific user and second for specific conversation. So -you may listen or subscribe one or both as per your wish. Finally you have to subscribe these events by using `talk_live()` helper function. -Go to where you want to subscribe to work with message data follow this code. +In this new version, broadcast section was added with Talk config. Here broadcast is disabled by default. If you want to enable live (realtime) messaging then you have to enable it first. Then add pusher credentials to your .env file and you must add a new line called PUSHER_APP_NAME in the .env file to specify your application pusher name. Thats it. Whenever you send message, Talk will automatically fire two event, one for specific user and second for specific conversation. So you may listen or subscribe one or both as per your wish. Finally you have to subscribe these events by using `talk_live()` helper function. Go to where you want to subscribe to work with message data follow this code. ``` @@ -564,40 +616,38 @@ Go to where you want to subscribe to work with message data follow this code. {!! talk_live(['user'=>["id"=>auth()->user()->id, 'callback'=>['msgshow']]]) !!} ``` -`talk_live()` supports one parameters as array. The first parameter is for channel name which you want to subscribe. You have not know which channel was broadcast. -Talk broadcast two channel by default. One for user and second for conversation. If you want to subscribe channel for currently loggedin user then you have to pass +`talk_live()` supports one parameters as array. The first parameter is for channel name which you want to subscribe. You have not know which channel was broadcast. Talk broadcast two channel by default. One for user and second for conversation. If you want to subscribe channel for currently loggedin user then you have to pass -logedin user id in 'user' key. `['user'=>['id'=>auth()->user()->id, 'callback'=>[]]` or you want to subscribe for conversation id you have pass conversation id as -'conversation' key. `['conversation'=>['id'=>$conversationID, 'callback'=>[]]`. You may pass both if you want. +logedin user id in 'user' key. `['user'=>['id'=>auth()->user()->id, 'callback'=>[]]` or you want to subscribe for conversation id you have pass conversation id as 'conversation' key. `['conversation'=>['id'=>$conversationID, 'callback'=>[]]`. You may pass both if you want. -You can pass a callback for working with pusher recieved data. For both `user` and `conversation` section support callbacks as array. So you can pass multiple callback as array value that was shown in previous example. +You can pass a callback for working with pusher received data. For both `user` and `conversation` section support callbacks as array. So you can pass multiple callback as array value that was shown in previous example. You can watch [Talk-Live-Demo](https://youtu.be/bN3s_LbObnQ) ## Oembed support -Talk also supports embed urls simply use `$message->toHtlmString()` in you views to render an embed link +Talk also supports embed urls simply use `$message->toHtmlString()` in you views to render an embed link -Eg. `This is a youtube embed link: https://www.youtube.com/watch?v=jNQXAC9IVRw` +Eg. `This is a YouTube embed link: https://www.youtube.com/watch?v=jNQXAC9IVRw` ```html
-

Chat with {{$withUser->name}}

- @foreach ($messages as $msg) -
-

{{$msg->sender->name}}

- {{$msg->humans_time}} -

- {{$msg->toHtmlString()}} -

-
- @endforeach +

Chat with {{$withUser->name}}

+ @foreach ($messages as $msg) +
+

{{$msg->sender->name}}

+ {{$msg->humans_time}} +

+ {{$msg->toHtmlString()}} +

+
+ @endforeach
-``` +``` ## Custom embed link -If you want to setup your own implementation of oembed you can configure it in the talk config file. You endpoint should follow the [Oembed](https://oembed.com/) specifications +If you want to setup your own implementation of oembed you can configure it in the Talk config file. You endpoint should follow the [Oembed](https://oembed.com/) specifications ```php 'user' => [ @@ -621,12 +671,13 @@ If you want to setup your own implementation of oembed you can configure it in t 'oembed' => [ 'enabled' => true, 'url' => 'http://your.domain/api/oembed', - 'key' => 'yout-auth-api-key' + 'key' => 'your-auth-api-key' ] ``` + ### Testing -Talk is backwards compatible with php 5.5. Use docker to run unit tests. +Talk is backwards compatible with php 5.5. Use docker to run unit tests. ```bash docker-compose run php55 composer install @@ -649,15 +700,17 @@ docker-compose run hhvm phpunit ``` ### Try Demo Project + [Talk-Example](https://github.com/nahid/talk-example) #### Special Thanks To + [Shipu Ahamed](https://github.com/shipu) Thanks :) ## Support for this project -Hey dude! Help me out for a couple of :beers:! -[![Beerpay](https://beerpay.io/nahid/talk/badge.svg?style=beer-square)](https://beerpay.io/nahid/talk) [![Beerpay](https://beerpay.io/nahid/talk/make-wish.svg?style=flat-square)](https://beerpay.io/nahid/talk?focus=wish) +Hey dude! Help me out for a couple of :beers:! +[![Beerpay](https://beerpay.io/nahid/talk/badge.svg?style=beer-square)](https://beerpay.io/nahid/talk) [![Beerpay](https://beerpay.io/nahid/talk/make-wish.svg?style=flat-square)](https://beerpay.io/nahid/talk?focus=wish) diff --git a/composer.json b/composer.json index 33c3470..a24454b 100644 --- a/composer.json +++ b/composer.json @@ -1,22 +1,30 @@ { - "name": "nahid/talk", - "description": "Talk is a Laravel 5 based realtime messaging, chatting and conversation system. It helps to develop users messaging, chatting and conversations in easy way.", - "keywords": ["message", "inbox", "conversations", "chat", "php", "laravel", "realtime", "real-time"], - "homepage": "https://github.com/nahid/talk", - "license": "CC-BY-3.0", - "authors": [ - { - "name": "Nahid Bin Azhar", - "email": "nahid.dns@gmail.com" - } - ], + "name": "nahid/talk", + "description": "Talk is a Laravel 5 based realtime messaging, chatting and conversation system. It helps to develop users messaging, chatting and conversations in easy way.", + "keywords": [ + "message", + "inbox", + "conversations", + "chat", + "php", + "laravel", + "realtime", + "real-time" + ], + "homepage": "https://github.com/nahid/talk", + "license": "CC-BY-3.0", + "authors": [ + { + "name": "Nahid Bin Azhar", + "email": "nahid.dns@gmail.com" + } + ], "require": { - "php": "^5.6 || ^7.0 || ^7.1 || ^7.2", - "illuminate/contracts": ">=5.1.0", + "php": ">=5.6", + "illuminate/contracts": ">=5.1", "illuminate/support": ">=5.1.0", - "sebastian-berc/repositories": "^1.0", "nesbot/carbon": "^2.22", - "pusher/pusher-php-server": "^3.0", + "pusher/pusher-php-server": "^7.0", "predis/predis": "~1.1.1", "mpratt/embera": "^1.9" }, @@ -38,16 +46,16 @@ "Nahid\\Talk\\Tests\\": "tests" } }, - "extra": { - "laravel": { - "providers": [ - "Nahid\\Talk\\TalkServiceProvider" - ], - "aliases": { - "Talk": "Nahid\\Talk\\Facades\\Talk" - } - } - }, + "extra": { + "laravel": { + "providers": [ + "Nahid\\Talk\\TalkServiceProvider" + ], + "aliases": { + "Talk": "Nahid\\Talk\\Facades\\Talk" + } + } + }, "minimum-stability": "dev", "prefer-stable": true } diff --git a/database/migrations/2015_10_05_110608_create_messages_table.php b/database/migrations/2015_10_05_110608_create_messages_table.php index cad9f29..fd75886 100644 --- a/database/migrations/2015_10_05_110608_create_messages_table.php +++ b/database/migrations/2015_10_05_110608_create_messages_table.php @@ -1,14 +1,14 @@ increments('id'); + $table->string('name'); + $table->integer('user_id')->unsigned()->nullable(); + $table->integer('is_special_tag')->default('0'); + $table->timestamps(); + + $table->foreign('user_id')->references('id')->on('users'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::drop('tags'); + } +} diff --git a/database/migrations/2018_11_10_161536_create_tagged_messages_table.php b/database/migrations/2018_11_10_161536_create_tagged_messages_table.php new file mode 100755 index 0000000..0a31bb7 --- /dev/null +++ b/database/migrations/2018_11_10_161536_create_tagged_messages_table.php @@ -0,0 +1,40 @@ +increments('id'); + $table->integer('message_id')->unsigned()->unique(); + $table->integer('tag_from_id')->unsigned()->nullable(); + $table->integer('tag_to_id')->unsigned()->nullable(); + $table->timestamps(); + + $table->foreign('message_id')->references('id')->on('messages'); + + $table->foreign('tag_from_id')->references('id')->on('tags'); + $table->foreign('tag_to_id')->references('id')->on('tags'); + + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::drop('tagged_messages'); + } +} diff --git a/database/migrations/2018_11_10_161622_create_conversation_tags_table.php b/database/migrations/2018_11_10_161622_create_conversation_tags_table.php new file mode 100644 index 0000000..f6dfd4b --- /dev/null +++ b/database/migrations/2018_11_10_161622_create_conversation_tags_table.php @@ -0,0 +1,33 @@ +increments('id'); + $table->integer('conversation_id'); + $table->integer('tag_id'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('conversation_tag'); + } +} diff --git a/database/migrations/2018_11_10_164802_add_title_column_to_conversations_table.php b/database/migrations/2018_11_10_164802_add_title_column_to_conversations_table.php new file mode 100644 index 0000000..517afc3 --- /dev/null +++ b/database/migrations/2018_11_10_164802_add_title_column_to_conversations_table.php @@ -0,0 +1,32 @@ +string('title'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('conversations', function (Blueprint $table) { + $table->dropColumn('title'); + }); + } +} diff --git a/database/migrations/2018_11_10_170722_add_is_read_column_to_conversations_table.php b/database/migrations/2018_11_10_170722_add_is_read_column_to_conversations_table.php new file mode 100644 index 0000000..4734609 --- /dev/null +++ b/database/migrations/2018_11_10_170722_add_is_read_column_to_conversations_table.php @@ -0,0 +1,32 @@ +boolean('is_read')->default(0); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('conversations', function (Blueprint $table) { + $table->dropColumn('is_read'); + }); + } +} diff --git a/database/migrations/2020_03_28_095235_add_is_read_column_to_messages_table.php b/database/migrations/2020_03_28_095235_add_is_read_column_to_messages_table.php new file mode 100644 index 0000000..198028a --- /dev/null +++ b/database/migrations/2020_03_28_095235_add_is_read_column_to_messages_table.php @@ -0,0 +1,32 @@ +boolean('is_read')->default(0); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('messages', function (Blueprint $table) { + $table->dropColumn('is_read'); + }); + } +} diff --git a/src/Conversations/Conversation.php b/src/Conversations/Conversation.php index d48ac00..bea2953 100644 --- a/src/Conversations/Conversation.php +++ b/src/Conversations/Conversation.php @@ -6,42 +6,63 @@ class Conversation extends Model { - protected $table = 'conversations'; - public $timestamps = true; - public $fillable = [ - 'user_one', - 'user_two', - 'status', - ]; - - /* - * make a relation between message - * - * return collection - * */ - public function messages() - { - return $this->hasMany('Nahid\Talk\Messages\Message', 'conversation_id') - ->with('sender'); - } - - /* - * make a relation between first user from conversation - * - * return collection - * */ - public function userone() - { - return $this->belongsTo(config('talk.user.model', 'App\User'), 'user_one', config('talk.user.ownerKey')); - } - - /* - * make a relation between second user from conversation - * - * return collection - * */ - public function usertwo() - { - return $this->belongsTo(config('talk.user.model', 'App\User'), 'user_two', config('talk.user.ownerKey')); - } + protected $table = 'conversations'; + public $timestamps = true; + public $fillable = [ + 'user_one', + 'user_two', + 'title', + 'status', + ]; + + /* + * make a relation with tags + * + * return relationship + * */ + public function tags() + { + return $this->belongsToMany('Nahid\Talk\Tags\Tag'); + } + + /* + * make a relation between message + * + * return collection + * */ + public function messages() + { + return $this->hasMany('Nahid\Talk\Messages\Message', 'conversation_id') + ->with('sender'); + } + + /* + * make a relation between first user from conversation + * + * return collection + * */ + public function userone() + { + return $this->belongsTo(config('talk.user.model', 'App\User'), 'user_one', config('talk.user.ownerKey')); + } + + /* + * make a relation between second user from conversation + * + * return collection + * */ + public function usertwo() + { + return $this->belongsTo(config('talk.user.model', 'App\User'), 'user_two', config('talk.user.ownerKey')); + } + + /* + * adds a tag to this conversation + * + * return void + * */ + public function addTag(\Nahid\Talk\Tags\Tag $tag) + { + return $this->tags()->attach($tag->id); + } } diff --git a/src/Conversations/ConversationRepository.php b/src/Conversations/ConversationRepository.php index 80645b6..7e09059 100644 --- a/src/Conversations/ConversationRepository.php +++ b/src/Conversations/ConversationRepository.php @@ -2,26 +2,18 @@ namespace Nahid\Talk\Conversations; -use SebastianBerc\Repositories\Repository; +use Illuminate\Database\Eloquent\Model; -class ConversationRepository extends Repository +class ConversationRepository extends Model { - /* - * this method is default method for repository package - * - * @return \Nahid\Talk\Conersations\Conversation - * */ - public function takeModel() - { - return Conversation::class; - } + protected $table = 'conversations'; - /* + /** * check this given user is exists * * @param int $id * @return bool - * */ + */ public function existsById($id) { $conversation = $this->find($id); @@ -32,13 +24,13 @@ public function existsById($id) return false; } - /* + /** * check this given two users is already make a conversation * * @param int $user1 * @param int $user2 * @return int|bool - * */ + */ public function isExistsAmongTwoUsers($user1, $user2) { $conversation = Conversation::where( @@ -65,60 +57,53 @@ function ($q) use ($user1, $user2) { return false; } - /* + /** * check this given user is involved with this given $conversation * * @param int $conversationId * @param int $userId * @return bool - * */ + */ public function isUserExists($conversationId, $userId) { $exists = Conversation::where('id', $conversationId) - ->where( - function ($query) use ($userId) { - $query->where('user_one', $userId)->orWhere('user_two', $userId); - } - ) + ->where(function ($query) use ($userId) { + $query->where('user_one', $userId)->orWhere('user_two', $userId); + }) ->exists(); return $exists; } - /* - * retrieve all message thread without soft deleted message with latest one message and - * sender and receiver user model + /** + * retrieve all message threads (i.e. conversations) without soft deleted message, including latest messages, + * sender and receiver user model. This method differs from the threadsAll() method in that each conversation returned + * contains a lot more data (each conversation contains the conversation model itself, the messages in the conversation, a + * collection of only unread messages in the conversation, the corresponding user, etc.) * * @param int $user * @param int $offset * @param int $take * @return collection - * */ - public function threads($user, $order, $offset, $take) + */ + public function threads($user_id, $order, $offset, $take) { - $conv = new Conversation(); - $conv->authUser = $user; - $msgThread = $conv->with( - [ - 'messages' => function ($q) use ($user) { - return $q->where( - function ($q) use ($user) { - $q->where('user_id', $user) - ->where('deleted_from_sender', 0); - } - ) - ->orWhere( - function ($q) use ($user) { - $q->where('user_id', '!=', $user); - $q->where('deleted_from_receiver', 0); - } - ) - ->latest(); - }, 'messages.sender', 'userone', 'usertwo' - ] - ) - ->where('user_one', $user) - ->orWhere('user_two', $user) + $conversation = new Conversation(); + $conversation->authUser = $user_id; + + $conversations = $conversation->with(['messages' => function ($q) use ($user_id) { + return $q->where(function ($q) use ($user_id) { + $q->where('user_id', $user_id) + ->where('deleted_from_sender', 0); + }) + ->orWhere(function ($q) use ($user_id) { + $q->where('user_id', '!=', $user_id); + $q->where('deleted_from_receiver', 0); + }) + ->latest(); + }, 'messages.sender', 'userone', 'usertwo']) + ->where('user_one', $user_id) + ->orWhere('user_two', $user_id) ->offset($offset) ->take($take) ->orderBy('updated_at', $order) @@ -126,49 +111,60 @@ function ($q) use ($user) { $threads = []; - foreach ($msgThread as $thread) { - $collection = (object)null; - $conversationWith = ($thread->userone->id == $user) ? $thread->usertwo : $thread->userone; - $collection->thread = $thread->messages->first(); + foreach ($conversations as $conversation) { + $conversationWith = ($conversation->userone->id == $user_id) ? $conversation->usertwo : $conversation->userone; + + $collection = (object) null; + $collection->thread = $conversation->messages->first(); + $collection->conversation = $conversation; + $collection->messages = $conversation->messages; + $collection->unreadmessages = $conversation->messages()->where(function ($query) use ($user_id) { + return $query + ->where('user_id', '!=', $user_id) + ->where('is_read', '=', '0'); + })->get(); + $collection->withUser = $conversationWith; + $threads[] = $collection; } return collect($threads); } - /* - * retrieve all message thread with latest one message and sender and receiver user model + /** + * retrieve all message threads (i.e. conversations) with the latest message and the corresponding user model. + * This method defers from the threads() method in that it is more light-weight and thus more efficient, because it + * only includes just a handful of information for each conversation (each conversation only contains the + * first message in the conversation and the corresponding user). * - * @param int $user + * @param int $user_id * @param int $offset * @param int $take + * * @return collection - * */ - public function threadsAll($user, $offset, $take) + */ + public function threadsAll($user_id, $offset, $take) { - $msgThread = Conversation::with( - [ - 'messages' => function ($q) use ($user) { - return $q->latest(); - }, 'userone', 'usertwo' - ] - ) - ->where('user_one', $user)->orWhere('user_two', $user)->offset($offset)->take($take)->get(); + $conversations = Conversation::with(['messages' => function ($q) use ($user_id) { + return $q->latest(); + }, 'userone', 'usertwo']) + ->where('user_one', $user_id)->orWhere('user_two', $user_id)->offset($offset)->take($take)->get(); $threads = []; - foreach ($msgThread as $thread) { - $conversationWith = ($thread->userone->id == $user) ? $thread->usertwo : $thread->userone; - $message = $thread->messages->first(); + foreach ($conversations as $conversation) { + $conversationWith = ($conversation->userone->id == $user_id) ? $conversation->usertwo : $conversation->userone; + + $message = $conversation->messages->first(); $message->user = $conversationWith; - $threads[] = $message; + $threads[] = $message; } return collect($threads); } - /* + /** * get all conversations by given conversation id * * @param int $conversationId @@ -176,50 +172,69 @@ public function threadsAll($user, $offset, $take) * @param int $offset * @param int $take * @return collection - * */ + */ public function getMessagesById($conversationId, $userId, $offset, $take) { - return Conversation::with( - [ - 'messages' => function ($query) use ($userId, $offset, $take) { - $query->where( - function ($qr) use ($userId) { - $qr->where('user_id', '=', $userId) - ->where('deleted_from_sender', 0); - } - ) - ->orWhere( - function ($q) use ($userId) { - $q->where('user_id', '!=', $userId) - ->where('deleted_from_receiver', 0); - } - ); - - $query->offset($offset)->take($take); - - } - ] - )->with(['userone', 'usertwo'])->find($conversationId); + return Conversation::with(['messages' => function ($query) use ($userId, $offset, $take) { + $query->where(function ($qr) use ($userId) { + $qr->where('user_id', '=', $userId) + ->where('deleted_from_sender', 0); + }) + ->orWhere(function ($q) use ($userId) { + $q->where('user_id', '!=', $userId) + ->where('deleted_from_receiver', 0); + }); + + $query->offset($offset)->take($take); + }])->with(['userone', 'usertwo'])->find($conversationId); + } + /** + * get all conversations by given tag id + * + * @param int $conversationId + * @param int $userId + * @return collection + */ + public function getMessagesByTagId($tagId, $userId) + { + return Conversation::with(['messages' => function ($query) use ($userId) { + $query + ->where(function ($qr) use ($userId) { + $qr->where('messages.user_id', '=', $userId) + ->where('messages.deleted_from_sender', 0); + }) + ->orWhere(function ($q) use ($userId) { + $q->where('messages.user_id', '!=', $userId) + ->where('messages.deleted_from_receiver', 0); + }); + }, + 'userone', + 'usertwo', + 'tags' => function ($query) use ($tagId) { + $query->where('tags.id', $tagId); + }, + ]) + ->where(function ($query) use ($userId) { + $query->where('user_one', $userId) + ->orWhere('user_two', $userId); + }) + ->get(); } - /* + /** * get all conversations with soft deleted message by given conversation id * * @param int $conversationId * @param int $offset * @param int $take * @return collection - * */ + */ public function getMessagesAllById($conversationId, $offset, $take) { - return $this->with( - [ - 'messages' => function ($q) use ($offset, $take) { - return $q->offset($offset) - ->take($take); - }, 'userone', 'usertwo' - ] - )->find($conversationId); + return $this->with(['messages' => function ($q) use ($offset, $take) { + return $q->offset($offset) + ->take($take); + }, 'userone', 'usertwo'])->find($conversationId); } } diff --git a/src/Live/Broadcast.php b/src/Live/Broadcast.php index a786cdd..6873e14 100644 --- a/src/Live/Broadcast.php +++ b/src/Live/Broadcast.php @@ -73,15 +73,20 @@ protected function connectPusher($options = []) * * @param \Nahid\Talk\Messages\Message $message */ - public function transmission(Message $message) + public function transmission(Message $message,bool $includeSender=null) { + $includeSender = is_null( $includeSender) ? true : $includeSender; + if (!$this->pusher) { return false; } - $sender = $message->sender->toArray(); $messageArray = $message->toArray(); - $messageArray['sender'] = $sender; + + if($includeSender){ + $messageArray['sender'] = $message->sender->toArray(); + } + $this->dispatch(new Webcast($messageArray)); } diff --git a/src/Messages/Message.php b/src/Messages/Message.php index 1615e15..f4e19bc 100644 --- a/src/Messages/Message.php +++ b/src/Messages/Message.php @@ -3,10 +3,11 @@ namespace Nahid\Talk\Messages; use Embera\Embera; -use Illuminate\Contracts\Support\Htmlable; -use Illuminate\Database\Eloquent\Model; +use Carbon\Carbon; use Nahid\Talk\Html\HtmlString; +use Illuminate\Database\Eloquent\Model; use Nahid\Talk\Html\HtmlStringInterface; +use Illuminate\Contracts\Support\Htmlable; class Message extends Model implements HtmlStringInterface { @@ -19,6 +20,7 @@ class Message extends Model implements HtmlStringInterface public $fillable = [ 'message', 'is_seen', + 'is_read', 'deleted_from_sender', 'deleted_from_receiver', 'user_id', @@ -32,12 +34,35 @@ class Message extends Model implements HtmlStringInterface * */ public function getHumansTimeAttribute() { - $date = $this->created_at; - $now = $date->now(); + //laravel sometimes has $this=null but attributes proprty works perfectly well + $date = Carbon::parse($this->attributes['created_at']); + $now = $date->now(); return $date->diffForHumans($now, true); } + /* + * make dynamic attribute for human readable time - with more naturalisic time modifiers + * + * @return string + * */ + public function getNaturalHumansTimeAttribute() + { + //laravel sometimes has $this=null but attributes proprty works perfectly well + $date = \Carbon\Carbon::parse($this->attributes['created_at']); + $now = $date->now(); + + if ($date->isToday()) { + return $date->diffForHumans(null, false, true); + } else { + if ($date->isSameYear($now)) { + return $date->format("M j"); + } + } + + return $date->format("M j, Y"); + } + /* * make a relation between conversation model * @@ -49,10 +74,10 @@ public function conversation() } /* - * make a relation between user model - * - * @return collection - * */ + * make a relation between user model + * + * @return collection + * */ public function user() { return $this->belongsTo( @@ -63,10 +88,10 @@ public function user() } /* - * its an alias of user relation - * - * @return collection - * */ + * its an alias of user relation + * + * @return collection + * */ public function sender() { return $this->user(); diff --git a/src/Messages/MessageRepository.php b/src/Messages/MessageRepository.php index 6b24026..b453ea6 100644 --- a/src/Messages/MessageRepository.php +++ b/src/Messages/MessageRepository.php @@ -2,18 +2,15 @@ namespace Nahid\Talk\Messages; -use SebastianBerc\Repositories\Repository; +use Illuminate\Database\Eloquent\Model; -class MessageRepository extends Repository +class MessageRepository extends Model { - public function takeModel() - { - return Message::class; - } + protected $table = 'messages'; public function deleteMessages($conversationId) { - return (boolean) Message::where('conversation_id', $conversationId)->delete(); + return (bool) Message::where('conversation_id', $conversationId)->delete(); } public function softDeleteMessage($messageId, $authUserId) @@ -33,7 +30,6 @@ public function softDeleteMessage($messageId, $authUserId) $message->deleted_from_receiver = 1; } - return (boolean) $this->update($message); - + return (bool) $this->update((array)$message); } } diff --git a/src/Tags/Tag.php b/src/Tags/Tag.php new file mode 100644 index 0000000..78a8ae5 --- /dev/null +++ b/src/Tags/Tag.php @@ -0,0 +1,34 @@ +hasMany('Nahid\Talk\Messages\Conversations', 'conversation_id') + ->with('sender'); + } + + public function scopeWithoutSpecialTags($query) + { + return $query->where(function ($query) { + $query->whereNull('is_special_tag')->orWhere('is_special_tag', '!=', 1); + }); + } +} diff --git a/src/Talk.php b/src/Talk.php index ce03929..adda5be 100644 --- a/src/Talk.php +++ b/src/Talk.php @@ -12,551 +12,941 @@ namespace Nahid\Talk; use Illuminate\Contracts\Config\Repository; +use Illuminate\Support\Collection; +use Nahid\Talk\Conversations\Conversation; use Nahid\Talk\Conversations\ConversationRepository; -use Nahid\Talk\Messages\MessageRepository; use Nahid\Talk\Live\Broadcast; +use Nahid\Talk\Messages\MessageRepository; +use Nahid\Talk\Tags\Tag; class Talk { - /** - * configurations instance. - * - * @var \Illuminate\Contracts\Config\Repository - */ - protected $config; - - /** - * The ConversationRepository class instance. - * - * @var \Nahid\Talk\Conversations\ConversationRepository - */ - protected $conversation; - - /** - * The MessageRepository class instance. - * - * @var \Nahid\Talk\Messages\MessageRepository - */ - protected $message; - - /** - * Broadcast class instance. - * - * @var \Nahid\Talk\Live\Broadcast - */ - protected $broadcast; - - /** - * Currently loggedin user id. - * - * @var int - */ - protected $authUserId; - - /** - * Initialize and instantiate conversation and message repositories. - * - * @param \Nahid\Talk\Conversations\ConversationRepository $conversation - * @param \Nahid\Talk\Messages\MessageRepository $message - */ - public function __construct(Repository $config, Broadcast $broadcast, ConversationRepository $conversation, MessageRepository $message) - { - $this->config = $config; - $this->conversation = $conversation; - $this->message = $message; - $this->broadcast = $broadcast; - } - - /** - * make two users as serialize with ascending order. - * - * @param int $user1 - * @param int $user2 - * - * @return array - */ - protected function getSerializeUser($user1, $user2) - { - $user = []; - $user['one'] = ($user1 < $user2) ? $user1 : $user2; - $user['two'] = ($user1 < $user2) ? $user2 : $user1; - - return $user; - } - - /** - * create a new message by using conversationId. - * - * @param int $conversationId - * @param string $message - * - * @return \Nahid\Talk\Messages\Message - */ - protected function makeMessage($conversationId, $message) - { - $message = $this->message->create([ - 'message' => $message, - 'conversation_id' => $conversationId, - 'user_id' => $this->authUserId, - 'is_seen' => 0, - ]); - - $message->conversation->touch(); - - $this->broadcast->transmission($message); - - return $message; - } - - /* - * Make new message collections to response with formatted data - * - *@param \Talk\Conversations\Conversation $conversations - *@return object|bool - */ - protected function makeMessageCollection($conversations) - { - if (!$conversations) { - return false; - } - - $collection = (object) null; - if ($conversations->user_one == $this->authUserId || $conversations->user_two == $this->authUserId) { - $withUser = ($conversations->userone->id === $this->authUserId) ? $conversations->usertwo : $conversations->userone; - $collection->withUser = $withUser; - $collection->messages = $conversations->messages; - - return $collection; - } - - return false; - } - - /** - * make new conversation the given receiverId with currently loggedin user. - * - * @param int $receiverId - * - * @return int - */ - protected function newConversation($receiverId) - { - $conversationId = $this->isConversationExists($receiverId); - $user = $this->getSerializeUser($this->authUserId, $receiverId); - - if ($conversationId === false) { - $conversation = $this->conversation->create([ - 'user_one' => $user['one'], - 'user_two' => $user['two'], - 'status' => 1, - ]); - - if ($conversation) { - return $conversation->id; - } - } - - return $conversationId; - } - - /** - * set currently authenticated user id for global usage. - * - * @param int $id - * - * @return int|bool - */ - public function setAuthUserId($id = null) - { - if (!is_null($id)) { - return $this->authUserId = $id; - } - - return false; - } - - /* - * its set user id instantly when you fetch or access data. if you you haven't - * set authenticated user id globally or you want to fetch work with - * instant users information, you may use it - * - * @param int $id - * @return \Nahid\Talk\Talk|bool - * */ - public function user($id = null) - { - if ($this->setAuthUserId($id)) { - return $this; - } - - return false; - } - - /** - * make sure is this conversation exist for this user with currently loggedin user. - * - * @param int $userId - * - * @return bool|int - */ - public function isConversationExists($userId) - { - if (empty($userId)) { - return false; - } - - $user = $this->getSerializeUser($this->authUserId, $userId); - - return $this->conversation->isExistsAmongTwoUsers($user['one'], $user['two']); - } - - /** - * check the given user exist for the given conversation. - * - * @param int $conversationId - * @param int $userId - * - * @return bool - */ - public function isAuthenticUser($conversationId, $userId) - { - if ($conversationId && $userId) { - return $this->conversation->isUserExists($conversationId, $userId); - } - - return false; - } - - /** - * send a message by using converstionid. - * - * @param int $conversationId - * @param string $message - * - * @return \Nahid\Talk\Messages\Message|bool - */ - public function sendMessage($conversatonId, $message) - { - if ($conversatonId && $message) { - if ($this->conversation->existsById($conversatonId)) { - $message = $this->makeMessage($conversatonId, $message); - - return $message; - } - } - - return false; - } - - /** - * create a new message by using receiverid. - * - * @param int $receiverId - * @param string $message - * - * @return \Nahid\Talk\Messages\Message - */ - public function sendMessageByUserId($receiverId, $message) - { - if ($conversationId = $this->isConversationExists($receiverId)) { - $message = $this->makeMessage($conversationId, $message); - - return $message; - } - - $convId = $this->newConversation($receiverId); - $message = $this->makeMessage($convId, $message); - - return $message; - } - - /** - * fetch all inbox for currently loggedin user with pagination. - * - * @param int $offset - * @param int $take - * - * @return array - */ - public function getInbox($order = 'desc', $offset = 0, $take = 20) - { - return $this->conversation->threads($this->authUserId, $order, $offset, $take); - } - - /** - * fetch all inbox with soft deleted message for currently loggedin user with pagination. - * - * @param int $offset - * @param int $take - * - * @return array - */ - public function getInboxAll($order = 'desc', $offset = 0, $take = 20) - { - return $this->conversation->threadsAll($this->authUserId, $order, $offset, $take); - } - - /** - * its a alias of getInbox method. - * - * @param int $offset - * @param int $take - * - * @return array - */ - public function threads($order = 'desc', $offset = 0, $take = 20) - { - return $this->getInbox($order, $offset, $take); - } - - /** - * its a alias of getInboxAll method. - * - * @param int $offset - * @param int $take - * - * @return array - */ - public function threadsAll($order = 'desc', $offset = 0, $take = 20) - { - return $this->getInboxAll($order, $offset, $take); - } - - /** - * fetch all conversation by using coversation id. - * - * @param int $conversationId - * @param int $offset = 0 - * @param int $take = 20 - * - * @return \Nahid\Talk\Messages\Message - */ - public function getConversationsById($conversationId, $offset = 0, $take = 20) - { - $conversations = $this->conversation->getMessagesById($conversationId, $this->authUserId, $offset, $take); - - return $this->makeMessageCollection($conversations); - } - - /** - * fetch all conversation with soft deleted messages by using coversation id. - * - * @param int $conversationId - * @param int $offset = 0 - * @param int $take = 20 - * - * @return \Nahid\Talk\Messages\Message - */ - public function getConversationsAllById($conversationId, $offset = 0, $take = 20) - { - $conversations = $this->conversation->getMessagesAllById($conversationId, $offset, $take); - - return $this->makeMessageCollection($conversations); - } - - /** - * create a new message by using sender id. - * - * @param int $senderId - * @param int $offset = 0 - * @param int $take = 20 - * - * @return \Nahid\Talk\Messages\Message|bool - */ - public function getConversationsByUserId($senderId, $offset = 0, $take = 20) - { - $conversationId = $this->isConversationExists($senderId, $this->authUserId); - if ($conversationId) { - return $this->getConversationsById($conversationId, $offset, $take); - } - - return false; - } - - /** - * create a new message by using sender id. - * - * @param int $senderId - * @param int $offset = 0 - * @param int $take = 20 - * - * @return \Nahid\Talk\Messages\Message|bool - */ - public function getConversationsAllByUserId($senderId, $offset = 0, $take = 20) - { - $conversationId = $this->isConversationExists($senderId, $this->authUserId); - if ($conversationId) { - return $this->getConversationsAllById($conversationId, $offset, $take); - } - - return false; - } - - /** - * its an alias of getConversationById. - * - * @param int $conversationId - * - * @return \Nahid\Talk\Messages\Message|bool - */ - public function getMessages($conversationId, $offset = 0, $take = 20) - { - return $this->getConversationsById($conversationId, $offset, $take); - } - - /** - * its an alias of getConversationAllById. - * - * @param int $conversationId - * - * @return \Nahid\Talk\Messages\Message|bool - */ - public function getMessagesAll($conversationId, $offset = 0, $take = 20) - { - return $this->getConversationsAllById($conversationId, $offset, $take); - } - - /** - * its an alias by getConversationByUserId. - * - * @param int $senderId - * - * @return \Nahid\Talk\Messages\Message|bool - */ - public function getMessagesByUserId($userId, $offset = 0, $take = 20) - { - return $this->getConversationsByUserId($userId, $offset, $take); - } - - /** - * its an alias by getConversationAllByUserId. - * - * @param int $senderId - * - * @return \Nahid\Talk\Messages\Message|bool - */ - public function getMessagesAllByUserId($userId, $offset = 0, $take = 20) - { - return $this->getConversationsAllByUserId($userId, $offset, $take); - } - - /** - * read a single message by message id. - * - * @param int $messageId - * - * @return \Nahid\Talk\Messages\Message|bool - */ - public function readMessage($messageId = null) - { - if (!is_null($messageId)) { - $message = $this->message->with(['sender', 'conversation'])->find($messageId); - - if ($message->coversation->user_one == $this->authUserId || $message->coversation->user_two == $this->authUserId) { - return $message; - } - } - - return false; - } - - /** - * make a message as seen. - * - * @param int $messageId - * - * @return bool - */ - public function makeSeen($messageId) - { - $seen = $this->message->update($messageId, ['is_seen' => 1]); - if ($seen) { - return true; - } - - return false; - } - - /** - * get receiver information for this conversation. - * - * @param int $conversationId - * - * @return UserModel - * - * @deprecated since version 2.0.0 Remove it from version 2.0.2 - */ - public function getReceiverInfo($conversationId) - { - $conversation = $this->conversation->find($conversationId); - $receiver = ''; - if ($conversation->user_one == $this->authUserId) { - $receiver = $conversation->user_two; - } else { - $receiver = $conversation->user_one; - } - - $userModel = $this->config('talk.user.model'); - $user = new $userModel(); - - return $user->find($receiver); - } - - /** - * delete a specific message, its a softdelete process. All message stored in db. - * - * @param int $messageId - * - * @return bool - */ - public function deleteMessage($messageId) - { - return $this->message->softDeleteMessage($messageId, $this->authUserId); - } - - /** - * permanently delete message for this id. - * - * @param int $messageId - * - * @return bool - */ - public function deleteForever($messageId) - { - $deleteMessage = $this->message->delete($messageId); - if ($deleteMessage) { - return true; - } - - return false; - } - - /** - * delete message threat or conversation by conversation id. - * - * @param int $id - * - * @return bool - */ - public function deleteConversations($id) - { - $deleteConversation = $this->conversation->delete($id); - if ($deleteConversation) { - return $this->message->deleteMessages($id); - } - - return false; - } - - /** - * its an alias of deleteConversations. - * - * @param int $id - * - * @return bool - */ - public function deleteThread($id = null) - { - return $this->deleteConversations($id); - } + + /** + * With this constant, conversations can be marked as being specially important by "star-ing" them. + * This is made possible because we can add tags to conversations. This constant is the name of a + * special tag that is used to label starred conversations. + * By the way, special tags, by definition and implementation, can only have one copy (i.e. by namr) in the system, + * and they do not have creator/owner, i.e. their user_id is null. + * This is useful because it ensures that special tags are not returned when getting the collection of tags that belongs to a user. + * + * @var string + */ + const STAR_TAG = "talk_special_tag_star"; + + /** + * Just like STAR_TAG, this constant is also courtesy of the tag feature of Talk. + * + * @var string + */ + const NOTIFICATION_TAG = "talk_special_tag_notification"; + + /** + * configurations instance. + * + * @var \Illuminate\Contracts\Config\Repository + */ + protected $config; + + /** + * The ConversationRepository class instance. + * + * @var \Nahid\Talk\Conversations\ConversationRepository + */ + protected $conversation; + + /** + * The MessageRepository class instance. + * + * @var \Nahid\Talk\Messages\MessageRepository + */ + protected $message; + + /** + * Broadcast class instance. + * + * @var \Nahid\Talk\Live\Broadcast + */ + protected $broadcast; + + /** + * just a helper for the last 5 messages in your mailbox + */ + protected $latestMessages = null; + + /** + * Currently loggedin user id. + * + * @var int + */ + protected $authUserId; + + /** + * Initialize and instantiate conversation and message repositories. + * + * @param \Nahid\Talk\Conversations\ConversationRepository $conversation + * @param \Nahid\Talk\Messages\MessageRepository $message + */ + public function __construct(Repository $config, Broadcast $broadcast, ConversationRepository $conversation, MessageRepository $message) + { + $this->config = $config; + $this->conversation = $conversation; + $this->message = $message; + $this->broadcast = $broadcast; + } + + /** + * make two users as serialize with ascending order. + * It returns an array whose elements are $user1 and $user2 + * + * @param int $user1 + * @param int $user2 This can be null in case of sending system notification + * + * @return array + */ + protected function getSerializeUser($user1_id, $user2_id = null) + { + $users = [ + 'one' => (($user1_id && $user1_id < $user2_id) ? $user1_id : $user2_id), + 'two' => (($user1_id && $user1_id < $user2_id) ? $user2_id : $user1_id), + ]; + + return $users; + } + + /** + * create a new message by using conversationId. + * + * @param int $conversationId + * @param string $message + * + * @return \Nahid\Talk\Messages\Message + */ + protected function makeMessage($conversationId, $message, $includeSenderInMessageBroadcast = null) + { + $includeSenderInMessageBroadcast = is_null($includeSenderInMessageBroadcast) ? true : $includeSenderInMessageBroadcast; + + $message = $this->message->create([ + 'message' => $message, + 'conversation_id' => $conversationId, + 'user_id' => $this->authUserId, + 'is_seen' => 0, + ]); + + $message->conversation->touch(); + $this->broadcast->transmission($message, $includeSenderInMessageBroadcast); + + return $message; + } + + /** + * Make new message collections to response with formatted data. Note that this method also marks + * all returned messages as "read" + * + *@param \Talk\Conversations\Conversation $conversations + *@return object|bool + */ + protected function makeMessageCollection($conversations) + { + if (!$conversations) { + return false; + } + + $collection = (object) null; + if ($conversations->user_one == $this->authUserId || $conversations->user_two == $this->authUserId) { + $withUser = ($conversations->userone->id === $this->authUserId) ? $conversations->usertwo : $conversations->userone; + $collection->withUser = $withUser; + $collection->messages = $conversations->messages; + + //mark them as read + foreach ($collection->messages as $message) { + if ($message->sender->id != $this->authUserId) { + if (!Talk::user($this->authUserId)->markRead($message->id)) { + return false; + } + } + } + + return $collection; + } + + return false; + } + + /** + * make new conversation with the given receiverId with currently loggedin user. + * + * @param int $receiverId + * @param string $title + * @param mixed $tagName + * + * @return int + */ + protected function newConversation($receiverId, $title, $tagName = null) + { + // $conversationId = $this->isConversationExists($receiverId); + $users = $this->getSerializeUser($this->authUserId, $receiverId); + + // if ($conversationId === false) { + $conversation = $this->conversation->create([ + 'user_one' => $users['one'], + 'user_two' => $users['two'], + 'title' => $title, + 'status' => 1, + ]); + + if ($conversation) { + if (!empty($tagName)) { + $tag = Tags\Tag::firstOrCreate(['user_id' => $this->authUserId, 'name' => $tagName])->first(); + + $conversation->addTag($tag); + } + + return $conversation->id; + } + // } + + return $conversation->id; + } + + /** + * set currently authenticated user id for global usage. + * + * @param int $id + * + * @return int|bool + */ + public function setAuthUserId($id = null) + { + if (!is_null($id)) { + return $this->authUserId = $id; + } + + return false; + } + + /** + * its set user id instantly when you fetch or access data. if you you haven't + * set authenticated user id globally or you want to fetch work with + * instant users information, you may use it + * + * @param int $id + * @return \Nahid\Talk\Talk|bool + */ + public function user($id = null) + { + if ($this->setAuthUserId($id)) { + return $this; + } + + return false; + } + + /** + * make sure is this conversation exist for this user with currently loggedin user. + * + * @param int $userId + * + * @return bool|int + */ + public function isConversationExists($userId) + { + if (empty($userId)) { + return false; + } + + $users = $this->getSerializeUser($this->authUserId, $userId); + + return $this->conversation->isExistsAmongTwoUsers($users['one'], $users['two']); + } + + /** + * check the given user exist for the given conversation. + * + * @param int $conversationId + * @param int $userId + * + * @return bool + */ + public function isAuthenticUser($conversationId, $userId) + { + if ($conversationId && $userId) { + return $this->conversation->isUserExists($conversationId, $userId); + } + + return false; + } + + /** + * send a message by using conversationId. + * + * @param int $conversationId + * @param string $message + * + * @return \Nahid\Talk\Messages\Message|bool + */ + public function sendMessage($conversationId, $message) + { + if ($conversationId && $message) { + if ($this->conversation->existsById($conversationId)) { + $message = $this->makeMessage($conversationId, $message); + + return $message; + } + } + + return false; + } + + /** + * create a new message by using receiverId. + * + * @param int $receiverId + * @param string $message + * + * @return \Nahid\Talk\Messages\Message + */ + public function sendMessageByUserId($receiverId, $message, $title = null, $tagName = null, bool $includeSenderInMessageBroadcast = null) + { + $includeSenderInMessageBroadcast = is_null($includeSenderInMessageBroadcast) ? true : $includeSenderInMessageBroadcast; + + if ($conversationId = $this->isConversationExists($receiverId)) { + $con = \Nahid\Talk\Conversations\Conversation::find($conversationId); + if ($con->title == $title) { + $message = $this->makeMessage($conversationId, $message); + return $message; + } + } + + $conversationId = $this->newConversation($receiverId, $title, $tagName); + $message = $this->makeMessage($conversationId, $message, $includeSenderInMessageBroadcast); + + return $message; + } + + /** + * Undocumented function + * + * @param int $receiverId + * @param string $message + * @param string $title + * @param string $customNotificationTagName + * + * @return \Nahid\Talk\Messages\Message + */ + public function sendNotificationToUser($receiverId, $message, $title = null, $customNotificationTagName = null) + { + if (is_null($this->authUserId)) { + throw new \Exception("Authenticated user not found"); + } + + $customNotificationTagName = empty($customNotificationTagName) ? self::NOTIFICATION_TAG : $customNotificationTagName; + + return $this->sendMessageByUserId($receiverId, $message, $title, $customNotificationTagName, false); + } + + /** + * fetch all inbox (i.e. conversations) for currently loggedin user with pagination. + * + * @param int $offset + * @param int $take + * + * @return array + */ + public function getInbox($order = 'desc', $offset = 0, $take = 20) + { + return $this->conversation->threads($this->authUserId, $order, $offset, $take); + } + + /** + * fetch all inbox with soft deleted message for currently loggedin user with pagination. + * + * @param int $offset + * @param int $take + * + * @return array + */ + public function getInboxAll($order = 'desc', $offset = 0, $take = 20) + { + return $this->conversation->threadsAll($this->authUserId, $order, $offset, $take); + } + + /** + * its a alias of getInbox method. + * + * @param int $offset + * @param int $take + * + * @return array + */ + public function threads($order = 'desc', $offset = 0, $take = 20) + { + return $this->getInbox($order, $offset, $take); + } + + /** + * its a alias of getInboxAll method. + * + * @param int $offset + * @param int $take + * + * @return array + */ + public function threadsAll($order = 'desc', $offset = 0, $take = 20) + { + return $this->getInboxAll($order, $offset, $take); + } + + /** + * fetch all conversation by using conversation id. Note that this method also marks + * all the messages in the returned conversations as "read" + * + * @param int $conversationId + * @param int $offset = 0 + * @param int $take = 20 + * + * @return \Nahid\Talk\Messages\Message + */ + public function getConversationsById($conversationId, $offset = 0, $take = 20) + { + $conversations = $this->conversation->getMessagesById($conversationId, $this->authUserId, $offset, $take); + + return $this->makeMessageCollection($conversations); + } + + /** + * Get conversations that have STAR_TAG + * + * @return Collection + */ + public function getStarredConversations() + { + $tag = Tag::where('name', self::STAR_TAG)->first(); + + if (is_null($tag)) { + return collect(); + } + + $conversations = $this->conversation->getMessagesByTagId($tag->id, $this->authUserId); + + return $this->makeMessageCollection($conversations); + } + + /** + * fetch all conversations that match the given tag id + * + * @param int $tag_id + * + * @return collection + */ + public function getConversationsByTagId($tag_id) + { + if (empty($tag_id)) { + return collect(); + } + + // $threads = $this->conversation->threads($this->authUserId, 'id', 6, 6); + $conversations_ = $this->conversation->getMessagesByTagId($tag_id, $this->authUserId); + + $user_id = $this->authUserId; + + $conversations = collect($conversations_)->filter(function ($item) use ($tag_id) { + return ($item->tags->pluck('id')->contains($tag_id)); + }); + + $threads = []; + + foreach ($conversations as $conversation) { + $collection = (object) null; + $conversationWith = ($conversation->userone->id == $user_id) ? $conversation->usertwo : $conversation->userone; + $collection->thread = $conversation->messages->first(); + $collection->conversation = $conversation; + $collection->messages = $conversation->messages; + $collection->unreadmessages = + $conversation->messages()->where(function ($query) use ($user_id) { + $query + ->where('user_id', '!=', $user_id) + ->where('is_read', '=', '0'); + })->get(); + $collection->withUser = $conversationWith; + $threads[] = $collection; + } + + return collect($threads); + } + + /** + * fetch all conversation with soft deleted messages by using conversation id. Note that this method also marks + * all the messages in the returned conversations as "read". + * + * @param int $conversationId + * @param int $offset = 0 + * @param int $take = 20 + * + * @return \Nahid\Talk\Messages\Message + */ + public function getConversationsAllById($conversationId, $offset = 0, $take = 20) + { + $conversations = $this->conversation->getMessagesAllById($conversationId, $offset, $take); + + return $this->makeMessageCollection($conversations); + } + + /** + * create a new message by using sender id. + * + * @param int $senderId + * @param int $offset = 0 + * @param int $take = 20 + * + * @return \Nahid\Talk\Messages\Message|bool + */ + public function getConversationsByUserId($senderId, $offset = 0, $take = 20) + { + $conversationId = $this->isConversationExists($senderId, $this->authUserId); + if ($conversationId) { + return $this->getConversationsById($conversationId, $offset, $take); + } + + return false; + } + + /** + * create a new message by using sender id. + * + * @param int $senderId + * @param int $offset = 0 + * @param int $take = 20 + * + * @return \Nahid\Talk\Messages\Message|bool + */ + public function getConversationsAllByUserId($senderId, $offset = 0, $take = 20) + { + $conversationId = $this->isConversationExists($senderId, $this->authUserId); + if ($conversationId) { + return $this->getConversationsAllById($conversationId, $offset, $take); + } + + return false; + } + + /** + * gets tags owned/created by this user + * + * @return collection + */ + public function getUserTags() + { + return Tags\Tag::where(['user_id' => $this->authUserId]) + ->get(); + } + + /** + * creates tag for user + * + * @param string $tagName + * + * @return bool + */ + public function createTagForUser($tagName) + { + if (!empty($tagName)) { + $tag = Tags\Tag::where(['user_id' => $this->authUserId, 'name' => $tagName])->first(); + if (is_null($tag)) { + $tag = Tags\Tag::create(['user_id' => $this->authUserId, 'name' => $tagName]); + } + + return !empty($tag); + } + + return false; + } + + /** + * adds a tag to an existing conversation. Creates the tag if it does not exist for the user + * This allows for several users to maintain same tag name conveniently without any conflicts/issues + * + * @param int $conversationId + * @param string $tagName + * @param bool $makeSpecialTag when set to true, ensures that only one tag with the specified name should be maintained, thus supporting use of custom "system tags" e.g. for notifications + * + * @return bool + */ + public function addTagToConversation($conversationId, string $tagName, bool $makeSpecialTag = null) + { + $makeSpecialTag = is_bool($makeSpecialTag) ? $makeSpecialTag : false; + + if (empty($tagName)) { + return false; + } + + $tag = Tags\Tag::where(['user_id' => $this->authUserId, 'name' => $tagName])->first(); + + //treat star tag specially + if ($tagName == \Nahid\Talk\Talk::STAR_TAG || $makeSpecialTag) { + //at any time, we want to always have only one star tag, irrespective of who created it + //Therefore, this will ensure that we have only one star tag in our db table + $tag = Tags\Tag::where(['name' => $tagName])->first(); + } + + if (is_null($tag)) { + //special tags do not have owners + if ($tagName == \Nahid\Talk\Talk::STAR_TAG || $makeSpecialTag) { + $tag = Tags\Tag::forceCreate([ + 'name' => $tagName, + 'is_special_tag' => 1, + ]); + } else { + $tag = Tags\Tag::create(['user_id' => $this->authUserId, 'name' => $tagName]); + } + } + + $conversation = Conversation::with('tags')->findOrFail($conversationId); + if (!$conversation->tags->pluck('id')->contains($tag->id)) { + $conversation->addTag($tag); + } + + return true; + } + + public function starThisConversation($conversationId) + { + return $this->addTagToConversation($conversationId, self::STAR_TAG); + } + + /** + *removes tag from a conversation + * + * @param int $conversationId + * @param int $tagId + * + * @return bool + */ + public function removeTagFromConversation($conversationId, $tagId) + { + if (!empty($conversationId) && !empty($tagId)) { + $conversation = \Nahid\Talk\Conversations\Conversation::with('tags') + ->where(function ($query) { + //just to ensure user belongs to the conversation + $query + ->where("user_one", $this->authUserId) + ->orWhere("user_two", $this->authUserId); + }) + ->findOrFail($conversationId); + + $conversation->tags()->detach($tagId); + + return true; + } + + return false; + } + /** + * its an alias of getConversationById. + * + * @param int $conversationId + * + * @return \Nahid\Talk\Messages\Message|bool + */ + public function getMessages($conversationId, $offset = 0, $take = 20) + { + return $this->getConversationsById($conversationId, $offset, $take); + } + + /** + * its an alias of getConversationAllById. + * + * @param int $conversationId + * + * @return \Nahid\Talk\Messages\Message|bool + */ + public function getMessagesAll($conversationId, $offset = 0, $take = 20) + { + return $this->getConversationsAllById($conversationId, $offset, $take); + } + + /** + * its an alias by getConversationByUserId. + * + * @param int $senderId + * + * @return \Nahid\Talk\Messages\Message|bool + */ + public function getMessagesByUserId($userId, $offset = 0, $take = 20) + { + return $this->getConversationsByUserId($userId, $offset, $take); + } + + /** + * its an alias by getConversationAllByUserId. + * + * @param int $senderId + * + * @return \Nahid\Talk\Messages\Message|bool + */ + public function getMessagesAllByUserId($userId, $offset = 0, $take = 20) + { + return $this->getConversationsAllByUserId($userId, $offset, $take); + } + + /** + * read a single message by message id. + * + * @param int $messageId + * + * @return \Nahid\Talk\Messages\Message|bool + */ + public function readMessage($messageId = null) + { + if (!is_null($messageId)) { + $message = $this->message->with(['sender', 'conversation'])->find($messageId); + + if ($message->conversation->user_one == $this->authUserId || $message->conversation->user_two == $this->authUserId) { + return $message; + } + } + + return false; + } + + /** + * marks a message as seen. + * + * @param int $messageId + * + * @return bool + */ + public function makeSeen($messageId) + { + $seen = $this->message->update($messageId, ['is_seen' => 1]); + if ($seen) { + return true; + } + + return false; + } + /** + * marks a message as read. + * + * @param int $messageId + * + * @return bool + */ + public function markRead($messageId) + { + if (!is_null($messageId)) { + $message = $this->message->with(['sender', 'conversation'])->find($messageId); + if ($message->conversation->user_one == $this->authUserId || $message->conversation->user_two == $this->authUserId) { + + //only needful to mark as read if you are the recipient + if ($message->sender->id != $this->authUserId) { + $read = $this->message->update($messageId, ['is_read' => 1]); + if (!$read) { + return false; + } + } + + return true; + } + } + + return false; + } + + /** + * gets messages not yet read in a particular conversation + * + * @param int $conversationId + * + * @return mixed + */ + public function getUnreadMessagesInConversation($conversationId) + { + if (!is_null($conversationId)) { + $message = $this->conversation->with(['messages'])->find($conversationId); + if ($message->conversation->user_one == $this->authUserId || $message->conversation->user_two == $this->authUserId) { + + $unread = []; + $unread = collect($this->conversation->messages)->filter(function ($message) { + return (($message->sender->id != $this->authUserId) && ($message->is_read != 1)); + }); + + return $unread; + } + } + + return false; + } + + /** + * gets all messages not yet read in all conversations altogether + * + * + * @param int $removeSpecialMessages When true will remove conversations that have special tags. + * Special tags is one of those features of Talk that makes it easy to mimic sending of system notifications + * As a rule of thumb, any conversation that is not "normal" message/conversation should simply be tagged as special, so + * that it is easy to get unread messages without confusing message contexts + * + * @return collection + */ + public function getAllUnreadMessages($removeSpecialMessages = false) + { + $messages = collect(); + $user_id = $this->authUserId; + $conversation = new \Nahid\Talk\Conversations\Conversation(); + $conversations = $conversation->with( + [ + 'messages' => function ($query) use ($user_id) { + $query + ->where('user_id', '!=', $user_id) + ->where('is_read', '=', '0'); + }, + + 'tags' => function ($query) use ($removeSpecialMessages) { + $query->when($removeSpecialMessages, function ($query) { + $query->where(function ($query) { + $query->whereNull('is_special_tag') + ->orWhere('is_special_tag', '!=', '1'); + }); + }); + }, + ]) + ->where(function ($query) use ($user_id) { + $query->where('user_one', $user_id) + ->orWhere('user_two', $user_id); + }) + ->get(); + + $messages = $conversations->pluck('messages')->flatten(); + + return $messages; + } + + /** + * gets all latest messages sent to the authenticated user + * + * @param int $conversationId + * + * @return collection + */ + public function getLatestMessages() + { + if ($this->latestMessages == null) { + + $messages = collect(); + $user_id = $this->authUserId; + $conversation = new \Nahid\Talk\Conversations\Conversation(); + $msgThread = $conversation->with(['messages' => function ($query) use ($user_id) { + $query->where('user_id', '!=', $user_id)->with(['conversation']); + }]) + ->where('user_one', $user_id) + ->orWhere('user_two', $user_id) + ->orderBy('created_at') + ->take(5) + ->get(); + + foreach ($msgThread as $thread) { + $messages = collect($messages)->merge($thread->messages); + } + + $this->latestMessages = $messages; + } + + return $this->latestMessages; + } + + /** + * gets the count of all messages not yet read in all conversations altogether + * + * @param int $removeSpecialMessages whether to remove special tag messages: This allows for Nahid to be useful for sending custom system notification messages to users + * + * @return int + */ + public function getUnreadMessagesCount($removeSpecialMessages = false) + { + return $this->getAllUnreadMessages($removeSpecialMessages)->count(); + } + + /** + * get receiver information for this conversation. + * + * @param int $conversationId + * + * @return UserModel + * + * @deprecated since version 2.0.0 Remove it from version 2.0.2 + */ + public function getReceiverInfo($conversationId) + { + $conversation = $this->conversation->find($conversationId); + $receiver = ''; + if ($conversation->user_one == $this->authUserId) { + $receiver = $conversation->user_two; + } else { + $receiver = $conversation->user_one; + } + + $userModel = $this->config('talk.user.model'); + $user = new $userModel(); + + return $user->find($receiver); + } + + /** + * delete a specific message, it is a softDelete process. All message stored in db. + * + * @param int $messageId + * + * @return bool + */ + public function deleteMessage($messageId) + { + return $this->message->softDeleteMessage($messageId, $this->authUserId); + } + + /** + * permanently delete message for this id. + * + * @param int $messageId + * + * @return bool + */ + public function deleteForever($messageId) + { + $deleteMessage = $this->message->delete($messageId); + if ($deleteMessage) { + return true; + } + + return false; + } + + /** + * delete message threat or conversation by conversation id. + * + * @param int $id + * + * @return bool + */ + public function deleteConversations($id) + { + $deleteConversation = $this->conversation->delete($id); + if ($deleteConversation) { + return $this->message->deleteMessages($id); + } + + return false; + } + + /** + * its an alias of deleteConversations. + * + * @param int $id + * + * @return bool + */ + public function deleteThread($id = null) + { + return $this->deleteConversations($id); + } } diff --git a/src/TalkServiceProvider.php b/src/TalkServiceProvider.php index 4b24577..8cb4ffa 100644 --- a/src/TalkServiceProvider.php +++ b/src/TalkServiceProvider.php @@ -19,6 +19,7 @@ public function boot() $this->setupConfig(); $this->setupMigrations(); $this->loadViewsFrom(__DIR__ . '/views', 'talk'); + $this->loadMigrationsFrom(__DIR__.'/../database/migrations'); } /** * Register the application services. @@ -38,11 +39,11 @@ protected function setupConfig() if ($this->app instanceof LaravelApplication && $this->app->runningInConsole()) { $this->publishes([$source => config_path('talk.php')]); } - + if ($this->app instanceof LumenApplication) { $this->app->configure('talk'); } - + $this->mergeConfigFrom($source, 'talk'); } /** diff --git a/tests/TestCase.php b/tests/TestCase.php index 927698e..b539808 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -17,7 +17,7 @@ abstract class TestCase extends AbstractPackageTestCase * * @return string */ - protected function getServiceProviderClass($app) + protected function getServiceProviderClass() { return TalkServiceProvider::class; }