summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorphecho <phecho@163.com>2016-12-21 10:58:41 +0800
committerphecho <phecho@163.com>2016-12-21 10:58:41 +0800
commit4724367e3b9c10af23bb6596f8f678477927c8c3 (patch)
tree06ee4e860252222c1784e182d87e22b879451751
parent56d00ac1592ba5ab7006dfd161f1893e1fdc9bb0 (diff)
parent9d5d389de841705450190fb1ebbaa11393870dfe (diff)
Fix conflict
-rw-r--r--ChangeLog2
-rw-r--r--app/Api/Procedure/BoardProcedure.php3
-rw-r--r--app/Controller/BoardAjaxController.php3
-rw-r--r--app/Controller/BoardViewController.php5
-rw-r--r--app/Controller/GroupAjaxController.php6
-rw-r--r--app/Controller/ICalendarController.php5
-rw-r--r--app/Controller/ProjectGanttController.php3
-rw-r--r--app/Controller/TaskAjaxController.php6
-rw-r--r--app/Controller/TaskGanttController.php3
-rw-r--r--app/Controller/TaskMovePositionController.php3
-rw-r--r--app/Controller/UserAjaxController.php10
-rw-r--r--app/Core/Base.php15
-rw-r--r--app/Core/ExternalTask/ExternalTaskManager.php7
-rw-r--r--app/Core/Filter/FormatterInterface.php2
-rw-r--r--app/Core/Tool.php25
-rw-r--r--app/Formatter/BoardColumnFormatter.php2
-rw-r--r--app/Formatter/BoardFormatter.php2
-rw-r--r--app/Formatter/BoardSwimlaneFormatter.php2
-rw-r--r--app/Formatter/GroupAutoCompleteFormatter.php22
-rw-r--r--app/Formatter/UserAutoCompleteFormatter.php6
-rw-r--r--app/Helper/CalendarHelper.php9
-rw-r--r--app/Helper/ICalHelper.php11
-rw-r--r--app/Helper/ProjectActivityHelper.php9
-rw-r--r--app/Locale/ru_RU/translations.php36
-rw-r--r--app/ServiceProvider/FormatterProvider.php48
-rw-r--r--app/common.php1
-rw-r--r--doc/plugin-overrides.markdown31
-rw-r--r--tests/units/Base.php1
-rw-r--r--tests/units/Core/ExternalTask/ExternalTaskManagerTest.php6
-rw-r--r--tests/units/ServiceProvider/ClassProviderTest.php21
-rw-r--r--tests/units/ServiceProvider/FormatterProviderTest.php21
31 files changed, 233 insertions, 93 deletions
diff --git a/ChangeLog b/ChangeLog
index 628a183c..648854a2 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -5,6 +5,7 @@ New features:
* Add slideshow for images
* Add API calls to manage tags
+* Offer the possibility to override internal formatter objects from plugins
Improvements:
@@ -16,6 +17,7 @@ Improvements:
Bug fixes:
+* Fix compatibility issue with PHP 5.3 for array_combine function
* Fix wrong controller name on project activity page when using filters
Version 1.0.35 (Dec 4, 2016)
diff --git a/app/Api/Procedure/BoardProcedure.php b/app/Api/Procedure/BoardProcedure.php
index 674b5466..69daaf09 100644
--- a/app/Api/Procedure/BoardProcedure.php
+++ b/app/Api/Procedure/BoardProcedure.php
@@ -3,7 +3,6 @@
namespace Kanboard\Api\Procedure;
use Kanboard\Api\Authorization\ProjectAuthorization;
-use Kanboard\Formatter\BoardFormatter;
/**
* Board API controller
@@ -17,7 +16,7 @@ class BoardProcedure extends BaseProcedure
{
ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'getBoard', $project_id);
- return BoardFormatter::getInstance($this->container)
+ return $this->boardFormatter
->withProjectId($project_id)
->withQuery($this->taskFinderModel->getExtendedQuery())
->format();
diff --git a/app/Controller/BoardAjaxController.php b/app/Controller/BoardAjaxController.php
index 484ef67d..ecb76e9c 100644
--- a/app/Controller/BoardAjaxController.php
+++ b/app/Controller/BoardAjaxController.php
@@ -3,7 +3,6 @@
namespace Kanboard\Controller;
use Kanboard\Core\Controller\AccessForbiddenException;
-use Kanboard\Formatter\BoardFormatter;
use Kanboard\Model\UserMetadataModel;
/**
@@ -139,7 +138,7 @@ class BoardAjaxController extends BaseController
'board_highlight_period' => $this->configModel->get('board_highlight_period'),
'swimlanes' => $this->taskLexer
->build($this->userSession->getFilters($project_id))
- ->format(BoardFormatter::getInstance($this->container)->withProjectId($project_id))
+ ->format($this->boardFormatter->withProjectId($project_id))
));
}
}
diff --git a/app/Controller/BoardViewController.php b/app/Controller/BoardViewController.php
index 10165908..9ef77e54 100644
--- a/app/Controller/BoardViewController.php
+++ b/app/Controller/BoardViewController.php
@@ -3,7 +3,6 @@
namespace Kanboard\Controller;
use Kanboard\Core\Controller\AccessForbiddenException;
-use Kanboard\Formatter\BoardFormatter;
use Kanboard\Model\TaskModel;
/**
@@ -35,7 +34,7 @@ class BoardViewController extends BaseController
$this->response->html($this->helper->layout->app('board/view_public', array(
'project' => $project,
- 'swimlanes' => BoardFormatter::getInstance($this->container)
+ 'swimlanes' => $this->boardFormatter
->withProjectId($project['id'])
->withQuery($query)
->format()
@@ -68,7 +67,7 @@ class BoardViewController extends BaseController
'board_highlight_period' => $this->configModel->get('board_highlight_period'),
'swimlanes' => $this->taskLexer
->build($search)
- ->format(BoardFormatter::getInstance($this->container)->withProjectId($project['id']))
+ ->format($this->boardFormatter->withProjectId($project['id']))
)));
}
}
diff --git a/app/Controller/GroupAjaxController.php b/app/Controller/GroupAjaxController.php
index 496e9ef2..308bba9e 100644
--- a/app/Controller/GroupAjaxController.php
+++ b/app/Controller/GroupAjaxController.php
@@ -2,8 +2,6 @@
namespace Kanboard\Controller;
-use Kanboard\Formatter\GroupAutoCompleteFormatter;
-
/**
* Group Ajax Controller
*
@@ -20,7 +18,7 @@ class GroupAjaxController extends BaseController
public function autocomplete()
{
$search = $this->request->getStringParam('term');
- $formatter = new GroupAutoCompleteFormatter($this->groupManager->find($search));
- $this->response->json($formatter->format());
+ $groups = $this->groupManager->find($search);
+ $this->response->json($this->groupAutoCompleteFormatter->withGroups($groups)->format());
}
}
diff --git a/app/Controller/ICalendarController.php b/app/Controller/ICalendarController.php
index e354c6f1..4fe8b78a 100644
--- a/app/Controller/ICalendarController.php
+++ b/app/Controller/ICalendarController.php
@@ -7,7 +7,6 @@ use Kanboard\Core\Filter\QueryBuilder;
use Kanboard\Filter\TaskAssigneeFilter;
use Kanboard\Filter\TaskProjectFilter;
use Kanboard\Filter\TaskStatusFilter;
-use Kanboard\Formatter\TaskICalFormatter;
use Kanboard\Model\TaskModel;
use Eluceo\iCal\Component\Calendar as iCalendar;
@@ -94,8 +93,6 @@ class ICalendarController extends BaseController
$end = $this->request->getStringParam('end', strtotime('+6 months'));
$this->helper->ical->addTaskDateDueEvents($queryBuilder, $calendar, $start, $end);
-
- $formatter = new TaskICalFormatter($this->container);
- $this->response->ical($formatter->setCalendar($calendar)->format());
+ $this->response->ical($this->taskICalFormatter->setCalendar($calendar)->format());
}
}
diff --git a/app/Controller/ProjectGanttController.php b/app/Controller/ProjectGanttController.php
index a70d9eee..8239005e 100644
--- a/app/Controller/ProjectGanttController.php
+++ b/app/Controller/ProjectGanttController.php
@@ -5,7 +5,6 @@ namespace Kanboard\Controller;
use Kanboard\Filter\ProjectIdsFilter;
use Kanboard\Filter\ProjectStatusFilter;
use Kanboard\Filter\ProjectTypeFilter;
-use Kanboard\Formatter\ProjectGanttFormatter;
use Kanboard\Model\ProjectModel;
/**
@@ -30,7 +29,7 @@ class ProjectGanttController extends BaseController
$filter->getQuery()->asc(ProjectModel::TABLE.'.start_date');
$this->response->html($this->helper->layout->app('project_gantt/show', array(
- 'projects' => $filter->format(new ProjectGanttFormatter($this->container)),
+ 'projects' => $filter->format($this->projectGanttFormatter),
'title' => t('Gantt chart for all projects'),
)));
}
diff --git a/app/Controller/TaskAjaxController.php b/app/Controller/TaskAjaxController.php
index 609dd23c..6d0b3fc2 100644
--- a/app/Controller/TaskAjaxController.php
+++ b/app/Controller/TaskAjaxController.php
@@ -8,8 +8,6 @@ use Kanboard\Filter\TaskProjectsFilter;
use Kanboard\Filter\TaskStartsWithIdFilter;
use Kanboard\Filter\TaskStatusFilter;
use Kanboard\Filter\TaskTitleFilter;
-use Kanboard\Formatter\TaskAutoCompleteFormatter;
-use Kanboard\Formatter\TaskSuggestMenuFormatter;
use Kanboard\Model\TaskModel;
/**
@@ -46,7 +44,7 @@ class TaskAjaxController extends BaseController
$filter->withFilter(new TaskTitleFilter($search));
}
- $this->response->json($filter->format(new TaskAutoCompleteFormatter($this->container)));
+ $this->response->json($filter->format($this->taskAutoCompleteFormatter));
}
}
@@ -66,7 +64,7 @@ class TaskAjaxController extends BaseController
->withFilter(new TaskStatusFilter(TaskModel::STATUS_OPEN))
->withFilter(new TaskStartsWithIdFilter($taskId));
- $this->response->json($filter->format(new TaskSuggestMenuFormatter($this->container)));
+ $this->response->json($filter->format($this->taskSuggestMenuFormatter));
}
}
}
diff --git a/app/Controller/TaskGanttController.php b/app/Controller/TaskGanttController.php
index 868368e1..b03b9d00 100644
--- a/app/Controller/TaskGanttController.php
+++ b/app/Controller/TaskGanttController.php
@@ -3,7 +3,6 @@
namespace Kanboard\Controller;
use Kanboard\Filter\TaskProjectFilter;
-use Kanboard\Formatter\TaskGanttFormatter;
use Kanboard\Model\TaskModel;
/**
@@ -35,7 +34,7 @@ class TaskGanttController extends BaseController
'title' => $project['name'],
'description' => $this->helper->projectHeader->getDescription($project),
'sorting' => $sorting,
- 'tasks' => $filter->format(new TaskGanttFormatter($this->container)),
+ 'tasks' => $filter->format($this->taskGanttFormatter),
)));
}
diff --git a/app/Controller/TaskMovePositionController.php b/app/Controller/TaskMovePositionController.php
index cb4afd04..caa074c9 100644
--- a/app/Controller/TaskMovePositionController.php
+++ b/app/Controller/TaskMovePositionController.php
@@ -3,7 +3,6 @@
namespace Kanboard\Controller;
use Kanboard\Core\Controller\AccessForbiddenException;
-use Kanboard\Formatter\BoardFormatter;
use Kanboard\Model\TaskModel;
/**
@@ -20,7 +19,7 @@ class TaskMovePositionController extends BaseController
$this->response->html($this->template->render('task_move_position/show', array(
'task' => $task,
- 'board' => BoardFormatter::getInstance($this->container)
+ 'board' => $this->boardFormatter
->withProjectId($task['project_id'])
->withQuery($this->taskFinderModel->getExtendedQuery()
->eq(TaskModel::TABLE.'.is_active', TaskModel::STATUS_OPEN)
diff --git a/app/Controller/UserAjaxController.php b/app/Controller/UserAjaxController.php
index d93bfe9a..17567a00 100644
--- a/app/Controller/UserAjaxController.php
+++ b/app/Controller/UserAjaxController.php
@@ -3,8 +3,6 @@
namespace Kanboard\Controller;
use Kanboard\Filter\UserNameFilter;
-use Kanboard\Formatter\UserAutoCompleteFormatter;
-use Kanboard\Formatter\UserMentionFormatter;
use Kanboard\Model\UserModel;
/**
@@ -25,7 +23,7 @@ class UserAjaxController extends BaseController
$search = $this->request->getStringParam('term');
$filter = $this->userQuery->withFilter(new UserNameFilter($search));
$filter->getQuery()->asc(UserModel::TABLE.'.name')->asc(UserModel::TABLE.'.username');
- $this->response->json($filter->format(new UserAutoCompleteFormatter($this->container)));
+ $this->response->json($filter->format($this->userAutoCompleteFormatter));
}
/**
@@ -39,11 +37,7 @@ class UserAjaxController extends BaseController
$query = $this->request->getStringParam('search');
$users = $this->projectPermissionModel->findUsernames($project_id, $query);
- $this->response->json(
- UserMentionFormatter::getInstance($this->container)
- ->withUsers($users)
- ->format()
- );
+ $this->response->json($this->userMentionFormatter->withUsers($users)->format());
}
/**
diff --git a/app/Core/Base.php b/app/Core/Base.php
index 881cccbd..d3c264d1 100644
--- a/app/Core/Base.php
+++ b/app/Core/Base.php
@@ -62,6 +62,21 @@ use Pimple\Container;
* @property \Kanboard\Decorator\ColumnRestrictionCacheDecorator $columnRestrictionCacheDecorator
* @property \Kanboard\Decorator\ColumnMoveRestrictionCacheDecorator $columnMoveRestrictionCacheDecorator
* @property \Kanboard\Decorator\ProjectRoleRestrictionCacheDecorator $projectRoleRestrictionCacheDecorator
+ * @property \Kanboard\Formatter\BoardColumnFormatter $boardColumnFormatter
+ * @property \Kanboard\Formatter\BoardFormatter $boardFormatter
+ * @property \Kanboard\Formatter\BoardSwimlaneFormatter $boardSwimlaneFormatter
+ * @property \Kanboard\Formatter\BoardTaskFormatter $boardTaskFormatter
+ * @property \Kanboard\Formatter\GroupAutoCompleteFormatter $groupAutoCompleteFormatter
+ * @property \Kanboard\Formatter\ProjectActivityEventFormatter $projectActivityEventFormatter
+ * @property \Kanboard\Formatter\ProjectGanttFormatter $projectGanttFormatter
+ * @property \Kanboard\Formatter\SubtaskTimeTrackingCalendarFormatter $subtaskTimeTrackingCalendarFormatter
+ * @property \Kanboard\Formatter\TaskAutoCompleteFormatter $taskAutoCompleteFormatter
+ * @property \Kanboard\Formatter\TaskCalendarFormatter $taskCalendarFormatter
+ * @property \Kanboard\Formatter\TaskGanttFormatter $taskGanttFormatter
+ * @property \Kanboard\Formatter\TaskICalFormatter $taskICalFormatter
+ * @property \Kanboard\Formatter\TaskSuggestMenuFormatter $taskSuggestMenuFormatter
+ * @property \Kanboard\Formatter\UserAutoCompleteFormatter $userAutoCompleteFormatter
+ * @property \Kanboard\Formatter\UserMentionFormatter $userMentionFormatter
* @property \Kanboard\Model\ActionModel $actionModel
* @property \Kanboard\Model\ActionParameterModel $actionParameterModel
* @property \Kanboard\Model\AvatarFileModel $avatarFileModel
diff --git a/app/Core/ExternalTask/ExternalTaskManager.php b/app/Core/ExternalTask/ExternalTaskManager.php
index 2ce6f106..102ec459 100644
--- a/app/Core/ExternalTask/ExternalTaskManager.php
+++ b/app/Core/ExternalTask/ExternalTaskManager.php
@@ -48,6 +48,11 @@ class ExternalTaskManager
public function getProvidersList()
{
$providers = array_keys($this->providers);
- return array_combine($providers, $providers);
+
+ if (count($providers)) {
+ return array_combine($providers, $providers);
+ }
+
+ return array();
}
}
diff --git a/app/Core/Filter/FormatterInterface.php b/app/Core/Filter/FormatterInterface.php
index b7c04c51..0ff84976 100644
--- a/app/Core/Filter/FormatterInterface.php
+++ b/app/Core/Filter/FormatterInterface.php
@@ -17,7 +17,7 @@ interface FormatterInterface
*
* @access public
* @param Table $query
- * @return FormatterInterface
+ * @return $this
*/
public function withQuery(Table $query);
diff --git a/app/Core/Tool.php b/app/Core/Tool.php
index 9b8820eb..6e457641 100644
--- a/app/Core/Tool.php
+++ b/app/Core/Tool.php
@@ -41,7 +41,7 @@ class Tool
}
/**
- * Build dependency injection container from an array
+ * Build dependency injection containers from an array
*
* @static
* @access public
@@ -64,6 +64,29 @@ class Tool
}
/**
+ * Build dependency injection container from an array
+ *
+ * @static
+ * @access public
+ * @param Container $container
+ * @param array $namespaces
+ * @return Container
+ */
+ public static function buildFactories(Container $container, array $namespaces)
+ {
+ foreach ($namespaces as $namespace => $classes) {
+ foreach ($classes as $name) {
+ $class = '\\Kanboard\\'.$namespace.'\\'.$name;
+ $container[lcfirst($name)] = $container->factory(function ($c) use ($class) {
+ return new $class($c);
+ });
+ }
+ }
+
+ return $container;
+ }
+
+ /**
* Build dependency injection container for custom helpers from an array
*
* @static
diff --git a/app/Formatter/BoardColumnFormatter.php b/app/Formatter/BoardColumnFormatter.php
index 85d31b5c..0d59f54e 100644
--- a/app/Formatter/BoardColumnFormatter.php
+++ b/app/Formatter/BoardColumnFormatter.php
@@ -79,7 +79,7 @@ class BoardColumnFormatter extends BaseFormatter implements FormatterInterface
{
foreach ($this->columns as &$column) {
$column['id'] = (int) $column['id'];
- $column['tasks'] = BoardTaskFormatter::getInstance($this->container)
+ $column['tasks'] = $this->boardTaskFormatter
->withTasks($this->tasks)
->withTags($this->tags)
->withSwimlaneId($this->swimlaneId)
diff --git a/app/Formatter/BoardFormatter.php b/app/Formatter/BoardFormatter.php
index df443a52..3f47bfa9 100644
--- a/app/Formatter/BoardFormatter.php
+++ b/app/Formatter/BoardFormatter.php
@@ -59,7 +59,7 @@ class BoardFormatter extends BaseFormatter implements FormatterInterface
$task_ids = array_column($tasks, 'id');
$tags = $this->taskTagModel->getTagsByTasks($task_ids);
- return BoardSwimlaneFormatter::getInstance($this->container)
+ return $this->boardSwimlaneFormatter
->withSwimlanes($swimlanes)
->withColumns($columns)
->withTasks($tasks)
diff --git a/app/Formatter/BoardSwimlaneFormatter.php b/app/Formatter/BoardSwimlaneFormatter.php
index ce67c8a8..18db259d 100644
--- a/app/Formatter/BoardSwimlaneFormatter.php
+++ b/app/Formatter/BoardSwimlaneFormatter.php
@@ -82,7 +82,7 @@ class BoardSwimlaneFormatter extends BaseFormatter implements FormatterInterface
foreach ($this->swimlanes as &$swimlane) {
$swimlane['id'] = (int) $swimlane['id'];
- $swimlane['columns'] = BoardColumnFormatter::getInstance($this->container)
+ $swimlane['columns'] = $this->boardColumnFormatter
->withSwimlaneId($swimlane['id'])
->withColumns($this->columns)
->withTasks($this->tasks)
diff --git a/app/Formatter/GroupAutoCompleteFormatter.php b/app/Formatter/GroupAutoCompleteFormatter.php
index 4d552886..d811de7f 100644
--- a/app/Formatter/GroupAutoCompleteFormatter.php
+++ b/app/Formatter/GroupAutoCompleteFormatter.php
@@ -12,36 +12,26 @@ use PicoDb\Table;
* @package formatter
* @author Frederic Guillot
*/
-class GroupAutoCompleteFormatter implements FormatterInterface
+class GroupAutoCompleteFormatter extends BaseFormatter implements FormatterInterface
{
/**
* Groups found
*
- * @access private
+ * @access protected
* @var GroupProviderInterface[]
*/
- private $groups;
+ protected $groups;
/**
- * Format groups for the ajax auto-completion
+ * Set groups
*
* @access public
* @param GroupProviderInterface[] $groups
+ * @return $this
*/
- public function __construct(array $groups)
+ public function withGroups(array $groups)
{
$this->groups = $groups;
- }
-
- /**
- * Set query
- *
- * @access public
- * @param Table $query
- * @return FormatterInterface
- */
- public function withQuery(Table $query)
- {
return $this;
}
diff --git a/app/Formatter/UserAutoCompleteFormatter.php b/app/Formatter/UserAutoCompleteFormatter.php
index cd23a2a4..c81af00a 100644
--- a/app/Formatter/UserAutoCompleteFormatter.php
+++ b/app/Formatter/UserAutoCompleteFormatter.php
@@ -14,7 +14,7 @@ use Kanboard\Core\Filter\FormatterInterface;
class UserAutoCompleteFormatter extends BaseFormatter implements FormatterInterface
{
/**
- * Format the tasks for the ajax autocompletion
+ * Format the tasks for the ajax auto-completion
*
* @access public
* @return array
@@ -24,11 +24,11 @@ class UserAutoCompleteFormatter extends BaseFormatter implements FormatterInterf
$users = $this->query->columns(UserModel::TABLE.'.id', UserModel::TABLE.'.username', UserModel::TABLE.'.name')->findAll();
foreach ($users as &$user) {
- $user['value'] = $user['username'].' (#'.$user['id'].')';
-
if (empty($user['name'])) {
+ $user['value'] = $user['username'].' (#'.$user['id'].')';
$user['label'] = $user['username'];
} else {
+ $user['value'] = $user['name'].' (#'.$user['id'].')';
$user['label'] = $user['name'].' ('.$user['username'].')';
}
}
diff --git a/app/Helper/CalendarHelper.php b/app/Helper/CalendarHelper.php
index 4f78b673..0942177d 100644
--- a/app/Helper/CalendarHelper.php
+++ b/app/Helper/CalendarHelper.php
@@ -5,8 +5,6 @@ namespace Kanboard\Helper;
use Kanboard\Core\Base;
use Kanboard\Core\Filter\QueryBuilder;
use Kanboard\Filter\TaskDueDateRangeFilter;
-use Kanboard\Formatter\SubtaskTimeTrackingCalendarFormatter;
-use Kanboard\Formatter\TaskCalendarFormatter;
/**
* Calendar Helper
@@ -44,7 +42,7 @@ class CalendarHelper extends Base
*/
public function getTaskDateDueEvents(QueryBuilder $queryBuilder, $start, $end)
{
- $formatter = new TaskCalendarFormatter($this->container);
+ $formatter = $this->taskCalendarFormatter;
$formatter->setFullDay();
$formatter->setColumns('date_due');
@@ -73,7 +71,7 @@ class CalendarHelper extends Base
'date_due'
));
- $formatter = new TaskCalendarFormatter($this->container);
+ $formatter = $this->taskCalendarFormatter;
$formatter->setColumns($startColumn, 'date_due');
return $queryBuilder->format($formatter);
@@ -90,8 +88,7 @@ class CalendarHelper extends Base
*/
public function getSubtaskTimeTrackingEvents($user_id, $start, $end)
{
- $formatter = new SubtaskTimeTrackingCalendarFormatter($this->container);
- return $formatter
+ return $this->subtaskTimeTrackingCalendarFormatter
->withQuery($this->subtaskTimeTrackingModel->getUserQuery($user_id)
->addCondition($this->getCalendarCondition(
$this->dateParser->getTimestampFromIsoFormat($start),
diff --git a/app/Helper/ICalHelper.php b/app/Helper/ICalHelper.php
index dc399bf8..95723417 100644
--- a/app/Helper/ICalHelper.php
+++ b/app/Helper/ICalHelper.php
@@ -5,7 +5,6 @@ namespace Kanboard\Helper;
use Kanboard\Core\Base;
use Kanboard\Core\Filter\QueryBuilder;
use Kanboard\Filter\TaskDueDateRangeFilter;
-use Kanboard\Formatter\TaskICalFormatter;
use Eluceo\iCal\Component\Calendar as iCalendar;
/**
@@ -29,10 +28,10 @@ class ICalHelper extends Base
{
$queryBuilder->withFilter(new TaskDueDateRangeFilter(array($start, $end)));
- $formatter = new TaskICalFormatter($this->container);
- $formatter->setColumns('date_due');
- $formatter->setCalendar($calendar);
- $formatter->withQuery($queryBuilder->getQuery());
- $formatter->addFullDayEvents();
+ $this->taskICalFormatter
+ ->setColumns('date_due')
+ ->setCalendar($calendar)
+ ->withQuery($queryBuilder->getQuery())
+ ->addFullDayEvents();
}
}
diff --git a/app/Helper/ProjectActivityHelper.php b/app/Helper/ProjectActivityHelper.php
index 704cd4fe..480db3d5 100644
--- a/app/Helper/ProjectActivityHelper.php
+++ b/app/Helper/ProjectActivityHelper.php
@@ -6,7 +6,6 @@ use Kanboard\Core\Base;
use Kanboard\Filter\ProjectActivityProjectIdFilter;
use Kanboard\Filter\ProjectActivityProjectIdsFilter;
use Kanboard\Filter\ProjectActivityTaskIdFilter;
-use Kanboard\Formatter\ProjectActivityEventFormatter;
use Kanboard\Model\ProjectActivityModel;
/**
@@ -38,7 +37,7 @@ class ProjectActivityHelper extends Base
->limit(500)
;
- $events = $queryBuilder->format(new ProjectActivityEventFormatter($this->container));
+ $events = $queryBuilder->format($this->projectActivityEventFormatter);
}
return $events;
@@ -62,7 +61,7 @@ class ProjectActivityHelper extends Base
->limit($limit)
;
- return $queryBuilder->format(new ProjectActivityEventFormatter($this->container));
+ return $queryBuilder->format($this->projectActivityEventFormatter);
}
/**
@@ -83,7 +82,7 @@ class ProjectActivityHelper extends Base
->limit($limit)
;
- return $queryBuilder->format(new ProjectActivityEventFormatter($this->container));
+ return $queryBuilder->format($this->projectActivityEventFormatter);
}
/**
@@ -100,6 +99,6 @@ class ProjectActivityHelper extends Base
$queryBuilder->getQuery()->desc(ProjectActivityModel::TABLE.'.id');
- return $queryBuilder->format(new ProjectActivityEventFormatter($this->container));
+ return $queryBuilder->format($this->projectActivityEventFormatter);
}
}
diff --git a/app/Locale/ru_RU/translations.php b/app/Locale/ru_RU/translations.php
index f55c595d..ffebcd6a 100644
--- a/app/Locale/ru_RU/translations.php
+++ b/app/Locale/ru_RU/translations.php
@@ -491,7 +491,7 @@ return array(
'All swimlanes' => 'Все дорожки',
'All colors' => 'Все цвета',
'Moved to column %s' => 'Перемещена в колонку %s',
- 'User dashboard' => 'Пользователь панели мониторинга',
+ 'User dashboard' => 'Панель управления',
'Allow only one subtask in progress at the same time for a user' => 'Разрешена только одна подзадача в разработке одновременно для одного пользователя',
'Edit column "%s"' => 'Редактировать колонку "%s"',
'Select the new status of the subtask: "%s"' => 'Выбрать новый статус для подзадачи: "%s"',
@@ -563,10 +563,10 @@ return array(
'EUR - Euro' => 'EUR - Евро',
'GBP - British Pound' => 'GBP - Британский фунт',
'INR - Indian Rupee' => 'INR - Индийский рупий',
- 'JPY - Japanese Yen' => 'JPY - Японскай йена',
+ 'JPY - Japanese Yen' => 'JPY - Японская йена',
'NZD - New Zealand Dollar' => 'NZD - Новозеландский доллар',
'RSD - Serbian dinar' => 'RSD - Сербский динар',
- // 'CNY - Chinese Yuan' => '',
+ 'CNY - Chinese Yuan' => 'CNY - Китайский юань',
'USD - US Dollar' => 'USD - доллар США',
'Destination column' => 'Колонка назначения',
'Move the task to another column when assigned to a user' => 'Переместить задачу в другую колонку, когда она назначена пользователю',
@@ -601,7 +601,7 @@ return array(
'Assign a color when the task is moved to a specific column' => 'Назначить цвет, когда задача перемещается в определенную колонку',
'%s via Kanboard' => '%s через Канборд',
'Burndown chart' => 'Диаграмма сгорания',
- 'This chart show the task complexity over the time (Work Remaining).' => 'Эта диаграмма показывают сложность задачи по времени (оставшейся работы).',
+ 'This chart show the task complexity over the time (Work Remaining).' => 'Эта диаграмма показывает сложность задачи по времени (оставшейся работы).',
'Screenshot taken %s' => 'Скриншот сделан %s',
'Add a screenshot' => 'Прикрепить картинку',
'Take a screenshot and press CTRL+V or ⌘+V to paste here.' => 'Сделайте скриншот и нажмите CTRL+V или ⌘+V для вложения',
@@ -951,13 +951,13 @@ return array(
'Estimated Time' => 'Запланировано времени',
'Actual Time' => 'Затрачено времени',
'Estimated vs actual time' => 'Запланировано и реально затрачено времени',
- 'RUB - Russian Ruble' => 'Руб - Российский рубль',
+ 'RUB - Russian Ruble' => 'РУБ - Российский рубль',
'Assign the task to the person who does the action when the column is changed' => 'Назначить задачу пользователю, который произвёл изменение в колонке',
'Close a task in a specific column' => 'Закрыть задачу в выбранной колонке',
'Time-based One-time Password Algorithm' => 'Зависимый от времени, одноразовый алгоритм пароля',
- 'Two-Factor Provider: ' => 'Провайдер двух-факторной авторизации: ',
- 'Disable two-factor authentication' => 'Отключить двух-факторную авторизацию',
- 'Enable two-factor authentication' => 'Включить двух-факторную авторизацию',
+ 'Two-Factor Provider: ' => 'Провайдер двухфакторной авторизации: ',
+ 'Disable two-factor authentication' => 'Отключить двухфакторную авторизацию',
+ 'Enable two-factor authentication' => 'Включить двухфакторную авторизацию',
'There is no integration registered at the moment.' => 'Интеграции в данный момент не зарегистрированы.',
'Password Reset for Kanboard' => 'Сброс пароля для Kanboard',
'Forgot password?' => 'Забыли пароль?',
@@ -1278,15 +1278,15 @@ return array(
'This field is required' => 'Заполните это поле',
'Moving a task is not permitted' => 'Перемещение задачи не разрешено',
'This value must be in the range %d to %d' => 'Значение должно находиться в диапазоне от %d до %d',
- // 'You are not allowed to move this task.' => '',
- // 'API User Access' => '',
- // 'Preview' => '',
- // 'Write' => '',
- // 'Write your text in Markdown' => '',
- // 'New External Task: %s' => '',
- // 'No personal API access token registered.' => '',
- // 'Your personal API access token is "%s"' => '',
- // 'Remove your token' => '',
- // 'Generate a new token' => '',
+ 'You are not allowed to move this task.' => 'Вам не разрешено перемещать эту задачу.',
+ 'API User Access' => 'Доступ к API',
+ 'Preview' => 'Предпросмотр',
+ 'Write' => 'Редактирование',
+ 'Write your text in Markdown' => 'Добавьте Ваше описание в формате Markdown',
+ 'New External Task: %s' => 'Новая внешняя задача: %s',
+ 'No personal API access token registered.' => 'Персональные токены доступа к API не созданы.',
+ 'Your personal API access token is "%s"' => 'Ваш персональный токен доступа к API: "%s"',
+ 'Remove your token' => 'Удалить токен',
+ 'Generate a new token' => 'Сгенерировать новый токен',
// 'Showing %d-%d of %d' => '',
);
diff --git a/app/ServiceProvider/FormatterProvider.php b/app/ServiceProvider/FormatterProvider.php
new file mode 100644
index 00000000..dbba3f3c
--- /dev/null
+++ b/app/ServiceProvider/FormatterProvider.php
@@ -0,0 +1,48 @@
+<?php
+
+namespace Kanboard\ServiceProvider;
+
+use Kanboard\Core\Tool;
+use Pimple\Container;
+use Pimple\ServiceProviderInterface;
+
+/**
+ * Class FormatterProvider
+ *
+ * @package Kanboard\ServiceProvider
+ * @author Frederic Guillot
+ */
+class FormatterProvider implements ServiceProviderInterface
+{
+ protected $formatters = array(
+ 'Formatter' => array(
+ 'BoardColumnFormatter',
+ 'BoardFormatter',
+ 'BoardSwimlaneFormatter',
+ 'BoardTaskFormatter',
+ 'GroupAutoCompleteFormatter',
+ 'ProjectActivityEventFormatter',
+ 'ProjectGanttFormatter',
+ 'SubtaskTimeTrackingCalendarFormatter',
+ 'TaskAutoCompleteFormatter',
+ 'TaskCalendarFormatter',
+ 'TaskGanttFormatter',
+ 'TaskICalFormatter',
+ 'TaskSuggestMenuFormatter',
+ 'UserAutoCompleteFormatter',
+ 'UserMentionFormatter',
+ )
+ );
+
+ /**
+ * Registers services on the given container.
+ *
+ * @param Container $container
+ * @return Container
+ */
+ public function register(Container $container)
+ {
+ Tool::buildFactories($container, $this->formatters);
+ return $container;
+ }
+}
diff --git a/app/common.php b/app/common.php
index 6ebb839e..fd55c0bb 100644
--- a/app/common.php
+++ b/app/common.php
@@ -48,6 +48,7 @@ $container->register(new Kanboard\ServiceProvider\ExternalLinkProvider());
$container->register(new Kanboard\ServiceProvider\ExternalTaskProvider());
$container->register(new Kanboard\ServiceProvider\AvatarProvider());
$container->register(new Kanboard\ServiceProvider\FilterProvider());
+$container->register(new Kanboard\ServiceProvider\FormatterProvider());
$container->register(new Kanboard\ServiceProvider\JobProvider());
$container->register(new Kanboard\ServiceProvider\QueueProvider());
$container->register(new Kanboard\ServiceProvider\ApiProvider());
diff --git a/doc/plugin-overrides.markdown b/doc/plugin-overrides.markdown
index 96a09e47..3b94bd60 100644
--- a/doc/plugin-overrides.markdown
+++ b/doc/plugin-overrides.markdown
@@ -40,3 +40,34 @@ You can still use the original template using the "kanboard:" prefix:
```php
<?= $this->render('kanboard:header') ?>
```
+
+Formatter Overrides
+-------------------
+
+Here an example to override formatter objects in Kanboard:
+
+```php
+class MyFormatter extends UserAutoCompleteFormatter
+{
+ public function format()
+ {
+ $users = parent::format();
+
+ foreach ($users as &$user) {
+ $user['label'] = 'something'; // Do something useful here
+ }
+
+ return $users;
+ }
+}
+
+class Plugin extends Base
+{
+ public function initialize()
+ {
+ $this->container['userAutoCompleteFormatter'] = $this->container->factory(function ($c) {
+ return new MyFormatter($c);
+ });
+ }
+}
+```
diff --git a/tests/units/Base.php b/tests/units/Base.php
index 1b986fcb..1c93e9b8 100644
--- a/tests/units/Base.php
+++ b/tests/units/Base.php
@@ -47,6 +47,7 @@ abstract class Base extends PHPUnit_Framework_TestCase
$this->container->register(new Kanboard\ServiceProvider\RouteProvider());
$this->container->register(new Kanboard\ServiceProvider\AvatarProvider());
$this->container->register(new Kanboard\ServiceProvider\FilterProvider());
+ $this->container->register(new Kanboard\ServiceProvider\FormatterProvider());
$this->container->register(new Kanboard\ServiceProvider\JobProvider());
$this->container->register(new Kanboard\ServiceProvider\QueueProvider());
$this->container->register(new Kanboard\ServiceProvider\ExternalTaskProvider());
diff --git a/tests/units/Core/ExternalTask/ExternalTaskManagerTest.php b/tests/units/Core/ExternalTask/ExternalTaskManagerTest.php
index e6f4e069..8eec64de 100644
--- a/tests/units/Core/ExternalTask/ExternalTaskManagerTest.php
+++ b/tests/units/Core/ExternalTask/ExternalTaskManagerTest.php
@@ -41,4 +41,10 @@ class ExternalTaskManagerTest extends Base
$expected = array('MyProvider1' => 'MyProvider1', 'MyProvider2' => 'MyProvider2');
$this->assertEquals($expected, $providers);
}
+
+ public function testGetProviderListWithNoProviders()
+ {
+ $manager = new ExternalTaskManager();
+ $this->assertSame(array(), $manager->getProvidersList());
+ }
}
diff --git a/tests/units/ServiceProvider/ClassProviderTest.php b/tests/units/ServiceProvider/ClassProviderTest.php
new file mode 100644
index 00000000..f6528918
--- /dev/null
+++ b/tests/units/ServiceProvider/ClassProviderTest.php
@@ -0,0 +1,21 @@
+<?php
+
+use Kanboard\ServiceProvider\ClassProvider;
+use Pimple\Container;
+
+require_once __DIR__.'/../Base.php';
+
+class ModelProviderTest extends Base
+{
+ public function testServiceInstance()
+ {
+ $container = new Container();
+ $serviceProvider = new ClassProvider($container);
+ $serviceProvider->register($container);
+
+ $instance1 = $container['userModel'];
+ $instance2 = $container['userModel'];
+
+ $this->assertSame($instance1, $instance2);
+ }
+}
diff --git a/tests/units/ServiceProvider/FormatterProviderTest.php b/tests/units/ServiceProvider/FormatterProviderTest.php
new file mode 100644
index 00000000..7984a12b
--- /dev/null
+++ b/tests/units/ServiceProvider/FormatterProviderTest.php
@@ -0,0 +1,21 @@
+<?php
+
+use Kanboard\ServiceProvider\FormatterProvider;
+use Pimple\Container;
+
+require_once __DIR__.'/../Base.php';
+
+class FormatterProviderTest extends Base
+{
+ public function testServiceInstance()
+ {
+ $container = new Container();
+ $serviceProvider = new FormatterProvider($container);
+ $serviceProvider->register($container);
+
+ $instance1 = $container['userAutoCompleteFormatter'];
+ $instance2 = $container['userAutoCompleteFormatter'];
+
+ $this->assertNotSame($instance1, $instance2);
+ }
+}