Added new API calls for external task links

This commit is contained in:
Frederic Guillot 2016-06-26 14:33:53 -04:00
parent b82589e75f
commit 3d34681610
No known key found for this signature in database
GPG Key ID: 92D77191BA7FBC99
10 changed files with 642 additions and 185 deletions

View File

@ -5,6 +5,7 @@ New features:
* Added application and project roles validation for API procedure calls
* Added new API call: "getProjectByIdentifier"
* Added new API calls for external task links
Improvements:

View File

@ -0,0 +1,106 @@
<?php
namespace Kanboard\Api\Procedure;
use Kanboard\Api\Authorization\TaskAuthorization;
use Kanboard\Core\ExternalLink\ExternalLinkManager;
use Kanboard\Core\ExternalLink\ExternalLinkProviderNotFound;
/**
* Task External Link API controller
*
* @package Kanboard\Api\Procedure
* @author Frederic Guillot
*/
class TaskExternalLinkProcedure extends BaseProcedure
{
public function getExternalTaskLinkTypes()
{
return $this->externalLinkManager->getTypes();
}
public function getExternalTaskLinkProviderDependencies($providerName)
{
try {
return $this->externalLinkManager->getProvider($providerName)->getDependencies();
} catch (ExternalLinkProviderNotFound $e) {
$this->logger->error(__METHOD__.': '.$e->getMessage());
return false;
}
}
public function getExternalTaskLinkById($task_id, $link_id)
{
TaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'getExternalTaskLink', $task_id);
return $this->taskExternalLinkModel->getById($link_id);
}
public function getAllExternalTaskLinks($task_id)
{
TaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'getExternalTaskLinks', $task_id);
return $this->taskExternalLinkModel->getAll($task_id);
}
public function createExternalTaskLink($task_id, $url, $dependency, $type = ExternalLinkManager::TYPE_AUTO, $title = '')
{
TaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'createExternalTaskLink', $task_id);
try {
$provider = $this->externalLinkManager
->setUserInputText($url)
->setUserInputType($type)
->find();
$link = $provider->getLink();
$values = array(
'task_id' => $task_id,
'title' => $title ?: $link->getTitle(),
'url' => $link->getUrl(),
'link_type' => $provider->getType(),
'dependency' => $dependency,
);
list($valid, $errors) = $this->externalLinkValidator->validateCreation($values);
if (! $valid) {
$this->logger->error(__METHOD__.': '.var_export($errors));
return false;
}
return $this->taskExternalLinkModel->create($values);
} catch (ExternalLinkProviderNotFound $e) {
$this->logger->error(__METHOD__.': '.$e->getMessage());
}
return false;
}
public function updateExternalTaskLink($task_id, $link_id, $title = null, $url = null, $dependency = null)
{
TaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'updateExternalTaskLink', $task_id);
$link = $this->taskExternalLinkModel->getById($link_id);
$values = $this->filterValues(array(
'title' => $title,
'url' => $url,
'dependency' => $dependency,
));
$values = array_merge($link, $values);
list($valid, $errors) = $this->externalLinkValidator->validateModification($values);
if (! $valid) {
$this->logger->error(__METHOD__.': '.var_export($errors));
return false;
}
return $this->taskExternalLinkModel->update($values);
}
public function removeExternalTaskLink($task_id, $link_id)
{
TaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'removeExternalTaskLink', $task_id);
return $this->taskExternalLinkModel->remove($link_id);
}
}

View File

@ -152,6 +152,30 @@ class ExternalLinkManager extends Base
return $this;
}
/**
* Set provider type
*
* @access public
* @param string $userInputType
* @return ExternalLinkManager
*/
public function setUserInputType($userInputType)
{
$this->userInputType = $userInputType;
return $this;
}
/**
* Set external link
* @param string $userInputText
* @return ExternalLinkManager
*/
public function setUserInputText($userInputText)
{
$this->userInputText = $userInputText;
return $this;
}
/**
* Find a provider that user input
*

View File

@ -9,6 +9,7 @@ use Kanboard\Api\Procedure\BoardProcedure;
use Kanboard\Api\Procedure\CategoryProcedure;
use Kanboard\Api\Procedure\ColumnProcedure;
use Kanboard\Api\Procedure\CommentProcedure;
use Kanboard\Api\Procedure\TaskExternalLinkProcedure;
use Kanboard\Api\Procedure\TaskFileProcedure;
use Kanboard\Api\Procedure\GroupProcedure;
use Kanboard\Api\Procedure\GroupMemberProcedure;
@ -65,6 +66,7 @@ class ApiProvider implements ServiceProviderInterface
->withObject(new SwimlaneProcedure($container))
->withObject(new TaskProcedure($container))
->withObject(new TaskLinkProcedure($container))
->withObject(new TaskExternalLinkProcedure($container))
->withObject(new UserProcedure($container))
->withObject(new GroupProcedure($container))
->withObject(new GroupMemberProcedure($container))

View File

@ -204,6 +204,7 @@ class AuthenticationProvider implements ServiceProviderInterface
$acl->add('SwimlaneProcedure', '*', Role::PROJECT_MANAGER);
$acl->add('TaskFileProcedure', '*', Role::PROJECT_MEMBER);
$acl->add('TaskLinkProcedure', '*', Role::PROJECT_MEMBER);
$acl->add('TaskExternalLinkProcedure', array('createExternalTaskLink', 'updateExternalTaskLink', 'removeExternalTaskLink'), Role::PROJECT_MEMBER);
$acl->add('TaskProcedure', '*', Role::PROJECT_MEMBER);
return $acl;

View File

@ -0,0 +1,221 @@
Internal Task Links API Procedures
==================================
## getExternalTaskLinkTypes
- Purpose: **Get all registered external link providers**
- Parameters: **none**
- Result on success: **dict**
- Result on failure: **false**
Request example:
```json
{"jsonrpc":"2.0","method":"getExternalTaskLinkTypes","id":477370568}
```
Response example:
```json
{
"jsonrpc": "2.0",
"result": {
"auto": "Auto",
"attachment": "Attachment",
"file": "Local File",
"weblink": "Web Link"
},
"id": 477370568
}
```
## getExternalTaskLinkProviderDependencies
- Purpose: **Get available dependencies for a given provider**
- Parameters:
- **providerName** (string, required)
- Result on success: **dict**
- Result on failure: **false**
Request example:
```json
{"jsonrpc":"2.0","method":"getExternalTaskLinkProviderDependencies","id":124790226,"params":["weblink"]}
```
Response example:
```json
{
"jsonrpc": "2.0",
"result": {
"related": "Related"
},
"id": 124790226
}
```
## createExternalTaskLink
- Purpose: **Create a new external link**
- Parameters:
- **task_id** (integer, required)
- **url** (string, required)
- **dependency** (string, required)
- **type** (string, optional)
- **title** (string, optional)
- Result on success: **link_id**
- Result on failure: **false**
Request example:
```json
{"jsonrpc":"2.0","method":"createExternalTaskLink","id":924217495,"params":[9,"http:\/\/localhost\/document.pdf","related","attachment"]}
```
Response example:
```json
{
"jsonrpc": "2.0",
"result": 1,
"id": 924217495
}
```
## updateExternalTaskLink
- Purpose: **Update external task link**
- Parameters:
- **task_id** (integer, required)
- **link_id** (integer, required)
- **title** (string, required)
- **url** (string, required)
- **dependency** (string, required)
- Result on success: **true**
- Result on failure: **false**
Request example:
```json
{
"jsonrpc":"2.0",
"method":"updateExternalTaskLink",
"id":1123562620,
"params": {
"task_id":9,
"link_id":1,
"title":"New title"
}
}
```
Response example:
```json
{
"jsonrpc": "2.0",
"result": true,
"id": 1123562620
}
```
## getExternalTaskLinkById
- Purpose: **Get an external task link**
- Parameters:
- **task_id** (integer, required)
- **link_id** (integer, required)
- Result on success: **dict**
- Result on failure: **false**
Request example:
```json
{"jsonrpc":"2.0","method":"getExternalTaskLinkById","id":2107066744,"params":[9,1]}
```
Response example:
```json
{
"jsonrpc": "2.0",
"result": {
"id": "1",
"link_type": "attachment",
"dependency": "related",
"title": "document.pdf",
"url": "http:\/\/localhost\/document.pdf",
"date_creation": "1466965256",
"date_modification": "1466965256",
"task_id": "9",
"creator_id": "0"
},
"id": 2107066744
}
```
## getAllExternalTaskLinks
- Purpose: **Get all external links attached to a task**
- Parameters:
- **task_id** (integer, required)
- Result on success: **list of external links**
- Result on failure: **false**
Request example:
```json
{"jsonrpc":"2.0","method":"getAllExternalTaskLinks","id":2069307223,"params":[9]}
```
Response example:
```json
{
"jsonrpc": "2.0",
"result": [
{
"id": "1",
"link_type": "attachment",
"dependency": "related",
"title": "New title",
"url": "http:\/\/localhost\/document.pdf",
"date_creation": "1466965256",
"date_modification": "1466965256",
"task_id": "9",
"creator_id": "0",
"creator_name": null,
"creator_username": null,
"dependency_label": "Related",
"type": "Attachment"
}
],
"id": 2069307223
}
```
## removeExternalTaskLink
- Purpose: **Remove an external link**
- Parameters:
- **task_id** (integer, required)
- **link_id** (integer, required)
- Result on success: **true**
- Result on failure: **false**
Request example:
```json
{"jsonrpc":"2.0","method":"removeExternalTaskLink","id":552055660,"params":[9,1]}
```
Response example:
```json
{
"jsonrpc": "2.0",
"result": true,
"id": 552055660
}
```

View File

@ -0,0 +1,187 @@
Internal Task Links API Procedures
==================================
## createTaskLink
- Purpose: **Create a link between two tasks**
- Parameters:
- **task_id** (integer, required)
- **opposite_task_id** (integer, required)
- **link_id** (integer, required)
- Result on success: **task_link_id**
- Result on failure: **false**
Request example:
```json
{
"jsonrpc": "2.0",
"method": "createTaskLink",
"id": 509742912,
"params": [
2,
3,
1
]
}
```
Response example:
```json
{
"jsonrpc": "2.0",
"id": 509742912,
"result": 1
}
```
## updateTaskLink
- Purpose: **Update task link**
- Parameters:
- **task_link_id** (integer, required)
- **task_id** (integer, required)
- **opposite_task_id** (integer, required)
- **link_id** (integer, required)
- Result on success: **true**
- Result on failure: **false**
Request example:
```json
{
"jsonrpc": "2.0",
"method": "updateTaskLink",
"id": 669037109,
"params": [
1,
2,
4,
2
]
}
```
Response example:
```json
{
"jsonrpc": "2.0",
"id": 669037109,
"result": true
}
```
## getTaskLinkById
- Purpose: **Get a task link**
- Parameters:
- **task_link_id** (integer, required)
- Result on success: **task link properties**
- Result on failure: **false**
Request example:
```json
{
"jsonrpc": "2.0",
"method": "getTaskLinkById",
"id": 809885202,
"params": [
1
]
}
```
Response example:
```json
{
"jsonrpc": "2.0",
"id": 809885202,
"result": {
"id": "1",
"link_id": "1",
"task_id": "2",
"opposite_task_id": "3"
}
}
```
## getAllTaskLinks
- Purpose: **Get all links related to a task**
- Parameters:
- **task_id** (integer, required)
- Result on success: **list of task link**
- Result on failure: **false**
Request example:
```json
{
"jsonrpc": "2.0",
"method": "getAllTaskLinks",
"id": 810848359,
"params": [
2
]
}
```
Response example:
```json
{
"jsonrpc": "2.0",
"id": 810848359,
"result": [
{
"id": "1",
"task_id": "3",
"label": "relates to",
"title": "B",
"is_active": "1",
"project_id": "1",
"task_time_spent": "0",
"task_time_estimated": "0",
"task_assignee_id": "0",
"task_assignee_username": null,
"task_assignee_name": null,
"column_title": "Backlog"
}
]
}
```
## removeTaskLink
- Purpose: **Remove a link between two tasks**
- Parameters:
- **task_link_id** (integer, required)
- Result on success: **true**
- Result on failure: **false**
Request example:
```json
{
"jsonrpc": "2.0",
"method": "removeTaskLink",
"id": 473028226,
"params": [
1
]
}
```
Response example:
```json
{
"jsonrpc": "2.0",
"id": 473028226,
"result": true
}
```

View File

@ -60,6 +60,8 @@ Usage
- [Subtasks](api-subtask-procedures.markdown)
- [Files](api-file-procedures.markdown)
- [Links](api-link-procedures.markdown)
- [Internal Task Links](api-internal-task-link-procedures.markdown)
- [External Task Links](api-external-task-link-procedures.markdown)
- [Comments](api-comment-procedures.markdown)
- [Users](api-user-procedures.markdown)
- [Groups](api-group-procedures.markdown)

View File

@ -283,188 +283,3 @@ Response example:
"result": true
}
```
## createTaskLink
- Purpose: **Create a link between two tasks**
- Parameters:
- **task_id** (integer, required)
- **opposite_task_id** (integer, required)
- **link_id** (integer, required)
- Result on success: **task_link_id**
- Result on failure: **false**
Request example:
```json
{
"jsonrpc": "2.0",
"method": "createTaskLink",
"id": 509742912,
"params": [
2,
3,
1
]
}
```
Response example:
```json
{
"jsonrpc": "2.0",
"id": 509742912,
"result": 1
}
```
## updateTaskLink
- Purpose: **Update task link**
- Parameters:
- **task_link_id** (integer, required)
- **task_id** (integer, required)
- **opposite_task_id** (integer, required)
- **link_id** (integer, required)
- Result on success: **true**
- Result on failure: **false**
Request example:
```json
{
"jsonrpc": "2.0",
"method": "updateTaskLink",
"id": 669037109,
"params": [
1,
2,
4,
2
]
}
```
Response example:
```json
{
"jsonrpc": "2.0",
"id": 669037109,
"result": true
}
```
## getTaskLinkById
- Purpose: **Get a task link**
- Parameters:
- **task_link_id** (integer, required)
- Result on success: **task link properties**
- Result on failure: **false**
Request example:
```json
{
"jsonrpc": "2.0",
"method": "getTaskLinkById",
"id": 809885202,
"params": [
1
]
}
```
Response example:
```json
{
"jsonrpc": "2.0",
"id": 809885202,
"result": {
"id": "1",
"link_id": "1",
"task_id": "2",
"opposite_task_id": "3"
}
}
```
## getAllTaskLinks
- Purpose: **Get all links related to a task**
- Parameters:
- **task_id** (integer, required)
- Result on success: **list of task link**
- Result on failure: **false**
Request example:
```json
{
"jsonrpc": "2.0",
"method": "getAllTaskLinks",
"id": 810848359,
"params": [
2
]
}
```
Response example:
```json
{
"jsonrpc": "2.0",
"id": 810848359,
"result": [
{
"id": "1",
"task_id": "3",
"label": "relates to",
"title": "B",
"is_active": "1",
"project_id": "1",
"task_time_spent": "0",
"task_time_estimated": "0",
"task_assignee_id": "0",
"task_assignee_username": null,
"task_assignee_name": null,
"column_title": "Backlog"
}
]
}
```
## removeTaskLink
- Purpose: **Remove a link between two tasks**
- Parameters:
- **task_link_id** (integer, required)
- Result on success: **true**
- Result on failure: **false**
Request example:
```json
{
"jsonrpc": "2.0",
"method": "removeTaskLink",
"id": 473028226,
"params": [
1
]
}
```
Response example:
```json
{
"jsonrpc": "2.0",
"id": 473028226,
"result": true
}
```

View File

@ -0,0 +1,98 @@
<?php
require_once __DIR__.'/BaseProcedureTest.php';
class TaskExternalLinkProcedureTest extends BaseProcedureTest
{
protected $projectName = 'My project to test external links';
private $linkId = 0;
public function testAll()
{
$this->assertCreateTeamProject();
$this->assertCreateTask();
$this->assertGetExternalTaskLinkTypes();
$this->assertGetExternalTaskLinkProviderDependencies();
$this->assertGetExternalTaskLinkProviderDependenciesWithProviderNotFound();
$this->assertCreateExternalTaskLink();
$this->assertUpdateExternalTaskLink();
$this->assertGetAllExternalTaskLinks();
$this->assertRemoveExternalTaskLink();
}
public function assertGetExternalTaskLinkTypes()
{
$expected = array(
'auto' => 'Auto',
'attachment' => 'Attachment',
'file' => 'Local File',
'weblink' => 'Web Link',
);
$types = $this->app->getExternalTaskLinkTypes();
$this->assertEquals($expected, $types);
}
public function assertGetExternalTaskLinkProviderDependencies()
{
$expected = array(
'related' => 'Related',
);
$dependencies = $this->app->getExternalTaskLinkProviderDependencies('weblink');
$this->assertEquals($expected, $dependencies);
}
public function assertGetExternalTaskLinkProviderDependenciesWithProviderNotFound()
{
$this->assertFalse($this->app->getExternalTaskLinkProviderDependencies('foobar'));
}
public function assertCreateExternalTaskLink()
{
$url = 'http://localhost/document.pdf';
$this->linkId = $this->app->createExternalTaskLink($this->taskId, $url, 'related', 'attachment');
$this->assertNotFalse($this->linkId);
$link = $this->app->getExternalTaskLinkById($this->taskId, $this->linkId);
$this->assertEquals($this->linkId, $link['id']);
$this->assertEquals($this->taskId, $link['task_id']);
$this->assertEquals('document.pdf', $link['title']);
$this->assertEquals($url, $link['url']);
$this->assertEquals('related', $link['dependency']);
$this->assertEquals(0, $link['creator_id']);
}
public function assertUpdateExternalTaskLink()
{
$this->assertTrue($this->app->updateExternalTaskLink(array(
'task_id' => $this->taskId,
'link_id' => $this->linkId,
'title' => 'New title',
)));
$link = $this->app->getExternalTaskLinkById($this->taskId, $this->linkId);
$this->assertEquals($this->linkId, $link['id']);
$this->assertEquals($this->taskId, $link['task_id']);
$this->assertEquals('New title', $link['title']);
$this->assertEquals('related', $link['dependency']);
$this->assertEquals(0, $link['creator_id']);
}
public function assertGetAllExternalTaskLinks()
{
$links = $this->app->getAllExternalTaskLinks($this->taskId);
$this->assertCount(1, $links);
$this->assertEquals($this->linkId, $links[0]['id']);
$this->assertEquals($this->taskId, $links[0]['task_id']);
$this->assertEquals('New title', $links[0]['title']);
$this->assertEquals('related', $links[0]['dependency']);
$this->assertEquals(0, $links[0]['creator_id']);
}
public function assertRemoveExternalTaskLink()
{
$this->assertTrue($this->app->removeExternalTaskLink($this->taskId, $this->linkId));
}
}