Make user mentions great again

This commit is contained in:
Frederic Guillot
2016-12-01 22:52:58 -05:00
parent be83821ef7
commit f73d0d2ac9
22 changed files with 270 additions and 140 deletions

View File

@@ -126,7 +126,6 @@ use Pimple\Container;
* @property \Kanboard\Model\TransitionModel $transitionModel
* @property \Kanboard\Model\UserModel $userModel
* @property \Kanboard\Model\UserLockingModel $userLockingModel
* @property \Kanboard\Model\UserMentionModel $userMentionModel
* @property \Kanboard\Model\UserNotificationModel $userNotificationModel
* @property \Kanboard\Model\UserNotificationTypeModel $userNotificationTypeModel
* @property \Kanboard\Model\UserNotificationFilterModel $userNotificationFilterModel
@@ -178,6 +177,7 @@ use Pimple\Container;
* @property \Kanboard\Job\ProjectFileEventJob $projectFileEventJob
* @property \Kanboard\Job\NotificationJob $notificationJob
* @property \Kanboard\Job\ProjectMetricJob $projectMetricJob
* @property \Kanboard\Job\UserMentionJob $userMentionJob
* @property \Psr\Log\LoggerInterface $logger
* @property \PicoDb\Database $db
* @property \Symfony\Component\EventDispatcher\EventDispatcher $dispatcher

View File

@@ -90,7 +90,7 @@ class Markdown extends Parsedown
$user_id = $this->container['userModel']->getIdByUsername($matches[1]);
if (! empty($user_id)) {
$url = $this->container['helper']->url->href('UserViewController', 'profile', array('user_id' => $user_id));
$url = $this->container['helper']->url->href('UserViewController', 'profile', array('user_id' => $user_id), false, '', true);
return array(
'extent' => strlen($matches[0]),

View File

@@ -14,6 +14,28 @@ class GenericEvent extends BaseEvent implements ArrayAccess
$this->container = $values;
}
public function getTaskId()
{
if (isset($this->container['task']['id'])) {
return $this->container['task']['id'];
}
if (isset($this->container['task_id'])) {
return $this->container['task_id'];
}
return null;
}
public function getProjectId()
{
if (isset($this->container['task']['project_id'])) {
return $this->container['task']['project_id'];
}
return null;
}
public function getAll()
{
return $this->container;

View File

@@ -4,4 +4,12 @@ namespace Kanboard\Event;
class ProjectFileEvent extends GenericEvent
{
public function getProjectId()
{
if (isset($this->container['file']['project_id'])) {
return $this->container['file']['project_id'];
}
return null;
}
}

View File

@@ -31,7 +31,6 @@ class CommentEventJob extends BaseJob
*
* @param int $commentId
* @param string $eventName
* @return $this
*/
public function execute($commentId, $eventName)
{
@@ -43,7 +42,8 @@ class CommentEventJob extends BaseJob
$this->dispatcher->dispatch($eventName, $event);
if ($eventName === CommentModel::EVENT_CREATE) {
$this->userMentionModel->fireEvents($event['comment']['comment'], CommentModel::EVENT_USER_MENTION, $event);
$userMentionJob = $this->userMentionJob->withParams($event['comment']['comment'], CommentModel::EVENT_USER_MENTION, $event);
$this->queueManager->push($userMentionJob);
}
}
}

View File

@@ -69,7 +69,8 @@ class TaskEventJob extends BaseJob
$this->dispatcher->dispatch($eventName, $event);
if ($eventName === TaskModel::EVENT_CREATE) {
$this->userMentionModel->fireEvents($event['task']['description'], TaskModel::EVENT_USER_MENTION, $event);
$userMentionJob = $this->userMentionJob->withParams($event['task']['description'], TaskModel::EVENT_USER_MENTION, $event);
$this->queueManager->push($userMentionJob);
}
}
}

View File

@@ -0,0 +1,71 @@
<?php
namespace Kanboard\Job;
use Kanboard\Event\GenericEvent;
use Kanboard\Model\UserModel;
/**
* Class UserMentionJob
*
* @package Kanboard\Job
* @author Frederic Guillot
*/
class UserMentionJob extends BaseJob
{
/**
* Set job parameters
*
* @param string $text
* @param string $eventName
* @param GenericEvent $event
* @return $this
*/
public function withParams($text, $eventName, GenericEvent $event)
{
$this->jobParams = array($text, $eventName, $event);
return $this;
}
/**
* Execute job
*
* @param string $text
* @param string $eventName
* @param GenericEvent $event
*/
public function execute($text, $eventName, GenericEvent $event)
{
$users = $this->getMentionedUsers($text);
foreach ($users as $user) {
if ($this->projectPermissionModel->isMember($event->getProjectId(), $user['id'])) {
$event['mention'] = $user;
$this->dispatcher->dispatch($eventName, $event);
}
}
}
/**
* Get list of mentioned users
*
* @access public
* @param string $text
* @return array
*/
public function getMentionedUsers($text)
{
$users = array();
if (preg_match_all('/@([^\s,!.:?]+)/', $text, $matches)) {
$users = $this->db->table(UserModel::TABLE)
->columns('id', 'username', 'name', 'email', 'language')
->eq('notifications_enabled', 1)
->neq('id', $this->userSession->getId())
->in('username', array_unique($matches[1]))
->findAll();
}
return $users;
}
}

View File

@@ -1,62 +0,0 @@
<?php
namespace Kanboard\Model;
use Kanboard\Core\Base;
use Kanboard\Event\GenericEvent;
/**
* User Mention
*
* @package Kanboard\Model
* @author Frederic Guillot
*/
class UserMentionModel extends Base
{
/**
* Get list of mentioned users
*
* @access public
* @param string $content
* @return array
*/
public function getMentionedUsers($content)
{
$users = array();
if (preg_match_all('/@([^\s]+)/', $content, $matches)) {
$users = $this->db->table(UserModel::TABLE)
->columns('id', 'username', 'name', 'email', 'language')
->eq('notifications_enabled', 1)
->neq('id', $this->userSession->getId())
->in('username', array_unique($matches[1]))
->findAll();
}
return $users;
}
/**
* Fire events for user mentions
*
* @access public
* @param string $content
* @param string $eventName
* @param GenericEvent $event
*/
public function fireEvents($content, $eventName, GenericEvent $event)
{
if (empty($event['project_id'])) {
$event['project_id'] = $this->taskFinderModel->getProjectId($event['task_id']);
}
$users = $this->getMentionedUsers($content);
foreach ($users as $user) {
if ($this->projectPermissionModel->isMember($event['project_id'], $user['id'])) {
$event['mention'] = $user;
$this->dispatcher->dispatch($eventName, $event);
}
}
}
}

View File

@@ -91,7 +91,6 @@ class ClassProvider implements ServiceProviderInterface
'TransitionModel',
'UserModel',
'UserLockingModel',
'UserMentionModel',
'UserNotificationModel',
'UserNotificationFilterModel',
'UserUnreadNotificationModel',

View File

@@ -10,6 +10,7 @@ use Kanboard\Job\SubtaskEventJob;
use Kanboard\Job\TaskEventJob;
use Kanboard\Job\TaskFileEventJob;
use Kanboard\Job\TaskLinkEventJob;
use Kanboard\Job\UserMentionJob;
use Pimple\Container;
use Pimple\ServiceProviderInterface;
@@ -62,6 +63,10 @@ class JobProvider implements ServiceProviderInterface
return new ProjectMetricJob($c);
});
$container['userMentionJob'] = $container->factory(function ($c) {
return new UserMentionJob($c);
});
return $container;
}
}

View File

@@ -15,25 +15,25 @@ class NotificationSubscriber extends BaseSubscriber implements EventSubscriberIn
public static function getSubscribedEvents()
{
return array(
TaskModel::EVENT_USER_MENTION => 'handleEvent',
TaskModel::EVENT_CREATE => 'handleEvent',
TaskModel::EVENT_UPDATE => 'handleEvent',
TaskModel::EVENT_CLOSE => 'handleEvent',
TaskModel::EVENT_OPEN => 'handleEvent',
TaskModel::EVENT_MOVE_COLUMN => 'handleEvent',
TaskModel::EVENT_MOVE_POSITION => 'handleEvent',
TaskModel::EVENT_MOVE_SWIMLANE => 'handleEvent',
TaskModel::EVENT_ASSIGNEE_CHANGE => 'handleEvent',
SubtaskModel::EVENT_CREATE => 'handleEvent',
SubtaskModel::EVENT_UPDATE => 'handleEvent',
SubtaskModel::EVENT_DELETE => 'handleEvent',
CommentModel::EVENT_CREATE => 'handleEvent',
CommentModel::EVENT_UPDATE => 'handleEvent',
CommentModel::EVENT_DELETE => 'handleEvent',
CommentModel::EVENT_USER_MENTION => 'handleEvent',
TaskFileModel::EVENT_CREATE => 'handleEvent',
TaskLinkModel::EVENT_CREATE_UPDATE => 'handleEvent',
TaskLinkModel::EVENT_DELETE => 'handleEvent',
TaskModel::EVENT_USER_MENTION => 'handleEvent',
TaskModel::EVENT_CREATE => 'handleEvent',
TaskModel::EVENT_UPDATE => 'handleEvent',
TaskModel::EVENT_CLOSE => 'handleEvent',
TaskModel::EVENT_OPEN => 'handleEvent',
TaskModel::EVENT_MOVE_COLUMN => 'handleEvent',
TaskModel::EVENT_MOVE_POSITION => 'handleEvent',
TaskModel::EVENT_MOVE_SWIMLANE => 'handleEvent',
TaskModel::EVENT_ASSIGNEE_CHANGE => 'handleEvent',
SubtaskModel::EVENT_CREATE => 'handleEvent',
SubtaskModel::EVENT_UPDATE => 'handleEvent',
SubtaskModel::EVENT_DELETE => 'handleEvent',
CommentModel::EVENT_CREATE => 'handleEvent',
CommentModel::EVENT_UPDATE => 'handleEvent',
CommentModel::EVENT_DELETE => 'handleEvent',
CommentModel::EVENT_USER_MENTION => 'handleEvent',
TaskFileModel::EVENT_CREATE => 'handleEvent',
TaskLinkModel::EVENT_CREATE_UPDATE => 'handleEvent',
TaskLinkModel::EVENT_DELETE => 'handleEvent',
);
}