Add external links for tasks with plugin api
This commit is contained in:
parent
ec66a779c9
commit
5c92f46786
|
|
@ -10,6 +10,7 @@ Breaking changes:
|
||||||
|
|
||||||
New features:
|
New features:
|
||||||
|
|
||||||
|
* Add external links for tasks with plugin api
|
||||||
* Add project owner (Directly Responsible Individual)
|
* Add project owner (Directly Responsible Individual)
|
||||||
* Add configurable task priority
|
* Add configurable task priority
|
||||||
* Add Greek translation
|
* Add Greek translation
|
||||||
|
|
|
||||||
|
|
@ -189,9 +189,15 @@ abstract class Base extends \Kanboard\Core\Base
|
||||||
*/
|
*/
|
||||||
protected function taskLayout($template, array $params)
|
protected function taskLayout($template, array $params)
|
||||||
{
|
{
|
||||||
|
$params['ajax'] = $this->request->isAjax() || $this->request->getIntegerParam('ajax') === 1;
|
||||||
$content = $this->template->render($template, $params);
|
$content = $this->template->render($template, $params);
|
||||||
$params['task_content_for_layout'] = $content;
|
|
||||||
|
if ($params['ajax']) {
|
||||||
|
return $content;
|
||||||
|
}
|
||||||
|
|
||||||
$params['title'] = $params['task']['project_name'].' > '.$params['task']['title'];
|
$params['title'] = $params['task']['project_name'].' > '.$params['task']['title'];
|
||||||
|
$params['task_content_for_layout'] = $content;
|
||||||
$params['board_selector'] = $this->projectUserRole->getActiveProjectsByUser($this->userSession->getId());
|
$params['board_selector'] = $this->projectUserRole->getActiveProjectsByUser($this->userSession->getId());
|
||||||
|
|
||||||
return $this->template->layout('task/layout', $params);
|
return $this->template->layout('task/layout', $params);
|
||||||
|
|
@ -319,7 +325,8 @@ abstract class Base extends \Kanboard\Core\Base
|
||||||
* @param array &$project
|
* @param array &$project
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
protected function getProjectDescription(array &$project) {
|
protected function getProjectDescription(array &$project)
|
||||||
|
{
|
||||||
if ($project['owner_id'] > 0) {
|
if ($project['owner_id'] > 0) {
|
||||||
$description = t('Project owner: ').'**'.$this->template->e($project['owner_name'] ?: $project['owner_username']).'**'.PHP_EOL.PHP_EOL;
|
$description = t('Project owner: ').'**'.$this->template->e($project['owner_name'] ?: $project['owner_username']).'**'.PHP_EOL.PHP_EOL;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,20 @@ class BoardTooltip extends Base
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get links on mouseover
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
public function externallinks()
|
||||||
|
{
|
||||||
|
$task = $this->getTask();
|
||||||
|
$this->response->html($this->template->render('board/tooltip_external_links', array(
|
||||||
|
'links' => $this->taskExternalLink->getAll($task['id']),
|
||||||
|
'task' => $task,
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get subtasks on mouseover
|
* Get subtasks on mouseover
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,6 @@ class Comment extends Base
|
||||||
public function create(array $values = array(), array $errors = array())
|
public function create(array $values = array(), array $errors = array())
|
||||||
{
|
{
|
||||||
$task = $this->getTask();
|
$task = $this->getTask();
|
||||||
$ajax = $this->request->isAjax() || $this->request->getIntegerParam('ajax');
|
|
||||||
|
|
||||||
if (empty($values)) {
|
if (empty($values)) {
|
||||||
$values = array(
|
$values = array(
|
||||||
|
|
@ -50,15 +49,6 @@ class Comment extends Base
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($ajax) {
|
|
||||||
$this->response->html($this->template->render('comment/create', array(
|
|
||||||
'values' => $values,
|
|
||||||
'errors' => $errors,
|
|
||||||
'task' => $task,
|
|
||||||
'ajax' => $ajax,
|
|
||||||
)));
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->response->html($this->taskLayout('comment/create', array(
|
$this->response->html($this->taskLayout('comment/create', array(
|
||||||
'values' => $values,
|
'values' => $values,
|
||||||
'errors' => $errors,
|
'errors' => $errors,
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,185 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Kanboard\Controller;
|
||||||
|
|
||||||
|
use Kanboard\Core\ExternalLink\ExternalLinkProviderNotFound;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Task External Link Controller
|
||||||
|
*
|
||||||
|
* @package controller
|
||||||
|
* @author Frederic Guillot
|
||||||
|
*/
|
||||||
|
class TaskExternalLink extends Base
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Creation form
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
public function show()
|
||||||
|
{
|
||||||
|
$task = $this->getTask();
|
||||||
|
|
||||||
|
$this->response->html($this->taskLayout('task_external_link/show', array(
|
||||||
|
'links' => $this->taskExternalLink->getAll($task['id']),
|
||||||
|
'task' => $task,
|
||||||
|
'title' => t('List of external links'),
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* First creation form
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
public function find(array $values = array(), array $errors = array())
|
||||||
|
{
|
||||||
|
$task = $this->getTask();
|
||||||
|
|
||||||
|
$this->response->html($this->taskLayout('task_external_link/find', array(
|
||||||
|
'values' => $values,
|
||||||
|
'errors' => $errors,
|
||||||
|
'task' => $task,
|
||||||
|
'types' => $this->externalLinkManager->getTypes(),
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Second creation form
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
public function create()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
|
||||||
|
$task = $this->getTask();
|
||||||
|
$values = $this->request->getValues();
|
||||||
|
|
||||||
|
$provider = $this->externalLinkManager->setUserInput($values)->find();
|
||||||
|
$link = $provider->getLink();
|
||||||
|
|
||||||
|
$this->response->html($this->taskLayout('task_external_link/create', array(
|
||||||
|
'values' => array(
|
||||||
|
'title' => $link->getTitle(),
|
||||||
|
'url' => $link->getUrl(),
|
||||||
|
'link_type' => $provider->getType(),
|
||||||
|
),
|
||||||
|
'dependencies' => $provider->getDependencies(),
|
||||||
|
'errors' => array(),
|
||||||
|
'task' => $task,
|
||||||
|
)));
|
||||||
|
|
||||||
|
} catch (ExternalLinkProviderNotFound $e) {
|
||||||
|
$errors = array('text' => array(t('Unable to fetch link information.')));
|
||||||
|
$this->find($values, $errors);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Save link
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
public function save()
|
||||||
|
{
|
||||||
|
$task = $this->getTask();
|
||||||
|
$values = $this->request->getValues();
|
||||||
|
list($valid, $errors) = $this->externalLinkValidator->validateCreation($values);
|
||||||
|
|
||||||
|
if ($valid && $this->taskExternalLink->create($values)) {
|
||||||
|
$this->flash->success(t('Link added successfully.'));
|
||||||
|
return $this->response->redirect($this->helper->url->to('TaskExternalLink', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->edit($values, $errors);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Edit form
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
public function edit(array $values = array(), array $errors = array())
|
||||||
|
{
|
||||||
|
$task = $this->getTask();
|
||||||
|
$link_id = $this->request->getIntegerParam('link_id');
|
||||||
|
|
||||||
|
if ($link_id > 0) {
|
||||||
|
$values = $this->taskExternalLink->getById($link_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($values)) {
|
||||||
|
return $this->notfound();
|
||||||
|
}
|
||||||
|
|
||||||
|
$provider = $this->externalLinkManager->getProvider($values['link_type']);
|
||||||
|
|
||||||
|
$this->response->html($this->taskLayout('task_external_link/edit', array(
|
||||||
|
'values' => $values,
|
||||||
|
'errors' => $errors,
|
||||||
|
'task' => $task,
|
||||||
|
'dependencies' => $provider->getDependencies(),
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update link
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
public function update()
|
||||||
|
{
|
||||||
|
$task = $this->getTask();
|
||||||
|
$values = $this->request->getValues();
|
||||||
|
list($valid, $errors) = $this->externalLinkValidator->validateModification($values);
|
||||||
|
|
||||||
|
if ($valid && $this->taskExternalLink->update($values)) {
|
||||||
|
$this->flash->success(t('Link updated successfully.'));
|
||||||
|
return $this->response->redirect($this->helper->url->to('TaskExternalLink', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])));
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->edit($values, $errors);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Confirmation dialog before removing a link
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
public function confirm()
|
||||||
|
{
|
||||||
|
$task = $this->getTask();
|
||||||
|
$link_id = $this->request->getIntegerParam('link_id');
|
||||||
|
$link = $this->taskExternalLink->getById($link_id);
|
||||||
|
|
||||||
|
if (empty($link)) {
|
||||||
|
return $this->notfound();
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->response->html($this->taskLayout('task_external_link/remove', array(
|
||||||
|
'link' => $link,
|
||||||
|
'task' => $task,
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove a link
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
public function remove()
|
||||||
|
{
|
||||||
|
$this->checkCSRFParam();
|
||||||
|
$task = $this->getTask();
|
||||||
|
|
||||||
|
if ($this->taskExternalLink->remove($this->request->getIntegerParam('link_id'))) {
|
||||||
|
$this->flash->success(t('Link removed successfully.'));
|
||||||
|
} else {
|
||||||
|
$this->flash->failure(t('Unable to remove this link.'));
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->response->redirect($this->helper->url->to('TaskExternalLink', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -28,6 +28,25 @@ class Tasklink extends Base
|
||||||
return $link;
|
return $link;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show links
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
public function show()
|
||||||
|
{
|
||||||
|
$task = $this->getTask();
|
||||||
|
$project = $this->project->getById($task['project_id']);
|
||||||
|
|
||||||
|
$this->response->html($this->taskLayout('tasklink/show', array(
|
||||||
|
'links' => $this->taskLink->getAllGroupedByLabel($task['id']),
|
||||||
|
'task' => $task,
|
||||||
|
'project' => $project,
|
||||||
|
'editable' => true,
|
||||||
|
'is_public' => false,
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creation form
|
* Creation form
|
||||||
*
|
*
|
||||||
|
|
@ -36,18 +55,6 @@ class Tasklink extends Base
|
||||||
public function create(array $values = array(), array $errors = array())
|
public function create(array $values = array(), array $errors = array())
|
||||||
{
|
{
|
||||||
$task = $this->getTask();
|
$task = $this->getTask();
|
||||||
$ajax = $this->request->isAjax() || $this->request->getIntegerParam('ajax');
|
|
||||||
|
|
||||||
if ($ajax && empty($errors)) {
|
|
||||||
$this->response->html($this->template->render('tasklink/create', array(
|
|
||||||
'values' => $values,
|
|
||||||
'errors' => $errors,
|
|
||||||
'task' => $task,
|
|
||||||
'labels' => $this->link->getList(0, false),
|
|
||||||
'title' => t('Add a new link'),
|
|
||||||
'ajax' => $ajax,
|
|
||||||
)));
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->response->html($this->taskLayout('tasklink/create', array(
|
$this->response->html($this->taskLayout('tasklink/create', array(
|
||||||
'values' => $values,
|
'values' => $values,
|
||||||
|
|
@ -76,10 +83,10 @@ class Tasklink extends Base
|
||||||
$this->flash->success(t('Link added successfully.'));
|
$this->flash->success(t('Link added successfully.'));
|
||||||
|
|
||||||
if ($ajax) {
|
if ($ajax) {
|
||||||
$this->response->redirect($this->helper->url->to('board', 'show', array('project_id' => $task['project_id'])));
|
return $this->response->redirect($this->helper->url->to('board', 'show', array('project_id' => $task['project_id'])));
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->response->redirect($this->helper->url->to('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])).'#links');
|
return $this->response->redirect($this->helper->url->to('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])).'#links');
|
||||||
}
|
}
|
||||||
|
|
||||||
$errors = array('title' => array(t('The exact same link already exists')));
|
$errors = array('title' => array(t('The exact same link already exists')));
|
||||||
|
|
@ -130,7 +137,7 @@ class Tasklink extends Base
|
||||||
if ($valid) {
|
if ($valid) {
|
||||||
if ($this->taskLink->update($values['id'], $values['task_id'], $values['opposite_task_id'], $values['link_id'])) {
|
if ($this->taskLink->update($values['id'], $values['task_id'], $values['opposite_task_id'], $values['link_id'])) {
|
||||||
$this->flash->success(t('Link updated successfully.'));
|
$this->flash->success(t('Link updated successfully.'));
|
||||||
$this->response->redirect($this->helper->url->to('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])).'#links');
|
return $this->response->redirect($this->helper->url->to('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])).'#links');
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->flash->failure(t('Unable to update your link.'));
|
$this->flash->failure(t('Unable to update your link.'));
|
||||||
|
|
|
||||||
|
|
@ -80,14 +80,9 @@ class Taskmodification extends Base
|
||||||
'values' => $values,
|
'values' => $values,
|
||||||
'errors' => $errors,
|
'errors' => $errors,
|
||||||
'task' => $task,
|
'task' => $task,
|
||||||
'ajax' => $ajax,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
if ($ajax) {
|
$this->response->html($this->taskLayout('task_modification/edit_description', $params));
|
||||||
$this->response->html($this->template->render('task_modification/edit_description', $params));
|
|
||||||
} else {
|
|
||||||
$this->response->html($this->taskLayout('task_modification/edit_description', $params));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ use Pimple\Container;
|
||||||
* @property \Kanboard\Analytic\AverageLeadCycleTimeAnalytic $averageLeadCycleTimeAnalytic
|
* @property \Kanboard\Analytic\AverageLeadCycleTimeAnalytic $averageLeadCycleTimeAnalytic
|
||||||
* @property \Kanboard\Analytic\AverageTimeSpentColumnAnalytic $averageTimeSpentColumnAnalytic
|
* @property \Kanboard\Analytic\AverageTimeSpentColumnAnalytic $averageTimeSpentColumnAnalytic
|
||||||
* @property \Kanboard\Core\Action\ActionManager $actionManager
|
* @property \Kanboard\Core\Action\ActionManager $actionManager
|
||||||
|
* @property \Kanboard\Core\ExternalLink\ExternalLinkManager $externalLinkManager
|
||||||
* @property \Kanboard\Core\Cache\MemoryCache $memoryCache
|
* @property \Kanboard\Core\Cache\MemoryCache $memoryCache
|
||||||
* @property \Kanboard\Core\Event\EventManager $eventManager
|
* @property \Kanboard\Core\Event\EventManager $eventManager
|
||||||
* @property \Kanboard\Core\Group\GroupManager $groupManager
|
* @property \Kanboard\Core\Group\GroupManager $groupManager
|
||||||
|
|
@ -97,6 +98,7 @@ use Pimple\Container;
|
||||||
* @property \Kanboard\Model\TaskCreation $taskCreation
|
* @property \Kanboard\Model\TaskCreation $taskCreation
|
||||||
* @property \Kanboard\Model\TaskDuplication $taskDuplication
|
* @property \Kanboard\Model\TaskDuplication $taskDuplication
|
||||||
* @property \Kanboard\Model\TaskExport $taskExport
|
* @property \Kanboard\Model\TaskExport $taskExport
|
||||||
|
* @property \Kanboard\Model\TaskExternalLink $taskExternalLink
|
||||||
* @property \Kanboard\Model\TaskImport $taskImport
|
* @property \Kanboard\Model\TaskImport $taskImport
|
||||||
* @property \Kanboard\Model\TaskFinder $taskFinder
|
* @property \Kanboard\Model\TaskFinder $taskFinder
|
||||||
* @property \Kanboard\Model\TaskFilter $taskFilter
|
* @property \Kanboard\Model\TaskFilter $taskFilter
|
||||||
|
|
@ -132,6 +134,7 @@ use Pimple\Container;
|
||||||
* @property \Kanboard\Validator\SubtaskValidator $subtaskValidator
|
* @property \Kanboard\Validator\SubtaskValidator $subtaskValidator
|
||||||
* @property \Kanboard\Validator\SwimlaneValidator $swimlaneValidator
|
* @property \Kanboard\Validator\SwimlaneValidator $swimlaneValidator
|
||||||
* @property \Kanboard\Validator\TaskLinkValidator $taskLinkValidator
|
* @property \Kanboard\Validator\TaskLinkValidator $taskLinkValidator
|
||||||
|
* @property \Kanboard\Validator\TaskExternalLinkValidator $taskExternalLinkValidator
|
||||||
* @property \Kanboard\Validator\TaskValidator $taskValidator
|
* @property \Kanboard\Validator\TaskValidator $taskValidator
|
||||||
* @property \Kanboard\Validator\UserValidator $userValidator
|
* @property \Kanboard\Validator\UserValidator $userValidator
|
||||||
* @property \Psr\Log\LoggerInterface $logger
|
* @property \Psr\Log\LoggerInterface $logger
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,36 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Kanboard\Core\ExternalLink;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* External Link Interface
|
||||||
|
*
|
||||||
|
* @package externalLink
|
||||||
|
* @author Frederic Guillot
|
||||||
|
*/
|
||||||
|
interface ExternalLinkInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Get link title
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getTitle();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get link URL
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getUrl();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set link URL
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param string $url
|
||||||
|
*/
|
||||||
|
public function setUrl($url);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,171 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Kanboard\Core\ExternalLink;
|
||||||
|
|
||||||
|
use Kanboard\Core\Base;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* External Link Manager
|
||||||
|
*
|
||||||
|
* @package externalLink
|
||||||
|
* @author Frederic Guillot
|
||||||
|
*/
|
||||||
|
class ExternalLinkManager extends Base
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Automatic type value
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
const TYPE_AUTO = 'auto';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registered providers
|
||||||
|
*
|
||||||
|
* @access private
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
private $providers = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Type chosen by the user
|
||||||
|
*
|
||||||
|
* @access private
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $userInputType = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Text entered by the user
|
||||||
|
*
|
||||||
|
* @access private
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $userInputText = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register a new provider
|
||||||
|
*
|
||||||
|
* Providers are registered in a LIFO queue
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param ExternalLinkProviderInterface $provider
|
||||||
|
* @return ExternalLinkManager
|
||||||
|
*/
|
||||||
|
public function register(ExternalLinkProviderInterface $provider)
|
||||||
|
{
|
||||||
|
array_unshift($this->providers, $provider);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get provider
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param string $type
|
||||||
|
* @throws ExternalLinkProviderNotFound
|
||||||
|
* @return ExternalLinkProviderInterface
|
||||||
|
*/
|
||||||
|
public function getProvider($type)
|
||||||
|
{
|
||||||
|
foreach ($this->providers as $provider) {
|
||||||
|
if ($provider->getType() === $type) {
|
||||||
|
return $provider;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new ExternalLinkProviderNotFound('Unable to find link provider: '.$type);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get link types
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getTypes()
|
||||||
|
{
|
||||||
|
$types = array();
|
||||||
|
|
||||||
|
foreach ($this->providers as $provider) {
|
||||||
|
$types[$provider->getType()] = $provider->getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
asort($types);
|
||||||
|
|
||||||
|
return array(self::TYPE_AUTO => t('Auto')) + $types;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get dependency label from a provider
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param string $type
|
||||||
|
* @param string $dependency
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getDependencyLabel($type, $dependency)
|
||||||
|
{
|
||||||
|
$provider = $this->getProvider($type);
|
||||||
|
$dependencies = $provider->getDependencies();
|
||||||
|
return isset($dependencies[$dependency]) ? $dependencies[$dependency] : $dependency;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find a provider that match
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @throws ExternalLinkProviderNotFound
|
||||||
|
* @return ExternalLinkProviderInterface
|
||||||
|
*/
|
||||||
|
public function find()
|
||||||
|
{
|
||||||
|
$provider = null;
|
||||||
|
|
||||||
|
if ($this->userInputType === self::TYPE_AUTO) {
|
||||||
|
$provider = $this->findProvider();
|
||||||
|
} else {
|
||||||
|
$provider = $this->getProvider($this->userInputType);
|
||||||
|
$provider->setUserTextInput($this->userInputText);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($provider === null) {
|
||||||
|
throw new ExternalLinkProviderNotFound('Unable to find link information from provided information');
|
||||||
|
}
|
||||||
|
|
||||||
|
return $provider;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set form values
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param array $values
|
||||||
|
* @return ExternalLinkManager
|
||||||
|
*/
|
||||||
|
public function setUserInput(array $values)
|
||||||
|
{
|
||||||
|
$this->userInputType = empty($values['type']) ? self::TYPE_AUTO : $values['type'];
|
||||||
|
$this->userInputText = empty($values['text']) ? '' : trim($values['text']);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find a provider that user input
|
||||||
|
*
|
||||||
|
* @access private
|
||||||
|
* @return ExternalLinkProviderInterface
|
||||||
|
*/
|
||||||
|
private function findProvider()
|
||||||
|
{
|
||||||
|
foreach ($this->providers as $provider) {
|
||||||
|
$provider->setUserTextInput($this->userInputText);
|
||||||
|
|
||||||
|
if ($provider->match()) {
|
||||||
|
return $provider;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,71 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Kanboard\Core\ExternalLink;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* External Link Provider Interface
|
||||||
|
*
|
||||||
|
* @package externalLink
|
||||||
|
* @author Frederic Guillot
|
||||||
|
*/
|
||||||
|
interface ExternalLinkProviderInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Get provider name (label)
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getName();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get link type (will be saved in the database)
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getType();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a dictionary of supported dependency types by the provider
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
*
|
||||||
|
* [
|
||||||
|
* 'related' => t('Related'),
|
||||||
|
* 'child' => t('Child'),
|
||||||
|
* 'parent' => t('Parent'),
|
||||||
|
* 'self' => t('Self'),
|
||||||
|
* ]
|
||||||
|
*
|
||||||
|
* The dictionary key is saved in the database.
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getDependencies();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set text entered by the user
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param string $input
|
||||||
|
*/
|
||||||
|
public function setUserTextInput($input);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return true if the provider can parse correctly the user input
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function match();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the link found with the properties
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return ExternalLinkInterface
|
||||||
|
*/
|
||||||
|
public function getLink();
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Kanboard\Core\ExternalLink;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* External Link Provider Not Found Exception
|
||||||
|
*
|
||||||
|
* @package externalLink
|
||||||
|
* @author Frederic Guillot
|
||||||
|
*/
|
||||||
|
class ExternalLinkProviderNotFound extends Exception
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
@ -33,6 +33,19 @@ class Client extends Base
|
||||||
*/
|
*/
|
||||||
const HTTP_USER_AGENT = 'Kanboard';
|
const HTTP_USER_AGENT = 'Kanboard';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send a GET HTTP request
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param string $url
|
||||||
|
* @param string[] $headers
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function get($url, array $headers = array())
|
||||||
|
{
|
||||||
|
return $this->doRequest('GET', $url, '', $headers);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send a GET HTTP request and parse JSON response
|
* Send a GET HTTP request and parse JSON response
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -68,11 +68,12 @@ class Response extends Base
|
||||||
*
|
*
|
||||||
* @access public
|
* @access public
|
||||||
* @param string $url Redirection URL
|
* @param string $url Redirection URL
|
||||||
|
* @param boolean $self If Ajax request and true: refresh the current page
|
||||||
*/
|
*/
|
||||||
public function redirect($url)
|
public function redirect($url, $self = false)
|
||||||
{
|
{
|
||||||
if ($this->request->getServerVariable('HTTP_X_REQUESTED_WITH') === 'XMLHttpRequest') {
|
if ($this->request->getServerVariable('HTTP_X_REQUESTED_WITH') === 'XMLHttpRequest') {
|
||||||
header('X-Ajax-Redirect: '.$url);
|
header('X-Ajax-Redirect: '.($self ? 'self' : $url));
|
||||||
} else {
|
} else {
|
||||||
header('Location: '.$url);
|
header('Location: '.$url);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Kanboard\ExternalLink;
|
||||||
|
|
||||||
|
use Kanboard\Core\ExternalLink\ExternalLinkInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attachment Link
|
||||||
|
*
|
||||||
|
* @package externalLink
|
||||||
|
* @author Frederic Guillot
|
||||||
|
*/
|
||||||
|
class AttachmentLink extends BaseLink implements ExternalLinkInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Get link title
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getTitle()
|
||||||
|
{
|
||||||
|
$path = parse_url($this->url, PHP_URL_PATH);
|
||||||
|
return basename($path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,117 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Kanboard\ExternalLink;
|
||||||
|
|
||||||
|
use Kanboard\Core\ExternalLink\ExternalLinkProviderInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attachment Link Provider
|
||||||
|
*
|
||||||
|
* @package externalLink
|
||||||
|
* @author Frederic Guillot
|
||||||
|
*/
|
||||||
|
class AttachmentLinkProvider extends BaseLinkProvider implements ExternalLinkProviderInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* File extensions that are not attachments
|
||||||
|
*
|
||||||
|
* @access protected
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $extensions = array(
|
||||||
|
'html',
|
||||||
|
'htm',
|
||||||
|
'xhtml',
|
||||||
|
'php',
|
||||||
|
'jsp',
|
||||||
|
'do',
|
||||||
|
'action',
|
||||||
|
'asp',
|
||||||
|
'aspx',
|
||||||
|
'cgi',
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get provider name
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getName()
|
||||||
|
{
|
||||||
|
return t('Attachment');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get link type
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getType()
|
||||||
|
{
|
||||||
|
return 'attachment';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a dictionary of supported dependency types by the provider
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getDependencies()
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
'related' => t('Related'),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return true if the provider can parse correctly the user input
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function match()
|
||||||
|
{
|
||||||
|
if (preg_match('/^https?:\/\/.*\.([^\/]+)$/', $this->userInput, $matches)) {
|
||||||
|
return $this->isValidExtension($matches[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the link found with the properties
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return ExternalLinkInterface
|
||||||
|
*/
|
||||||
|
public function getLink()
|
||||||
|
{
|
||||||
|
$link = new AttachmentLink($this->container);
|
||||||
|
$link->setUrl($this->userInput);
|
||||||
|
|
||||||
|
return $link;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check file extension
|
||||||
|
*
|
||||||
|
* @access protected
|
||||||
|
* @param string $extension
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
protected function isValidExtension($extension)
|
||||||
|
{
|
||||||
|
$extension = strtolower($extension);
|
||||||
|
|
||||||
|
foreach ($this->extensions as $ext) {
|
||||||
|
if ($extension === $ext) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Kanboard\ExternalLink;
|
||||||
|
|
||||||
|
use Kanboard\Core\Base;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base Link
|
||||||
|
*
|
||||||
|
* @package externalLink
|
||||||
|
* @author Frederic Guillot
|
||||||
|
*/
|
||||||
|
abstract class BaseLink extends Base
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* URL
|
||||||
|
*
|
||||||
|
* @access protected
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $url = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get link URL
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getUrl()
|
||||||
|
{
|
||||||
|
return $this->url;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set link URL
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param string $url
|
||||||
|
*/
|
||||||
|
public function setUrl($url)
|
||||||
|
{
|
||||||
|
$this->url = $url;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Kanboard\ExternalLink;
|
||||||
|
|
||||||
|
use Kanboard\Core\Base;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base Link Provider
|
||||||
|
*
|
||||||
|
* @package externalLink
|
||||||
|
* @author Frederic Guillot
|
||||||
|
*/
|
||||||
|
abstract class BaseLinkProvider extends Base
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* User input
|
||||||
|
*
|
||||||
|
* @access protected
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $userInput = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set text entered by the user
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param string $input
|
||||||
|
*/
|
||||||
|
public function setUserTextInput($input)
|
||||||
|
{
|
||||||
|
$this->userInput = trim($input);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,37 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Kanboard\ExternalLink;
|
||||||
|
|
||||||
|
use Kanboard\Core\ExternalLink\ExternalLinkInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Web Link
|
||||||
|
*
|
||||||
|
* @package externalLink
|
||||||
|
* @author Frederic Guillot
|
||||||
|
*/
|
||||||
|
class WebLink extends BaseLink implements ExternalLinkInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Get link title
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getTitle()
|
||||||
|
{
|
||||||
|
$html = $this->httpClient->get($this->url);
|
||||||
|
|
||||||
|
if (preg_match('/<title>(.*)<\/title>/siU', $html, $matches)) {
|
||||||
|
return trim($matches[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$components = parse_url($this->url);
|
||||||
|
|
||||||
|
if (! empty($components['host']) && ! empty($components['path'])) {
|
||||||
|
return $components['host'].$components['path'];
|
||||||
|
}
|
||||||
|
|
||||||
|
return t('Title not found');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,77 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Kanboard\ExternalLink;
|
||||||
|
|
||||||
|
use Kanboard\Core\ExternalLink\ExternalLinkProviderInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Web Link Provider
|
||||||
|
*
|
||||||
|
* @package externalLink
|
||||||
|
* @author Frederic Guillot
|
||||||
|
*/
|
||||||
|
class WebLinkProvider extends BaseLinkProvider implements ExternalLinkProviderInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Get provider name
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getName()
|
||||||
|
{
|
||||||
|
return t('Web Link');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get link type
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getType()
|
||||||
|
{
|
||||||
|
return 'weblink';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a dictionary of supported dependency types by the provider
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getDependencies()
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
'related' => t('Related'),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return true if the provider can parse correctly the user input
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function match()
|
||||||
|
{
|
||||||
|
$startWithHttp = strpos($this->userInput, 'http://') === 0 || strpos($this->userInput, 'https://') === 0;
|
||||||
|
$validUrl = filter_var($this->userInput, FILTER_VALIDATE_URL);
|
||||||
|
|
||||||
|
return $startWithHttp && $validUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the link found with the properties
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return ExternalLinkInterface
|
||||||
|
*/
|
||||||
|
public function getLink()
|
||||||
|
{
|
||||||
|
$link = new WebLink($this->container);
|
||||||
|
$link->setUrl($this->userInput);
|
||||||
|
|
||||||
|
return $link;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1097,4 +1097,30 @@ return array(
|
||||||
// 'Highest priority' => '',
|
// 'Highest priority' => '',
|
||||||
// 'If you put zero to the low and high priority, this feature will be disabled.' => '',
|
// 'If you put zero to the low and high priority, this feature will be disabled.' => '',
|
||||||
// 'Priority: %d' => '',
|
// 'Priority: %d' => '',
|
||||||
|
// 'Close a task when there is no activity' => '',
|
||||||
|
// 'Duration in days' => '',
|
||||||
|
// 'Send email when there is no activity on a task' => '',
|
||||||
|
// 'List of external links' => '',
|
||||||
|
// 'Unable to fetch link information.' => '',
|
||||||
|
// 'Daily background job for tasks' => '',
|
||||||
|
// 'Auto' => '',
|
||||||
|
// 'Related' => '',
|
||||||
|
// 'Attachment' => '',
|
||||||
|
// 'Title not found' => '',
|
||||||
|
// 'Web Link' => '',
|
||||||
|
// 'External links' => '',
|
||||||
|
// 'Add external link' => '',
|
||||||
|
// 'Type' => '',
|
||||||
|
// 'Dependency' => '',
|
||||||
|
// 'View internal links' => '',
|
||||||
|
// 'View external links' => '',
|
||||||
|
// 'Add internal link' => '',
|
||||||
|
// 'Add a new external link' => '',
|
||||||
|
// 'Edit external link' => '',
|
||||||
|
// 'External link' => '',
|
||||||
|
// 'Copy and paste your link here...' => '',
|
||||||
|
// 'URL' => '',
|
||||||
|
// 'There is no external link for the moment.' => '',
|
||||||
|
// 'Internal links' => '',
|
||||||
|
// 'There is no internal link for the moment.' => '',
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -1097,4 +1097,30 @@ return array(
|
||||||
// 'Highest priority' => '',
|
// 'Highest priority' => '',
|
||||||
// 'If you put zero to the low and high priority, this feature will be disabled.' => '',
|
// 'If you put zero to the low and high priority, this feature will be disabled.' => '',
|
||||||
// 'Priority: %d' => '',
|
// 'Priority: %d' => '',
|
||||||
|
// 'Close a task when there is no activity' => '',
|
||||||
|
// 'Duration in days' => '',
|
||||||
|
// 'Send email when there is no activity on a task' => '',
|
||||||
|
// 'List of external links' => '',
|
||||||
|
// 'Unable to fetch link information.' => '',
|
||||||
|
// 'Daily background job for tasks' => '',
|
||||||
|
// 'Auto' => '',
|
||||||
|
// 'Related' => '',
|
||||||
|
// 'Attachment' => '',
|
||||||
|
// 'Title not found' => '',
|
||||||
|
// 'Web Link' => '',
|
||||||
|
// 'External links' => '',
|
||||||
|
// 'Add external link' => '',
|
||||||
|
// 'Type' => '',
|
||||||
|
// 'Dependency' => '',
|
||||||
|
// 'View internal links' => '',
|
||||||
|
// 'View external links' => '',
|
||||||
|
// 'Add internal link' => '',
|
||||||
|
// 'Add a new external link' => '',
|
||||||
|
// 'Edit external link' => '',
|
||||||
|
// 'External link' => '',
|
||||||
|
// 'Copy and paste your link here...' => '',
|
||||||
|
// 'URL' => '',
|
||||||
|
// 'There is no external link for the moment.' => '',
|
||||||
|
// 'Internal links' => '',
|
||||||
|
// 'There is no internal link for the moment.' => '',
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -1097,4 +1097,30 @@ return array(
|
||||||
// 'Highest priority' => '',
|
// 'Highest priority' => '',
|
||||||
// 'If you put zero to the low and high priority, this feature will be disabled.' => '',
|
// 'If you put zero to the low and high priority, this feature will be disabled.' => '',
|
||||||
// 'Priority: %d' => '',
|
// 'Priority: %d' => '',
|
||||||
|
// 'Close a task when there is no activity' => '',
|
||||||
|
// 'Duration in days' => '',
|
||||||
|
// 'Send email when there is no activity on a task' => '',
|
||||||
|
// 'List of external links' => '',
|
||||||
|
// 'Unable to fetch link information.' => '',
|
||||||
|
// 'Daily background job for tasks' => '',
|
||||||
|
// 'Auto' => '',
|
||||||
|
// 'Related' => '',
|
||||||
|
// 'Attachment' => '',
|
||||||
|
// 'Title not found' => '',
|
||||||
|
// 'Web Link' => '',
|
||||||
|
// 'External links' => '',
|
||||||
|
// 'Add external link' => '',
|
||||||
|
// 'Type' => '',
|
||||||
|
// 'Dependency' => '',
|
||||||
|
// 'View internal links' => '',
|
||||||
|
// 'View external links' => '',
|
||||||
|
// 'Add internal link' => '',
|
||||||
|
// 'Add a new external link' => '',
|
||||||
|
// 'Edit external link' => '',
|
||||||
|
// 'External link' => '',
|
||||||
|
// 'Copy and paste your link here...' => '',
|
||||||
|
// 'URL' => '',
|
||||||
|
// 'There is no external link for the moment.' => '',
|
||||||
|
// 'Internal links' => '',
|
||||||
|
// 'There is no internal link for the moment.' => '',
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -1097,4 +1097,30 @@ return array(
|
||||||
'Highest priority' => 'Höchste Priorität',
|
'Highest priority' => 'Höchste Priorität',
|
||||||
'If you put zero to the low and high priority, this feature will be disabled.' => 'Wenn Sie Null bei höchster und niedrigster Priorität eintragen, wird diese Funktion deaktiviert.',
|
'If you put zero to the low and high priority, this feature will be disabled.' => 'Wenn Sie Null bei höchster und niedrigster Priorität eintragen, wird diese Funktion deaktiviert.',
|
||||||
'Priority: %d' => 'Priorität: %d',
|
'Priority: %d' => 'Priorität: %d',
|
||||||
|
// 'Close a task when there is no activity' => '',
|
||||||
|
// 'Duration in days' => '',
|
||||||
|
// 'Send email when there is no activity on a task' => '',
|
||||||
|
// 'List of external links' => '',
|
||||||
|
// 'Unable to fetch link information.' => '',
|
||||||
|
// 'Daily background job for tasks' => '',
|
||||||
|
// 'Auto' => '',
|
||||||
|
// 'Related' => '',
|
||||||
|
// 'Attachment' => '',
|
||||||
|
// 'Title not found' => '',
|
||||||
|
// 'Web Link' => '',
|
||||||
|
// 'External links' => '',
|
||||||
|
// 'Add external link' => '',
|
||||||
|
// 'Type' => '',
|
||||||
|
// 'Dependency' => '',
|
||||||
|
// 'View internal links' => '',
|
||||||
|
// 'View external links' => '',
|
||||||
|
// 'Add internal link' => '',
|
||||||
|
// 'Add a new external link' => '',
|
||||||
|
// 'Edit external link' => '',
|
||||||
|
// 'External link' => '',
|
||||||
|
// 'Copy and paste your link here...' => '',
|
||||||
|
// 'URL' => '',
|
||||||
|
// 'There is no external link for the moment.' => '',
|
||||||
|
// 'Internal links' => '',
|
||||||
|
// 'There is no internal link for the moment.' => '',
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -1097,4 +1097,30 @@ return array(
|
||||||
// 'Highest priority' => '',
|
// 'Highest priority' => '',
|
||||||
// 'If you put zero to the low and high priority, this feature will be disabled.' => '',
|
// 'If you put zero to the low and high priority, this feature will be disabled.' => '',
|
||||||
// 'Priority: %d' => '',
|
// 'Priority: %d' => '',
|
||||||
|
// 'Close a task when there is no activity' => '',
|
||||||
|
// 'Duration in days' => '',
|
||||||
|
// 'Send email when there is no activity on a task' => '',
|
||||||
|
// 'List of external links' => '',
|
||||||
|
// 'Unable to fetch link information.' => '',
|
||||||
|
// 'Daily background job for tasks' => '',
|
||||||
|
// 'Auto' => '',
|
||||||
|
// 'Related' => '',
|
||||||
|
// 'Attachment' => '',
|
||||||
|
// 'Title not found' => '',
|
||||||
|
// 'Web Link' => '',
|
||||||
|
// 'External links' => '',
|
||||||
|
// 'Add external link' => '',
|
||||||
|
// 'Type' => '',
|
||||||
|
// 'Dependency' => '',
|
||||||
|
// 'View internal links' => '',
|
||||||
|
// 'View external links' => '',
|
||||||
|
// 'Add internal link' => '',
|
||||||
|
// 'Add a new external link' => '',
|
||||||
|
// 'Edit external link' => '',
|
||||||
|
// 'External link' => '',
|
||||||
|
// 'Copy and paste your link here...' => '',
|
||||||
|
// 'URL' => '',
|
||||||
|
// 'There is no external link for the moment.' => '',
|
||||||
|
// 'Internal links' => '',
|
||||||
|
// 'There is no internal link for the moment.' => '',
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -1097,4 +1097,30 @@ return array(
|
||||||
// 'Highest priority' => '',
|
// 'Highest priority' => '',
|
||||||
// 'If you put zero to the low and high priority, this feature will be disabled.' => '',
|
// 'If you put zero to the low and high priority, this feature will be disabled.' => '',
|
||||||
// 'Priority: %d' => '',
|
// 'Priority: %d' => '',
|
||||||
|
// 'Close a task when there is no activity' => '',
|
||||||
|
// 'Duration in days' => '',
|
||||||
|
// 'Send email when there is no activity on a task' => '',
|
||||||
|
// 'List of external links' => '',
|
||||||
|
// 'Unable to fetch link information.' => '',
|
||||||
|
// 'Daily background job for tasks' => '',
|
||||||
|
// 'Auto' => '',
|
||||||
|
// 'Related' => '',
|
||||||
|
// 'Attachment' => '',
|
||||||
|
// 'Title not found' => '',
|
||||||
|
// 'Web Link' => '',
|
||||||
|
// 'External links' => '',
|
||||||
|
// 'Add external link' => '',
|
||||||
|
// 'Type' => '',
|
||||||
|
// 'Dependency' => '',
|
||||||
|
// 'View internal links' => '',
|
||||||
|
// 'View external links' => '',
|
||||||
|
// 'Add internal link' => '',
|
||||||
|
// 'Add a new external link' => '',
|
||||||
|
// 'Edit external link' => '',
|
||||||
|
// 'External link' => '',
|
||||||
|
// 'Copy and paste your link here...' => '',
|
||||||
|
// 'URL' => '',
|
||||||
|
// 'There is no external link for the moment.' => '',
|
||||||
|
// 'Internal links' => '',
|
||||||
|
// 'There is no internal link for the moment.' => '',
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -1097,4 +1097,30 @@ return array(
|
||||||
// 'Highest priority' => '',
|
// 'Highest priority' => '',
|
||||||
// 'If you put zero to the low and high priority, this feature will be disabled.' => '',
|
// 'If you put zero to the low and high priority, this feature will be disabled.' => '',
|
||||||
// 'Priority: %d' => '',
|
// 'Priority: %d' => '',
|
||||||
|
// 'Close a task when there is no activity' => '',
|
||||||
|
// 'Duration in days' => '',
|
||||||
|
// 'Send email when there is no activity on a task' => '',
|
||||||
|
// 'List of external links' => '',
|
||||||
|
// 'Unable to fetch link information.' => '',
|
||||||
|
// 'Daily background job for tasks' => '',
|
||||||
|
// 'Auto' => '',
|
||||||
|
// 'Related' => '',
|
||||||
|
// 'Attachment' => '',
|
||||||
|
// 'Title not found' => '',
|
||||||
|
// 'Web Link' => '',
|
||||||
|
// 'External links' => '',
|
||||||
|
// 'Add external link' => '',
|
||||||
|
// 'Type' => '',
|
||||||
|
// 'Dependency' => '',
|
||||||
|
// 'View internal links' => '',
|
||||||
|
// 'View external links' => '',
|
||||||
|
// 'Add internal link' => '',
|
||||||
|
// 'Add a new external link' => '',
|
||||||
|
// 'Edit external link' => '',
|
||||||
|
// 'External link' => '',
|
||||||
|
// 'Copy and paste your link here...' => '',
|
||||||
|
// 'URL' => '',
|
||||||
|
// 'There is no external link for the moment.' => '',
|
||||||
|
// 'Internal links' => '',
|
||||||
|
// 'There is no internal link for the moment.' => '',
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -1100,4 +1100,30 @@ return array(
|
||||||
'Highest priority' => 'Priorité haute',
|
'Highest priority' => 'Priorité haute',
|
||||||
'If you put zero to the low and high priority, this feature will be disabled.' => 'Si vous mettez zéro pour la priorité basse et haute, cette fonctionnalité sera désactivée.',
|
'If you put zero to the low and high priority, this feature will be disabled.' => 'Si vous mettez zéro pour la priorité basse et haute, cette fonctionnalité sera désactivée.',
|
||||||
'Priority: %d' => 'Priorité : %d',
|
'Priority: %d' => 'Priorité : %d',
|
||||||
|
'Close a task when there is no activity' => 'Fermer une tâche sans activité',
|
||||||
|
'Duration in days' => 'Durée en jours',
|
||||||
|
'Send email when there is no activity on a task' => 'Envoyer un email lorsqu\'il n\'y a pas d\'activité sur une tâche',
|
||||||
|
'List of external links' => 'Liste des liens externes',
|
||||||
|
'Unable to fetch link information.' => 'Impossible de récupérer les informations sur le lien.',
|
||||||
|
'Daily background job for tasks' => 'Tâche planifée quotidienne pour les tâches',
|
||||||
|
'Auto' => 'Auto',
|
||||||
|
'Related' => 'Relié',
|
||||||
|
'Attachment' => 'Pièce-jointe',
|
||||||
|
'Title not found' => 'Titre non trouvé',
|
||||||
|
'Web Link' => 'Lien web',
|
||||||
|
'External links' => 'Liens externes',
|
||||||
|
'Add external link' => 'Ajouter un lien externe',
|
||||||
|
'Type' => 'Type',
|
||||||
|
'Dependency' => 'Dépendance',
|
||||||
|
'View internal links' => 'Voir les liens internes',
|
||||||
|
'View external links' => 'Voir les liens externes',
|
||||||
|
'Add internal link' => 'Ajouter un lien interne',
|
||||||
|
'Add a new external link' => 'Ajouter un nouveau lien externe',
|
||||||
|
'Edit external link' => 'Modifier un lien externe',
|
||||||
|
'External link' => 'Lien externe',
|
||||||
|
'Copy and paste your link here...' => 'Copier-coller vôtre lien ici...',
|
||||||
|
'URL' => 'URL',
|
||||||
|
'There is no external link for the moment.' => 'Il n\'y a pas de lien externe pour le moment.',
|
||||||
|
'Internal links' => 'Liens internes',
|
||||||
|
'There is no internal link for the moment.' => 'Il n\'y a pas de lien interne pour le moment.',
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -1097,4 +1097,30 @@ return array(
|
||||||
// 'Highest priority' => '',
|
// 'Highest priority' => '',
|
||||||
// 'If you put zero to the low and high priority, this feature will be disabled.' => '',
|
// 'If you put zero to the low and high priority, this feature will be disabled.' => '',
|
||||||
// 'Priority: %d' => '',
|
// 'Priority: %d' => '',
|
||||||
|
// 'Close a task when there is no activity' => '',
|
||||||
|
// 'Duration in days' => '',
|
||||||
|
// 'Send email when there is no activity on a task' => '',
|
||||||
|
// 'List of external links' => '',
|
||||||
|
// 'Unable to fetch link information.' => '',
|
||||||
|
// 'Daily background job for tasks' => '',
|
||||||
|
// 'Auto' => '',
|
||||||
|
// 'Related' => '',
|
||||||
|
// 'Attachment' => '',
|
||||||
|
// 'Title not found' => '',
|
||||||
|
// 'Web Link' => '',
|
||||||
|
// 'External links' => '',
|
||||||
|
// 'Add external link' => '',
|
||||||
|
// 'Type' => '',
|
||||||
|
// 'Dependency' => '',
|
||||||
|
// 'View internal links' => '',
|
||||||
|
// 'View external links' => '',
|
||||||
|
// 'Add internal link' => '',
|
||||||
|
// 'Add a new external link' => '',
|
||||||
|
// 'Edit external link' => '',
|
||||||
|
// 'External link' => '',
|
||||||
|
// 'Copy and paste your link here...' => '',
|
||||||
|
// 'URL' => '',
|
||||||
|
// 'There is no external link for the moment.' => '',
|
||||||
|
// 'Internal links' => '',
|
||||||
|
// 'There is no internal link for the moment.' => '',
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -1097,4 +1097,30 @@ return array(
|
||||||
// 'Highest priority' => '',
|
// 'Highest priority' => '',
|
||||||
// 'If you put zero to the low and high priority, this feature will be disabled.' => '',
|
// 'If you put zero to the low and high priority, this feature will be disabled.' => '',
|
||||||
// 'Priority: %d' => '',
|
// 'Priority: %d' => '',
|
||||||
|
// 'Close a task when there is no activity' => '',
|
||||||
|
// 'Duration in days' => '',
|
||||||
|
// 'Send email when there is no activity on a task' => '',
|
||||||
|
// 'List of external links' => '',
|
||||||
|
// 'Unable to fetch link information.' => '',
|
||||||
|
// 'Daily background job for tasks' => '',
|
||||||
|
// 'Auto' => '',
|
||||||
|
// 'Related' => '',
|
||||||
|
// 'Attachment' => '',
|
||||||
|
// 'Title not found' => '',
|
||||||
|
// 'Web Link' => '',
|
||||||
|
// 'External links' => '',
|
||||||
|
// 'Add external link' => '',
|
||||||
|
// 'Type' => '',
|
||||||
|
// 'Dependency' => '',
|
||||||
|
// 'View internal links' => '',
|
||||||
|
// 'View external links' => '',
|
||||||
|
// 'Add internal link' => '',
|
||||||
|
// 'Add a new external link' => '',
|
||||||
|
// 'Edit external link' => '',
|
||||||
|
// 'External link' => '',
|
||||||
|
// 'Copy and paste your link here...' => '',
|
||||||
|
// 'URL' => '',
|
||||||
|
// 'There is no external link for the moment.' => '',
|
||||||
|
// 'Internal links' => '',
|
||||||
|
// 'There is no internal link for the moment.' => '',
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -1097,4 +1097,30 @@ return array(
|
||||||
'Highest priority' => 'Priorità massima',
|
'Highest priority' => 'Priorità massima',
|
||||||
'If you put zero to the low and high priority, this feature will be disabled.' => 'Se imposti a zero la priorità massima e minima, questa funzionalità sarà disabilitata.',
|
'If you put zero to the low and high priority, this feature will be disabled.' => 'Se imposti a zero la priorità massima e minima, questa funzionalità sarà disabilitata.',
|
||||||
'Priority: %d' => 'Priorità: %d',
|
'Priority: %d' => 'Priorità: %d',
|
||||||
|
// 'Close a task when there is no activity' => '',
|
||||||
|
// 'Duration in days' => '',
|
||||||
|
// 'Send email when there is no activity on a task' => '',
|
||||||
|
// 'List of external links' => '',
|
||||||
|
// 'Unable to fetch link information.' => '',
|
||||||
|
// 'Daily background job for tasks' => '',
|
||||||
|
// 'Auto' => '',
|
||||||
|
// 'Related' => '',
|
||||||
|
// 'Attachment' => '',
|
||||||
|
// 'Title not found' => '',
|
||||||
|
// 'Web Link' => '',
|
||||||
|
// 'External links' => '',
|
||||||
|
// 'Add external link' => '',
|
||||||
|
// 'Type' => '',
|
||||||
|
// 'Dependency' => '',
|
||||||
|
// 'View internal links' => '',
|
||||||
|
// 'View external links' => '',
|
||||||
|
// 'Add internal link' => '',
|
||||||
|
// 'Add a new external link' => '',
|
||||||
|
// 'Edit external link' => '',
|
||||||
|
// 'External link' => '',
|
||||||
|
// 'Copy and paste your link here...' => '',
|
||||||
|
// 'URL' => '',
|
||||||
|
// 'There is no external link for the moment.' => '',
|
||||||
|
// 'Internal links' => '',
|
||||||
|
// 'There is no internal link for the moment.' => '',
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -1097,4 +1097,30 @@ return array(
|
||||||
// 'Highest priority' => '',
|
// 'Highest priority' => '',
|
||||||
// 'If you put zero to the low and high priority, this feature will be disabled.' => '',
|
// 'If you put zero to the low and high priority, this feature will be disabled.' => '',
|
||||||
// 'Priority: %d' => '',
|
// 'Priority: %d' => '',
|
||||||
|
// 'Close a task when there is no activity' => '',
|
||||||
|
// 'Duration in days' => '',
|
||||||
|
// 'Send email when there is no activity on a task' => '',
|
||||||
|
// 'List of external links' => '',
|
||||||
|
// 'Unable to fetch link information.' => '',
|
||||||
|
// 'Daily background job for tasks' => '',
|
||||||
|
// 'Auto' => '',
|
||||||
|
// 'Related' => '',
|
||||||
|
// 'Attachment' => '',
|
||||||
|
// 'Title not found' => '',
|
||||||
|
// 'Web Link' => '',
|
||||||
|
// 'External links' => '',
|
||||||
|
// 'Add external link' => '',
|
||||||
|
// 'Type' => '',
|
||||||
|
// 'Dependency' => '',
|
||||||
|
// 'View internal links' => '',
|
||||||
|
// 'View external links' => '',
|
||||||
|
// 'Add internal link' => '',
|
||||||
|
// 'Add a new external link' => '',
|
||||||
|
// 'Edit external link' => '',
|
||||||
|
// 'External link' => '',
|
||||||
|
// 'Copy and paste your link here...' => '',
|
||||||
|
// 'URL' => '',
|
||||||
|
// 'There is no external link for the moment.' => '',
|
||||||
|
// 'Internal links' => '',
|
||||||
|
// 'There is no internal link for the moment.' => '',
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -1097,4 +1097,30 @@ return array(
|
||||||
// 'Highest priority' => '',
|
// 'Highest priority' => '',
|
||||||
// 'If you put zero to the low and high priority, this feature will be disabled.' => '',
|
// 'If you put zero to the low and high priority, this feature will be disabled.' => '',
|
||||||
// 'Priority: %d' => '',
|
// 'Priority: %d' => '',
|
||||||
|
// 'Close a task when there is no activity' => '',
|
||||||
|
// 'Duration in days' => '',
|
||||||
|
// 'Send email when there is no activity on a task' => '',
|
||||||
|
// 'List of external links' => '',
|
||||||
|
// 'Unable to fetch link information.' => '',
|
||||||
|
// 'Daily background job for tasks' => '',
|
||||||
|
// 'Auto' => '',
|
||||||
|
// 'Related' => '',
|
||||||
|
// 'Attachment' => '',
|
||||||
|
// 'Title not found' => '',
|
||||||
|
// 'Web Link' => '',
|
||||||
|
// 'External links' => '',
|
||||||
|
// 'Add external link' => '',
|
||||||
|
// 'Type' => '',
|
||||||
|
// 'Dependency' => '',
|
||||||
|
// 'View internal links' => '',
|
||||||
|
// 'View external links' => '',
|
||||||
|
// 'Add internal link' => '',
|
||||||
|
// 'Add a new external link' => '',
|
||||||
|
// 'Edit external link' => '',
|
||||||
|
// 'External link' => '',
|
||||||
|
// 'Copy and paste your link here...' => '',
|
||||||
|
// 'URL' => '',
|
||||||
|
// 'There is no external link for the moment.' => '',
|
||||||
|
// 'Internal links' => '',
|
||||||
|
// 'There is no internal link for the moment.' => '',
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -1097,4 +1097,30 @@ return array(
|
||||||
// 'Highest priority' => '',
|
// 'Highest priority' => '',
|
||||||
// 'If you put zero to the low and high priority, this feature will be disabled.' => '',
|
// 'If you put zero to the low and high priority, this feature will be disabled.' => '',
|
||||||
// 'Priority: %d' => '',
|
// 'Priority: %d' => '',
|
||||||
|
// 'Close a task when there is no activity' => '',
|
||||||
|
// 'Duration in days' => '',
|
||||||
|
// 'Send email when there is no activity on a task' => '',
|
||||||
|
// 'List of external links' => '',
|
||||||
|
// 'Unable to fetch link information.' => '',
|
||||||
|
// 'Daily background job for tasks' => '',
|
||||||
|
// 'Auto' => '',
|
||||||
|
// 'Related' => '',
|
||||||
|
// 'Attachment' => '',
|
||||||
|
// 'Title not found' => '',
|
||||||
|
// 'Web Link' => '',
|
||||||
|
// 'External links' => '',
|
||||||
|
// 'Add external link' => '',
|
||||||
|
// 'Type' => '',
|
||||||
|
// 'Dependency' => '',
|
||||||
|
// 'View internal links' => '',
|
||||||
|
// 'View external links' => '',
|
||||||
|
// 'Add internal link' => '',
|
||||||
|
// 'Add a new external link' => '',
|
||||||
|
// 'Edit external link' => '',
|
||||||
|
// 'External link' => '',
|
||||||
|
// 'Copy and paste your link here...' => '',
|
||||||
|
// 'URL' => '',
|
||||||
|
// 'There is no external link for the moment.' => '',
|
||||||
|
// 'Internal links' => '',
|
||||||
|
// 'There is no internal link for the moment.' => '',
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -1097,4 +1097,30 @@ return array(
|
||||||
// 'Highest priority' => '',
|
// 'Highest priority' => '',
|
||||||
// 'If you put zero to the low and high priority, this feature will be disabled.' => '',
|
// 'If you put zero to the low and high priority, this feature will be disabled.' => '',
|
||||||
// 'Priority: %d' => '',
|
// 'Priority: %d' => '',
|
||||||
|
// 'Close a task when there is no activity' => '',
|
||||||
|
// 'Duration in days' => '',
|
||||||
|
// 'Send email when there is no activity on a task' => '',
|
||||||
|
// 'List of external links' => '',
|
||||||
|
// 'Unable to fetch link information.' => '',
|
||||||
|
// 'Daily background job for tasks' => '',
|
||||||
|
// 'Auto' => '',
|
||||||
|
// 'Related' => '',
|
||||||
|
// 'Attachment' => '',
|
||||||
|
// 'Title not found' => '',
|
||||||
|
// 'Web Link' => '',
|
||||||
|
// 'External links' => '',
|
||||||
|
// 'Add external link' => '',
|
||||||
|
// 'Type' => '',
|
||||||
|
// 'Dependency' => '',
|
||||||
|
// 'View internal links' => '',
|
||||||
|
// 'View external links' => '',
|
||||||
|
// 'Add internal link' => '',
|
||||||
|
// 'Add a new external link' => '',
|
||||||
|
// 'Edit external link' => '',
|
||||||
|
// 'External link' => '',
|
||||||
|
// 'Copy and paste your link here...' => '',
|
||||||
|
// 'URL' => '',
|
||||||
|
// 'There is no external link for the moment.' => '',
|
||||||
|
// 'Internal links' => '',
|
||||||
|
// 'There is no internal link for the moment.' => '',
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -1097,4 +1097,30 @@ return array(
|
||||||
// 'Highest priority' => '',
|
// 'Highest priority' => '',
|
||||||
// 'If you put zero to the low and high priority, this feature will be disabled.' => '',
|
// 'If you put zero to the low and high priority, this feature will be disabled.' => '',
|
||||||
// 'Priority: %d' => '',
|
// 'Priority: %d' => '',
|
||||||
|
// 'Close a task when there is no activity' => '',
|
||||||
|
// 'Duration in days' => '',
|
||||||
|
// 'Send email when there is no activity on a task' => '',
|
||||||
|
// 'List of external links' => '',
|
||||||
|
// 'Unable to fetch link information.' => '',
|
||||||
|
// 'Daily background job for tasks' => '',
|
||||||
|
// 'Auto' => '',
|
||||||
|
// 'Related' => '',
|
||||||
|
// 'Attachment' => '',
|
||||||
|
// 'Title not found' => '',
|
||||||
|
// 'Web Link' => '',
|
||||||
|
// 'External links' => '',
|
||||||
|
// 'Add external link' => '',
|
||||||
|
// 'Type' => '',
|
||||||
|
// 'Dependency' => '',
|
||||||
|
// 'View internal links' => '',
|
||||||
|
// 'View external links' => '',
|
||||||
|
// 'Add internal link' => '',
|
||||||
|
// 'Add a new external link' => '',
|
||||||
|
// 'Edit external link' => '',
|
||||||
|
// 'External link' => '',
|
||||||
|
// 'Copy and paste your link here...' => '',
|
||||||
|
// 'URL' => '',
|
||||||
|
// 'There is no external link for the moment.' => '',
|
||||||
|
// 'Internal links' => '',
|
||||||
|
// 'There is no internal link for the moment.' => '',
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -1097,4 +1097,30 @@ return array(
|
||||||
// 'Highest priority' => '',
|
// 'Highest priority' => '',
|
||||||
// 'If you put zero to the low and high priority, this feature will be disabled.' => '',
|
// 'If you put zero to the low and high priority, this feature will be disabled.' => '',
|
||||||
// 'Priority: %d' => '',
|
// 'Priority: %d' => '',
|
||||||
|
// 'Close a task when there is no activity' => '',
|
||||||
|
// 'Duration in days' => '',
|
||||||
|
// 'Send email when there is no activity on a task' => '',
|
||||||
|
// 'List of external links' => '',
|
||||||
|
// 'Unable to fetch link information.' => '',
|
||||||
|
// 'Daily background job for tasks' => '',
|
||||||
|
// 'Auto' => '',
|
||||||
|
// 'Related' => '',
|
||||||
|
// 'Attachment' => '',
|
||||||
|
// 'Title not found' => '',
|
||||||
|
// 'Web Link' => '',
|
||||||
|
// 'External links' => '',
|
||||||
|
// 'Add external link' => '',
|
||||||
|
// 'Type' => '',
|
||||||
|
// 'Dependency' => '',
|
||||||
|
// 'View internal links' => '',
|
||||||
|
// 'View external links' => '',
|
||||||
|
// 'Add internal link' => '',
|
||||||
|
// 'Add a new external link' => '',
|
||||||
|
// 'Edit external link' => '',
|
||||||
|
// 'External link' => '',
|
||||||
|
// 'Copy and paste your link here...' => '',
|
||||||
|
// 'URL' => '',
|
||||||
|
// 'There is no external link for the moment.' => '',
|
||||||
|
// 'Internal links' => '',
|
||||||
|
// 'There is no internal link for the moment.' => '',
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -1097,4 +1097,30 @@ return array(
|
||||||
'Highest priority' => 'Prioridade mais alta',
|
'Highest priority' => 'Prioridade mais alta',
|
||||||
'If you put zero to the low and high priority, this feature will be disabled.' => 'Se colocar zero na prioridade baixa ou alta, essa funcionalidade será desactivada.',
|
'If you put zero to the low and high priority, this feature will be disabled.' => 'Se colocar zero na prioridade baixa ou alta, essa funcionalidade será desactivada.',
|
||||||
'Priority: %d' => 'Prioridade: %d',
|
'Priority: %d' => 'Prioridade: %d',
|
||||||
|
// 'Close a task when there is no activity' => '',
|
||||||
|
// 'Duration in days' => '',
|
||||||
|
// 'Send email when there is no activity on a task' => '',
|
||||||
|
// 'List of external links' => '',
|
||||||
|
// 'Unable to fetch link information.' => '',
|
||||||
|
// 'Daily background job for tasks' => '',
|
||||||
|
// 'Auto' => '',
|
||||||
|
// 'Related' => '',
|
||||||
|
// 'Attachment' => '',
|
||||||
|
// 'Title not found' => '',
|
||||||
|
// 'Web Link' => '',
|
||||||
|
// 'External links' => '',
|
||||||
|
// 'Add external link' => '',
|
||||||
|
// 'Type' => '',
|
||||||
|
// 'Dependency' => '',
|
||||||
|
// 'View internal links' => '',
|
||||||
|
// 'View external links' => '',
|
||||||
|
// 'Add internal link' => '',
|
||||||
|
// 'Add a new external link' => '',
|
||||||
|
// 'Edit external link' => '',
|
||||||
|
// 'External link' => '',
|
||||||
|
// 'Copy and paste your link here...' => '',
|
||||||
|
// 'URL' => '',
|
||||||
|
// 'There is no external link for the moment.' => '',
|
||||||
|
// 'Internal links' => '',
|
||||||
|
// 'There is no internal link for the moment.' => '',
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -1097,4 +1097,30 @@ return array(
|
||||||
'Highest priority' => 'Нивысший приоритет',
|
'Highest priority' => 'Нивысший приоритет',
|
||||||
'If you put zero to the low and high priority, this feature will be disabled.' => 'Если Вы введете 0 для наименьшего и наивысшего приоритета, этот функционал будет отключен.',
|
'If you put zero to the low and high priority, this feature will be disabled.' => 'Если Вы введете 0 для наименьшего и наивысшего приоритета, этот функционал будет отключен.',
|
||||||
'Priority: %d' => 'Приоритет: %d',
|
'Priority: %d' => 'Приоритет: %d',
|
||||||
|
// 'Close a task when there is no activity' => '',
|
||||||
|
// 'Duration in days' => '',
|
||||||
|
// 'Send email when there is no activity on a task' => '',
|
||||||
|
// 'List of external links' => '',
|
||||||
|
// 'Unable to fetch link information.' => '',
|
||||||
|
// 'Daily background job for tasks' => '',
|
||||||
|
// 'Auto' => '',
|
||||||
|
// 'Related' => '',
|
||||||
|
// 'Attachment' => '',
|
||||||
|
// 'Title not found' => '',
|
||||||
|
// 'Web Link' => '',
|
||||||
|
// 'External links' => '',
|
||||||
|
// 'Add external link' => '',
|
||||||
|
// 'Type' => '',
|
||||||
|
// 'Dependency' => '',
|
||||||
|
// 'View internal links' => '',
|
||||||
|
// 'View external links' => '',
|
||||||
|
// 'Add internal link' => '',
|
||||||
|
// 'Add a new external link' => '',
|
||||||
|
// 'Edit external link' => '',
|
||||||
|
// 'External link' => '',
|
||||||
|
// 'Copy and paste your link here...' => '',
|
||||||
|
// 'URL' => '',
|
||||||
|
// 'There is no external link for the moment.' => '',
|
||||||
|
// 'Internal links' => '',
|
||||||
|
// 'There is no internal link for the moment.' => '',
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -1097,4 +1097,30 @@ return array(
|
||||||
// 'Highest priority' => '',
|
// 'Highest priority' => '',
|
||||||
// 'If you put zero to the low and high priority, this feature will be disabled.' => '',
|
// 'If you put zero to the low and high priority, this feature will be disabled.' => '',
|
||||||
// 'Priority: %d' => '',
|
// 'Priority: %d' => '',
|
||||||
|
// 'Close a task when there is no activity' => '',
|
||||||
|
// 'Duration in days' => '',
|
||||||
|
// 'Send email when there is no activity on a task' => '',
|
||||||
|
// 'List of external links' => '',
|
||||||
|
// 'Unable to fetch link information.' => '',
|
||||||
|
// 'Daily background job for tasks' => '',
|
||||||
|
// 'Auto' => '',
|
||||||
|
// 'Related' => '',
|
||||||
|
// 'Attachment' => '',
|
||||||
|
// 'Title not found' => '',
|
||||||
|
// 'Web Link' => '',
|
||||||
|
// 'External links' => '',
|
||||||
|
// 'Add external link' => '',
|
||||||
|
// 'Type' => '',
|
||||||
|
// 'Dependency' => '',
|
||||||
|
// 'View internal links' => '',
|
||||||
|
// 'View external links' => '',
|
||||||
|
// 'Add internal link' => '',
|
||||||
|
// 'Add a new external link' => '',
|
||||||
|
// 'Edit external link' => '',
|
||||||
|
// 'External link' => '',
|
||||||
|
// 'Copy and paste your link here...' => '',
|
||||||
|
// 'URL' => '',
|
||||||
|
// 'There is no external link for the moment.' => '',
|
||||||
|
// 'Internal links' => '',
|
||||||
|
// 'There is no internal link for the moment.' => '',
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -1097,4 +1097,30 @@ return array(
|
||||||
// 'Highest priority' => '',
|
// 'Highest priority' => '',
|
||||||
// 'If you put zero to the low and high priority, this feature will be disabled.' => '',
|
// 'If you put zero to the low and high priority, this feature will be disabled.' => '',
|
||||||
// 'Priority: %d' => '',
|
// 'Priority: %d' => '',
|
||||||
|
// 'Close a task when there is no activity' => '',
|
||||||
|
// 'Duration in days' => '',
|
||||||
|
// 'Send email when there is no activity on a task' => '',
|
||||||
|
// 'List of external links' => '',
|
||||||
|
// 'Unable to fetch link information.' => '',
|
||||||
|
// 'Daily background job for tasks' => '',
|
||||||
|
// 'Auto' => '',
|
||||||
|
// 'Related' => '',
|
||||||
|
// 'Attachment' => '',
|
||||||
|
// 'Title not found' => '',
|
||||||
|
// 'Web Link' => '',
|
||||||
|
// 'External links' => '',
|
||||||
|
// 'Add external link' => '',
|
||||||
|
// 'Type' => '',
|
||||||
|
// 'Dependency' => '',
|
||||||
|
// 'View internal links' => '',
|
||||||
|
// 'View external links' => '',
|
||||||
|
// 'Add internal link' => '',
|
||||||
|
// 'Add a new external link' => '',
|
||||||
|
// 'Edit external link' => '',
|
||||||
|
// 'External link' => '',
|
||||||
|
// 'Copy and paste your link here...' => '',
|
||||||
|
// 'URL' => '',
|
||||||
|
// 'There is no external link for the moment.' => '',
|
||||||
|
// 'Internal links' => '',
|
||||||
|
// 'There is no internal link for the moment.' => '',
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -1097,4 +1097,30 @@ return array(
|
||||||
// 'Highest priority' => '',
|
// 'Highest priority' => '',
|
||||||
// 'If you put zero to the low and high priority, this feature will be disabled.' => '',
|
// 'If you put zero to the low and high priority, this feature will be disabled.' => '',
|
||||||
// 'Priority: %d' => '',
|
// 'Priority: %d' => '',
|
||||||
|
// 'Close a task when there is no activity' => '',
|
||||||
|
// 'Duration in days' => '',
|
||||||
|
// 'Send email when there is no activity on a task' => '',
|
||||||
|
// 'List of external links' => '',
|
||||||
|
// 'Unable to fetch link information.' => '',
|
||||||
|
// 'Daily background job for tasks' => '',
|
||||||
|
// 'Auto' => '',
|
||||||
|
// 'Related' => '',
|
||||||
|
// 'Attachment' => '',
|
||||||
|
// 'Title not found' => '',
|
||||||
|
// 'Web Link' => '',
|
||||||
|
// 'External links' => '',
|
||||||
|
// 'Add external link' => '',
|
||||||
|
// 'Type' => '',
|
||||||
|
// 'Dependency' => '',
|
||||||
|
// 'View internal links' => '',
|
||||||
|
// 'View external links' => '',
|
||||||
|
// 'Add internal link' => '',
|
||||||
|
// 'Add a new external link' => '',
|
||||||
|
// 'Edit external link' => '',
|
||||||
|
// 'External link' => '',
|
||||||
|
// 'Copy and paste your link here...' => '',
|
||||||
|
// 'URL' => '',
|
||||||
|
// 'There is no external link for the moment.' => '',
|
||||||
|
// 'Internal links' => '',
|
||||||
|
// 'There is no internal link for the moment.' => '',
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -1097,4 +1097,30 @@ return array(
|
||||||
// 'Highest priority' => '',
|
// 'Highest priority' => '',
|
||||||
// 'If you put zero to the low and high priority, this feature will be disabled.' => '',
|
// 'If you put zero to the low and high priority, this feature will be disabled.' => '',
|
||||||
// 'Priority: %d' => '',
|
// 'Priority: %d' => '',
|
||||||
|
// 'Close a task when there is no activity' => '',
|
||||||
|
// 'Duration in days' => '',
|
||||||
|
// 'Send email when there is no activity on a task' => '',
|
||||||
|
// 'List of external links' => '',
|
||||||
|
// 'Unable to fetch link information.' => '',
|
||||||
|
// 'Daily background job for tasks' => '',
|
||||||
|
// 'Auto' => '',
|
||||||
|
// 'Related' => '',
|
||||||
|
// 'Attachment' => '',
|
||||||
|
// 'Title not found' => '',
|
||||||
|
// 'Web Link' => '',
|
||||||
|
// 'External links' => '',
|
||||||
|
// 'Add external link' => '',
|
||||||
|
// 'Type' => '',
|
||||||
|
// 'Dependency' => '',
|
||||||
|
// 'View internal links' => '',
|
||||||
|
// 'View external links' => '',
|
||||||
|
// 'Add internal link' => '',
|
||||||
|
// 'Add a new external link' => '',
|
||||||
|
// 'Edit external link' => '',
|
||||||
|
// 'External link' => '',
|
||||||
|
// 'Copy and paste your link here...' => '',
|
||||||
|
// 'URL' => '',
|
||||||
|
// 'There is no external link for the moment.' => '',
|
||||||
|
// 'Internal links' => '',
|
||||||
|
// 'There is no internal link for the moment.' => '',
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -1097,4 +1097,30 @@ return array(
|
||||||
// 'Highest priority' => '',
|
// 'Highest priority' => '',
|
||||||
// 'If you put zero to the low and high priority, this feature will be disabled.' => '',
|
// 'If you put zero to the low and high priority, this feature will be disabled.' => '',
|
||||||
// 'Priority: %d' => '',
|
// 'Priority: %d' => '',
|
||||||
|
// 'Close a task when there is no activity' => '',
|
||||||
|
// 'Duration in days' => '',
|
||||||
|
// 'Send email when there is no activity on a task' => '',
|
||||||
|
// 'List of external links' => '',
|
||||||
|
// 'Unable to fetch link information.' => '',
|
||||||
|
// 'Daily background job for tasks' => '',
|
||||||
|
// 'Auto' => '',
|
||||||
|
// 'Related' => '',
|
||||||
|
// 'Attachment' => '',
|
||||||
|
// 'Title not found' => '',
|
||||||
|
// 'Web Link' => '',
|
||||||
|
// 'External links' => '',
|
||||||
|
// 'Add external link' => '',
|
||||||
|
// 'Type' => '',
|
||||||
|
// 'Dependency' => '',
|
||||||
|
// 'View internal links' => '',
|
||||||
|
// 'View external links' => '',
|
||||||
|
// 'Add internal link' => '',
|
||||||
|
// 'Add a new external link' => '',
|
||||||
|
// 'Edit external link' => '',
|
||||||
|
// 'External link' => '',
|
||||||
|
// 'Copy and paste your link here...' => '',
|
||||||
|
// 'URL' => '',
|
||||||
|
// 'There is no external link for the moment.' => '',
|
||||||
|
// 'Internal links' => '',
|
||||||
|
// 'There is no internal link for the moment.' => '',
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,99 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Kanboard\Model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Task External Link Model
|
||||||
|
*
|
||||||
|
* @package model
|
||||||
|
* @author Frederic Guillot
|
||||||
|
*/
|
||||||
|
class TaskExternalLink extends Base
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* SQL table name
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
const TABLE = 'task_has_external_links';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all links
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param integer $task_id
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getAll($task_id)
|
||||||
|
{
|
||||||
|
$types = $this->externalLinkManager->getTypes();
|
||||||
|
|
||||||
|
$links = $this->db->table(self::TABLE)
|
||||||
|
->columns(self::TABLE.'.*', User::TABLE.'.name AS creator_name', User::TABLE.'.username AS creator_username')
|
||||||
|
->eq('task_id', $task_id)
|
||||||
|
->asc('title')
|
||||||
|
->join(User::TABLE, 'id', 'creator_id')
|
||||||
|
->findAll();
|
||||||
|
|
||||||
|
foreach ($links as &$link) {
|
||||||
|
$link['dependency_label'] = $this->externalLinkManager->getDependencyLabel($link['link_type'], $link['dependency']);
|
||||||
|
$link['type'] = isset($types[$link['link_type']]) ? $types[$link['link_type']] : t('Unknown');
|
||||||
|
}
|
||||||
|
|
||||||
|
return $links;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get link
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param integer $link_id
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getById($link_id)
|
||||||
|
{
|
||||||
|
return $this->db->table(self::TABLE)->eq('id', $link_id)->findOne();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a new link in the database
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param array $values Form values
|
||||||
|
* @return boolean|integer
|
||||||
|
*/
|
||||||
|
public function create(array $values)
|
||||||
|
{
|
||||||
|
unset($values['id']);
|
||||||
|
$values['creator_id'] = $this->userSession->getId();
|
||||||
|
$values['date_creation'] = time();
|
||||||
|
$values['date_modification'] = $values['date_creation'];
|
||||||
|
|
||||||
|
return $this->persist(self::TABLE, $values);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Modify external link
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param array $values Form values
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function update(array $values)
|
||||||
|
{
|
||||||
|
$values['date_modification'] = time();
|
||||||
|
return $this->db->table(self::TABLE)->eq('id', $values['id'])->update($values);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove a link
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param integer $link_id
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function remove($link_id)
|
||||||
|
{
|
||||||
|
return $this->db->table(self::TABLE)->eq('id', $link_id)->remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -88,11 +88,12 @@ class TaskFinder extends Base
|
||||||
return $this->db
|
return $this->db
|
||||||
->table(Task::TABLE)
|
->table(Task::TABLE)
|
||||||
->columns(
|
->columns(
|
||||||
'(SELECT count(*) FROM '.Comment::TABLE.' WHERE task_id=tasks.id) AS nb_comments',
|
'(SELECT COUNT(*) FROM '.Comment::TABLE.' WHERE task_id=tasks.id) AS nb_comments',
|
||||||
'(SELECT count(*) FROM '.File::TABLE.' WHERE task_id=tasks.id) AS nb_files',
|
'(SELECT COUNT(*) FROM '.File::TABLE.' WHERE task_id=tasks.id) AS nb_files',
|
||||||
'(SELECT count(*) FROM '.Subtask::TABLE.' WHERE '.Subtask::TABLE.'.task_id=tasks.id) AS nb_subtasks',
|
'(SELECT COUNT(*) FROM '.Subtask::TABLE.' WHERE '.Subtask::TABLE.'.task_id=tasks.id) AS nb_subtasks',
|
||||||
'(SELECT count(*) FROM '.Subtask::TABLE.' WHERE '.Subtask::TABLE.'.task_id=tasks.id AND status=2) AS nb_completed_subtasks',
|
'(SELECT COUNT(*) FROM '.Subtask::TABLE.' WHERE '.Subtask::TABLE.'.task_id=tasks.id AND status=2) AS nb_completed_subtasks',
|
||||||
'(SELECT count(*) FROM '.TaskLink::TABLE.' WHERE '.TaskLink::TABLE.'.task_id = tasks.id) AS nb_links',
|
'(SELECT COUNT(*) FROM '.TaskLink::TABLE.' WHERE '.TaskLink::TABLE.'.task_id = tasks.id) AS nb_links',
|
||||||
|
'(SELECT COUNT(*) FROM '.TaskExternalLink::TABLE.' WHERE '.TaskExternalLink::TABLE.'.task_id = tasks.id) AS nb_external_links',
|
||||||
'(SELECT DISTINCT 1 FROM '.TaskLink::TABLE.' WHERE '.TaskLink::TABLE.'.task_id = tasks.id AND '.TaskLink::TABLE.'.link_id = 9) AS is_milestone',
|
'(SELECT DISTINCT 1 FROM '.TaskLink::TABLE.' WHERE '.TaskLink::TABLE.'.task_id = tasks.id AND '.TaskLink::TABLE.'.link_id = 9) AS is_milestone',
|
||||||
'tasks.id',
|
'tasks.id',
|
||||||
'tasks.reference',
|
'tasks.reference',
|
||||||
|
|
|
||||||
|
|
@ -265,7 +265,7 @@ class User extends Base
|
||||||
*
|
*
|
||||||
* @access public
|
* @access public
|
||||||
* @param array $values Form values
|
* @param array $values Form values
|
||||||
* @return array
|
* @return boolean
|
||||||
*/
|
*/
|
||||||
public function update(array $values)
|
public function update(array $values)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,25 @@ use PDO;
|
||||||
use Kanboard\Core\Security\Token;
|
use Kanboard\Core\Security\Token;
|
||||||
use Kanboard\Core\Security\Role;
|
use Kanboard\Core\Security\Role;
|
||||||
|
|
||||||
const VERSION = 103;
|
const VERSION = 104;
|
||||||
|
|
||||||
|
function version_104(PDO $pdo)
|
||||||
|
{
|
||||||
|
$pdo->exec("
|
||||||
|
CREATE TABLE task_has_external_links (
|
||||||
|
id INT NOT NULL AUTO_INCREMENT,
|
||||||
|
link_type VARCHAR(100) NOT NULL,
|
||||||
|
dependency VARCHAR(100) NOT NULL,
|
||||||
|
title VARCHAR(255) NOT NULL,
|
||||||
|
url VARCHAR(255) NOT NULL,
|
||||||
|
date_creation INT NOT NULL,
|
||||||
|
date_modification INT NOT NULL,
|
||||||
|
task_id INT NOT NULL,
|
||||||
|
creator_id INT DEFAULT 0,
|
||||||
|
FOREIGN KEY(task_id) REFERENCES tasks(id) ON DELETE CASCADE
|
||||||
|
) ENGINE=InnoDB CHARSET=utf8
|
||||||
|
");
|
||||||
|
}
|
||||||
|
|
||||||
function version_103(PDO $pdo)
|
function version_103(PDO $pdo)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,25 @@ use PDO;
|
||||||
use Kanboard\Core\Security\Token;
|
use Kanboard\Core\Security\Token;
|
||||||
use Kanboard\Core\Security\Role;
|
use Kanboard\Core\Security\Role;
|
||||||
|
|
||||||
const VERSION = 83;
|
const VERSION = 84;
|
||||||
|
|
||||||
|
function version_84(PDO $pdo)
|
||||||
|
{
|
||||||
|
$pdo->exec("
|
||||||
|
CREATE TABLE task_has_external_links (
|
||||||
|
id SERIAL,
|
||||||
|
link_type VARCHAR(100) NOT NULL,
|
||||||
|
dependency VARCHAR(100) NOT NULL,
|
||||||
|
title VARCHAR(255) NOT NULL,
|
||||||
|
url VARCHAR(255) NOT NULL,
|
||||||
|
date_creation INT NOT NULL,
|
||||||
|
date_modification INT NOT NULL,
|
||||||
|
task_id INT NOT NULL,
|
||||||
|
creator_id INT DEFAULT 0,
|
||||||
|
FOREIGN KEY(task_id) REFERENCES tasks(id) ON DELETE CASCADE
|
||||||
|
)
|
||||||
|
");
|
||||||
|
}
|
||||||
|
|
||||||
function version_83(PDO $pdo)
|
function version_83(PDO $pdo)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,25 @@ use Kanboard\Core\Security\Token;
|
||||||
use Kanboard\Core\Security\Role;
|
use Kanboard\Core\Security\Role;
|
||||||
use PDO;
|
use PDO;
|
||||||
|
|
||||||
const VERSION = 95;
|
const VERSION = 96;
|
||||||
|
|
||||||
|
function version_96(PDO $pdo)
|
||||||
|
{
|
||||||
|
$pdo->exec("
|
||||||
|
CREATE TABLE task_has_external_links (
|
||||||
|
id INTEGER PRIMARY KEY,
|
||||||
|
link_type TEXT NOT NULL,
|
||||||
|
dependency TEXT NOT NULL,
|
||||||
|
title TEXT NOT NULL,
|
||||||
|
url TEXT NOT NULL,
|
||||||
|
date_creation INTEGER NOT NULL,
|
||||||
|
date_modification INTEGER NOT NULL,
|
||||||
|
task_id INTEGER NOT NULL,
|
||||||
|
creator_id INTEGER DEFAULT 0,
|
||||||
|
FOREIGN KEY(task_id) REFERENCES tasks(id) ON DELETE CASCADE
|
||||||
|
)
|
||||||
|
");
|
||||||
|
}
|
||||||
|
|
||||||
function version_95(PDO $pdo)
|
function version_95(PDO $pdo)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -89,6 +89,9 @@ class AuthenticationProvider implements ServiceProviderInterface
|
||||||
$acl->add('Taskduplication', '*', Role::PROJECT_MEMBER);
|
$acl->add('Taskduplication', '*', Role::PROJECT_MEMBER);
|
||||||
$acl->add('TaskImport', '*', Role::PROJECT_MANAGER);
|
$acl->add('TaskImport', '*', Role::PROJECT_MANAGER);
|
||||||
$acl->add('Tasklink', '*', Role::PROJECT_MEMBER);
|
$acl->add('Tasklink', '*', Role::PROJECT_MEMBER);
|
||||||
|
$acl->add('Tasklink', array('show'), Role::PROJECT_VIEWER);
|
||||||
|
$acl->add('TaskExternalLink', '*', Role::PROJECT_MEMBER);
|
||||||
|
$acl->add('TaskExternalLink', array('show'), Role::PROJECT_VIEWER);
|
||||||
$acl->add('Taskmodification', '*', Role::PROJECT_MEMBER);
|
$acl->add('Taskmodification', '*', Role::PROJECT_MEMBER);
|
||||||
$acl->add('Taskstatus', '*', Role::PROJECT_MEMBER);
|
$acl->add('Taskstatus', '*', Role::PROJECT_MEMBER);
|
||||||
$acl->add('Timer', '*', Role::PROJECT_MEMBER);
|
$acl->add('Timer', '*', Role::PROJECT_MEMBER);
|
||||||
|
|
|
||||||
|
|
@ -61,6 +61,7 @@ class ClassProvider implements ServiceProviderInterface
|
||||||
'TaskCreation',
|
'TaskCreation',
|
||||||
'TaskDuplication',
|
'TaskDuplication',
|
||||||
'TaskExport',
|
'TaskExport',
|
||||||
|
'TaskExternalLink',
|
||||||
'TaskFinder',
|
'TaskFinder',
|
||||||
'TaskFilter',
|
'TaskFilter',
|
||||||
'TaskLink',
|
'TaskLink',
|
||||||
|
|
@ -97,6 +98,7 @@ class ClassProvider implements ServiceProviderInterface
|
||||||
'CommentValidator',
|
'CommentValidator',
|
||||||
'CurrencyValidator',
|
'CurrencyValidator',
|
||||||
'CustomFilterValidator',
|
'CustomFilterValidator',
|
||||||
|
'ExternalLinkValidator',
|
||||||
'GroupValidator',
|
'GroupValidator',
|
||||||
'LinkValidator',
|
'LinkValidator',
|
||||||
'PasswordResetValidator',
|
'PasswordResetValidator',
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,34 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Kanboard\ServiceProvider;
|
||||||
|
|
||||||
|
use Pimple\Container;
|
||||||
|
use Pimple\ServiceProviderInterface;
|
||||||
|
use Kanboard\Core\ExternalLink\ExternalLinkManager;
|
||||||
|
use Kanboard\ExternalLink\WebLinkProvider;
|
||||||
|
use Kanboard\ExternalLink\AttachmentLinkProvider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* External Link Provider
|
||||||
|
*
|
||||||
|
* @package serviceProvider
|
||||||
|
* @author Frederic Guillot
|
||||||
|
*/
|
||||||
|
class ExternalLinkProvider implements ServiceProviderInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Register providers
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param \Pimple\Container $container
|
||||||
|
* @return \Pimple\Container
|
||||||
|
*/
|
||||||
|
public function register(Container $container)
|
||||||
|
{
|
||||||
|
$container['externalLinkManager'] = new ExternalLinkManager($container);
|
||||||
|
$container['externalLinkManager']->register(new WebLinkProvider($container));
|
||||||
|
$container['externalLinkManager']->register(new AttachmentLinkProvider($container));
|
||||||
|
|
||||||
|
return $container;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -106,11 +106,18 @@ class RouteProvider implements ServiceProviderInterface
|
||||||
$container['route']->addRoute('project/:project_id/task/:task_id/screenshot', 'file', 'screenshot');
|
$container['route']->addRoute('project/:project_id/task/:task_id/screenshot', 'file', 'screenshot');
|
||||||
$container['route']->addRoute('project/:project_id/task/:task_id/upload', 'file', 'create');
|
$container['route']->addRoute('project/:project_id/task/:task_id/upload', 'file', 'create');
|
||||||
$container['route']->addRoute('project/:project_id/task/:task_id/comment', 'comment', 'create');
|
$container['route']->addRoute('project/:project_id/task/:task_id/comment', 'comment', 'create');
|
||||||
|
$container['route']->addRoute('project/:project_id/task/:task_id/links', 'tasklink', 'show');
|
||||||
$container['route']->addRoute('project/:project_id/task/:task_id/link', 'tasklink', 'create');
|
$container['route']->addRoute('project/:project_id/task/:task_id/link', 'tasklink', 'create');
|
||||||
$container['route']->addRoute('project/:project_id/task/:task_id/transitions', 'task', 'transitions');
|
$container['route']->addRoute('project/:project_id/task/:task_id/transitions', 'task', 'transitions');
|
||||||
$container['route']->addRoute('project/:project_id/task/:task_id/analytics', 'task', 'analytics');
|
$container['route']->addRoute('project/:project_id/task/:task_id/analytics', 'task', 'analytics');
|
||||||
$container['route']->addRoute('project/:project_id/task/:task_id/remove', 'task', 'remove');
|
$container['route']->addRoute('project/:project_id/task/:task_id/remove', 'task', 'remove');
|
||||||
|
|
||||||
|
$container['route']->addRoute('project/:project_id/task/:task_id/links/external', 'TaskExternalLink', 'show');
|
||||||
|
$container['route']->addRoute('project/:project_id/task/:task_id/link/external/new', 'TaskExternalLink', 'find');
|
||||||
|
$container['route']->addRoute('project/:project_id/task/:task_id/link/external/save', 'TaskExternalLink', 'create');
|
||||||
|
$container['route']->addRoute('project/:project_id/task/:task_id/link/external/:link_id', 'TaskExternalLink', 'edit');
|
||||||
|
$container['route']->addRoute('project/:project_id/task/:task_id/link/external/:link_id/remove', 'TaskExternalLink', 'confirm');
|
||||||
|
|
||||||
$container['route']->addRoute('project/:project_id/task/:task_id/edit', 'taskmodification', 'edit');
|
$container['route']->addRoute('project/:project_id/task/:task_id/edit', 'taskmodification', 'edit');
|
||||||
$container['route']->addRoute('project/:project_id/task/:task_id/description', 'taskmodification', 'description');
|
$container['route']->addRoute('project/:project_id/task/:task_id/description', 'taskmodification', 'description');
|
||||||
$container['route']->addRoute('project/:project_id/task/:task_id/recurrence', 'taskmodification', 'recurrence');
|
$container['route']->addRoute('project/:project_id/task/:task_id/recurrence', 'taskmodification', 'recurrence');
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,11 @@
|
||||||
<?php endif ?>
|
<?php endif ?>
|
||||||
|
|
||||||
<?php if (! empty($task['nb_links'])): ?>
|
<?php if (! empty($task['nb_links'])): ?>
|
||||||
<span title="<?= t('Links') ?>" class="tooltip" data-href="<?= $this->url->href('BoardTooltip', 'tasklinks', array('task_id' => $task['id'], 'project_id' => $task['project_id'])) ?>"><i class="fa fa-code-fork"></i> <?= $task['nb_links'] ?></span>
|
<span title="<?= t('Links') ?>" class="tooltip" data-href="<?= $this->url->href('BoardTooltip', 'tasklinks', array('task_id' => $task['id'], 'project_id' => $task['project_id'])) ?>"><i class="fa fa-code-fork fa-fw"></i><?= $task['nb_links'] ?></span>
|
||||||
|
<?php endif ?>
|
||||||
|
|
||||||
|
<?php if (! empty($task['nb_external_links'])): ?>
|
||||||
|
<span title="<?= t('External links') ?>" class="tooltip" data-href="<?= $this->url->href('BoardTooltip', 'externallinks', array('task_id' => $task['id'], 'project_id' => $task['project_id'])) ?>"><i class="fa fa-external-link fa-fw"></i><?= $task['nb_external_links'] ?></span>
|
||||||
<?php endif ?>
|
<?php endif ?>
|
||||||
|
|
||||||
<?php if (! empty($task['nb_subtasks'])): ?>
|
<?php if (! empty($task['nb_subtasks'])): ?>
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@
|
||||||
<li><i class="fa fa-pencil-square-o fa-fw"></i> <?= $this->url->link(t('Edit this task'), 'taskmodification', 'edit', array('task_id' => $task['id'], 'project_id' => $task['project_id']), false, 'popover') ?></li>
|
<li><i class="fa fa-pencil-square-o fa-fw"></i> <?= $this->url->link(t('Edit this task'), 'taskmodification', 'edit', array('task_id' => $task['id'], 'project_id' => $task['project_id']), false, 'popover') ?></li>
|
||||||
<li><i class="fa fa-comment-o fa-fw"></i> <?= $this->url->link(t('Add a comment'), 'comment', 'create', array('task_id' => $task['id'], 'project_id' => $task['project_id']), false, 'popover') ?></li>
|
<li><i class="fa fa-comment-o fa-fw"></i> <?= $this->url->link(t('Add a comment'), 'comment', 'create', array('task_id' => $task['id'], 'project_id' => $task['project_id']), false, 'popover') ?></li>
|
||||||
<li><i class="fa fa-code-fork fa-fw"></i> <?= $this->url->link(t('Add a link'), 'tasklink', 'create', array('task_id' => $task['id'], 'project_id' => $task['project_id']), false, 'popover') ?></li>
|
<li><i class="fa fa-code-fork fa-fw"></i> <?= $this->url->link(t('Add a link'), 'tasklink', 'create', array('task_id' => $task['id'], 'project_id' => $task['project_id']), false, 'popover') ?></li>
|
||||||
|
<li><i class="fa fa-external-link fa-fw"></i> <?= $this->url->link(t('Add external link'), 'TaskExternalLink', 'find', array('task_id' => $task['id'], 'project_id' => $task['project_id']), false, 'popover') ?></li>
|
||||||
<li><i class="fa fa-camera fa-fw"></i> <?= $this->url->link(t('Add a screenshot'), 'BoardPopover', 'screenshot', array('task_id' => $task['id'], 'project_id' => $task['project_id']), false, 'popover') ?></li>
|
<li><i class="fa fa-camera fa-fw"></i> <?= $this->url->link(t('Add a screenshot'), 'BoardPopover', 'screenshot', array('task_id' => $task['id'], 'project_id' => $task['project_id']), false, 'popover') ?></li>
|
||||||
<?php if ($task['is_active'] == 1): ?>
|
<?php if ($task['is_active'] == 1): ?>
|
||||||
<li><i class="fa fa-close fa-fw"></i> <?= $this->url->link(t('Close this task'), 'taskstatus', 'close', array('task_id' => $task['id'], 'project_id' => $task['project_id'], 'redirect' => 'board'), false, 'popover') ?></li>
|
<li><i class="fa fa-close fa-fw"></i> <?= $this->url->link(t('Close this task'), 'taskstatus', 'close', array('task_id' => $task['id'], 'project_id' => $task['project_id'], 'redirect' => 'board'), false, 'popover') ?></li>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
<table class="table-striped table-small">
|
||||||
|
<tr>
|
||||||
|
<th class="column-20"><?= t('Type') ?></th>
|
||||||
|
<th class="column-80"><?= t('Title') ?></th>
|
||||||
|
<th class="column-10"><?= t('Dependency') ?></th>
|
||||||
|
</tr>
|
||||||
|
<?php foreach ($links as $link): ?>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<?= $link['type'] ?>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<a href="<?= $link['url'] ?>" target="_blank"><?= $this->e($link['title']) ?></a>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<?= $this->e($link['dependency_label']) ?>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<?php endforeach ?>
|
||||||
|
</table>
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
<h2><?= t('Add a comment') ?></h2>
|
<h2><?= t('Add a comment') ?></h2>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<form method="post" action="<?= $this->url->href('comment', 'save', array('task_id' => $task['id'], 'project_id' => $task['project_id'], 'ajax' => isset($ajax))) ?>" autocomplete="off" class="form-comment">
|
<form method="post" action="<?= $this->url->href('comment', 'save', array('task_id' => $task['id'], 'project_id' => $task['project_id'], 'ajax' => $ajax)) ?>" autocomplete="off" class="form-comment">
|
||||||
<?= $this->form->csrf() ?>
|
<?= $this->form->csrf() ?>
|
||||||
<?= $this->form->hidden('task_id', $values) ?>
|
<?= $this->form->hidden('task_id', $values) ?>
|
||||||
<?= $this->form->hidden('user_id', $values) ?>
|
<?= $this->form->hidden('user_id', $values) ?>
|
||||||
|
|
@ -41,7 +41,7 @@
|
||||||
<input type="submit" value="<?= t('Save') ?>" class="btn btn-blue"/>
|
<input type="submit" value="<?= t('Save') ?>" class="btn btn-blue"/>
|
||||||
<?php if (! isset($skip_cancel)): ?>
|
<?php if (! isset($skip_cancel)): ?>
|
||||||
<?= t('or') ?>
|
<?= t('or') ?>
|
||||||
<?php if (isset($ajax)): ?>
|
<?php if ($ajax): ?>
|
||||||
<?= $this->url->link(t('cancel'), 'board', 'show', array('project_id' => $task['project_id'])) ?>
|
<?= $this->url->link(t('cancel'), 'board', 'show', array('project_id' => $task['project_id'])) ?>
|
||||||
<?php else: ?>
|
<?php else: ?>
|
||||||
<?= $this->url->link(t('cancel'), 'task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])) ?>
|
<?= $this->url->link(t('cancel'), 'task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])) ?>
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,8 @@
|
||||||
'task_id' => $task['id'],
|
'task_id' => $task['id'],
|
||||||
),
|
),
|
||||||
'errors' => array(),
|
'errors' => array(),
|
||||||
'task' => $task
|
'task' => $task,
|
||||||
|
'ajax' => $ajax,
|
||||||
)) ?>
|
)) ?>
|
||||||
<?php endif ?>
|
<?php endif ?>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -13,14 +13,6 @@
|
||||||
|
|
||||||
<?= $this->render('task/description', array('task' => $task)) ?>
|
<?= $this->render('task/description', array('task' => $task)) ?>
|
||||||
|
|
||||||
<?= $this->render('tasklink/show', array(
|
|
||||||
'task' => $task,
|
|
||||||
'links' => $links,
|
|
||||||
'link_label_list' => $link_label_list,
|
|
||||||
'editable' => $this->user->hasProjectAccess('tasklink', 'edit', $project['id']),
|
|
||||||
'is_public' => false,
|
|
||||||
)) ?>
|
|
||||||
|
|
||||||
<?= $this->render('subtask/show', array(
|
<?= $this->render('subtask/show', array(
|
||||||
'task' => $task,
|
'task' => $task,
|
||||||
'subtasks' => $subtasks,
|
'subtasks' => $subtasks,
|
||||||
|
|
@ -29,6 +21,14 @@
|
||||||
'editable' => $this->user->hasProjectAccess('subtask', 'edit', $project['id']),
|
'editable' => $this->user->hasProjectAccess('subtask', 'edit', $project['id']),
|
||||||
)) ?>
|
)) ?>
|
||||||
|
|
||||||
|
<?= $this->render('tasklink/show', array(
|
||||||
|
'task' => $task,
|
||||||
|
'links' => $links,
|
||||||
|
'link_label_list' => $link_label_list,
|
||||||
|
'editable' => $this->user->hasProjectAccess('tasklink', 'edit', $project['id']),
|
||||||
|
'is_public' => false,
|
||||||
|
)) ?>
|
||||||
|
|
||||||
<?= $this->render('task/time_tracking_summary', array('task' => $task)) ?>
|
<?= $this->render('task/time_tracking_summary', array('task' => $task)) ?>
|
||||||
|
|
||||||
<?= $this->render('file/show', array(
|
<?= $this->render('file/show', array(
|
||||||
|
|
@ -42,4 +42,5 @@
|
||||||
'comments' => $comments,
|
'comments' => $comments,
|
||||||
'project' => $project,
|
'project' => $project,
|
||||||
'editable' => $this->user->hasProjectAccess('comment', 'edit', $project['id']),
|
'editable' => $this->user->hasProjectAccess('comment', 'edit', $project['id']),
|
||||||
|
'ajax' => $ajax,
|
||||||
)) ?>
|
)) ?>
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,25 @@
|
||||||
|
|
||||||
<?= $this->hook->render('template:task:sidebar:information') ?>
|
<?= $this->hook->render('template:task:sidebar:information') ?>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
<h2><?= t('Links') ?></h2>
|
||||||
|
<ul>
|
||||||
|
<li <?= $this->app->checkMenuSelection('tasklink', 'show') ?>>
|
||||||
|
<?= $this->url->link(t('View internal links'), 'tasklink', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])) ?>
|
||||||
|
</li>
|
||||||
|
<li <?= $this->app->checkMenuSelection('TaskExternalLink', 'show') ?>>
|
||||||
|
<?= $this->url->link(t('View external links'), 'TaskExternalLink', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])) ?>
|
||||||
|
</li>
|
||||||
|
<?php if ($this->user->hasProjectAccess('tasklink', 'create', $task['project_id'])): ?>
|
||||||
|
<li <?= $this->app->checkMenuSelection('tasklink', 'create') ?>>
|
||||||
|
<?= $this->url->link(t('Add internal link'), 'tasklink', 'create', array('task_id' => $task['id'], 'project_id' => $task['project_id'])) ?>
|
||||||
|
</li>
|
||||||
|
<li <?= $this->app->checkMenuSelection('TaskExternalLink', 'find') ?>>
|
||||||
|
<?= $this->url->link(t('Add external link'), 'TaskExternalLink', 'find', array('task_id' => $task['id'], 'project_id' => $task['project_id'])) ?>
|
||||||
|
</li>
|
||||||
|
<?php endif ?>
|
||||||
|
</ul>
|
||||||
|
|
||||||
<?php if ($this->user->hasProjectAccess('taskmodification', 'edit', $task['project_id'])): ?>
|
<?php if ($this->user->hasProjectAccess('taskmodification', 'edit', $task['project_id'])): ?>
|
||||||
<h2><?= t('Actions') ?></h2>
|
<h2><?= t('Actions') ?></h2>
|
||||||
<ul>
|
<ul>
|
||||||
|
|
@ -36,9 +55,6 @@
|
||||||
<li <?= $this->app->checkMenuSelection('subtask', 'create') ?>>
|
<li <?= $this->app->checkMenuSelection('subtask', 'create') ?>>
|
||||||
<?= $this->url->link(t('Add a sub-task'), 'subtask', 'create', array('task_id' => $task['id'], 'project_id' => $task['project_id'])) ?>
|
<?= $this->url->link(t('Add a sub-task'), 'subtask', 'create', array('task_id' => $task['id'], 'project_id' => $task['project_id'])) ?>
|
||||||
</li>
|
</li>
|
||||||
<li <?= $this->app->checkMenuSelection('tasklink', 'create') ?>>
|
|
||||||
<?= $this->url->link(t('Add a link'), 'tasklink', 'create', array('task_id' => $task['id'], 'project_id' => $task['project_id'])) ?>
|
|
||||||
</li>
|
|
||||||
<li <?= $this->app->checkMenuSelection('comment', 'create') ?>>
|
<li <?= $this->app->checkMenuSelection('comment', 'create') ?>>
|
||||||
<?= $this->url->link(t('Add a comment'), 'comment', 'create', array('task_id' => $task['id'], 'project_id' => $task['project_id'])) ?>
|
<?= $this->url->link(t('Add a comment'), 'comment', 'create', array('task_id' => $task['id'], 'project_id' => $task['project_id'])) ?>
|
||||||
</li>
|
</li>
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@
|
||||||
</div>
|
</div>
|
||||||
<?php endif ?>
|
<?php endif ?>
|
||||||
|
|
||||||
<form id="task-form" method="post" action="<?= $this->url->href('taskcreation', 'save', array('project_id' => $values['project_id'])) ?>" autocomplete="off">
|
<form id="task-form" class="popover-form" method="post" action="<?= $this->url->href('taskcreation', 'save', array('project_id' => $values['project_id'])) ?>" autocomplete="off">
|
||||||
|
|
||||||
<?= $this->form->csrf() ?>
|
<?= $this->form->csrf() ?>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
<div class="page-header">
|
||||||
|
<h2><?= t('Add a new external link') ?></h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<form class="popover-form" action="<?= $this->url->href('TaskExternalLink', 'save', array('task_id' => $task['id'], 'project_id' => $task['project_id'], 'ajax' => $ajax)) ?>" method="post" autocomplete="off">
|
||||||
|
<?= $this->render('task_external_link/form', array('task' => $task, 'dependencies' => $dependencies, 'values' => $values, 'errors' => $errors)) ?>
|
||||||
|
|
||||||
|
<div class="form-actions">
|
||||||
|
<input type="submit" value="<?= t('Save') ?>" class="btn btn-blue">
|
||||||
|
<?= t('or') ?>
|
||||||
|
<?= $this->url->link(t('cancel'), 'TaskExternalLink', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id']), false, 'close-popover') ?>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
<div class="page-header">
|
||||||
|
<h2><?= t('Edit external link') ?></h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<form class="popover-form" action="<?= $this->url->href('TaskExternalLink', 'update', array('task_id' => $task['id'], 'project_id' => $task['project_id'], 'ajax' => $ajax)) ?>" method="post" autocomplete="off">
|
||||||
|
<?= $this->render('task_external_link/form', array('task' => $task, 'dependencies' => $dependencies, 'values' => $values, 'errors' => $errors)) ?>
|
||||||
|
|
||||||
|
<div class="form-actions">
|
||||||
|
<input type="submit" value="<?= t('Save') ?>" class="btn btn-blue">
|
||||||
|
<?= t('or') ?>
|
||||||
|
<?= $this->url->link(t('cancel'), 'TaskExternalLink', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id']), false, 'close-popover') ?>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
<div class="page-header">
|
||||||
|
<h2><?= t('Add a new external link') ?></h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<form class="popover-form" action="<?= $this->url->href('TaskExternalLink', 'create', array('task_id' => $task['id'], 'project_id' => $task['project_id'], 'ajax' => $ajax)) ?>" method="post" autocomplete="off">
|
||||||
|
<?= $this->form->csrf() ?>
|
||||||
|
<?= $this->form->hidden('task_id', array('task_id' => $task['id'])) ?>
|
||||||
|
|
||||||
|
<?= $this->form->label(t('External link'), 'text') ?>
|
||||||
|
<?= $this->form->text(
|
||||||
|
'text',
|
||||||
|
$values,
|
||||||
|
$errors,
|
||||||
|
array(
|
||||||
|
'required',
|
||||||
|
'autofocus',
|
||||||
|
'placeholder="'.t('Copy and paste your link here...').'"',
|
||||||
|
)) ?>
|
||||||
|
|
||||||
|
<?= $this->form->label(t('Link type'), 'type') ?>
|
||||||
|
<?= $this->form->select('type', $types, $values) ?>
|
||||||
|
|
||||||
|
<div class="form-actions">
|
||||||
|
<input type="submit" value="<?= t('Next') ?>" class="btn btn-blue"/>
|
||||||
|
<?= t('or') ?>
|
||||||
|
<?php if ($ajax): ?>
|
||||||
|
<?= $this->url->link(t('cancel'), 'board', 'show', array('project_id' => $task['project_id']), false, 'close-popover') ?>
|
||||||
|
<?php else: ?>
|
||||||
|
<?= $this->url->link(t('cancel'), 'task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])) ?>
|
||||||
|
<?php endif ?>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
<?= $this->form->csrf() ?>
|
||||||
|
<?= $this->form->hidden('task_id', array('task_id' => $task['id'])) ?>
|
||||||
|
<?= $this->form->hidden('id', $values) ?>
|
||||||
|
<?= $this->form->hidden('link_type', $values) ?>
|
||||||
|
|
||||||
|
<?= $this->form->label(t('URL'), 'url') ?>
|
||||||
|
<?= $this->form->text('url', $values, $errors, array('required')) ?>
|
||||||
|
|
||||||
|
<?= $this->form->label(t('Title'), 'title') ?>
|
||||||
|
<?= $this->form->text('title', $values, $errors, array('required')) ?>
|
||||||
|
|
||||||
|
<?= $this->form->label(t('Dependency'), 'dependency') ?>
|
||||||
|
<?= $this->form->select('dependency', $dependencies, $values, $errors) ?>
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
<div class="page-header">
|
||||||
|
<h2><?= t('Remove a link') ?></h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="confirm">
|
||||||
|
<p class="alert alert-info">
|
||||||
|
<?= t('Do you really want to remove this link: "%s"?', $link['title']) ?>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="form-actions">
|
||||||
|
<?= $this->url->link(t('Yes'), 'TaskExternalLink', 'remove', array('link_id' => $link['id'], 'task_id' => $task['id'], 'project_id' => $task['project_id']), true, 'btn btn-red') ?>
|
||||||
|
<?= t('or') ?>
|
||||||
|
<?= $this->url->link(t('cancel'), 'TaskExternalLink', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])) ?>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
@ -0,0 +1,50 @@
|
||||||
|
<div class="page-header">
|
||||||
|
<h2><?= t('External links') ?></h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<?php if (empty($links)): ?>
|
||||||
|
<p class="alert"><?= t('There is no external link for the moment.') ?></p>
|
||||||
|
<?php else: ?>
|
||||||
|
<table class="table-stripped table-small">
|
||||||
|
<tr>
|
||||||
|
<th class="column-10"><?= t('Type') ?></th>
|
||||||
|
<th><?= t('Title') ?></th>
|
||||||
|
<th class="column-10"><?= t('Dependency') ?></th>
|
||||||
|
<th class="column-15"><?= t('Creator') ?></th>
|
||||||
|
<th class="column-15"><?= t('Date') ?></th>
|
||||||
|
<?php if ($this->user->hasProjectAccess('TaskExternalLink', 'edit', $task['project_id'])): ?>
|
||||||
|
<th class="column-5"><?= t('Action') ?></th>
|
||||||
|
<?php endif ?>
|
||||||
|
</tr>
|
||||||
|
<?php foreach ($links as $link): ?>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<?= $link['type'] ?>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<a href="<?= $link['url'] ?>" target="_blank"><?= $this->e($link['title']) ?></a>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<?= $this->e($link['dependency_label']) ?>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<?= $this->e($link['creator_name'] ?: $link['creator_username']) ?>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<?= dt('%B %e, %Y', $link['date_creation']) ?>
|
||||||
|
</td>
|
||||||
|
<?php if ($this->user->hasProjectAccess('TaskExternalLink', 'edit', $task['project_id'])): ?>
|
||||||
|
<td>
|
||||||
|
<div class="dropdown">
|
||||||
|
<a href="#" class="dropdown-menu dropdown-menu-link-icon"><i class="fa fa-cog fa-fw"></i><i class="fa fa-caret-down"></i></a>
|
||||||
|
<ul>
|
||||||
|
<li><?= $this->url->link(t('Edit'), 'TaskExternalLink', 'edit', array('link_id' => $link['id'], 'task_id' => $task['id'], 'project_id' => $task['project_id'])) ?></li>
|
||||||
|
<li><?= $this->url->link(t('Remove'), 'TaskExternalLink', 'confirm', array('link_id' => $link['id'], 'task_id' => $task['id'], 'project_id' => $task['project_id'])) ?></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<?php endif ?>
|
||||||
|
</tr>
|
||||||
|
<?php endforeach ?>
|
||||||
|
</table>
|
||||||
|
<?php endif ?>
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
<h2><?= t('Add a new link') ?></h2>
|
<h2><?= t('Add a new link') ?></h2>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<form action="<?= $this->url->href('tasklink', 'save', array('task_id' => $task['id'], 'project_id' => $task['project_id'], 'ajax' => isset($ajax))) ?>" method="post" autocomplete="off">
|
<form action="<?= $this->url->href('tasklink', 'save', array('task_id' => $task['id'], 'project_id' => $task['project_id'], 'ajax' => $ajax)) ?>" method="post" autocomplete="off">
|
||||||
|
|
||||||
<?= $this->form->csrf() ?>
|
<?= $this->form->csrf() ?>
|
||||||
<?= $this->form->hidden('task_id', array('task_id' => $task['id'])) ?>
|
<?= $this->form->hidden('task_id', array('task_id' => $task['id'])) ?>
|
||||||
|
|
@ -28,7 +28,7 @@
|
||||||
<div class="form-actions">
|
<div class="form-actions">
|
||||||
<input type="submit" value="<?= t('Save') ?>" class="btn btn-blue"/>
|
<input type="submit" value="<?= t('Save') ?>" class="btn btn-blue"/>
|
||||||
<?= t('or') ?>
|
<?= t('or') ?>
|
||||||
<?php if (isset($ajax)): ?>
|
<?php if ($ajax): ?>
|
||||||
<?= $this->url->link(t('cancel'), 'board', 'show', array('project_id' => $task['project_id']), false, 'close-popover') ?>
|
<?= $this->url->link(t('cancel'), 'board', 'show', array('project_id' => $task['project_id']), false, 'close-popover') ?>
|
||||||
<?php else: ?>
|
<?php else: ?>
|
||||||
<?= $this->url->link(t('cancel'), 'task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])) ?>
|
<?= $this->url->link(t('cancel'), 'task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])) ?>
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,17 @@
|
||||||
<?php if (! empty($links)): ?>
|
|
||||||
<div class="page-header">
|
<div class="page-header">
|
||||||
<h2><?= t('Links') ?></h2>
|
<h2><?= t('Internal links') ?></h2>
|
||||||
</div>
|
</div>
|
||||||
<table id="links">
|
<?php if (empty($links)): ?>
|
||||||
|
<p class="alert"><?= t('There is no internal link for the moment.') ?></p>
|
||||||
|
<?php else: ?>
|
||||||
|
<table id="links" class="table-small table-stripped">
|
||||||
<tr>
|
<tr>
|
||||||
<th class="column-20"><?= t('Label') ?></th>
|
<th class="column-20"><?= t('Label') ?></th>
|
||||||
<th class="column-30"><?= t('Task') ?></th>
|
<th class="column-30"><?= t('Task') ?></th>
|
||||||
<th class="column-20"><?= t('Project') ?></th>
|
<th class="column-20"><?= t('Project') ?></th>
|
||||||
<th><?= t('Column') ?></th>
|
<th><?= t('Column') ?></th>
|
||||||
<th><?= t('Assignee') ?></th>
|
<th><?= t('Assignee') ?></th>
|
||||||
<?php if ($editable): ?>
|
<?php if ($editable && $this->user->hasProjectAccess('Tasklink', 'edit', $task['project_id'])): ?>
|
||||||
<th class="column-5"><?= t('Action') ?></th>
|
<th class="column-5"><?= t('Action') ?></th>
|
||||||
<?php endif ?>
|
<?php endif ?>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
@ -64,7 +66,7 @@
|
||||||
<?php endif ?>
|
<?php endif ?>
|
||||||
<?php endif ?>
|
<?php endif ?>
|
||||||
</td>
|
</td>
|
||||||
<?php if ($editable): ?>
|
<?php if ($editable && $this->user->hasProjectAccess('Tasklink', 'edit', $task['project_id'])): ?>
|
||||||
<td>
|
<td>
|
||||||
<div class="dropdown">
|
<div class="dropdown">
|
||||||
<a href="#" class="dropdown-menu dropdown-menu-link-icon"><i class="fa fa-cog fa-fw"></i><i class="fa fa-caret-down"></i></a>
|
<a href="#" class="dropdown-menu dropdown-menu-link-icon"><i class="fa fa-cog fa-fw"></i><i class="fa fa-caret-down"></i></a>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,76 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Kanboard\Validator;
|
||||||
|
|
||||||
|
use SimpleValidator\Validator;
|
||||||
|
use SimpleValidator\Validators;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* External Link Validator
|
||||||
|
*
|
||||||
|
* @package validator
|
||||||
|
* @author Frederic Guillot
|
||||||
|
*/
|
||||||
|
class ExternalLinkValidator extends Base
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Validate creation
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param array $values Form values
|
||||||
|
* @return array $valid, $errors [0] = Success or not, [1] = List of errors
|
||||||
|
*/
|
||||||
|
public function validateCreation(array $values)
|
||||||
|
{
|
||||||
|
$v = new Validator($values, $this->commonValidationRules());
|
||||||
|
|
||||||
|
return array(
|
||||||
|
$v->execute(),
|
||||||
|
$v->getErrors()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate modification
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param array $values Form values
|
||||||
|
* @return array $valid, $errors [0] = Success or not, [1] = List of errors
|
||||||
|
*/
|
||||||
|
public function validateModification(array $values)
|
||||||
|
{
|
||||||
|
$rules = array(
|
||||||
|
new Validators\Required('id', t('The id is required')),
|
||||||
|
);
|
||||||
|
|
||||||
|
$v = new Validator($values, array_merge($rules, $this->commonValidationRules()));
|
||||||
|
|
||||||
|
return array(
|
||||||
|
$v->execute(),
|
||||||
|
$v->getErrors()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Common validation rules
|
||||||
|
*
|
||||||
|
* @access private
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
private function commonValidationRules()
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
new Validators\Required('url', t('Field required')),
|
||||||
|
new Validators\MaxLength('url', t('The maximum length is %d characters', 255), 255),
|
||||||
|
new Validators\Required('title', t('Field required')),
|
||||||
|
new Validators\MaxLength('title', t('The maximum length is %d characters', 255), 255),
|
||||||
|
new Validators\Required('link_type', t('Field required')),
|
||||||
|
new Validators\MaxLength('link_type', t('The maximum length is %d characters', 100), 100),
|
||||||
|
new Validators\Required('dependency', t('Field required')),
|
||||||
|
new Validators\MaxLength('dependency', t('The maximum length is %d characters', 100), 100),
|
||||||
|
new Validators\Integer('id', t('This value must be an integer')),
|
||||||
|
new Validators\Required('task_id', t('Field required')),
|
||||||
|
new Validators\Integer('task_id', t('This value must be an integer')),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -34,4 +34,5 @@ $container->register(new Kanboard\ServiceProvider\EventDispatcherProvider);
|
||||||
$container->register(new Kanboard\ServiceProvider\GroupProvider);
|
$container->register(new Kanboard\ServiceProvider\GroupProvider);
|
||||||
$container->register(new Kanboard\ServiceProvider\RouteProvider);
|
$container->register(new Kanboard\ServiceProvider\RouteProvider);
|
||||||
$container->register(new Kanboard\ServiceProvider\ActionProvider);
|
$container->register(new Kanboard\ServiceProvider\ActionProvider);
|
||||||
|
$container->register(new Kanboard\ServiceProvider\ExternalLinkProvider);
|
||||||
$container->register(new Kanboard\ServiceProvider\PluginProvider);
|
$container->register(new Kanboard\ServiceProvider\PluginProvider);
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -55,22 +55,25 @@ Popover.prototype.listen = function() {
|
||||||
|
|
||||||
Popover.prototype.afterOpen = function() {
|
Popover.prototype.afterOpen = function() {
|
||||||
var self = this;
|
var self = this;
|
||||||
var taskForm = $("#task-form");
|
var popoverForm = $(".popover-form");
|
||||||
|
|
||||||
if (taskForm) {
|
if (popoverForm) {
|
||||||
taskForm.on("submit", function(e) {
|
popoverForm.on("submit", function(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
$.ajax({
|
$.ajax({
|
||||||
type: "POST",
|
type: "POST",
|
||||||
url: taskForm.attr("action"),
|
url: popoverForm.attr("action"),
|
||||||
data: taskForm.serialize(),
|
data: popoverForm.serialize(),
|
||||||
success: function(data, textStatus, request) {
|
success: function(data, textStatus, request) {
|
||||||
if (request.getResponseHeader("X-Ajax-Redirect")) {
|
var redirect = request.getResponseHeader("X-Ajax-Redirect");
|
||||||
window.location = request.getResponseHeader("X-Ajax-Redirect");
|
|
||||||
|
if (redirect) {
|
||||||
|
window.location = redirect === 'self' ? window.location.href : redirect;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$("#popover-content").html(data);
|
$("#popover-content").html(data);
|
||||||
|
$("input[autofocus]").focus();
|
||||||
self.afterOpen();
|
self.afterOpen();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,120 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
require_once __DIR__.'/../../Base.php';
|
||||||
|
|
||||||
|
use Kanboard\Core\ExternalLink\ExternalLinkManager;
|
||||||
|
use Kanboard\ExternalLink\WebLinkProvider;
|
||||||
|
use Kanboard\ExternalLink\AttachmentLinkProvider;
|
||||||
|
|
||||||
|
class ExternalLinkManagerTest extends Base
|
||||||
|
{
|
||||||
|
public function testRegister()
|
||||||
|
{
|
||||||
|
$externalLinkManager = new ExternalLinkManager($this->container);
|
||||||
|
$webLinkProvider = new WebLinkProvider($this->container);
|
||||||
|
$attachmentLinkProvider = new AttachmentLinkProvider($this->container);
|
||||||
|
|
||||||
|
$externalLinkManager->register($webLinkProvider);
|
||||||
|
$externalLinkManager->register($attachmentLinkProvider);
|
||||||
|
|
||||||
|
$this->assertInstanceOf(get_class($webLinkProvider), $externalLinkManager->getProvider($webLinkProvider->getType()));
|
||||||
|
$this->assertInstanceOf(get_class($attachmentLinkProvider), $externalLinkManager->getProvider($attachmentLinkProvider->getType()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGetProviderNotFound()
|
||||||
|
{
|
||||||
|
$externalLinkManager = new ExternalLinkManager($this->container);
|
||||||
|
|
||||||
|
$this->setExpectedException('\Kanboard\Core\ExternalLink\ExternalLinkProviderNotFound');
|
||||||
|
$externalLinkManager->getProvider('not found');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGetTypes()
|
||||||
|
{
|
||||||
|
$externalLinkManager = new ExternalLinkManager($this->container);
|
||||||
|
$webLinkProvider = new WebLinkProvider($this->container);
|
||||||
|
$attachmentLinkProvider = new AttachmentLinkProvider($this->container);
|
||||||
|
|
||||||
|
$this->assertEquals(array(ExternalLinkManager::TYPE_AUTO => 'Auto'), $externalLinkManager->getTypes());
|
||||||
|
|
||||||
|
$externalLinkManager->register($webLinkProvider);
|
||||||
|
$externalLinkManager->register($attachmentLinkProvider);
|
||||||
|
|
||||||
|
$this->assertEquals(
|
||||||
|
array(ExternalLinkManager::TYPE_AUTO => 'Auto', 'attachment' => 'Attachment', 'weblink' => 'Web Link'),
|
||||||
|
$externalLinkManager->getTypes()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGetDependencyLabel()
|
||||||
|
{
|
||||||
|
$externalLinkManager = new ExternalLinkManager($this->container);
|
||||||
|
$webLinkProvider = new WebLinkProvider($this->container);
|
||||||
|
$attachmentLinkProvider = new AttachmentLinkProvider($this->container);
|
||||||
|
|
||||||
|
$externalLinkManager->register($webLinkProvider);
|
||||||
|
$externalLinkManager->register($attachmentLinkProvider);
|
||||||
|
|
||||||
|
$this->assertSame('Related', $externalLinkManager->getDependencyLabel($webLinkProvider->getType(), 'related'));
|
||||||
|
$this->assertSame('custom', $externalLinkManager->getDependencyLabel($webLinkProvider->getType(), 'custom'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testFindProviderNotFound()
|
||||||
|
{
|
||||||
|
$externalLinkManager = new ExternalLinkManager($this->container);
|
||||||
|
$webLinkProvider = new WebLinkProvider($this->container);
|
||||||
|
$attachmentLinkProvider = new AttachmentLinkProvider($this->container);
|
||||||
|
|
||||||
|
$externalLinkManager->register($webLinkProvider);
|
||||||
|
$externalLinkManager->register($attachmentLinkProvider);
|
||||||
|
|
||||||
|
$this->setExpectedException('\Kanboard\Core\ExternalLink\ExternalLinkProviderNotFound');
|
||||||
|
$externalLinkManager->find();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testFindProvider()
|
||||||
|
{
|
||||||
|
$externalLinkManager = new ExternalLinkManager($this->container);
|
||||||
|
$webLinkProvider = new WebLinkProvider($this->container);
|
||||||
|
$attachmentLinkProvider = new AttachmentLinkProvider($this->container);
|
||||||
|
|
||||||
|
$externalLinkManager->register($webLinkProvider);
|
||||||
|
$externalLinkManager->register($attachmentLinkProvider);
|
||||||
|
|
||||||
|
$externalLinkManager->setUserInput(array('text' => 'https://google.com/', 'type' => ExternalLinkManager::TYPE_AUTO));
|
||||||
|
$this->assertSame($webLinkProvider, $externalLinkManager->find());
|
||||||
|
|
||||||
|
$externalLinkManager->setUserInput(array('text' => 'https://google.com/file.pdf', 'type' => ExternalLinkManager::TYPE_AUTO));
|
||||||
|
$this->assertSame($attachmentLinkProvider, $externalLinkManager->find());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testFindProviderWithSelectedType()
|
||||||
|
{
|
||||||
|
$externalLinkManager = new ExternalLinkManager($this->container);
|
||||||
|
$webLinkProvider = new WebLinkProvider($this->container);
|
||||||
|
$attachmentLinkProvider = new AttachmentLinkProvider($this->container);
|
||||||
|
|
||||||
|
$externalLinkManager->register($webLinkProvider);
|
||||||
|
$externalLinkManager->register($attachmentLinkProvider);
|
||||||
|
|
||||||
|
$externalLinkManager->setUserInput(array('text' => 'https://google.com/', 'type' => $webLinkProvider->getType()));
|
||||||
|
$this->assertSame($webLinkProvider, $externalLinkManager->find());
|
||||||
|
|
||||||
|
$externalLinkManager->setUserInput(array('text' => 'https://google.com/file.pdf', 'type' => $attachmentLinkProvider->getType()));
|
||||||
|
$this->assertSame($attachmentLinkProvider, $externalLinkManager->find());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testFindProviderWithSelectedTypeNotFound()
|
||||||
|
{
|
||||||
|
$externalLinkManager = new ExternalLinkManager($this->container);
|
||||||
|
$webLinkProvider = new WebLinkProvider($this->container);
|
||||||
|
$attachmentLinkProvider = new AttachmentLinkProvider($this->container);
|
||||||
|
|
||||||
|
$externalLinkManager->register($webLinkProvider);
|
||||||
|
$externalLinkManager->register($attachmentLinkProvider);
|
||||||
|
|
||||||
|
$this->setExpectedException('\Kanboard\Core\ExternalLink\ExternalLinkProviderNotFound');
|
||||||
|
$externalLinkManager->setUserInput(array('text' => 'https://google.com/', 'type' => 'not found'));
|
||||||
|
$externalLinkManager->find();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,64 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
require_once __DIR__.'/../Base.php';
|
||||||
|
|
||||||
|
use Kanboard\ExternalLink\AttachmentLinkProvider;
|
||||||
|
|
||||||
|
class AttachmentLinkProviderTest extends Base
|
||||||
|
{
|
||||||
|
public function testGetName()
|
||||||
|
{
|
||||||
|
$attachmentLinkProvider = new AttachmentLinkProvider($this->container);
|
||||||
|
$this->assertEquals('Attachment', $attachmentLinkProvider->getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGetType()
|
||||||
|
{
|
||||||
|
$attachmentLinkProvider = new AttachmentLinkProvider($this->container);
|
||||||
|
$this->assertEquals('attachment', $attachmentLinkProvider->getType());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGetDependencies()
|
||||||
|
{
|
||||||
|
$attachmentLinkProvider = new AttachmentLinkProvider($this->container);
|
||||||
|
$this->assertEquals(array('related' => 'Related'), $attachmentLinkProvider->getDependencies());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testMatch()
|
||||||
|
{
|
||||||
|
$attachmentLinkProvider = new AttachmentLinkProvider($this->container);
|
||||||
|
|
||||||
|
$attachmentLinkProvider->setUserTextInput('http://kanboard.net/FILE.DOC');
|
||||||
|
$this->assertTrue($attachmentLinkProvider->match());
|
||||||
|
|
||||||
|
$attachmentLinkProvider->setUserTextInput('http://kanboard.net/folder/document.PDF');
|
||||||
|
$this->assertTrue($attachmentLinkProvider->match());
|
||||||
|
|
||||||
|
$attachmentLinkProvider->setUserTextInput('http://kanboard.net/archive.zip');
|
||||||
|
$this->assertTrue($attachmentLinkProvider->match());
|
||||||
|
|
||||||
|
$attachmentLinkProvider->setUserTextInput(' https://kanboard.net/folder/archive.tar ');
|
||||||
|
$this->assertTrue($attachmentLinkProvider->match());
|
||||||
|
|
||||||
|
$attachmentLinkProvider->setUserTextInput('http:// invalid url');
|
||||||
|
$this->assertFalse($attachmentLinkProvider->match());
|
||||||
|
|
||||||
|
$attachmentLinkProvider->setUserTextInput('');
|
||||||
|
$this->assertFalse($attachmentLinkProvider->match());
|
||||||
|
|
||||||
|
$attachmentLinkProvider->setUserTextInput('http://kanboard.net/folder/document.html');
|
||||||
|
$this->assertFalse($attachmentLinkProvider->match());
|
||||||
|
|
||||||
|
$attachmentLinkProvider->setUserTextInput('http://kanboard.net/folder/DOC.HTML');
|
||||||
|
$this->assertFalse($attachmentLinkProvider->match());
|
||||||
|
|
||||||
|
$attachmentLinkProvider->setUserTextInput('http://kanboard.net/folder/document.do');
|
||||||
|
$this->assertFalse($attachmentLinkProvider->match());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGetLink()
|
||||||
|
{
|
||||||
|
$attachmentLinkProvider = new AttachmentLinkProvider($this->container);
|
||||||
|
$this->assertInstanceOf('\Kanboard\ExternalLink\AttachmentLink', $attachmentLinkProvider->getLink());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
require_once __DIR__.'/../Base.php';
|
||||||
|
|
||||||
|
use Kanboard\ExternalLink\AttachmentLink;
|
||||||
|
|
||||||
|
class AttachmentLinkTest extends Base
|
||||||
|
{
|
||||||
|
public function testGetTitleFromUrl()
|
||||||
|
{
|
||||||
|
$url = 'https://kanboard.net/folder/document.pdf';
|
||||||
|
|
||||||
|
$link = new AttachmentLink($this->container);
|
||||||
|
$link->setUrl($url);
|
||||||
|
$this->assertEquals($url, $link->getUrl());
|
||||||
|
$this->assertEquals('document.pdf', $link->getTitle());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,52 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
require_once __DIR__.'/../Base.php';
|
||||||
|
|
||||||
|
use Kanboard\ExternalLink\WebLinkProvider;
|
||||||
|
|
||||||
|
class WebLinkProviderTest extends Base
|
||||||
|
{
|
||||||
|
public function testGetName()
|
||||||
|
{
|
||||||
|
$webLinkProvider = new WebLinkProvider($this->container);
|
||||||
|
$this->assertEquals('Web Link', $webLinkProvider->getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGetType()
|
||||||
|
{
|
||||||
|
$webLinkProvider = new WebLinkProvider($this->container);
|
||||||
|
$this->assertEquals('weblink', $webLinkProvider->getType());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGetDependencies()
|
||||||
|
{
|
||||||
|
$webLinkProvider = new WebLinkProvider($this->container);
|
||||||
|
$this->assertEquals(array('related' => 'Related'), $webLinkProvider->getDependencies());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testMatch()
|
||||||
|
{
|
||||||
|
$webLinkProvider = new WebLinkProvider($this->container);
|
||||||
|
|
||||||
|
$webLinkProvider->setUserTextInput('http://kanboard.net/');
|
||||||
|
$this->assertTrue($webLinkProvider->match());
|
||||||
|
|
||||||
|
$webLinkProvider->setUserTextInput('http://kanboard.net/mypage');
|
||||||
|
$this->assertTrue($webLinkProvider->match());
|
||||||
|
|
||||||
|
$webLinkProvider->setUserTextInput(' https://kanboard.net/ ');
|
||||||
|
$this->assertTrue($webLinkProvider->match());
|
||||||
|
|
||||||
|
$webLinkProvider->setUserTextInput('http:// invalid url');
|
||||||
|
$this->assertFalse($webLinkProvider->match());
|
||||||
|
|
||||||
|
$webLinkProvider->setUserTextInput('');
|
||||||
|
$this->assertFalse($webLinkProvider->match());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGetLink()
|
||||||
|
{
|
||||||
|
$webLinkProvider = new WebLinkProvider($this->container);
|
||||||
|
$this->assertInstanceOf('\Kanboard\ExternalLink\WebLink', $webLinkProvider->getLink());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,57 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
require_once __DIR__.'/../Base.php';
|
||||||
|
|
||||||
|
use Kanboard\ExternalLink\WebLink;
|
||||||
|
|
||||||
|
class WebLinkTest extends Base
|
||||||
|
{
|
||||||
|
public function testGetTitleFromHtml()
|
||||||
|
{
|
||||||
|
$url = 'http://kanboard.net/something';
|
||||||
|
$title = 'My title';
|
||||||
|
$html = '<!DOCTYPE html><html><head><title> '.$title.' </title></head><body>Test</body></html>';
|
||||||
|
|
||||||
|
$this->container['httpClient'] = $this
|
||||||
|
->getMockBuilder('\Kanboard\Core\Http\Client')
|
||||||
|
->setConstructorArgs(array($this->container))
|
||||||
|
->setMethods(array('get'))
|
||||||
|
->getMock();
|
||||||
|
|
||||||
|
$webLink = new WebLink($this->container);
|
||||||
|
$webLink->setUrl($url);
|
||||||
|
$this->assertEquals($url, $webLink->getUrl());
|
||||||
|
|
||||||
|
$this->container['httpClient']
|
||||||
|
->expects($this->once())
|
||||||
|
->method('get')
|
||||||
|
->with($url)
|
||||||
|
->will($this->returnValue($html));
|
||||||
|
|
||||||
|
$this->assertEquals($title, $webLink->getTitle());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGetTitleFromUrl()
|
||||||
|
{
|
||||||
|
$url = 'http://kanboard.net/something';
|
||||||
|
$html = '<!DOCTYPE html><html><head></head><body>Test</body></html>';
|
||||||
|
|
||||||
|
$this->container['httpClient'] = $this
|
||||||
|
->getMockBuilder('\Kanboard\Core\Http\Client')
|
||||||
|
->setConstructorArgs(array($this->container))
|
||||||
|
->setMethods(array('get'))
|
||||||
|
->getMock();
|
||||||
|
|
||||||
|
$webLink = new WebLink($this->container);
|
||||||
|
$webLink->setUrl($url);
|
||||||
|
$this->assertEquals($url, $webLink->getUrl());
|
||||||
|
|
||||||
|
$this->container['httpClient']
|
||||||
|
->expects($this->once())
|
||||||
|
->method('get')
|
||||||
|
->with($url)
|
||||||
|
->will($this->returnValue($html));
|
||||||
|
|
||||||
|
$this->assertEquals('kanboard.net/something', $webLink->getTitle());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,167 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
require_once __DIR__.'/../Base.php';
|
||||||
|
|
||||||
|
use Kanboard\Model\TaskCreation;
|
||||||
|
use Kanboard\Model\Project;
|
||||||
|
use Kanboard\Model\TaskExternalLink;
|
||||||
|
use Kanboard\Core\ExternalLink\ExternalLinkManager;
|
||||||
|
use Kanboard\ExternalLink\WebLinkProvider;
|
||||||
|
|
||||||
|
class TaskExternalLinkTest extends Base
|
||||||
|
{
|
||||||
|
public function testCreate()
|
||||||
|
{
|
||||||
|
$projectModel = new Project($this->container);
|
||||||
|
$taskCreationModel = new TaskCreation($this->container);
|
||||||
|
$taskExternalLinkModel = new TaskExternalLink($this->container);
|
||||||
|
|
||||||
|
$this->assertEquals(1, $projectModel->create(array('name' => 'Test')));
|
||||||
|
$this->assertEquals(1, $taskCreationModel->create(array('title' => 'Test', 'project_id' => 1)));
|
||||||
|
$this->assertEquals(1, $taskExternalLinkModel->create(array('task_id' => 1, 'id' => '', 'url' => 'http://kanboard.net/', 'title' => 'My website', 'link_type' => 'weblink', 'dependency' => 'related')));
|
||||||
|
|
||||||
|
$link = $taskExternalLinkModel->getById(1);
|
||||||
|
$this->assertNotEmpty($link);
|
||||||
|
$this->assertEquals('My website', $link['title']);
|
||||||
|
$this->assertEquals('http://kanboard.net/', $link['url']);
|
||||||
|
$this->assertEquals('related', $link['dependency']);
|
||||||
|
$this->assertEquals('weblink', $link['link_type']);
|
||||||
|
$this->assertEquals(0, $link['creator_id']);
|
||||||
|
$this->assertEquals(time(), $link['date_modification'], '', 2);
|
||||||
|
$this->assertEquals(time(), $link['date_creation'], '', 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testCreateWithUserSession()
|
||||||
|
{
|
||||||
|
$this->container['sessionStorage']->user = array('id' => 1);
|
||||||
|
|
||||||
|
$projectModel = new Project($this->container);
|
||||||
|
$taskCreationModel = new TaskCreation($this->container);
|
||||||
|
$taskExternalLinkModel = new TaskExternalLink($this->container);
|
||||||
|
|
||||||
|
$this->assertEquals(1, $projectModel->create(array('name' => 'Test')));
|
||||||
|
$this->assertEquals(1, $taskCreationModel->create(array('title' => 'Test', 'project_id' => 1)));
|
||||||
|
$this->assertEquals(1, $taskExternalLinkModel->create(array('task_id' => 1, 'id' => '', 'url' => 'http://kanboard.net/', 'title' => 'My website', 'link_type' => 'weblink', 'dependency' => 'related')));
|
||||||
|
|
||||||
|
$link = $taskExternalLinkModel->getById(1);
|
||||||
|
$this->assertNotEmpty($link);
|
||||||
|
$this->assertEquals('My website', $link['title']);
|
||||||
|
$this->assertEquals('http://kanboard.net/', $link['url']);
|
||||||
|
$this->assertEquals('related', $link['dependency']);
|
||||||
|
$this->assertEquals('weblink', $link['link_type']);
|
||||||
|
$this->assertEquals(1, $link['creator_id']);
|
||||||
|
$this->assertEquals(time(), $link['date_modification'], '', 2);
|
||||||
|
$this->assertEquals(time(), $link['date_creation'], '', 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testCreateWithNoType()
|
||||||
|
{
|
||||||
|
$projectModel = new Project($this->container);
|
||||||
|
$taskCreationModel = new TaskCreation($this->container);
|
||||||
|
$taskExternalLinkModel = new TaskExternalLink($this->container);
|
||||||
|
|
||||||
|
$this->assertEquals(1, $projectModel->create(array('name' => 'Test')));
|
||||||
|
$this->assertEquals(1, $taskCreationModel->create(array('title' => 'Test', 'project_id' => 1)));
|
||||||
|
$this->assertFalse($taskExternalLinkModel->create(array('task_id' => 1, 'id' => '', 'url' => 'http://kanboard.net/', 'title' => 'My website', 'dependency' => 'related')));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testCreateWithNoDependency()
|
||||||
|
{
|
||||||
|
$projectModel = new Project($this->container);
|
||||||
|
$taskCreationModel = new TaskCreation($this->container);
|
||||||
|
$taskExternalLinkModel = new TaskExternalLink($this->container);
|
||||||
|
|
||||||
|
$this->assertEquals(1, $projectModel->create(array('name' => 'Test')));
|
||||||
|
$this->assertEquals(1, $taskCreationModel->create(array('title' => 'Test', 'project_id' => 1)));
|
||||||
|
$this->assertFalse($taskExternalLinkModel->create(array('task_id' => 1, 'id' => '', 'url' => 'http://kanboard.net/', 'title' => 'My website', 'link_type' => 'test')));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testCreateWithNoTitle()
|
||||||
|
{
|
||||||
|
$projectModel = new Project($this->container);
|
||||||
|
$taskCreationModel = new TaskCreation($this->container);
|
||||||
|
$taskExternalLinkModel = new TaskExternalLink($this->container);
|
||||||
|
|
||||||
|
$this->assertEquals(1, $projectModel->create(array('name' => 'Test')));
|
||||||
|
$this->assertEquals(1, $taskCreationModel->create(array('title' => 'Test', 'project_id' => 1)));
|
||||||
|
$this->assertFalse($taskExternalLinkModel->create(array('task_id' => 1, 'id' => '', 'url' => 'http://kanboard.net/', 'link_type' => 'test', 'dependency' => 'test')));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testCreateWithNoUrl()
|
||||||
|
{
|
||||||
|
$projectModel = new Project($this->container);
|
||||||
|
$taskCreationModel = new TaskCreation($this->container);
|
||||||
|
$taskExternalLinkModel = new TaskExternalLink($this->container);
|
||||||
|
|
||||||
|
$this->assertEquals(1, $projectModel->create(array('name' => 'Test')));
|
||||||
|
$this->assertEquals(1, $taskCreationModel->create(array('title' => 'Test', 'project_id' => 1)));
|
||||||
|
$this->assertFalse($taskExternalLinkModel->create(array('task_id' => 1, 'id' => '', 'title' => 'test', 'link_type' => 'test', 'dependency' => 'test')));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testModification()
|
||||||
|
{
|
||||||
|
$projectModel = new Project($this->container);
|
||||||
|
$taskCreationModel = new TaskCreation($this->container);
|
||||||
|
$taskExternalLinkModel = new TaskExternalLink($this->container);
|
||||||
|
|
||||||
|
$this->assertEquals(1, $projectModel->create(array('name' => 'Test')));
|
||||||
|
$this->assertEquals(1, $taskCreationModel->create(array('title' => 'Test', 'project_id' => 1)));
|
||||||
|
$this->assertEquals(1, $taskExternalLinkModel->create(array('task_id' => 1, 'id' => '', 'url' => 'http://kanboard.net/', 'title' => 'My website', 'link_type' => 'weblink', 'dependency' => 'related')));
|
||||||
|
|
||||||
|
sleep(1);
|
||||||
|
|
||||||
|
$this->assertTrue($taskExternalLinkModel->update(array('id' => 1, 'url' => 'https://kanboard.net/')));
|
||||||
|
|
||||||
|
$link = $taskExternalLinkModel->getById(1);
|
||||||
|
$this->assertNotEmpty($link);
|
||||||
|
$this->assertEquals('https://kanboard.net/', $link['url']);
|
||||||
|
$this->assertEquals(time(), $link['date_modification'], '', 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testRemove()
|
||||||
|
{
|
||||||
|
$projectModel = new Project($this->container);
|
||||||
|
$taskCreationModel = new TaskCreation($this->container);
|
||||||
|
$taskExternalLinkModel = new TaskExternalLink($this->container);
|
||||||
|
|
||||||
|
$this->assertEquals(1, $projectModel->create(array('name' => 'Test')));
|
||||||
|
$this->assertEquals(1, $taskCreationModel->create(array('title' => 'Test', 'project_id' => 1)));
|
||||||
|
$this->assertEquals(1, $taskExternalLinkModel->create(array('task_id' => 1, 'id' => '', 'url' => 'http://kanboard.net/', 'title' => 'My website', 'link_type' => 'weblink', 'dependency' => 'related')));
|
||||||
|
|
||||||
|
$this->assertTrue($taskExternalLinkModel->remove(1));
|
||||||
|
$this->assertFalse($taskExternalLinkModel->remove(1));
|
||||||
|
|
||||||
|
$this->assertEmpty($taskExternalLinkModel->getById(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGetAll()
|
||||||
|
{
|
||||||
|
$this->container['sessionStorage']->user = array('id' => 1);
|
||||||
|
$this->container['externalLinkManager'] = new ExternalLinkManager($this->container);
|
||||||
|
|
||||||
|
$projectModel = new Project($this->container);
|
||||||
|
$taskCreationModel = new TaskCreation($this->container);
|
||||||
|
$taskExternalLinkModel = new TaskExternalLink($this->container);
|
||||||
|
$webLinkProvider = new WebLinkProvider($this->container);
|
||||||
|
|
||||||
|
$this->container['externalLinkManager']->register($webLinkProvider);
|
||||||
|
|
||||||
|
$this->assertEquals(1, $projectModel->create(array('name' => 'Test')));
|
||||||
|
$this->assertEquals(1, $taskCreationModel->create(array('title' => 'Test', 'project_id' => 1)));
|
||||||
|
$this->assertEquals(1, $taskExternalLinkModel->create(array('task_id' => 1, 'url' => 'https://miniflux.net/', 'title' => 'MX', 'link_type' => 'weblink', 'dependency' => 'related')));
|
||||||
|
$this->assertEquals(2, $taskExternalLinkModel->create(array('task_id' => 1, 'url' => 'http://kanboard.net/', 'title' => 'KB', 'link_type' => 'weblink', 'dependency' => 'related')));
|
||||||
|
|
||||||
|
$links = $taskExternalLinkModel->getAll(1);
|
||||||
|
$this->assertCount(2, $links);
|
||||||
|
$this->assertEquals('KB', $links[0]['title']);
|
||||||
|
$this->assertEquals('MX', $links[1]['title']);
|
||||||
|
$this->assertEquals('Web Link', $links[0]['type']);
|
||||||
|
$this->assertEquals('Web Link', $links[1]['type']);
|
||||||
|
$this->assertEquals('Related', $links[0]['dependency_label']);
|
||||||
|
$this->assertEquals('Related', $links[1]['dependency_label']);
|
||||||
|
$this->assertEquals('admin', $links[0]['creator_username']);
|
||||||
|
$this->assertEquals('admin', $links[1]['creator_username']);
|
||||||
|
$this->assertEquals('', $links[0]['creator_name']);
|
||||||
|
$this->assertEquals('', $links[1]['creator_name']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,63 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
require_once __DIR__.'/../Base.php';
|
||||||
|
|
||||||
|
use Kanboard\Validator\ExternalLinkValidator;
|
||||||
|
|
||||||
|
class ExternalLinkValidatorTest extends Base
|
||||||
|
{
|
||||||
|
public function testValidateCreation()
|
||||||
|
{
|
||||||
|
$validator = new ExternalLinkValidator($this->container);
|
||||||
|
|
||||||
|
$result = $validator->validateCreation(array('url' => 'http://somewhere', 'task_id' => 1, 'title' => 'Title', 'link_type' => 'weblink', 'dependency' => 'related'));
|
||||||
|
$this->assertTrue($result[0]);
|
||||||
|
|
||||||
|
$result = $validator->validateCreation(array('url' => 'http://somewhere', 'task_id' => 'abc', 'title' => 'Title', 'link_type' => 'weblink', 'dependency' => 'related'));
|
||||||
|
$this->assertFalse($result[0]);
|
||||||
|
|
||||||
|
$result = $validator->validateCreation(array('url' => 'http://somewhere', 'task_id' => 1, 'title' => 'Title', 'link_type' => 'weblink'));
|
||||||
|
$this->assertFalse($result[0]);
|
||||||
|
|
||||||
|
$result = $validator->validateCreation(array('url' => 'http://somewhere', 'task_id' => 1, 'title' => 'Title', 'dependency' => 'related'));
|
||||||
|
$this->assertFalse($result[0]);
|
||||||
|
|
||||||
|
$result = $validator->validateCreation(array('url' => 'http://somewhere', 'task_id' => 1, 'link_type' => 'weblink', 'dependency' => 'related'));
|
||||||
|
$this->assertFalse($result[0]);
|
||||||
|
|
||||||
|
$result = $validator->validateCreation(array('url' => 'http://somewhere', 'title' => 'Title', 'link_type' => 'weblink', 'dependency' => 'related'));
|
||||||
|
$this->assertFalse($result[0]);
|
||||||
|
|
||||||
|
$result = $validator->validateCreation(array('task_id' => 1, 'title' => 'Title', 'link_type' => 'weblink', 'dependency' => 'related'));
|
||||||
|
$this->assertFalse($result[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testValidateModification()
|
||||||
|
{
|
||||||
|
$validator = new ExternalLinkValidator($this->container);
|
||||||
|
|
||||||
|
$result = $validator->validateModification(array('id' => 1, 'url' => 'http://somewhere', 'task_id' => 1, 'title' => 'Title', 'link_type' => 'weblink', 'dependency' => 'related'));
|
||||||
|
$this->assertTrue($result[0]);
|
||||||
|
|
||||||
|
$result = $validator->validateModification(array('id' => 1, 'url' => 'http://somewhere', 'task_id' => 'abc', 'title' => 'Title', 'link_type' => 'weblink', 'dependency' => 'related'));
|
||||||
|
$this->assertFalse($result[0]);
|
||||||
|
|
||||||
|
$result = $validator->validateModification(array('id' => 1, 'url' => 'http://somewhere', 'task_id' => 1, 'title' => 'Title', 'link_type' => 'weblink'));
|
||||||
|
$this->assertFalse($result[0]);
|
||||||
|
|
||||||
|
$result = $validator->validateModification(array('id' => 1, 'url' => 'http://somewhere', 'task_id' => 1, 'title' => 'Title', 'dependency' => 'related'));
|
||||||
|
$this->assertFalse($result[0]);
|
||||||
|
|
||||||
|
$result = $validator->validateModification(array('id' => 1, 'url' => 'http://somewhere', 'task_id' => 1, 'link_type' => 'weblink', 'dependency' => 'related'));
|
||||||
|
$this->assertFalse($result[0]);
|
||||||
|
|
||||||
|
$result = $validator->validateModification(array('id' => 1, 'url' => 'http://somewhere', 'title' => 'Title', 'link_type' => 'weblink', 'dependency' => 'related'));
|
||||||
|
$this->assertFalse($result[0]);
|
||||||
|
|
||||||
|
$result = $validator->validateModification(array('id' => 1, 'task_id' => 1, 'title' => 'Title', 'link_type' => 'weblink', 'dependency' => 'related'));
|
||||||
|
$this->assertFalse($result[0]);
|
||||||
|
|
||||||
|
$result = $validator->validateModification(array('url' => 'http://somewhere', 'task_id' => 1, 'title' => 'Title', 'link_type' => 'weblink', 'dependency' => 'related'));
|
||||||
|
$this->assertFalse($result[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue