crixuamg / laravel-mentions
A package to parse a @mention from a text and mention the user with a notification.
Installs: 4 906
Dependents: 0
Suggesters: 0
Security: 0
Stars: 6
Watchers: 1
Forks: 22
Open Issues: 1
Requires
- illuminate/console: ^9.0
- illuminate/contracts: ^9.0
- illuminate/database: ^9.0
- illuminate/http: ^9.0
- illuminate/pagination: ^9.0
- illuminate/support: ^9.0
- illuminate/validation: ^9.0
Requires (Dev)
- barryvdh/laravel-ide-helper: ^2.10
- friendsofphp/php-cs-fixer: ^3.0
- mockery/mockery: ^1.4
- nunomaduro/phpinsights: ^2.0
- orchestra/testbench: ^7.4
- phpmd/phpmd: ^2.10
- phpunit/phpunit: ^9.5
- squizlabs/php_codesniffer: ^3.6
README
Laravel Mentions
A package to parse
@mentions
from a text and mention the user with a notification.By default this package is configured to parse any text type and it will replace any matched
@mention
with a markdown link ([@Mention](/users/profile/@Mention)
) if the mentionned user exist in the database. It will also send a notification with the LaravelNotifiable
trait to all mentionned users. (Inspired from the laravel-mentions package.)Quick example :
Input text :
Lorem ipsu @admin crepu @Member quis nostrud @UserDoesNotExist ullamcorper fail@mention nostrud @admin.Output text :
Lorem ipsu [@Admin](/users/profile/@Admin) crepu [@Member](/users/profile/@Member) quis nostrud @UserDoesNotExist ullamcorper fail@mention nostrud [@Admin](/users/profile/@Admin).And Both
Admin
andMember
users will be notified. ButAdmin
will be notified only one time. (Yes the Parser include an anti-spam rule.)Table of Contents
Requirement
Installation
composer require CrixuAMG/Laravel-mentions
ServiceProviders
Import the
MentionServiceProvider
in yourconfig/app.php
:'providers' => [ //... CrixuAMG\Mentions\Providers\MentionServiceProvider::class, //... ]Vendor Publish
Publish the vendor files to your application (included the config file
config/mentions.php
and the migration file) :php artisan vendor:publish --provider="CrixuAMG\Mentions\Providers\MentionServiceProvider"Then migrate the database :
php artisan migrateConfiguration
<?php return [ 'pools' => [ // Here you configure as many pools as you want. But basically we // notify only the Users. 'users' => [ // Model that will be mentioned. 'model' => App\Models\User::class, // The column that will be used to search the model by the parser. 'column' => 'username', // The route used to generate the user link. 'route' => '/users/profile/@', // Notification class to use when this model is mentioned. 'notification' => App\Notifications\MentionNotification::class, ] ] ];Usage
First, you will need to add the
HasMentionTrait
to the mentioner Model :<?php namespace App\Models; use Illuminate\Database\Eloquent\Model; use CrixuAMG\Mentions\Models\Traits\HasMentionsTrait; class Comment extends Model { use HasMentionsTrait; }Now, you can start to parse a text in your controller or where you want :
<?php namespace App\Http\Controllers; use CrixuAMG\Mentions\Parser\MentionParser; class CommentController extends Controller { public function create(Request $request) { // Handle the comment creation however you like $comment = Comment::create($request->all()); // Register a new Parser and parse the content. $parser = new MentionParser($comment); $content = $parser->parse($comment->content); /** * Re-assign the parsed content and save it. * * Note : If you use a custom Parser and you don't modify * the `$content` in your custom Parser, you can ignore that. */ $comment->content = $content; $comment->save(); } }And that's all ! At least with the default configuration. 😝
Parser configuration
The
MentionParser
take a second parameter who is a configuration array, this is the default configuration :<?php [ // The pool used with the parser. 'pool' => 'users', // If `false`, the parser won't mention the user. 'mention' => true, /** * If `false` the parser won't notify the user. * * Note : If the `mention` option is set to `false`, this setting is ignored. */ 'notify' => true, /** * The character that will trigger the mention. * Note : If you modify this setting, you will also need to modify * the `regex_replacement.{character}` option to match this setting. */ 'character' => '@', // The regex used to parse the mentions. 'regex' => '/\s({character}{pattern}{rules})/', /** * The replacement used to replace the regex pattarn. * Can be usefull if you want to allow a special character in the mention like `_` or `-` * or pass dynamic value to the regex. * * Note : The parse use the PHP function `strtr` to replace the pattarn in the regex. */ 'regex_replacement' => [ '{character}' => '@', '{pattern}' => '[A-Za-z0-9]', '{rules}' => '{4,20}' ] ]The configuration is merged with the default configuration, so you can set only the options that you want to modify. Exemple :
<?php $parser = new MentionParser($comment, [ 'pool' => 'members', 'notify' => false ]);You can also set a configuration at the runtime :
<?php $parser = new MentionParser($comment); $parser->setOption('notify', false); $content = $parser->parse($comment->content);Or even get a configuration option value :
<?php $value = $parser->getOption('notify'); // falseParser configuration methods :
The parser use the Xety/Configurator package to manage the configuration. Check this repository to get all the methods and their description.
Custom Parser
If you want more flexibility for the Parser, the best way is to create a new Parser and overwrite the methods that you want to modify. For an example, let's create a new Parser that will return a HTML link instead of a Markdown link :
<?php namespace App\Parser; use Illuminate\Support\Str; use CrixuAMG\Mentions\Parser\MentionParser; class CustomParser extends MentionParser { protected function replace(array $match): string { $character = $this->getOption('character'); $mention = Str::title(str_replace($character, '', trim($match[0]))); $route = config('mentions.pools.' . $this->getOption('pool') . '.route'); $link = $route . $mention; // Here we return a HTML link instead of the default Markdown. return " <a class=\"link\" href=\"{$link} \">{$character}{$mention}</a>"; } }To use it :
<?php $parser = new \App\Parser\CustomParser($comment); $content = $parser->parse($comment->content);You can of course overwrite all Parser's methods if you need to.
Notification
You will need to write your own Notififation class, but I'm cool with you, you can find an example here using the delivery channel
database
:<?php namespace App\Notifications; use Illuminate\Bus\Queueable; use Illuminate\Notifications\Notification; class MentionNotification extends Notification { use Queueable; /** * The Comment instance. * * @var \Illuminate\Database\Eloquent\Model */ public $model; /** * Create a new notification instance. * * @param \Illuminate\Database\Eloquent\Model $model */ public function __construct($model) { $this->model = $model; } /** * Get the notification's delivery channels. * * @param mixed $notifiable * * @return array */ public function via($notifiable): array { return ['database']; } /** * Get the array representation of the notification. * * @param mixed $notifiable * * @return array */ public function toDatabase($notifiable): array { // The instance `$this->model` represent the `Comment` model. $username = $this->model->user->username; $modelId = $this->model->getKey(); $message = "<strong>@{ $username }</strong> has mentionned your name in his comment !"; // You could (and probably should) use a route name here with the function `route()`. $link = "/comment/show/{ $modelId }"; return [ 'message' => $message, 'link' => $link, 'type' => 'mention' ]; } }Contribute
If you want to contribute, please follow this guide.