diff options
author | Frédéric Guillot <fred@kanboard.net> | 2014-09-28 18:23:21 -0400 |
---|---|---|
committer | Frédéric Guillot <fred@kanboard.net> | 2014-09-28 18:23:21 -0400 |
commit | 33f9cdbc976e0f97c3dd24658dc7d0097497c6d7 (patch) | |
tree | 3a5dc8ca9a6b3db268ba95aec357a2e5a8aad80e /app/Model | |
parent | 03fa01ac7b036820ee232d893ec63241918c6012 (diff) |
Add support for Github Issue Webhooks
Diffstat (limited to 'app/Model')
-rw-r--r-- | app/Model/Action.php | 21 | ||||
-rw-r--r-- | app/Model/GithubWebhook.php | 209 | ||||
-rw-r--r-- | app/Model/Project.php | 7 | ||||
-rw-r--r-- | app/Model/Task.php | 16 |
4 files changed, 245 insertions, 8 deletions
diff --git a/app/Model/Action.php b/app/Model/Action.php index 6b1ebdad..56a1a2bb 100644 --- a/app/Model/Action.php +++ b/app/Model/Action.php @@ -36,8 +36,9 @@ class Action extends Base */ public function getAvailableActions() { - return array( + $values = array( 'TaskClose' => t('Close a task'), + 'TaskOpen' => t('Open a task'), 'TaskAssignSpecificUser' => t('Assign the task to a specific user'), 'TaskAssignCurrentUser' => t('Assign the task to the person who does the action'), 'TaskDuplicateAnotherProject' => t('Duplicate the task to another project'), @@ -45,7 +46,14 @@ class Action extends Base 'TaskAssignColorUser' => t('Assign a color to a specific user'), 'TaskAssignColorCategory' => t('Assign automatically a color based on a category'), 'TaskAssignCategoryColor' => t('Assign automatically a category based on a color'), + 'TaskCreation' => t('Create a task from an external provider'), + 'TaskAssignUser' => t('Change the assignee based on an external username'), + 'TaskAssignCategoryLabel' => t('Change the category based on an external label'), ); + + asort($values); + + return $values; } /** @@ -56,7 +64,7 @@ class Action extends Base */ public function getAvailableEvents() { - return array( + $values = array( Task::EVENT_MOVE_COLUMN => t('Move a task to another column'), Task::EVENT_UPDATE => t('Task modification'), Task::EVENT_CREATE => t('Task creation'), @@ -65,7 +73,16 @@ class Action extends Base Task::EVENT_CREATE_UPDATE => t('Task creation or modification'), Task::EVENT_ASSIGNEE_CHANGE => t('Task assignee change'), GithubWebhook::EVENT_COMMIT => t('Github commit received'), + GithubWebhook::EVENT_ISSUE_OPENED => t('Github issue opened'), + GithubWebhook::EVENT_ISSUE_CLOSED => t('Github issue closed'), + GithubWebhook::EVENT_ISSUE_REOPENED => t('Github issue reopened'), + GithubWebhook::EVENT_ISSUE_ASSIGNEE_CHANGE => t('Github issue assignee change'), + GithubWebhook::EVENT_ISSUE_LABEL_CHANGE => t('Github issue label change'), ); + + asort($values); + + return $values; } /** diff --git a/app/Model/GithubWebhook.php b/app/Model/GithubWebhook.php index 688ab601..b5f95eeb 100644 --- a/app/Model/GithubWebhook.php +++ b/app/Model/GithubWebhook.php @@ -15,11 +15,32 @@ class GithubWebhook extends Base * * @var string */ - const EVENT_ISSUE_OPENED = 'github.webhook.issue.opened'; - const EVENT_ISSUE_CLOSED = 'github.webhook.issue.closed'; - const EVENT_ISSUE_LABELED = 'github.webhook.issue.labeled'; - const EVENT_ISSUE_COMMENT = 'github.webhook.issue.commented'; - const EVENT_COMMIT = 'github.webhook.commit'; + const EVENT_ISSUE_OPENED = 'github.webhook.issue.opened'; + const EVENT_ISSUE_CLOSED = 'github.webhook.issue.closed'; + const EVENT_ISSUE_REOPENED = 'github.webhook.issue.reopened'; + const EVENT_ISSUE_ASSIGNEE_CHANGE = 'github.webhook.issue.assignee'; + const EVENT_ISSUE_LABEL_CHANGE = 'github.webhook.issue.label'; + const EVENT_ISSUE_COMMENT = 'github.webhook.issue.commented'; + const EVENT_COMMIT = 'github.webhook.commit'; + + /** + * Project id + * + * @access private + * @var integer + */ + private $project_id = 0; + + /** + * Set the project id + * + * @access public + * @param integer $project_id Project id + */ + public function setProjectId($project_id) + { + $this->project_id = $project_id; + } /** * Parse Github events @@ -76,6 +97,184 @@ class GithubWebhook extends Base */ public function parseIssueEvent(array $payload) { + switch ($payload['action']) { + case 'opened': + $this->handleIssueOpened($payload['issue']); + break; + case 'closed': + $this->handleIssueClosed($payload['issue']); + break; + case 'reopened': + $this->handleIssueReopened($payload['issue']); + break; + case 'assigned': + $this->handleIssueAssigned($payload['issue']); + break; + case 'unassigned': + $this->handleIssueUnassigned($payload['issue']); + break; + case 'labeled': + $this->handleIssueLabeled($payload['issue'], $payload['label']); + break; + case 'unlabeled': + $this->handleIssueUnlabeled($payload['issue'], $payload['label']); + break; + } + } + + /** + * Handle new issues + * + * @access public + * @param array $issue Issue data + */ + public function handleIssueOpened(array $issue) + { + $event = array( + 'project_id' => $this->project_id, + 'reference' => $issue['number'], + 'title' => $issue['title'], + 'description' => $issue['body']."\n\n[".t('Github Issue').']('.$issue['html_url'].')', + ); + + $this->event->trigger(self::EVENT_ISSUE_OPENED, $event); + } + + /** + * Handle issue closing + * + * @access public + * @param array $issue Issue data + */ + public function handleIssueClosed(array $issue) + { + $task = $this->task->getByReference($issue['number']); + if ($task) { + $event = array( + 'project_id' => $this->project_id, + 'task_id' => $task['id'], + 'reference' => $issue['number'], + ); + + $this->event->trigger(self::EVENT_ISSUE_CLOSED, $event); + } + } + + /** + * Handle issue reopened + * + * @access public + * @param array $issue Issue data + */ + public function handleIssueReopened(array $issue) + { + $task = $this->task->getByReference($issue['number']); + + if ($task) { + $event = array( + 'project_id' => $this->project_id, + 'task_id' => $task['id'], + 'reference' => $issue['number'], + ); + + $this->event->trigger(self::EVENT_ISSUE_REOPENED, $event); + } + } + + /** + * Handle issue assignee change + * + * @access public + * @param array $issue Issue data + */ + public function handleIssueAssigned(array $issue) + { + $user = $this->user->getByUsername($issue['assignee']['login']); + $task = $this->task->getByReference($issue['number']); + + if ($user && $task) { + + $event = array( + 'project_id' => $this->project_id, + 'task_id' => $task['id'], + 'owner_id' => $user['id'], + 'reference' => $issue['number'], + ); + + $this->event->trigger(self::EVENT_ISSUE_ASSIGNEE_CHANGE, $event); + } + } + + /** + * Handle unassigned issue + * + * @access public + * @param array $issue Issue data + */ + public function handleIssueUnassigned(array $issue) + { + $task = $this->task->getByReference($issue['number']); + + if ($task) { + + $event = array( + 'project_id' => $this->project_id, + 'task_id' => $task['id'], + 'owner_id' => 0, + 'reference' => $issue['number'], + ); + + $this->event->trigger(self::EVENT_ISSUE_ASSIGNEE_CHANGE, $event); + } + } + + /** + * Handle labeled issue + * + * @access public + * @param array $issue Issue data + * @param array $label Label data + */ + public function handleIssueLabeled(array $issue, array $label) + { + $task = $this->task->getByReference($issue['number']); + + if ($task) { + + $event = array( + 'project_id' => $this->project_id, + 'task_id' => $task['id'], + 'reference' => $issue['number'], + 'label' => $label['name'], + ); + + $this->event->trigger(self::EVENT_ISSUE_LABEL_CHANGE, $event); + } + } + + /** + * Handle unlabeled issue + * + * @access public + * @param array $issue Issue data + * @param array $label Label data + */ + public function handleIssueUnlabeled(array $issue, array $label) + { + $task = $this->task->getByReference($issue['number']); + + if ($task) { + + $event = array( + 'project_id' => $this->project_id, + 'task_id' => $task['id'], + 'reference' => $issue['number'], + 'label' => $label['name'], + 'category_id' => 0, + ); + + $this->event->trigger(self::EVENT_ISSUE_LABEL_CHANGE, $event); + } } } diff --git a/app/Model/Project.php b/app/Model/Project.php index 1eabe239..c3e8cc55 100644 --- a/app/Model/Project.php +++ b/app/Model/Project.php @@ -505,6 +505,13 @@ class Project extends Base Task::EVENT_MOVE_COLUMN, Task::EVENT_MOVE_POSITION, Task::EVENT_ASSIGNEE_CHANGE, + GithubWebhook::EVENT_ISSUE_OPENED, + GithubWebhook::EVENT_ISSUE_CLOSED, + GithubWebhook::EVENT_ISSUE_REOPENED, + GithubWebhook::EVENT_ISSUE_ASSIGNEE_CHANGE, + GithubWebhook::EVENT_ISSUE_LABEL_CHANGE, + GithubWebhook::EVENT_ISSUE_COMMENT, + GithubWebhook::EVENT_COMMIT, ); $listener = new ProjectModificationDate($this); diff --git a/app/Model/Task.php b/app/Model/Task.php index 3e19555f..54dc0a2f 100644 --- a/app/Model/Task.php +++ b/app/Model/Task.php @@ -82,6 +82,7 @@ class Task extends Base $sql = ' SELECT tasks.id, + tasks.reference, tasks.title, tasks.description, tasks.date_creation, @@ -118,7 +119,7 @@ class Task extends Base } /** - * Fetch one task + * Fetch a task by the id * * @access public * @param integer $task_id Task id @@ -130,6 +131,18 @@ class Task extends Base } /** + * Fetch a task by the reference (external id) + * + * @access public + * @param string $reference Task reference + * @return array + */ + public function getByReference($reference) + { + return $this->db->table(self::TABLE)->eq('reference', $reference)->findOne(); + } + + /** * Count all tasks for a given project and status * * @access public @@ -200,6 +213,7 @@ class Task extends Base '(SELECT count(*) FROM task_has_subtasks WHERE task_id=tasks.id) AS nb_subtasks', '(SELECT count(*) FROM task_has_subtasks WHERE task_id=tasks.id AND status=2) AS nb_completed_subtasks', 'tasks.id', + 'tasks.reference', 'tasks.title', 'tasks.description', 'tasks.date_creation', |