diff options
Diffstat (limited to 'app')
-rw-r--r-- | app/Action/ActionCommentCreationTest.php | 124 | ||||
-rw-r--r-- | app/Action/CommentCreation.php | 1 | ||||
-rw-r--r-- | app/Action/TaskAssignUser.php | 2 | ||||
-rw-r--r-- | app/Action/TaskClose.php | 4 | ||||
-rw-r--r-- | app/Action/TaskCreation.php | 2 | ||||
-rw-r--r-- | app/Action/TaskOpen.php | 2 | ||||
-rw-r--r-- | app/Controller/Webhook.php | 12 | ||||
-rw-r--r-- | app/Core/Request.php | 2 | ||||
-rw-r--r-- | app/Integration/BitbucketWebhook.php | 236 | ||||
-rw-r--r-- | app/Model/Action.php | 7 |
10 files changed, 251 insertions, 141 deletions
diff --git a/app/Action/ActionCommentCreationTest.php b/app/Action/ActionCommentCreationTest.php deleted file mode 100644 index a4ca284e..00000000 --- a/app/Action/ActionCommentCreationTest.php +++ /dev/null @@ -1,124 +0,0 @@ -<?php - -require_once __DIR__.'/Base.php'; - -use Event\GenericEvent; -use Model\Task; -use Model\TaskCreation; -use Model\Comment; -use Model\Project; -use Integration\GithubWebhook; - -class ActionCommentCreationTest extends Base -{ - public function testWithoutRequiredParams() - { - $action = new Action\CommentCreation($this->container, 1, GithubWebhook::EVENT_ISSUE_COMMENT); - - // We create a task in the first column - $tc = new TaskCreation($this->container); - $p = new Project($this->container); - $c = new Comment($this->container); - $this->assertEquals(1, $p->create(array('name' => 'test'))); - $this->assertEquals(1, $tc->create(array('title' => 'test', 'project_id' => 1, 'column_id' => 1))); - - // We create an event to move the task to the 2nd column - $event = array( - 'project_id' => 1, - 'task_id' => 1, - 'user_id' => 1, - ); - - // Our event should be executed - $this->assertTrue($action->execute(new GenericEvent($event))); - - $comment = $c->getById(1); - $this->assertEmpty($comment); - } - - public function testWithCommitMessage() - { - $action = new Action\CommentCreation($this->container, 1, GithubWebhook::EVENT_ISSUE_COMMENT); - - // We create a task in the first column - $tc = new TaskCreation($this->container); - $p = new Project($this->container); - $c = new Comment($this->container); - $this->assertEquals(1, $p->create(array('name' => 'test'))); - $this->assertEquals(1, $tc->create(array('title' => 'test', 'project_id' => 1, 'column_id' => 1))); - - // We create an event to move the task to the 2nd column - $event = array( - 'project_id' => 1, - 'task_id' => 1, - 'commit_comment' => 'plop', - ); - - // Our event should be executed - $this->assertTrue($action->execute(new GenericEvent($event))); - - $comment = $c->getById(1); - $this->assertNotEmpty($comment); - $this->assertEquals(1, $comment['task_id']); - $this->assertEquals(0, $comment['user_id']); - $this->assertEquals('plop', $comment['comment']); - } - - public function testWithUser() - { - $action = new Action\CommentCreation($this->container, 1, GithubWebhook::EVENT_ISSUE_COMMENT); - - // We create a task in the first column - $tc = new TaskCreation($this->container); - $p = new Project($this->container); - $c = new Comment($this->container); - $this->assertEquals(1, $p->create(array('name' => 'test'))); - $this->assertEquals(1, $tc->create(array('title' => 'test', 'project_id' => 1, 'column_id' => 1))); - - // We create an event to move the task to the 2nd column - $event = array( - 'project_id' => 1, - 'task_id' => 1, - 'user_id' => 1, - 'comment' => 'youpi', - ); - - // Our event should be executed - $this->assertTrue($action->execute(new GenericEvent($event))); - - $comment = $c->getById(1); - $this->assertNotEmpty($comment); - $this->assertEquals(1, $comment['task_id']); - $this->assertEquals(1, $comment['user_id']); - $this->assertEquals('youpi', $comment['comment']); - } - - public function testWithNoUser() - { - $action = new Action\CommentCreation($this->container, 1, GithubWebhook::EVENT_ISSUE_COMMENT); - - // We create a task in the first column - $tc = new TaskCreation($this->container); - $p = new Project($this->container); - $c = new Comment($this->container); - $this->assertEquals(1, $p->create(array('name' => 'test'))); - $this->assertEquals(1, $tc->create(array('title' => 'test', 'project_id' => 1, 'column_id' => 1))); - - // We create an event to move the task to the 2nd column - $event = array( - 'project_id' => 1, - 'task_id' => 1, - 'user_id' => 0, - 'comment' => 'youpi', - ); - - // Our event should be executed - $this->assertTrue($action->execute(new GenericEvent($event))); - - $comment = $c->getById(1); - $this->assertNotEmpty($comment); - $this->assertEquals(1, $comment['task_id']); - $this->assertEquals(0, $comment['user_id']); - $this->assertEquals('youpi', $comment['comment']); - } -} diff --git a/app/Action/CommentCreation.php b/app/Action/CommentCreation.php index fb9f1172..5dfd1c89 100644 --- a/app/Action/CommentCreation.php +++ b/app/Action/CommentCreation.php @@ -25,6 +25,7 @@ class CommentCreation extends Base return array( GithubWebhook::EVENT_ISSUE_COMMENT, GithubWebhook::EVENT_COMMIT, + BitbucketWebhook::EVENT_ISSUE_COMMENT, BitbucketWebhook::EVENT_COMMIT, GitlabWebhook::EVENT_COMMIT, ); diff --git a/app/Action/TaskAssignUser.php b/app/Action/TaskAssignUser.php index cf2a9a4b..c28df9fb 100644 --- a/app/Action/TaskAssignUser.php +++ b/app/Action/TaskAssignUser.php @@ -3,6 +3,7 @@ namespace Action; use Integration\GithubWebhook; +use Integration\BitbucketWebhook; /** * Assign a task to someone @@ -22,6 +23,7 @@ class TaskAssignUser extends Base { return array( GithubWebhook::EVENT_ISSUE_ASSIGNEE_CHANGE, + BitbucketWebhook::EVENT_ISSUE_ASSIGNEE_CHANGE, ); } diff --git a/app/Action/TaskClose.php b/app/Action/TaskClose.php index b7cd4dbf..0fe58dac 100644 --- a/app/Action/TaskClose.php +++ b/app/Action/TaskClose.php @@ -30,6 +30,7 @@ class TaskClose extends Base GitlabWebhook::EVENT_COMMIT, GitlabWebhook::EVENT_ISSUE_CLOSED, BitbucketWebhook::EVENT_COMMIT, + BitbucketWebhook::EVENT_ISSUE_CLOSED, ); } @@ -47,6 +48,7 @@ class TaskClose extends Base case GitlabWebhook::EVENT_COMMIT: case GitlabWebhook::EVENT_ISSUE_CLOSED: case BitbucketWebhook::EVENT_COMMIT: + case BitbucketWebhook::EVENT_ISSUE_CLOSED: return array(); default: return array('column_id' => t('Column')); @@ -67,6 +69,7 @@ class TaskClose extends Base case GitlabWebhook::EVENT_COMMIT: case GitlabWebhook::EVENT_ISSUE_CLOSED: case BitbucketWebhook::EVENT_COMMIT: + case BitbucketWebhook::EVENT_ISSUE_CLOSED: return array('task_id'); default: return array('task_id', 'column_id'); @@ -100,6 +103,7 @@ class TaskClose extends Base case GitlabWebhook::EVENT_COMMIT: case GitlabWebhook::EVENT_ISSUE_CLOSED: case BitbucketWebhook::EVENT_COMMIT: + case BitbucketWebhook::EVENT_ISSUE_CLOSED: return true; default: return $data['column_id'] == $this->getParam('column_id'); diff --git a/app/Action/TaskCreation.php b/app/Action/TaskCreation.php index 1c093eee..bb5b05c2 100644 --- a/app/Action/TaskCreation.php +++ b/app/Action/TaskCreation.php @@ -4,6 +4,7 @@ namespace Action; use Integration\GithubWebhook; use Integration\GitlabWebhook; +use Integration\BitbucketWebhook; /** * Create automatically a task from a webhook @@ -24,6 +25,7 @@ class TaskCreation extends Base return array( GithubWebhook::EVENT_ISSUE_OPENED, GitlabWebhook::EVENT_ISSUE_OPENED, + BitbucketWebhook::EVENT_ISSUE_OPENED, ); } diff --git a/app/Action/TaskOpen.php b/app/Action/TaskOpen.php index 73f1fad3..ee42ab32 100644 --- a/app/Action/TaskOpen.php +++ b/app/Action/TaskOpen.php @@ -3,6 +3,7 @@ namespace Action; use Integration\GithubWebhook; +use Integration\BitbucketWebhook; /** * Open automatically a task @@ -22,6 +23,7 @@ class TaskOpen extends Base { return array( GithubWebhook::EVENT_ISSUE_REOPENED, + BitbucketWebhook::EVENT_ISSUE_REOPENED, ); } diff --git a/app/Controller/Webhook.php b/app/Controller/Webhook.php index d04f83b3..1a4cfe9a 100644 --- a/app/Controller/Webhook.php +++ b/app/Controller/Webhook.php @@ -53,7 +53,7 @@ class Webhook extends Base $result = $this->githubWebhook->parsePayload( $this->request->getHeader('X-Github-Event'), - $this->request->getJson() ?: array() + $this->request->getJson() ); echo $result ? 'PARSED' : 'IGNORED'; @@ -69,7 +69,7 @@ class Webhook extends Base $this->checkWebhookToken(); $this->gitlabWebhook->setProjectId($this->request->getIntegerParam('project_id')); - $result = $this->gitlabWebhook->parsePayload($this->request->getJson() ?: array()); + $result = $this->gitlabWebhook->parsePayload($this->request->getJson()); echo $result ? 'PARSED' : 'IGNORED'; } @@ -84,7 +84,11 @@ class Webhook extends Base $this->checkWebhookToken(); $this->bitbucketWebhook->setProjectId($this->request->getIntegerParam('project_id')); - $result = $this->bitbucketWebhook->parsePayload(json_decode(@$_POST['payload'], true) ?: array()); + + $result = $this->bitbucketWebhook->parsePayload( + $this->request->getHeader('X-Event-Key'), + $this->request->getJson() + ); echo $result ? 'PARSED' : 'IGNORED'; } @@ -97,7 +101,7 @@ class Webhook extends Base public function postmark() { $this->checkWebhookToken(); - echo $this->postmark->receiveEmail($this->request->getJson() ?: array()) ? 'PARSED' : 'IGNORED'; + echo $this->postmark->receiveEmail($this->request->getJson()) ? 'PARSED' : 'IGNORED'; } /** diff --git a/app/Core/Request.php b/app/Core/Request.php index c7ca3184..b399a1f0 100644 --- a/app/Core/Request.php +++ b/app/Core/Request.php @@ -83,7 +83,7 @@ class Request */ public function getJson() { - return json_decode($this->getBody(), true); + return json_decode($this->getBody(), true) ?: array(); } /** diff --git a/app/Integration/BitbucketWebhook.php b/app/Integration/BitbucketWebhook.php index eced5596..d9dc45b1 100644 --- a/app/Integration/BitbucketWebhook.php +++ b/app/Integration/BitbucketWebhook.php @@ -18,7 +18,12 @@ class BitbucketWebhook extends \Core\Base * * @var string */ - const EVENT_COMMIT = 'bitbucket.webhook.commit'; + const EVENT_COMMIT = 'bitbucket.webhook.commit'; + const EVENT_ISSUE_OPENED = 'bitbucket.webhook.issue.opened'; + const EVENT_ISSUE_CLOSED = 'bitbucket.webhook.issue.closed'; + const EVENT_ISSUE_REOPENED = 'bitbucket.webhook.issue.reopened'; + const EVENT_ISSUE_ASSIGNEE_CHANGE = 'bitbucket.webhook.issue.assignee'; + const EVENT_ISSUE_COMMENT = 'bitbucket.webhook.issue.commented'; /** * Project id @@ -40,19 +45,227 @@ class BitbucketWebhook extends \Core\Base } /** - * Parse events + * Parse incoming events * * @access public - * @param array $payload Gitlab event + * @param string $type Bitbucket event type + * @param array $payload Bitbucket event * @return boolean */ - public function parsePayload(array $payload) + public function parsePayload($type, array $payload) { - if (! empty($payload['commits'])) { + switch ($type) { + case 'issue:comment_created': + return $this->handleCommentCreated($payload); + case 'issue:created': + return $this->handleIssueOpened($payload); + case 'issue:updated': + return $this->handleIssueUpdated($payload); + case 'repo:push': + return $this->handlePush($payload); + } + + return false; + } + + /** + * Parse comment issue events + * + * @access public + * @param array $payload + * @return boolean + */ + public function handleCommentCreated(array $payload) + { + $task = $this->taskFinder->getByReference($this->project_id, $payload['issue']['id']); + + if (! empty($task)) { + + $user = $this->user->getByUsername($payload['actor']['username']); + + if (! empty($user) && ! $this->projectPermission->isMember($this->project_id, $user['id'])) { + $user = array(); + } + + $event = array( + 'project_id' => $this->project_id, + 'reference' => $payload['comment']['id'], + 'comment' => $payload['comment']['content']['raw']."\n\n[".t('By @%s on Bitbucket', $payload['actor']['display_name']).']('.$payload['comment']['links']['html']['href'].')', + 'user_id' => ! empty($user) ? $user['id'] : 0, + 'task_id' => $task['id'], + ); + + $this->container['dispatcher']->dispatch( + self::EVENT_ISSUE_COMMENT, + new GenericEvent($event) + ); + + return true; + } + + return false; + } + + /** + * Handle new issues + * + * @access public + * @param array $payload + * @return boolean + */ + public function handleIssueOpened(array $payload) + { + $event = array( + 'project_id' => $this->project_id, + 'reference' => $payload['issue']['id'], + 'title' => $payload['issue']['title'], + 'description' => $payload['issue']['content']['raw']."\n\n[".t('Bitbucket Issue').']('.$payload['issue']['links']['html']['href'].')', + ); + + $this->container['dispatcher']->dispatch( + self::EVENT_ISSUE_OPENED, + new GenericEvent($event) + ); + + return true; + } + + /** + * Handle issue updates + * + * @access public + * @param array $payload + * @return boolean + */ + public function handleIssueUpdated(array $payload) + { + $task = $this->taskFinder->getByReference($this->project_id, $payload['issue']['id']); + + if (empty($task)) { + return false; + } + + if (isset($payload['changes']['status'])) { + return $this->handleStatusChange($task, $payload); + } + else if (isset($payload['changes']['assignee'])) { + return $this->handleAssigneeChange($task, $payload); + } + + return false; + } + + /** + * Handle issue status change + * + * @access public + * @param array $task + * @param array $payload + * @return boolean + */ + public function handleStatusChange(array $task, array $payload) + { + $event = array( + 'project_id' => $this->project_id, + 'task_id' => $task['id'], + 'reference' => $payload['issue']['id'], + ); + + switch ($payload['issue']['state']) { + case 'closed': + $this->container['dispatcher']->dispatch(self::EVENT_ISSUE_CLOSED, new GenericEvent($event)); + return true; + case 'open': + $this->container['dispatcher']->dispatch(self::EVENT_ISSUE_REOPENED, new GenericEvent($event)); + return true; + } + + return false; + } + + /** + * Handle issue assignee change + * + * @access public + * @param array $task + * @param array $payload + * @return boolean + */ + public function handleAssigneeChange(array $task, array $payload) + { + if (empty($payload['issue']['assignee'])) { + return $this->handleIssueUnassigned($task, $payload); + } + + return $this->handleIssueAssigned($task, $payload); + } + + /** + * Handle issue assigned + * + * @access public + * @param array $task + * @param array $payload + * @return boolean + */ + public function handleIssueAssigned(array $task, array $payload) + { + $user = $this->user->getByUsername($payload['issue']['assignee']['username']); + + if (empty($user)) { + return false; + } + + if (! $this->projectPermission->isMember($this->project_id, $user['id'])) { + return false; + } + + $event = array( + 'project_id' => $this->project_id, + 'task_id' => $task['id'], + 'owner_id' => $user['id'], + 'reference' => $payload['issue']['id'], + ); + + $this->container['dispatcher']->dispatch(self::EVENT_ISSUE_ASSIGNEE_CHANGE, new GenericEvent($event)); + + return true; + } + + /** + * Handle issue unassigned + * + * @access public + * @param array $task + * @param array $payload + * @return boolean + */ + public function handleIssueUnassigned(array $task, array $payload) + { + $event = array( + 'project_id' => $this->project_id, + 'task_id' => $task['id'], + 'owner_id' => 0, + 'reference' => $payload['issue']['id'], + ); + + $this->container['dispatcher']->dispatch(self::EVENT_ISSUE_ASSIGNEE_CHANGE, new GenericEvent($event)); - foreach ($payload['commits'] as $commit) { + return true; + } - if ($this->handleCommit($commit)) { + /** + * Parse push events + * + * @access public + * @param array $payload + * @return boolean + */ + public function handlePush(array $payload) + { + if (isset($payload['push']['changes'])) { + foreach ($payload['push']['changes'] as $change) { + if (isset($change['new']['target']) && $this->handleCommit($change['new']['target'], $payload['actor'])) { return true; } } @@ -65,10 +278,11 @@ class BitbucketWebhook extends \Core\Base * Parse commit * * @access public - * @param array $commit Gitlab commit + * @param array $commit Bitbucket commit + * @param array $actor Bitbucket actor * @return boolean */ - public function handleCommit(array $commit) + public function handleCommit(array $commit, array $actor) { $task_id = $this->task->getTaskIdFromText($commit['message']); @@ -91,8 +305,8 @@ class BitbucketWebhook extends \Core\Base new GenericEvent(array( 'task_id' => $task_id, 'commit_message' => $commit['message'], - 'commit_url' => '', - 'commit_comment' => $commit['message']."\n\n".t('Commit made by @%s on Bitbucket', $commit['author']) + 'commit_url' => $commit['links']['html']['href'], + 'commit_comment' => $commit['message']."\n\n[".t('Commit made by @%s on Bitbucket', $actor['display_name']).']('.$commit['links']['html']['href'].')', ) + $task) ); diff --git a/app/Model/Action.php b/app/Model/Action.php index 35872bdd..4ede5661 100644 --- a/app/Model/Action.php +++ b/app/Model/Action.php @@ -78,7 +78,7 @@ class Action extends Base Task::EVENT_MOVE_COLUMN => t('Move a task to another column'), Task::EVENT_UPDATE => t('Task modification'), Task::EVENT_CREATE => t('Task creation'), - Task::EVENT_OPEN => t('Open a closed task'), + Task::EVENT_OPEN => t('Reopen a task'), Task::EVENT_CLOSE => t('Closing a task'), Task::EVENT_CREATE_UPDATE => t('Task creation or modification'), Task::EVENT_ASSIGNEE_CHANGE => t('Task assignee change'), @@ -93,6 +93,11 @@ class Action extends Base GitlabWebhook::EVENT_ISSUE_OPENED => t('Gitlab issue opened'), GitlabWebhook::EVENT_ISSUE_CLOSED => t('Gitlab issue closed'), BitbucketWebhook::EVENT_COMMIT => t('Bitbucket commit received'), + BitbucketWebhook::EVENT_ISSUE_OPENED => t('Bitbucket issue opened'), + BitbucketWebhook::EVENT_ISSUE_CLOSED => t('Bitbucket issue closed'), + BitbucketWebhook::EVENT_ISSUE_REOPENED => t('Bitbucket issue reopened'), + BitbucketWebhook::EVENT_ISSUE_ASSIGNEE_CHANGE => t('Bitbucket issue assignee change'), + BitbucketWebhook::EVENT_ISSUE_COMMENT => t('Bitbucket issue comment created'), ); asort($values); |