Helpers refactoring

This commit is contained in:
Frederic Guillot 2015-05-24 16:02:25 -04:00
parent 65e9e5d1be
commit eeac2329ba
239 changed files with 2441 additions and 2337 deletions

View File

@ -10,17 +10,8 @@ use Pimple\Container;
*
* @package action
* @author Frederic Guillot
*
* @property \Model\UserSession $userSession
* @property \Model\Comment $comment
* @property \Model\Task $task
* @property \Model\TaskCreation $taskCreation
* @property \Model\TaskModification $taskModification
* @property \Model\TaskDuplication $taskDuplication
* @property \Model\TaskFinder $taskFinder
* @property \Model\TaskStatus $taskStatus
*/
abstract class Base
abstract class Base extends \Core\Base
{
/**
* Flag for called listener
@ -135,18 +126,6 @@ abstract class Base
return get_called_class();
}
/**
* Load automatically models
*
* @access public
* @param string $name Model name
* @return mixed
*/
public function __get($name)
{
return $this->container[$name];
}
/**
* Set an user defined parameter
*

View File

@ -2,7 +2,6 @@
namespace Api;
use Pimple\Container;
use JsonRPC\AuthenticationFailure;
use Symfony\Component\EventDispatcher\Event;
@ -11,56 +10,9 @@ use Symfony\Component\EventDispatcher\Event;
*
* @package api
* @author Frederic Guillot
*
* @property \Model\Board $board
* @property \Model\Config $config
* @property \Model\Comment $comment
* @property \Model\LastLogin $lastLogin
* @property \Model\Notification $notification
* @property \Model\Project $project
* @property \Model\ProjectPermission $projectPermission
* @property \Model\ProjectActivity $projectActivity
* @property \Model\ProjectAnalytic $projectAnalytic
* @property \Model\ProjectDailySummary $projectDailySummary
* @property \Model\Subtask $subtask
* @property \Model\Task $task
* @property \Model\TaskDuplication $taskDuplication
* @property \Model\TaskExport $taskExport
* @property \Model\TaskFinder $taskFinder
*/
abstract class Base
abstract class Base extends \Core\Base
{
/**
* Container instance
*
* @access protected
* @var \Pimple\Container
*/
protected $container;
/**
* Constructor
*
* @access public
* @param \Pimple\Container $container
*/
public function __construct(Container $container)
{
$this->container = $container;
}
/**
* Load automatically models
*
* @access public
* @param string $name Model name
* @return mixed
*/
public function __get($name)
{
return $this->container[$name];
}
/**
* Check api credentials
*

View File

@ -9,14 +9,8 @@ use Pimple\Container;
*
* @package auth
* @author Frederic Guillot
*
* @property \Core\Session $session
* @property \Model\Acl $acl
* @property \Model\LastLogin $lastLogin
* @property \Model\User $user
* @property \Model\UserSession $userSession
*/
abstract class Base
abstract class Base extends \Core\Base
{
/**
* Database instance
@ -26,14 +20,6 @@ abstract class Base
*/
protected $db;
/**
* Container instance
*
* @access protected
* @var \Pimple\Container
*/
protected $container;
/**
* Constructor
*
@ -45,16 +31,4 @@ abstract class Base
$this->container = $container;
$this->db = $this->container['db'];
}
/**
* Load automatically models
*
* @access public
* @param string $name Model name
* @return mixed
*/
public function __get($name)
{
return $this->container[$name];
}
}

View File

@ -90,7 +90,7 @@ class App extends Base
$this->response->html('<p>'.t('Nothing to preview...').'</p>');
}
$this->response->html($this->template->markdown($payload['text']));
$this->response->html($this->helper->text->markdown($payload['text']));
}
/**

View File

@ -18,7 +18,7 @@ class Auth extends Base
public function login(array $values = array(), array $errors = array())
{
if ($this->userSession->isLogged()) {
$this->response->redirect($this->helper->url('app', 'index'));
$this->response->redirect($this->helper->url->to('app', 'index'));
}
$this->response->html($this->template->layout('auth/index', array(
@ -47,7 +47,7 @@ class Auth extends Base
$this->response->redirect('?'.urldecode($redirect_query));
}
$this->response->redirect($this->helper->url('app', 'index'));
$this->response->redirect($this->helper->url->to('app', 'index'));
}
$this->login($values, $errors);
@ -62,6 +62,6 @@ class Auth extends Base
{
$this->authentication->backend('rememberMe')->destroy($this->userSession->getId());
$this->session->close();
$this->response->redirect($this->helper->url('auth', 'login'));
$this->response->redirect($this->helper->url->to('auth', 'login'));
}
}

View File

@ -16,67 +16,8 @@ use Symfony\Component\EventDispatcher\Event;
*
* @package controller
* @author Frederic Guillot
*
* @property \Core\Helper $helper
* @property \Core\Session $session
* @property \Core\Template $template
* @property \Core\Paginator $paginator
* @property \Integration\GithubWebhook $githubWebhook
* @property \Integration\GitlabWebhook $gitlabWebhook
* @property \Integration\BitbucketWebhook $bitbucketWebhook
* @property \Integration\PostmarkWebhook $postmarkWebhook
* @property \Integration\SendgridWebhook $sendgridWebhook
* @property \Integration\MailgunWebhook $mailgunWebhook
* @property \Model\Acl $acl
* @property \Model\Authentication $authentication
* @property \Model\Action $action
* @property \Model\Board $board
* @property \Model\Category $category
* @property \Model\Color $color
* @property \Model\Comment $comment
* @property \Model\Config $config
* @property \Model\DateParser $dateParser
* @property \Model\File $file
* @property \Model\HourlyRate $hourlyRate
* @property \Model\LastLogin $lastLogin
* @property \Model\Notification $notification
* @property \Model\Project $project
* @property \Model\ProjectPermission $projectPermission
* @property \Model\ProjectDuplication $projectDuplication
* @property \Model\ProjectAnalytic $projectAnalytic
* @property \Model\ProjectActivity $projectActivity
* @property \Model\ProjectDailySummary $projectDailySummary
* @property \Model\ProjectIntegration $projectIntegration
* @property \Model\Subtask $subtask
* @property \Model\SubtaskForecast $subtaskForecast
* @property \Model\Swimlane $swimlane
* @property \Model\Task $task
* @property \Model\Link $link
* @property \Model\TaskCreation $taskCreation
* @property \Model\TaskModification $taskModification
* @property \Model\TaskDuplication $taskDuplication
* @property \Model\TaskHistory $taskHistory
* @property \Model\TaskExport $taskExport
* @property \Model\TaskFinder $taskFinder
* @property \Model\TaskFilter $taskFilter
* @property \Model\TaskPosition $taskPosition
* @property \Model\TaskPermission $taskPermission
* @property \Model\TaskStatus $taskStatus
* @property \Model\Timetable $timetable
* @property \Model\TimetableDay $timetableDay
* @property \Model\TimetableWeek $timetableWeek
* @property \Model\TimetableExtra $timetableExtra
* @property \Model\TimetableOff $timetableOff
* @property \Model\TaskValidator $taskValidator
* @property \Model\TaskLink $taskLink
* @property \Model\CommentHistory $commentHistory
* @property \Model\SubtaskHistory $subtaskHistory
* @property \Model\SubtaskTimeTracking $subtaskTimeTracking
* @property \Model\User $user
* @property \Model\UserSession $userSession
* @property \Model\Webhook $webhook
*/
abstract class Base
abstract class Base extends \Core\Base
{
/**
* Request instance
@ -94,14 +35,6 @@ abstract class Base
*/
protected $response;
/**
* Container instance
*
* @access private
* @var \Pimple\Container
*/
private $container;
/**
* Constructor
*
@ -133,18 +66,6 @@ abstract class Base
}
}
/**
* Load automatically models
*
* @access public
* @param string $name Model name
* @return mixed
*/
public function __get($name)
{
return $this->container[$name];
}
/**
* Send HTTP headers
*
@ -201,7 +122,7 @@ abstract class Base
$this->response->text('Not Authorized', 401);
}
$this->response->redirect($this->helper->url('auth', 'login', array('redirect_query' => urlencode($this->request->getQueryString()))));
$this->response->redirect($this->helper->url->to('auth', 'login', array('redirect_query' => urlencode($this->request->getQueryString()))));
}
}
@ -220,7 +141,7 @@ abstract class Base
$this->response->text('Not Authorized', 401);
}
$this->response->redirect($this->helper->url('twofactor', 'code'));
$this->response->redirect($this->helper->url->to('twofactor', 'code'));
}
}

View File

@ -295,7 +295,7 @@ class Board extends Base
$this->session->flashError(t('Unable to update your task.'));
}
$this->response->redirect($this->helper->url('board', 'show', array('project_id' => $values['project_id'])));
$this->response->redirect($this->helper->url->to('board', 'show', array('project_id' => $values['project_id'])));
}
/**
@ -333,7 +333,7 @@ class Board extends Base
$this->session->flashError(t('Unable to update your task.'));
}
$this->response->redirect($this->helper->url('board', 'show', array('project_id' => $values['project_id'])));
$this->response->redirect($this->helper->url->to('board', 'show', array('project_id' => $values['project_id'])));
}
/**

View File

@ -88,7 +88,7 @@ class Budget extends Base
if ($this->budget->create($values['project_id'], $values['amount'], $values['comment'], $values['date'])) {
$this->session->flash(t('The budget line have been created successfully.'));
$this->response->redirect($this->helper->url('budget', 'create', array('project_id' => $project['id'])));
$this->response->redirect($this->helper->url->to('budget', 'create', array('project_id' => $project['id'])));
}
else {
$this->session->flashError(t('Unable to create the budget line.'));
@ -130,6 +130,6 @@ class Budget extends Base
$this->session->flashError(t('Unable to remove this budget line.'));
}
$this->response->redirect($this->helper->url('budget', 'create', array('project_id' => $project['id'])));
$this->response->redirect($this->helper->url->to('budget', 'create', array('project_id' => $project['id'])));
}
}

View File

@ -57,7 +57,7 @@ class Column extends Base
if ($this->board->addColumn($project['id'], $data['title'], $data['task_limit'], $data['description'])) {
$this->session->flash(t('Board updated successfully.'));
$this->response->redirect($this->helper->url('column', 'index', array('project_id' => $project['id'])));
$this->response->redirect($this->helper->url->to('column', 'index', array('project_id' => $project['id'])));
}
else {
$this->session->flashError(t('Unable to update this board.'));
@ -102,7 +102,7 @@ class Column extends Base
if ($this->board->updateColumn($values['id'], $values['title'], $values['task_limit'], $values['description'])) {
$this->session->flash(t('Board updated successfully.'));
$this->response->redirect($this->helper->url('column', 'index', array('project_id' => $project['id'])));
$this->response->redirect($this->helper->url->to('column', 'index', array('project_id' => $project['id'])));
}
else {
$this->session->flashError(t('Unable to update this board.'));
@ -128,7 +128,7 @@ class Column extends Base
$this->board->{'move'.$direction}($project['id'], $column_id);
}
$this->response->redirect($this->helper->url('column', 'index', array('project_id' => $project['id'])));
$this->response->redirect($this->helper->url->to('column', 'index', array('project_id' => $project['id'])));
}
/**
@ -165,6 +165,6 @@ class Column extends Base
$this->session->flashError(t('Unable to remove this column.'));
}
$this->response->redirect($this->helper->url('column', 'index', array('project_id' => $project['id'])));
$this->response->redirect($this->helper->url->to('column', 'index', array('project_id' => $project['id'])));
}
}

View File

@ -57,7 +57,7 @@ class Currency extends Base
if ($this->currency->create($values['currency'], $values['rate'])) {
$this->session->flash(t('The currency rate have been added successfully.'));
$this->response->redirect($this->helper->url('currency', 'index'));
$this->response->redirect($this->helper->url->to('currency', 'index'));
}
else {
$this->session->flashError(t('Unable to add this currency rate.'));
@ -84,6 +84,6 @@ class Currency extends Base
$this->session->flashError(t('Unable to save your settings.'));
}
$this->response->redirect($this->helper->url('currency', 'index'));
$this->response->redirect($this->helper->url->to('currency', 'index'));
}
}

View File

@ -24,10 +24,10 @@ class File extends Base
$this->session->flash(t('Screenshot uploaded successfully.'));
if ($this->request->getStringParam('redirect') === 'board') {
$this->response->redirect($this->helper->url('board', 'show', array('project_id' => $task['project_id'])));
$this->response->redirect($this->helper->url->to('board', 'show', array('project_id' => $task['project_id'])));
}
$this->response->redirect($this->helper->url('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])));
$this->response->redirect($this->helper->url->to('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])));
}
$this->response->html($this->taskLayout('file/screenshot', array(
@ -64,7 +64,7 @@ class File extends Base
$this->session->flashError(t('Unable to upload the file.'));
}
$this->response->redirect($this->helper->url('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])));
$this->response->redirect($this->helper->url->to('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])));
}
/**
@ -83,7 +83,7 @@ class File extends Base
$this->response->binary(file_get_contents($filename));
}
$this->response->redirect($this->helper->url('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])));
$this->response->redirect($this->helper->url->to('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])));
}
/**
@ -164,7 +164,7 @@ class File extends Base
$this->session->flashError(t('Unable to remove this file.'));
}
$this->response->redirect($this->helper->url('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])));
$this->response->redirect($this->helper->url->to('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])));
}
/**

View File

@ -42,7 +42,7 @@ class Hourlyrate extends User
if ($this->hourlyRate->create($values['user_id'], $values['rate'], $values['currency'], $values['date_effective'])) {
$this->session->flash(t('Hourly rate created successfully.'));
$this->response->redirect($this->helper->url('hourlyrate', 'index', array('user_id' => $values['user_id'])));
$this->response->redirect($this->helper->url->to('hourlyrate', 'index', array('user_id' => $values['user_id'])));
}
else {
$this->session->flashError(t('Unable to save the hourly rate.'));
@ -84,6 +84,6 @@ class Hourlyrate extends User
$this->session->flash(t('Unable to remove this rate.'));
}
$this->response->redirect($this->helper->url('hourlyrate', 'index', array('user_id' => $user['id'])));
$this->response->redirect($this->helper->url->to('hourlyrate', 'index', array('user_id' => $user['id'])));
}
}

View File

@ -73,7 +73,7 @@ class Link extends Base
if ($this->link->create($values['label'], $values['opposite_label'])) {
$this->session->flash(t('Link added successfully.'));
$this->response->redirect($this->helper->url('link', 'index'));
$this->response->redirect($this->helper->url->to('link', 'index'));
}
else {
$this->session->flashError(t('Unable to create your link.'));
@ -115,7 +115,7 @@ class Link extends Base
if ($valid) {
if ($this->link->update($values)) {
$this->session->flash(t('Link updated successfully.'));
$this->response->redirect($this->helper->url('link', 'index'));
$this->response->redirect($this->helper->url->to('link', 'index'));
}
else {
$this->session->flashError(t('Unable to update your link.'));
@ -157,6 +157,6 @@ class Link extends Base
$this->session->flashError(t('Unable to remove this link.'));
}
$this->response->redirect($this->helper->url('link', 'index'));
$this->response->redirect($this->helper->url->to('link', 'index'));
}
}

View File

@ -252,11 +252,11 @@ class Subtask extends Base
{
switch ($redirect) {
case 'board':
$this->response->redirect($this->helper->url('board', 'show', array('project_id' => $task['project_id'])));
$this->response->redirect($this->helper->url->to('board', 'show', array('project_id' => $task['project_id'])));
case 'dashboard':
$this->response->redirect($this->helper->url('app', 'index'));
$this->response->redirect($this->helper->url->to('app', 'index'));
default:
$this->response->redirect($this->helper->url('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])));
$this->response->redirect($this->helper->url->to('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])));
}
}
@ -275,6 +275,6 @@ class Subtask extends Base
$method = $direction === 'up' ? 'moveUp' : 'moveDown';
$this->subtask->$method($task_id, $subtask_id);
$this->response->redirect($this->helper->url('task', 'show', array('project_id' => $project_id, 'task_id' => $task_id)).'#subtasks');
$this->response->redirect($this->helper->url->to('task', 'show', array('project_id' => $project_id, 'task_id' => $task_id)).'#subtasks');
}
}

View File

@ -288,10 +288,10 @@ class Task extends Base
}
if ($redirect === 'board') {
$this->response->redirect($this->helper->url('board', 'show', array('project_id' => $task['project_id'])));
$this->response->redirect($this->helper->url->to('board', 'show', array('project_id' => $task['project_id'])));
}
$this->response->redirect($this->helper->url('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])));
$this->response->redirect($this->helper->url->to('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])));
}
if ($this->request->isAjax()) {

View File

@ -77,10 +77,10 @@ class Tasklink extends Base
$this->session->flash(t('Link added successfully.'));
if ($ajax) {
$this->response->redirect($this->helper->url('board', 'show', array('project_id' => $task['project_id'])));
$this->response->redirect($this->helper->url->to('board', 'show', array('project_id' => $task['project_id'])));
}
$this->response->redirect($this->helper->url('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])).'#links');
$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')));
@ -132,7 +132,7 @@ class Tasklink extends Base
if ($this->taskLink->update($values['id'], $values['task_id'], $values['opposite_task_id'], $values['link_id'])) {
$this->session->flash(t('Link updated successfully.'));
$this->response->redirect($this->helper->url('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])).'#links');
$this->response->redirect($this->helper->url->to('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])).'#links');
}
$this->session->flashError(t('Unable to update your link.'));
@ -174,6 +174,6 @@ class Tasklink extends Base
$this->session->flashError(t('Unable to remove this link.'));
}
$this->response->redirect($this->helper->url('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])).'#links');
$this->response->redirect($this->helper->url->to('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])).'#links');
}
}

View File

@ -41,7 +41,7 @@ class Timetableday extends User
if ($this->timetableDay->create($values['user_id'], $values['start'], $values['end'])) {
$this->session->flash(t('Time slot created successfully.'));
$this->response->redirect($this->helper->url('timetableday', 'index', array('user_id' => $values['user_id'])));
$this->response->redirect($this->helper->url->to('timetableday', 'index', array('user_id' => $values['user_id'])));
}
else {
$this->session->flashError(t('Unable to save this time slot.'));
@ -83,6 +83,6 @@ class Timetableday extends User
$this->session->flash(t('Unable to remove this time slot.'));
}
$this->response->redirect($this->helper->url('timetableday', 'index', array('user_id' => $user['id'])));
$this->response->redirect($this->helper->url->to('timetableday', 'index', array('user_id' => $user['id'])));
}
}

View File

@ -60,7 +60,7 @@ class Timetableoff extends User
$values['comment'])) {
$this->session->flash(t('Time slot created successfully.'));
$this->response->redirect($this->helper->url($this->controller_url, 'index', array('user_id' => $values['user_id'])));
$this->response->redirect($this->helper->url->to($this->controller_url, 'index', array('user_id' => $values['user_id'])));
}
else {
$this->session->flashError(t('Unable to save this time slot.'));
@ -102,6 +102,6 @@ class Timetableoff extends User
$this->session->flash(t('Unable to remove this time slot.'));
}
$this->response->redirect($this->helper->url($this->controller_url, 'index', array('user_id' => $user['id'])));
$this->response->redirect($this->helper->url->to($this->controller_url, 'index', array('user_id' => $user['id'])));
}
}

View File

@ -52,7 +52,7 @@ class Timetableweek extends User
if ($this->timetableWeek->create($values['user_id'], $values['day'], $values['start'], $values['end'])) {
$this->session->flash(t('Time slot created successfully.'));
$this->response->redirect($this->helper->url('timetableweek', 'index', array('user_id' => $values['user_id'])));
$this->response->redirect($this->helper->url->to('timetableweek', 'index', array('user_id' => $values['user_id'])));
}
else {
$this->session->flashError(t('Unable to save this time slot.'));
@ -94,6 +94,6 @@ class Timetableweek extends User
$this->session->flash(t('Unable to remove this time slot.'));
}
$this->response->redirect($this->helper->url('timetableweek', 'index', array('user_id' => $user['id'])));
$this->response->redirect($this->helper->url->to('timetableweek', 'index', array('user_id' => $user['id'])));
}
}

View File

@ -76,7 +76,7 @@ class Twofactor extends User
$_SESSION['user']['twofactor_activated'] = false;
$this->session->flash(t('User updated successfully.'));
$this->response->redirect($this->helper->url('twofactor', 'index', array('user_id' => $user['id'])));
$this->response->redirect($this->helper->url->to('twofactor', 'index', array('user_id' => $user['id'])));
}
/**
@ -99,7 +99,7 @@ class Twofactor extends User
$this->session->flashError(t('The two factor authentication code is not valid.'));
}
$this->response->redirect($this->helper->url('twofactor', 'index', array('user_id' => $user['id'])));
$this->response->redirect($this->helper->url->to('twofactor', 'index', array('user_id' => $user['id'])));
}
/**
@ -118,11 +118,11 @@ class Twofactor extends User
if (! empty($values['code']) && $otp->checkTotp(Base32::decode($user['twofactor_secret']), $values['code'])) {
$this->session['2fa_validated'] = true;
$this->session->flash(t('The two factor authentication code is valid.'));
$this->response->redirect($this->helper->url('app', 'index'));
$this->response->redirect($this->helper->url->to('app', 'index'));
}
else {
$this->session->flashError(t('The two factor authentication code is not valid.'));
$this->response->redirect($this->helper->url('twofactor', 'code'));
$this->response->redirect($this->helper->url->to('twofactor', 'code'));
}
}
@ -157,7 +157,7 @@ class Twofactor extends User
'twofactor_secret' => '',
));
$this->response->redirect($this->helper->url('user', 'show', array('user_id' => $user['id'])));
$this->response->redirect($this->helper->url->to('user', 'show', array('user_id' => $user['id'])));
}
$this->response->html($this->layout('twofactor/disable', array(

View File

@ -268,7 +268,7 @@ class User extends Base
$this->session->flashError(t('Unable to update this user.'));
}
$this->response->redirect($this->helper->url('user', 'share', array('user_id' => $user['id'])));
$this->response->redirect($this->helper->url->to('user', 'share', array('user_id' => $user['id'])));
}
$this->response->html($this->layout('user/share', array(

View File

@ -96,7 +96,7 @@ class Webhook extends Base
$this->bitbucketWebhook->setProjectId($this->request->getIntegerParam('project_id'));
$result = $this->bitbucketWebhook->parsePayload(json_decode(@$_POST['payload'], true));
$result = $this->bitbucketWebhook->parsePayload(json_decode(@$_POST['payload'], true) ?: array());
echo $result ? 'PARSED' : 'IGNORED';
}

110
app/Core/Base.php Normal file
View File

@ -0,0 +1,110 @@
<?php
namespace Core;
use Pimple\Container;
/**
* Base class
*
* @package core
* @author Frederic Guillot
*
* @property \Core\Helper $helper
* @property \Core\HttpClient $httpClient
* @property \Core\Paginator $paginator
* @property \Core\Request $request
* @property \Core\Session $session
* @property \Core\Template $template
* @property \Integration\BitbucketWebhook $bitbucketWebhook
* @property \Integration\GithubWebhook $githubWebhook
* @property \Integration\GitlabWebhook $gitlabWebhook
* @property \Integration\HipchatWebhook $hipchatWebhook
* @property \Integration\Jabber $jabber
* @property \Integration\MailgunWebhook $mailgunWebhook
* @property \Integration\PostmarkWebhook $postmarkWebhook
* @property \Integration\SendgridWebhook $sendgridWebhook
* @property \Integration\SlackWebhook $slackWebhook
* @property \Model\Acl $acl
* @property \Model\Action $action
* @property \Model\Authentication $authentication
* @property \Model\Board $board
* @property \Model\Budget $budget
* @property \Model\Category $category
* @property \Model\Color $color
* @property \Model\Comment $comment
* @property \Model\Config $config
* @property \Model\Currency $currency
* @property \Model\DateParser $dateParser
* @property \Model\File $file
* @property \Model\HourlyRate $hourlyRate
* @property \Model\LastLogin $lastLogin
* @property \Model\Link $link
* @property \Model\Notification $notification
* @property \Model\Project $project
* @property \Model\ProjectActivity $projectActivity
* @property \Model\ProjectAnalytic $projectAnalytic
* @property \Model\ProjectDuplication $projectDuplication
* @property \Model\ProjectDailySummary $projectDailySummary
* @property \Model\ProjectIntegration $projectIntegration
* @property \Model\ProjectPermission $projectPermission
* @property \Model\Subtask $subtask
* @property \Model\SubtaskExport $subtaskExport
* @property \Model\SubtaskForecast $subtaskForecast
* @property \Model\SubtaskTimeTracking $subtaskTimeTracking
* @property \Model\Swimlane $swimlane
* @property \Model\Task $task
* @property \Model\TaskCreation $taskCreation
* @property \Model\TaskDuplication $taskDuplication
* @property \Model\TaskExport $taskExport
* @property \Model\TaskFinder $taskFinder
* @property \Model\TaskFilter $taskFilter
* @property \Model\TaskLink $taskLink
* @property \Model\TaskModification $taskModification
* @property \Model\TaskPermission $taskPermission
* @property \Model\TaskPosition $taskPosition
* @property \Model\TaskStatus $taskStatus
* @property \Model\TaskValidator $taskValidator
* @property \Model\Timetable $timetable
* @property \Model\TimetableDay $timetableDay
* @property \Model\TimetableExtra $timetableExtra
* @property \Model\TimetableOff $timetableOff
* @property \Model\TimetableWeek $timetableWeek
* @property \Model\Transition $transition
* @property \Model\User $user
* @property \Model\UserSession $userSession
* @property \Model\Webhook $webhook
*/
abstract class Base
{
/**
* Container instance
*
* @access protected
* @var \Pimple\Container
*/
protected $container;
/**
* Constructor
*
* @access public
* @param \Pimple\Container $container
*/
public function __construct(Container $container)
{
$this->container = $container;
}
/**
* Load automatically models
*
* @access public
* @param string $name Model name
* @return mixed
*/
public function __get($name)
{
return $this->container[$name];
}
}

View File

@ -1,41 +0,0 @@
<?php
namespace Core;
class FileCache extends Cache
{
const CACHE_FOLDER = 'data/cache/';
public function init()
{
if (! is_dir(self::CACHE_FOLDER)) {
mkdir(self::CACHE_FOLDER);
}
}
public function set($key, $value)
{
file_put_contents(self::CACHE_FOLDER.$key, json_encode($value));
}
public function get($key)
{
if (file_exists(self::CACHE_FOLDER.$key)) {
return json_decode(file_get_contents(self::CACHE_FOLDER.$key), true);
}
return null;
}
public function flush()
{
foreach (glob(self::CACHE_FOLDER.'*') as $filename) {
@unlink($filename);
}
}
public function remove($key)
{
@unlink(self::CACHE_FOLDER.$key);
}
}

View File

@ -2,105 +2,49 @@
namespace Core;
use Pimple\Container;
/**
* Template helpers
* Helper base class
*
* @package core
* @author Frederic Guillot
*
* @property \Core\Session $session
* @property \Model\Acl $acl
* @property \Model\Config $config
* @property \Model\User $user
* @property \Model\UserSession $userSession
* @property \Helper\App $app
* @property \Helper\Asset $asset
* @property \Helper\Datetime $datetime
* @property \Helper\File $file
* @property \Helper\Form $form
* @property \Helper\Subtask $subtask
* @property \Helper\Task $task
* @property \Helper\Text $text
* @property \Helper\Url $url
* @property \Helper\User $user
*/
class Helper
class Helper extends Base
{
/**
* Container instance
* Helper instances
*
* @access protected
* @var \Pimple\Container
* @static
* @access private
* @var array
*/
protected $container;
private static $helpers = array();
/**
* Constructor
* Load automatically helpers
*
* @access public
* @param \Pimple\Container $container
*/
public function __construct(Container $container)
{
$this->container = $container;
}
/**
* Load automatically models
*
* @access public
* @param string $name Model name
* @param string $name Helper name
* @return mixed
*/
public function __get($name)
{
return $this->container[$name];
}
/**
* Get the age of an item in quasi human readable format.
* It's in this format: <1h , NNh, NNd
*
* @access public
* @param integer $timestamp Unix timestamp of the artifact for which age will be calculated
* @param integer $now Compare with this timestamp (Default value is the current unix timestamp)
* @return string
*/
public function getTaskAge($timestamp, $now = null)
{
if ($now === null) {
$now = time();
if (! isset(self::$helpers[$name])) {
$class = '\Helper\\'.ucfirst($name);
self::$helpers[$name] = new $class($this->container);
}
$diff = $now - $timestamp;
if ($diff < 3600) {
return t('<1h');
}
else if ($diff < 86400) {
return t('%dh', $diff / 3600);
}
return t('%dd', ($now - $timestamp) / 86400);
}
/**
* Proxy cache helper for acl::isManagerActionAllowed()
*
* @access public
* @param integer $project_id
* @return boolean
*/
public function isManager($project_id)
{
if ($this->userSession->isAdmin()) {
return true;
}
return $this->container['memoryCache']->proxy('acl', 'isManagerActionAllowed', $project_id);
}
/**
* Return the user full name
*
* @param array $user User properties
* @return string
*/
public function getFullname(array $user = array())
{
return $this->user->getFullname(empty($user) ? $_SESSION['user'] : $user);
return self::$helpers[$name];
}
/**
@ -113,688 +57,4 @@ class Helper
{
return htmlspecialchars($value, ENT_QUOTES, 'UTF-8', false);
}
/**
* Add a Javascript asset
*
* @param string $filename Filename
* @return string
*/
public function js($filename)
{
return '<script type="text/javascript" src="'.$filename.'?'.filemtime($filename).'"></script>';
}
/**
* Add a stylesheet asset
*
* @param string $filename Filename
* @param boolean $is_file Add file timestamp
* @param string $media Media
* @return string
*/
public function css($filename, $is_file = true, $media = 'screen')
{
return '<link rel="stylesheet" href="'.$filename.($is_file ? '?'.filemtime($filename) : '').'" media="'.$media.'">';
}
/**
* Display the form error class
*
* @param array $errors Error list
* @param string $name Field name
* @return string
*/
public function errorClass(array $errors, $name)
{
return ! isset($errors[$name]) ? '' : ' form-error';
}
/**
* Display a list of form errors
*
* @param array $errors List of errors
* @param string $name Field name
* @return string
*/
public function errorList(array $errors, $name)
{
$html = '';
if (isset($errors[$name])) {
$html .= '<ul class="form-errors">';
foreach ($errors[$name] as $error) {
$html .= '<li>'.$this->e($error).'</li>';
}
$html .= '</ul>';
}
return $html;
}
/**
* Get an escaped form value
*
* @param mixed $values Values
* @param string $name Field name
* @return string
*/
public function formValue($values, $name)
{
if (isset($values->$name)) {
return 'value="'.$this->e($values->$name).'"';
}
return isset($values[$name]) ? 'value="'.$this->e($values[$name]).'"' : '';
}
/**
* Hidden CSRF token field
*
* @return string
*/
public function formCsrf()
{
return '<input type="hidden" name="csrf_token" value="'.Security::getCSRFToken().'"/>';
}
/**
* Display a hidden form field
*
* @param string $name Field name
* @param array $values Form values
* @return string
*/
public function formHidden($name, array $values = array())
{
return '<input type="hidden" name="'.$name.'" id="form-'.$name.'" '.$this->formValue($values, $name).'/>';
}
/**
* Display a select field
*
* @param string $name Field name
* @param array $options Options
* @param array $values Form values
* @param array $errors Form errors
* @param string $class CSS class
* @return string
*/
public function formSelect($name, array $options, array $values = array(), array $errors = array(), array $attributes = array(), $class = '')
{
$html = '<select name="'.$name.'" id="form-'.$name.'" class="'.$class.'" '.implode(' ', $attributes).'>';
foreach ($options as $id => $value) {
$html .= '<option value="'.$this->e($id).'"';
if (isset($values->$name) && $id == $values->$name) $html .= ' selected="selected"';
if (isset($values[$name]) && $id == $values[$name]) $html .= ' selected="selected"';
$html .= '>'.$this->e($value).'</option>';
}
$html .= '</select>';
$html .= $this->errorList($errors, $name);
return $html;
}
/**
* Display a radio field group
*
* @param string $name Field name
* @param array $options Options
* @param array $values Form values
* @return string
*/
public function formRadios($name, array $options, array $values = array())
{
$html = '';
foreach ($options as $value => $label) {
$html .= $this->formRadio($name, $label, $value, isset($values[$name]) && $values[$name] == $value);
}
return $html;
}
/**
* Display a radio field
*
* @param string $name Field name
* @param string $label Form label
* @param string $value Form value
* @param boolean $selected Field selected or not
* @param string $class CSS class
* @return string
*/
public function formRadio($name, $label, $value, $selected = false, $class = '')
{
return '<label><input type="radio" name="'.$name.'" class="'.$class.'" value="'.$this->e($value).'" '.($selected ? 'checked="checked"' : '').'> '.$this->e($label).'</label>';
}
/**
* Display a checkbox field
*
* @param string $name Field name
* @param string $label Form label
* @param string $value Form value
* @param boolean $checked Field selected or not
* @param string $class CSS class
* @return string
*/
public function formCheckbox($name, $label, $value, $checked = false, $class = '')
{
return '<label><input type="checkbox" name="'.$name.'" class="'.$class.'" value="'.$this->e($value).'" '.($checked ? 'checked="checked"' : '').'>&nbsp;'.$this->e($label).'</label>';
}
/**
* Display a form label
*
* @param string $name Field name
* @param string $label Form label
* @param array $attributes HTML attributes
* @return string
*/
public function formLabel($label, $name, array $attributes = array())
{
return '<label for="form-'.$name.'" '.implode(' ', $attributes).'>'.$this->e($label).'</label>';
}
/**
* Display a textarea
*
* @param string $name Field name
* @param array $values Form values
* @param array $errors Form errors
* @param array $attributes HTML attributes
* @param string $class CSS class
* @return string
*/
public function formTextarea($name, $values = array(), array $errors = array(), array $attributes = array(), $class = '')
{
$class .= $this->errorClass($errors, $name);
$html = '<textarea name="'.$name.'" id="form-'.$name.'" class="'.$class.'" ';
$html .= implode(' ', $attributes).'>';
$html .= isset($values->$name) ? $this->e($values->$name) : isset($values[$name]) ? $values[$name] : '';
$html .= '</textarea>';
$html .= $this->errorList($errors, $name);
return $html;
}
/**
* Display a input field
*
* @param string $type HMTL input tag type
* @param string $name Field name
* @param array $values Form values
* @param array $errors Form errors
* @param array $attributes HTML attributes
* @param string $class CSS class
* @return string
*/
public function formInput($type, $name, $values = array(), array $errors = array(), array $attributes = array(), $class = '')
{
$class .= $this->errorClass($errors, $name);
$html = '<input type="'.$type.'" name="'.$name.'" id="form-'.$name.'" '.$this->formValue($values, $name).' class="'.$class.'" ';
$html .= implode(' ', $attributes).'/>';
if (in_array('required', $attributes)) $html .= '<span class="form-required">*</span>';
$html .= $this->errorList($errors, $name);
return $html;
}
/**
* Display a text field
*
* @param string $name Field name
* @param array $values Form values
* @param array $errors Form errors
* @param array $attributes HTML attributes
* @param string $class CSS class
* @return string
*/
public function formText($name, $values = array(), array $errors = array(), array $attributes = array(), $class = '')
{
return $this->formInput('text', $name, $values, $errors, $attributes, $class);
}
/**
* Display a password field
*
* @param string $name Field name
* @param array $values Form values
* @param array $errors Form errors
* @param array $attributes HTML attributes
* @param string $class CSS class
* @return string
*/
public function formPassword($name, $values = array(), array $errors = array(), array $attributes = array(), $class = '')
{
return $this->formInput('password', $name, $values, $errors, $attributes, $class);
}
/**
* Display an email field
*
* @param string $name Field name
* @param array $values Form values
* @param array $errors Form errors
* @param array $attributes HTML attributes
* @param string $class CSS class
* @return string
*/
public function formEmail($name, $values = array(), array $errors = array(), array $attributes = array(), $class = '')
{
return $this->formInput('email', $name, $values, $errors, $attributes, $class);
}
/**
* Display a number field
*
* @param string $name Field name
* @param array $values Form values
* @param array $errors Form errors
* @param array $attributes HTML attributes
* @param string $class CSS class
* @return string
*/
public function formNumber($name, $values = array(), array $errors = array(), array $attributes = array(), $class = '')
{
return $this->formInput('number', $name, $values, $errors, $attributes, $class);
}
/**
* Display a numeric field (allow decimal number)
*
* @param string $name Field name
* @param array $values Form values
* @param array $errors Form errors
* @param array $attributes HTML attributes
* @param string $class CSS class
* @return string
*/
public function formNumeric($name, $values = array(), array $errors = array(), array $attributes = array(), $class = '')
{
return $this->formInput('text', $name, $values, $errors, $attributes, $class.' form-numeric');
}
/**
* Link
*
* a('link', 'task', 'show', array('task_id' => $task_id))
*
* @param string $label Link label
* @param string $controller Controller name
* @param string $action Action name
* @param array $params Url parameters
* @param boolean $csrf Add a CSRF token
* @param string $class CSS class attribute
* @param boolean $new_tab Open the link in a new tab
* @return string
*/
public function a($label, $controller, $action, array $params = array(), $csrf = false, $class = '', $title = '', $new_tab = false)
{
return '<a href="'.$this->u($controller, $action, $params, $csrf).'" class="'.$class.'" title="'.$title.'" '.($new_tab ? 'target="_blank"' : '').'>'.$label.'</a>';
}
/**
* Generate controller/action url for templates
*
* u('task', 'show', array('task_id' => $task_id))
*
* @param string $controller Controller name
* @param string $action Action name
* @param array $params Url parameters
* @param boolean $csrf Add a CSRF token
* @return string
*/
public function u($controller, $action, array $params = array(), $csrf = false)
{
$values = array(
'controller' => $controller,
'action' => $action,
);
if ($csrf) {
$params['csrf_token'] = Security::getCSRFToken();
}
$values += $params;
return '?'.http_build_query($values, '', '&amp;');
}
/**
* Generate controller/action url
*
* l('task', 'show', array('task_id' => $task_id))
*
* @param string $controller Controller name
* @param string $action Action name
* @param array $params Url parameters
* @return string
*/
public function url($controller, $action, array $params = array())
{
$values = array(
'controller' => $controller,
'action' => $action,
);
$values += $params;
return '?'.http_build_query($values);
}
/**
* Markdown transformation
*
* @param string $text Markdown content
* @param array $link Link parameters for replacement
* @return string
*/
public function markdown($text, array $link = array())
{
$parser = new Markdown($link, $this);
$parser->setMarkupEscaped(MARKDOWN_ESCAPE_HTML);
return $parser->text($text);
}
/**
* Get the current URL without the querystring
*
* @return string
*/
public function getCurrentBaseUrl()
{
$application_url = $this->config->get('application_url');
if (! empty($application_url)) {
return $application_url;
}
$self = str_replace('\\', '/', dirname($_SERVER['PHP_SELF']));
$url = Request::isHTTPS() ? 'https://' : 'http://';
$url .= $_SERVER['SERVER_NAME'];
$url .= $_SERVER['SERVER_PORT'] == 80 || $_SERVER['SERVER_PORT'] == 443 ? '' : ':'.$_SERVER['SERVER_PORT'];
$url .= $self !== '/' ? $self.'/' : '/';
return $url;
}
/**
* Dispplay the flash session message
*
* @param string $html HTML wrapper
* @return string
*/
public function flash($html)
{
return $this->flashMessage('flash_message', $html);
}
/**
* Display the flash session error message
*
* @param string $html HTML wrapper
* @return string
*/
public function flashError($html)
{
return $this->flashMessage('flash_error_message', $html);
}
/**
* Fetch and remove a flash session message
*
* @access private
* @param string $name Message name
* @param string $html HTML wrapper
* @return string
*/
private function flashMessage($name, $html)
{
$data = '';
if (isset($this->session[$name])) {
$data = sprintf($html, $this->e($this->session[$name]));
unset($this->session[$name]);
}
return $data;
}
/**
* Format a file size
*
* @param integer $size Size in bytes
* @param integer $precision Precision
* @return string
*/
public function formatBytes($size, $precision = 2)
{
$base = log($size) / log(1024);
$suffixes = array('', 'k', 'M', 'G', 'T');
return round(pow(1024, $base - floor($base)), $precision).$suffixes[(int)floor($base)];
}
/**
* Truncate a long text
*
* @param string $value Text
* @param integer $max_length Max Length
* @param string $end Text end
* @return string
*/
public function summary($value, $max_length = 85, $end = '[...]')
{
$length = strlen($value);
if ($length > $max_length) {
return substr($value, 0, $max_length).' '.$end;
}
return $value;
}
/**
* Return true if needle is contained in the haystack
*
* @param string $haystack Haystack
* @param string $needle Needle
* @return boolean
*/
public function contains($haystack, $needle)
{
return strpos($haystack, $needle) !== false;
}
/**
* Return a value from a dictionary
*
* @param mixed $id Key
* @param array $listing Dictionary
* @param string $default_value Value displayed when the key doesn't exists
* @return string
*/
public function inList($id, array $listing, $default_value = '?')
{
if (isset($listing[$id])) {
return $this->e($listing[$id]);
}
return $default_value;
}
/**
* Get javascript language code
*
* @access public
* @return string
*/
public function jsLang()
{
return $this->config->getJsLanguageCode();
}
/**
* Get current timezone
*
* @access public
* @return string
*/
public function getTimezone()
{
return $this->config->getCurrentTimezone();
}
/**
* Get the link to toggle subtask status
*
* @access public
* @param array $subtask
* @param string $redirect
* @return string
*/
public function toggleSubtaskStatus(array $subtask, $redirect)
{
if ($subtask['status'] == 0 && isset($this->session['has_subtask_inprogress']) && $this->session['has_subtask_inprogress'] === true) {
return $this->a(
trim($this->render('subtask/icons', array('subtask' => $subtask))) . $this->e($subtask['title']),
'subtask',
'subtaskRestriction',
array('task_id' => $subtask['task_id'], 'subtask_id' => $subtask['id'], 'redirect' => $redirect),
false,
'popover task-board-popover'
);
}
return $this->a(
trim($this->render('subtask/icons', array('subtask' => $subtask))) . $this->e($subtask['title']),
'subtask',
'toggleStatus',
array('task_id' => $subtask['task_id'], 'subtask_id' => $subtask['id'], 'redirect' => $redirect)
);
}
/**
* Get all hours for day
*
* @access public
* @return array
*/
public function getDayHours()
{
$values = array();
foreach (range(0, 23) as $hour) {
foreach (array(0, 30) as $minute) {
$time = sprintf('%02d:%02d', $hour, $minute);
$values[$time] = $time;
}
}
return $values;
}
/**
* Get all days of a week
*
* @access public
* @return array
*/
public function getWeekDays()
{
$values = array();
foreach (range(1, 7) as $day) {
$values[$day] = $this->getWeekDay($day);
}
return $values;
}
/**
* Get the localized day name from the day number
*
* @access public
* @param integer $day Day number
* @return string
*/
public function getWeekDay($day)
{
return dt('%A', strtotime('next Monday +'.($day - 1).' days'));
}
/**
* Get file icon
*
* @access public
* @param string $filename Filename
* @return string Font-Awesome-Icon-Name
*/
public function getFileIcon($filename){
$extension = strtolower(pathinfo($filename, PATHINFO_EXTENSION));
switch ($extension) {
case 'jpeg':
case 'jpg':
case 'png':
case 'gif':
return 'fa-file-image-o';
case 'xls':
case 'xlsx':
return 'fa-file-excel-o';
case 'doc':
case 'docx':
return 'fa-file-word-o';
case 'ppt':
case 'pptx':
return 'fa-file-powerpoint-o';
case 'zip':
case 'rar':
return 'fa-file-archive-o';
case 'mp3':
return 'fa-audio-o';
case 'avi':
return 'fa-video-o';
case 'php':
case 'html':
case 'css':
return 'fa-code-o';
case 'pdf':
return 'fa-file-pdf-o';
}
return 'fa-file-o';
}
/**
* Display gravatar image
*
* @access public
* @param string $email
* @param string $alt
* @return string
*/
public function avatar($email, $alt = '')
{
if (! empty($email) && $this->config->get('integration_gravatar') == 1) {
return '<img class="avatar" src="https://www.gravatar.com/avatar/'.md5(strtolower($email)).'?s=25" alt="'.$this->e($alt).'" title="'.$this->e($alt).'">';
}
return '';
}
}

View File

@ -3,6 +3,7 @@
namespace Core;
use Parsedown;
use Helper\Url;
/**
* Specific Markdown rules for Kanboard
@ -15,8 +16,8 @@ class Markdown extends Parsedown
{
private $link;
private $helper;
public function __construct($link, Helper $helper)
public function __construct($link, Url $helper)
{
$this->link = $link;
$this->helper = $helper;
@ -29,9 +30,12 @@ class Markdown extends Parsedown
// Replace task #123 by a link to the task
if (! empty($this->link) && preg_match('!#(\d+)!i', $Excerpt['text'], $matches)) {
$url = $this->helper->u($this->link['controller'],
$this->link['action'],
$this->link['params'] + array('task_id' => $matches[1]));
$url = $this->helper->href(
$this->link['controller'],
$this->link['action'],
$this->link['params'] + array('task_id' => $matches[1])
);
return array(
'extent' => strlen($matches[0]),
'element' => array(

View File

@ -349,7 +349,7 @@ class Paginator
$html = '<span class="pagination-previous">';
if ($this->offset > 0) {
$html .= $this->container['helper']->a(
$html .= $this->container['helper']->url->link(
'&larr; '.t('Previous'),
$this->controller,
$this->action,
@ -376,7 +376,7 @@ class Paginator
$html = '<span class="pagination-next">';
if (($this->total - $this->offset) > $this->limit) {
$html .= $this->container['helper']->a(
$html .= $this->container['helper']->url->link(
t('Next').' &rarr;',
$this->controller,
$this->action,
@ -451,7 +451,7 @@ class Paginator
$direction = $this->direction === 'DESC' ? 'ASC' : 'DESC';
}
return $prefix.$this->container['helper']->a(
return $prefix.$this->container['helper']->url->link(
$label,
$this->controller,
$this->action,

56
app/Helper/App.php Normal file
View File

@ -0,0 +1,56 @@
<?php
namespace Helper;
/**
* Application helpers
*
* @package helper
* @author Frederic Guillot
*/
class App extends \Core\Base
{
/**
* Get javascript language code
*
* @access public
* @return string
*/
public function jsLang()
{
return $this->config->getJsLanguageCode();
}
/**
* Get current timezone
*
* @access public
* @return string
*/
public function getTimezone()
{
return $this->config->getCurrentTimezone();
}
/**
* Get session flash message
*
* @access public
* @return string
*/
public function flashMessage()
{
$html = '';
if (isset($this->session['flash_message'])) {
$html = '<div class="alert alert-success alert-fade-out">'.$this->helper->e($this->session['flash_message']).'</div>';
unset($this->session['flash_message']);
}
else if (isset($this->session['flash_error_message'])) {
$html = '<div class="alert alert-error">'.$this->helper->e($this->session['flash_error_message']).'</div>';
unset($this->session['flash_error_message']);
}
return $html;
}
}

51
app/Helper/Asset.php Normal file
View File

@ -0,0 +1,51 @@
<?php
namespace Helper;
/**
* Assets helpers
*
* @package helper
* @author Frederic Guillot
*/
class Asset extends \Core\Base
{
/**
* Add a Javascript asset
*
* @param string $filename Filename
* @return string
*/
public function js($filename)
{
return '<script type="text/javascript" src="'.$filename.'?'.filemtime($filename).'"></script>';
}
/**
* Add a stylesheet asset
*
* @param string $filename Filename
* @param boolean $is_file Add file timestamp
* @param string $media Media
* @return string
*/
public function css($filename, $is_file = true, $media = 'screen')
{
return '<link rel="stylesheet" href="'.$filename.($is_file ? '?'.filemtime($filename) : '').'" media="'.$media.'">';
}
/**
* Get custom css
*
* @access public
* @return string
*/
public function customCss()
{
if ($this->config->get('application_stylesheet')) {
return '<style>'.$this->config->get('application_stylesheet').'</style>';
}
return '';
}
}

61
app/Helper/Datetime.php Normal file
View File

@ -0,0 +1,61 @@
<?php
namespace Helper;
/**
* DateTime helpers
*
* @package helper
* @author Frederic Guillot
*/
class Datetime extends \Core\Base
{
/**
* Get all hours for day
*
* @access public
* @return array
*/
public function getDayHours()
{
$values = array();
foreach (range(0, 23) as $hour) {
foreach (array(0, 30) as $minute) {
$time = sprintf('%02d:%02d', $hour, $minute);
$values[$time] = $time;
}
}
return $values;
}
/**
* Get all days of a week
*
* @access public
* @return array
*/
public function getWeekDays()
{
$values = array();
foreach (range(1, 7) as $day) {
$values[$day] = $this->getWeekDay($day);
}
return $values;
}
/**
* Get the localized day name from the day number
*
* @access public
* @param integer $day Day number
* @return string
*/
public function getWeekDay($day)
{
return dt('%A', strtotime('next Monday +'.($day - 1).' days'));
}
}

56
app/Helper/File.php Normal file
View File

@ -0,0 +1,56 @@
<?php
namespace Helper;
/**
* File helpers
*
* @package helper
* @author Frederic Guillot
*/
class File extends \Core\Base
{
/**
* Get file icon
*
* @access public
* @param string $filename Filename
* @return string Font-Awesome-Icon-Name
*/
public function icon($filename){
$extension = strtolower(pathinfo($filename, PATHINFO_EXTENSION));
switch ($extension) {
case 'jpeg':
case 'jpg':
case 'png':
case 'gif':
return 'fa-file-image-o';
case 'xls':
case 'xlsx':
return 'fa-file-excel-o';
case 'doc':
case 'docx':
return 'fa-file-word-o';
case 'ppt':
case 'pptx':
return 'fa-file-powerpoint-o';
case 'zip':
case 'rar':
return 'fa-file-archive-o';
case 'mp3':
return 'fa-audio-o';
case 'avi':
return 'fa-video-o';
case 'php':
case 'html':
case 'css':
return 'fa-code-o';
case 'pdf':
return 'fa-file-pdf-o';
}
return 'fa-file-o';
}
}

323
app/Helper/Form.php Normal file
View File

@ -0,0 +1,323 @@
<?php
namespace Helper;
use Core\Security;
/**
* Form helpers
*
* @package helper
* @author Frederic Guillot
*/
class Form extends \Core\Base
{
/**
* Hidden CSRF token field
*
* @access public
* @return string
*/
public function csrf()
{
return '<input type="hidden" name="csrf_token" value="'.Security::getCSRFToken().'"/>';
}
/**
* Display a hidden form field
*
* @access public
* @param string $name Field name
* @param array $values Form values
* @return string
*/
public function hidden($name, array $values = array())
{
return '<input type="hidden" name="'.$name.'" id="form-'.$name.'" '.$this->formValue($values, $name).'/>';
}
/**
* Display a select field
*
* @access public
* @param string $name Field name
* @param array $options Options
* @param array $values Form values
* @param array $errors Form errors
* @param string $class CSS class
* @return string
*/
public function select($name, array $options, array $values = array(), array $errors = array(), array $attributes = array(), $class = '')
{
$html = '<select name="'.$name.'" id="form-'.$name.'" class="'.$class.'" '.implode(' ', $attributes).'>';
foreach ($options as $id => $value) {
$html .= '<option value="'.$this->helper->e($id).'"';
if (isset($values->$name) && $id == $values->$name) $html .= ' selected="selected"';
if (isset($values[$name]) && $id == $values[$name]) $html .= ' selected="selected"';
$html .= '>'.$this->helper->e($value).'</option>';
}
$html .= '</select>';
$html .= $this->errorList($errors, $name);
return $html;
}
/**
* Display a radio field group
*
* @access public
* @param string $name Field name
* @param array $options Options
* @param array $values Form values
* @return string
*/
public function radios($name, array $options, array $values = array())
{
$html = '';
foreach ($options as $value => $label) {
$html .= $this->radio($name, $label, $value, isset($values[$name]) && $values[$name] == $value);
}
return $html;
}
/**
* Display a radio field
*
* @access public
* @param string $name Field name
* @param string $label Form label
* @param string $value Form value
* @param boolean $selected Field selected or not
* @param string $class CSS class
* @return string
*/
public function radio($name, $label, $value, $selected = false, $class = '')
{
return '<label><input type="radio" name="'.$name.'" class="'.$class.'" value="'.$this->helper->e($value).'" '.($selected ? 'checked="checked"' : '').'> '.$this->helper->e($label).'</label>';
}
/**
* Display a checkbox field
*
* @access public
* @param string $name Field name
* @param string $label Form label
* @param string $value Form value
* @param boolean $checked Field selected or not
* @param string $class CSS class
* @return string
*/
public function checkbox($name, $label, $value, $checked = false, $class = '')
{
return '<label><input type="checkbox" name="'.$name.'" class="'.$class.'" value="'.$this->helper->e($value).'" '.($checked ? 'checked="checked"' : '').'>&nbsp;'.$this->helper->e($label).'</label>';
}
/**
* Display a form label
*
* @access public
* @param string $name Field name
* @param string $label Form label
* @param array $attributes HTML attributes
* @return string
*/
public function label($label, $name, array $attributes = array())
{
return '<label for="form-'.$name.'" '.implode(' ', $attributes).'>'.$this->helper->e($label).'</label>';
}
/**
* Display a textarea
*
* @access public
* @param string $name Field name
* @param array $values Form values
* @param array $errors Form errors
* @param array $attributes HTML attributes
* @param string $class CSS class
* @return string
*/
public function textarea($name, $values = array(), array $errors = array(), array $attributes = array(), $class = '')
{
$class .= $this->errorClass($errors, $name);
$html = '<textarea name="'.$name.'" id="form-'.$name.'" class="'.$class.'" ';
$html .= implode(' ', $attributes).'>';
$html .= isset($values->$name) ? $this->helper->e($values->$name) : isset($values[$name]) ? $values[$name] : '';
$html .= '</textarea>';
$html .= $this->errorList($errors, $name);
return $html;
}
/**
* Display a input field
*
* @access public
* @param string $type HMTL input tag type
* @param string $name Field name
* @param array $values Form values
* @param array $errors Form errors
* @param array $attributes HTML attributes
* @param string $class CSS class
* @return string
*/
public function input($type, $name, $values = array(), array $errors = array(), array $attributes = array(), $class = '')
{
$class .= $this->errorClass($errors, $name);
$html = '<input type="'.$type.'" name="'.$name.'" id="form-'.$name.'" '.$this->formValue($values, $name).' class="'.$class.'" ';
$html .= implode(' ', $attributes).'>';
if (in_array('required', $attributes)) {
$html .= '<span class="form-required">*</span>';
}
$html .= $this->errorList($errors, $name);
return $html;
}
/**
* Display a text field
*
* @access public
* @param string $name Field name
* @param array $values Form values
* @param array $errors Form errors
* @param array $attributes HTML attributes
* @param string $class CSS class
* @return string
*/
public function text($name, $values = array(), array $errors = array(), array $attributes = array(), $class = '')
{
return $this->input('text', $name, $values, $errors, $attributes, $class);
}
/**
* Display a password field
*
* @access public
* @param string $name Field name
* @param array $values Form values
* @param array $errors Form errors
* @param array $attributes HTML attributes
* @param string $class CSS class
* @return string
*/
public function password($name, $values = array(), array $errors = array(), array $attributes = array(), $class = '')
{
return $this->input('password', $name, $values, $errors, $attributes, $class);
}
/**
* Display an email field
*
* @access public
* @param string $name Field name
* @param array $values Form values
* @param array $errors Form errors
* @param array $attributes HTML attributes
* @param string $class CSS class
* @return string
*/
public function email($name, $values = array(), array $errors = array(), array $attributes = array(), $class = '')
{
return $this->input('email', $name, $values, $errors, $attributes, $class);
}
/**
* Display a number field
*
* @access public
* @param string $name Field name
* @param array $values Form values
* @param array $errors Form errors
* @param array $attributes HTML attributes
* @param string $class CSS class
* @return string
*/
public function number($name, $values = array(), array $errors = array(), array $attributes = array(), $class = '')
{
return $this->input('number', $name, $values, $errors, $attributes, $class);
}
/**
* Display a numeric field (allow decimal number)
*
* @access public
* @param string $name Field name
* @param array $values Form values
* @param array $errors Form errors
* @param array $attributes HTML attributes
* @param string $class CSS class
* @return string
*/
public function numeric($name, $values = array(), array $errors = array(), array $attributes = array(), $class = '')
{
return $this->input('text', $name, $values, $errors, $attributes, $class.' form-numeric');
}
/**
* Display the form error class
*
* @access private
* @param array $errors Error list
* @param string $name Field name
* @return string
*/
private function errorClass(array $errors, $name)
{
return ! isset($errors[$name]) ? '' : ' form-error';
}
/**
* Display a list of form errors
*
* @access private
* @param array $errors List of errors
* @param string $name Field name
* @return string
*/
private function errorList(array $errors, $name)
{
$html = '';
if (isset($errors[$name])) {
$html .= '<ul class="form-errors">';
foreach ($errors[$name] as $error) {
$html .= '<li>'.$this->helper->e($error).'</li>';
}
$html .= '</ul>';
}
return $html;
}
/**
* Get an escaped form value
*
* @access private
* @param mixed $values Values
* @param string $name Field name
* @return string
*/
private function formValue($values, $name)
{
if (isset($values->$name)) {
return 'value="'.$this->helper->e($values->$name).'"';
}
return isset($values[$name]) ? 'value="'.$this->helper->e($values[$name]).'"' : '';
}
}

42
app/Helper/Subtask.php Normal file
View File

@ -0,0 +1,42 @@
<?php
namespace Helper;
/**
* Subtask helpers
*
* @package helper
* @author Frederic Guillot
*/
class Subtask extends \Core\Base
{
/**
* Get the link to toggle subtask status
*
* @access public
* @param array $subtask
* @param string $redirect
* @return string
*/
public function toggleStatus(array $subtask, $redirect)
{
if ($subtask['status'] == 0 && isset($this->session['has_subtask_inprogress']) && $this->session['has_subtask_inprogress'] === true) {
return $this->helper->url->link(
trim($this->template->render('subtask/icons', array('subtask' => $subtask))) . $this->helper->e($subtask['title']),
'subtask',
'subtaskRestriction',
array('task_id' => $subtask['task_id'], 'subtask_id' => $subtask['id'], 'redirect' => $redirect),
false,
'popover task-board-popover'
);
}
return $this->helper->url->link(
trim($this->template->render('subtask/icons', array('subtask' => $subtask))) . $this->helper->e($subtask['title']),
'subtask',
'toggleStatus',
array('task_id' => $subtask['task_id'], 'subtask_id' => $subtask['id'], 'redirect' => $redirect)
);
}
}

59
app/Helper/Task.php Normal file
View File

@ -0,0 +1,59 @@
<?php
namespace Helper;
/**
* Task helpers
*
* @package helper
* @author Frederic Guillot
*/
class Task extends \Core\Base
{
/**
* Get the age of an item in quasi human readable format.
* It's in this format: <1h , NNh, NNd
*
* @access public
* @param integer $timestamp Unix timestamp of the artifact for which age will be calculated
* @param integer $now Compare with this timestamp (Default value is the current unix timestamp)
* @return string
*/
public function age($timestamp, $now = null)
{
if ($now === null) {
$now = time();
}
$diff = $now - $timestamp;
if ($diff < 3600) {
return t('<1h');
}
else if ($diff < 86400) {
return t('%dh', $diff / 3600);
}
return t('%dd', ($now - $timestamp) / 86400);
}
public function recurrenceTriggers()
{
return $this->task->getRecurrenceTriggerList();
}
public function recurrenceTimeframes()
{
return $this->task->getRecurrenceTimeframeList();
}
public function recurrenceBasedates()
{
return $this->task->getRecurrenceBasedateList();
}
public function canRemove(array $task)
{
return $this->taskPermission->canRemoveTask($task);
}
}

91
app/Helper/Text.php Normal file
View File

@ -0,0 +1,91 @@
<?php
namespace Helper;
use Core\Markdown;
/**
* Text helpers
*
* @package helper
* @author Frederic Guillot
*/
class Text extends \Core\Base
{
/**
* Markdown transformation
*
* @param string $text Markdown content
* @param array $link Link parameters for replacement
* @return string
*/
public function markdown($text, array $link = array())
{
$parser = new Markdown($link, $this->helper->url);
$parser->setMarkupEscaped(MARKDOWN_ESCAPE_HTML);
return $parser->text($text);
}
/**
* Format a file size
*
* @param integer $size Size in bytes
* @param integer $precision Precision
* @return string
*/
public function bytes($size, $precision = 2)
{
$base = log($size) / log(1024);
$suffixes = array('', 'k', 'M', 'G', 'T');
return round(pow(1024, $base - floor($base)), $precision).$suffixes[(int)floor($base)];
}
/**
* Truncate a long text
*
* @param string $value Text
* @param integer $max_length Max Length
* @param string $end Text end
* @return string
*/
public function truncate($value, $max_length = 85, $end = '[...]')
{
$length = strlen($value);
if ($length > $max_length) {
return substr($value, 0, $max_length).' '.$end;
}
return $value;
}
/**
* Return true if needle is contained in the haystack
*
* @param string $haystack Haystack
* @param string $needle Needle
* @return boolean
*/
public function contains($haystack, $needle)
{
return strpos($haystack, $needle) !== false;
}
/**
* Return a value from a dictionary
*
* @param mixed $id Key
* @param array $listing Dictionary
* @param string $default_value Value displayed when the key doesn't exists
* @return string
*/
public function in($id, array $listing, $default_value = '?')
{
if (isset($listing[$id])) {
return $this->helper->e($listing[$id]);
}
return $default_value;
}
}

115
app/Helper/Url.php Normal file
View File

@ -0,0 +1,115 @@
<?php
namespace Helper;
use Core\Request;
use Core\Security;
/**
* Url helpers
*
* @package helper
* @author Frederic Guillot
*/
class Url extends \Core\Base
{
/**
* HTML Link tag
*
* @access public
* @param string $label Link label
* @param string $controller Controller name
* @param string $action Action name
* @param array $params Url parameters
* @param boolean $csrf Add a CSRF token
* @param string $class CSS class attribute
* @param boolean $new_tab Open the link in a new tab
* @return string
*/
public function link($label, $controller, $action, array $params = array(), $csrf = false, $class = '', $title = '', $new_tab = false)
{
return '<a href="'.$this->href($controller, $action, $params, $csrf).'" class="'.$class.'" title="'.$title.'" '.($new_tab ? 'target="_blank"' : '').'>'.$label.'</a>';
}
/**
* Hyperlink
*
* @access public
* @param string $controller Controller name
* @param string $action Action name
* @param array $params Url parameters
* @param boolean $csrf Add a CSRF token
* @return string
*/
public function href($controller, $action, array $params = array(), $csrf = false)
{
$values = array(
'controller' => $controller,
'action' => $action,
);
if ($csrf) {
$params['csrf_token'] = Security::getCSRFToken();
}
$values += $params;
return '?'.http_build_query($values, '', '&amp;');
}
/**
* Generate controller/action url
*
* @access public
* @param string $controller Controller name
* @param string $action Action name
* @param array $params Url parameters
* @return string
*/
public function to($controller, $action, array $params = array())
{
$values = array(
'controller' => $controller,
'action' => $action,
);
$values += $params;
return '?'.http_build_query($values, '', '&');
}
/**
* Get application base url
*
* @access public
* @return string
*/
public function base()
{
$application_url = $this->config->get('application_url');
if (! empty($application_url)) {
return $application_url;
}
return $this->server();
}
/**
* Get current server base url
*
* @access public
* @return string
*/
public function server()
{
$self = str_replace('\\', '/', dirname($_SERVER['PHP_SELF']));
$url = Request::isHTTPS() ? 'https://' : 'http://';
$url .= $_SERVER['SERVER_NAME'];
$url .= $_SERVER['SERVER_PORT'] == 80 || $_SERVER['SERVER_PORT'] == 443 ? '' : ':'.$_SERVER['SERVER_PORT'];
$url .= $self !== '/' ? $self.'/' : '/';
return $url;
}
}

93
app/Helper/User.php Normal file
View File

@ -0,0 +1,93 @@
<?php
namespace Helper;
/**
* User helpers
*
* @package helper
* @author Frederic Guillot
*/
class User extends \Core\Base
{
/**
* Get user profile
*
* @access public
* @return string
*/
public function getProfileLink()
{
return $this->helper->url->link(
$this->helper->e($this->getFullname()),
'user',
'show',
array('user_id' => $this->userSession->getId())
);
}
/**
* Check if the given user_id is the connected user
*
* @param integer $user_id User id
* @return boolean
*/
public function isCurrentUser($user_id)
{
return $this->userSession->getId() == $user_id;
}
/**
* Return if the logged user is admin
*
* @access public
* @return boolean
*/
public function isAdmin()
{
return $this->userSession->isAdmin();
}
/**
* Proxy cache helper for acl::isManagerActionAllowed()
*
* @access public
* @param integer $project_id
* @return boolean
*/
public function isManager($project_id)
{
if ($this->userSession->isAdmin()) {
return true;
}
return $this->memoryCache->proxy('acl', 'isManagerActionAllowed', $project_id);
}
/**
* Return the user full name
*
* @param array $user User properties
* @return string
*/
public function getFullname(array $user = array())
{
return $this->user->getFullname(empty($user) ? $_SESSION['user'] : $user);
}
/**
* Display gravatar image
*
* @access public
* @param string $email
* @param string $alt
* @return string
*/
public function avatar($email, $alt = '')
{
if (! empty($email) && $this->config->get('integration_gravatar') == 1) {
return '<img class="avatar" src="https://www.gravatar.com/avatar/'.md5(strtolower($email)).'?s=25" alt="'.$this->helper->e($alt).'" title="'.$this->helper->e($alt).'">';
}
return '';
}
}

View File

@ -1,53 +0,0 @@
<?php
namespace Integration;
use Pimple\Container;
/**
* Base class
*
* @package integration
* @author Frederic Guillot
*
* @property \Model\ProjectActivity $projectActivity
* @property \Model\ProjectIntegration $projectIntegration
* @property \Model\ProjectPermission $projectPermission
* @property \Model\Task $task
* @property \Model\TaskFinder $taskFinder
* @property \Model\User $user
* @property \Model\Project $project
*/
abstract class Base
{
/**
* Container instance
*
* @access protected
* @var \Pimple\Container
*/
protected $container;
/**
* Constructor
*
* @access public
* @param \Pimple\Container $container
*/
public function __construct(Container $container)
{
$this->container = $container;
}
/**
* Load automatically class from the container
*
* @access public
* @param string $name
* @return mixed
*/
public function __get($name)
{
return $this->container[$name];
}
}

View File

@ -11,7 +11,7 @@ use Model\Task;
* @package integration
* @author Frederic Guillot
*/
class BitbucketWebhook extends Base
class BitbucketWebhook extends \Core\Base
{
/**
* Events

View File

@ -11,7 +11,7 @@ use Model\Task;
* @package integration
* @author Frederic Guillot
*/
class GithubWebhook extends Base
class GithubWebhook extends \Core\Base
{
/**
* Events

View File

@ -12,7 +12,7 @@ use Model\Task;
* @package integration
* @author Frederic Guillot
*/
class GitlabWebhook extends Base
class GitlabWebhook extends \Core\Base
{
/**
* Events

View File

@ -8,7 +8,7 @@ namespace Integration;
* @package integration
* @author Frederic Guillot
*/
class HipchatWebhook extends Base
class HipchatWebhook extends \Core\Base
{
/**
* Return true if Hipchat is enabled for this project or globally

View File

@ -14,7 +14,7 @@ use Fabiang\Xmpp\Protocol\Presence;
* @package integration
* @author Frederic Guillot
*/
class Jabber extends Base
class Jabber extends \Core\Base
{
/**
* Return true if Jabber is enabled for this project or globally
@ -82,7 +82,7 @@ class Jabber extends Base
if ($this->config->get('application_url')) {
$payload .= ' '.$this->config->get('application_url');
$payload .= $this->helper->url('task', 'show', array('task_id' => $task_id, 'project_id' => $project_id));
$payload .= $this->helper->url->to('task', 'show', array('task_id' => $task_id, 'project_id' => $project_id));
}
$this->sendMessage($project_id, $payload);

View File

@ -11,7 +11,7 @@ use Core\Tool;
* @package integration
* @author Frederic Guillot
*/
class MailgunWebhook extends Base
class MailgunWebhook extends \Core\Base
{
/**
* Parse incoming email

View File

@ -10,7 +10,7 @@ use HTML_To_Markdown;
* @package integration
* @author Frederic Guillot
*/
class PostmarkWebhook extends Base
class PostmarkWebhook extends \Core\Base
{
/**
* Parse incoming email

View File

@ -11,7 +11,7 @@ use Core\Tool;
* @package integration
* @author Frederic Guillot
*/
class SendgridWebhook extends Base
class SendgridWebhook extends \Core\Base
{
/**
* Parse incoming email

View File

@ -8,7 +8,7 @@ namespace Integration;
* @package integration
* @author Frederic Guillot
*/
class SlackWebhook extends Base
class SlackWebhook extends \Core\Base
{
/**
* Return true if Slack is enabled for this project or globally

View File

@ -9,51 +9,8 @@ use Pimple\Container;
*
* @package model
* @author Frederic Guillot
*
* @property \Core\Session $session
* @property \Core\Template $template
* @property \Model\Acl $acl
* @property \Model\Action $action
* @property \Model\Authentication $authentication
* @property \Model\Board $board
* @property \Model\Budget $budget
* @property \Model\Category $category
* @property \Model\Comment $comment
* @property \Model\CommentHistory $commentHistory
* @property \Model\Color $color
* @property \Model\Config $config
* @property \Model\DateParser $dateParser
* @property \Model\File $file
* @property \Model\Helper $helper
* @property \Model\LastLogin $lastLogin
* @property \Model\Link $link
* @property \Model\Notification $notification
* @property \Model\Project $project
* @property \Model\ProjectDuplication $projectDuplication
* @property \Model\ProjectPermission $projectPermission
* @property \Model\Subtask $subtask
* @property \Model\SubtaskHistory $subtaskHistory
* @property \Model\Swimlane $swimlane
* @property \Model\Task $task
* @property \Model\TaskCreation $taskCreation
* @property \Model\TaskDuplication $taskDuplication
* @property \Model\TaskExport $taskExport
* @property \Model\TaskFinder $taskFinder
* @property \Model\TaskHistory $taskHistory
* @property \Model\TaskLink $taskLink
* @property \Model\TaskPosition $taskPosition
* @property \Model\TaskValidator $taskValidator
* @property \Model\Timetable $timetable
* @property \Model\TimetableDay $timetableDay
* @property \Model\TimetableExtra $timetableExtra
* @property \Model\TimetableOff $timetableOff
* @property \Model\TimetableWeek $timetableWeek
* @property \Model\SubtaskTimeTracking $subtaskTimeTracking
* @property \Model\User $user
* @property \Model\UserSession $userSession
* @property \Model\Webhook $webhook
*/
abstract class Base
abstract class Base extends \Core\Base
{
/**
* Database instance
@ -63,14 +20,6 @@ abstract class Base
*/
protected $db;
/**
* Container instance
*
* @access protected
* @var \Pimple\Container
*/
protected $container;
/**
* Constructor
*
@ -83,18 +32,6 @@ abstract class Base
$this->db = $this->container['db'];
}
/**
* Load automatically models
*
* @access public
* @param string $name Model name
* @return mixed
*/
public function __get($name)
{
return $this->container[$name];
}
/**
* Save a record in the database
*
@ -203,7 +140,7 @@ abstract class Base
'backgroundColor' => $this->color->getBackgroundColor($task['color_id']),
'borderColor' => $this->color->getBorderColor($task['color_id']),
'textColor' => 'black',
'url' => $this->helper->url('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])),
'url' => $this->helper->url->to('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])),
);
}
}

View File

@ -96,7 +96,7 @@ class SubtaskForecast extends Base
'id' => $subtasks[$offset]['id'].'-'.$subtasks[$offset]['task_id'].'-'.$offset,
'subtask_id' => $subtasks[$offset]['id'],
'title' => t('#%d', $subtasks[$offset]['task_id']).' '.$subtasks[$offset]['title'],
'url' => $this->helper->url('task', 'show', array('task_id' => $subtasks[$offset]['task_id'], 'project_id' => $subtasks[$offset]['project_id'])),
'url' => $this->helper->url->to('task', 'show', array('task_id' => $subtasks[$offset]['task_id'], 'project_id' => $subtasks[$offset]['project_id'])),
'editable' => false,
'start' => date('Y-m-d\TH:i:s', $start),
);

View File

@ -196,7 +196,7 @@ class SubtaskTimeTracking extends Base
'backgroundColor' => $this->color->getBackgroundColor($row['color_id']),
'borderColor' => $this->color->getBorderColor($row['color_id']),
'textColor' => 'black',
'url' => $this->helper->url('task', 'show', array('task_id' => $row['task_id'], 'project_id' => $row['project_id'])),
'url' => $this->helper->url->to('task', 'show', array('task_id' => $row['task_id'], 'project_id' => $row['project_id'])),
'editable' => false,
);
}

View File

@ -450,7 +450,7 @@ class TaskFilter extends Base
$vEvent->setModified($dateModif);
$vEvent->setUseTimezone(true);
$vEvent->setSummary(t('#%d', $task['id']).' '.$task['title']);
$vEvent->setUrl($this->helper->getCurrentBaseUrl().$this->helper->url('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])));
$vEvent->setUrl($this->helper->url->base().$this->helper->url->to('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])));
if (! empty($task['creator_id'])) {
$vEvent->setOrganizer('MAILTO:'.($task['creator_email'] ?: $task['creator_username'].'@kanboard.local'));

View File

@ -85,17 +85,6 @@ class UserSession extends Base
return isset($this->session['user']['id']) ? (int) $this->session['user']['id'] : 0;
}
/**
* Check if the given user_id is the connected user
*
* @param integer $user_id User id
* @return boolean
*/
public function isCurrentUser($user_id)
{
return $this->getId() == $user_id;
}
/**
* Check is the user is connected
*

View File

@ -55,9 +55,9 @@ class ClassProvider implements ServiceProviderInterface
'TaskValidator',
'Timetable',
'TimetableDay',
'TimetableExtra',
'TimetableWeek',
'TimetableOff',
'TimetableExtra',
'Transition',
'User',
'UserSession',
@ -65,23 +65,22 @@ class ClassProvider implements ServiceProviderInterface
),
'Core' => array(
'Helper',
'Template',
'Session',
'MemoryCache',
'FileCache',
'Request',
'HttpClient',
'MemoryCache',
'Request',
'Session',
'Template',
),
'Integration' => array(
'GitlabWebhook',
'GithubWebhook',
'BitbucketWebhook',
'GithubWebhook',
'GitlabWebhook',
'HipchatWebhook',
'Jabber',
'MailgunWebhook',
'PostmarkWebhook',
'SendgridWebhook',
'SlackWebhook',
'PostmarkWebhook',
'Jabber',
)
);

View File

@ -6,7 +6,7 @@ use Core\Request;
use Event\AuthEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class AuthSubscriber extends Base implements EventSubscriberInterface
class AuthSubscriber extends \Core\Base implements EventSubscriberInterface
{
public static function getSubscribedEvents()
{

View File

@ -1,66 +0,0 @@
<?php
namespace Subscriber;
use Pimple\Container;
/**
* Base subscriber class
*
* @package subscriber
* @author Frederic Guillot
*
* @property \Integration\SlackWebhook $slackWebhook
* @property \Integration\HipchatWebhook $hipchatWebhook
* @property \Model\Board $board
* @property \Model\Config $config
* @property \Model\Comment $comment
* @property \Model\LastLogin $lastLogin
* @property \Model\Notification $notification
* @property \Model\Project $project
* @property \Model\ProjectPermission $projectPermission
* @property \Model\ProjectActivity $projectActivity
* @property \Model\ProjectAnalytic $projectAnalytic
* @property \Model\ProjectDailySummary $projectDailySummary
* @property \Model\Subtask $subtask
* @property \Model\Task $task
* @property \Model\TaskDuplication $taskDuplication
* @property \Model\TaskExport $taskExport
* @property \Model\TaskFinder $taskFinder
* @property \Model\SubtaskTimeTracking $subtaskTimeTracking
* @property \Model\UserSession $userSession
* @property \Model\Webhook $webhook
*/
abstract class Base
{
/**
* Container instance
*
* @access protected
* @var \Pimple\Container
*/
protected $container;
/**
* Constructor
*
* @access public
* @param \Pimple\Container $container
*/
public function __construct(Container $container)
{
$this->container = $container;
}
/**
* Load automatically models
*
* @access public
* @param string $name Model name
* @return mixed
*/
public function __get($name)
{
return $this->container[$name];
}
}

View File

@ -4,7 +4,7 @@ namespace Subscriber;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class BootstrapSubscriber extends Base implements EventSubscriberInterface
class BootstrapSubscriber extends \Core\Base implements EventSubscriberInterface
{
public static function getSubscribedEvents()
{

View File

@ -9,7 +9,7 @@ use Model\Subtask;
use Model\File;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class NotificationSubscriber extends Base implements EventSubscriberInterface
class NotificationSubscriber extends \Core\Base implements EventSubscriberInterface
{
private $templates = array(
Task::EVENT_CREATE => 'task_creation',

View File

@ -8,7 +8,7 @@ use Model\Comment;
use Model\Subtask;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class ProjectActivitySubscriber extends Base implements EventSubscriberInterface
class ProjectActivitySubscriber extends \Core\Base implements EventSubscriberInterface
{
public static function getSubscribedEvents()
{

View File

@ -6,7 +6,7 @@ use Event\TaskEvent;
use Model\Task;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class ProjectDailySummarySubscriber extends Base implements EventSubscriberInterface
class ProjectDailySummarySubscriber extends \Core\Base implements EventSubscriberInterface
{
public static function getSubscribedEvents()
{

View File

@ -6,7 +6,7 @@ use Event\GenericEvent;
use Model\Task;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class ProjectModificationDateSubscriber extends Base implements EventSubscriberInterface
class ProjectModificationDateSubscriber extends \Core\Base implements EventSubscriberInterface
{
public static function getSubscribedEvents()
{

View File

@ -6,7 +6,7 @@ use Event\TaskEvent;
use Model\Task;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class RecurringTaskSubscriber extends Base implements EventSubscriberInterface
class RecurringTaskSubscriber extends \Core\Base implements EventSubscriberInterface
{
public static function getSubscribedEvents()
{

View File

@ -6,7 +6,7 @@ use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Model\Subtask;
use Event\SubtaskEvent;
class SubtaskTimesheetSubscriber extends Base implements EventSubscriberInterface
class SubtaskTimesheetSubscriber extends \Core\Base implements EventSubscriberInterface
{
public static function getSubscribedEvents()
{

View File

@ -6,7 +6,7 @@ use Event\TaskEvent;
use Model\Task;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class TaskMovedDateSubscriber extends Base implements EventSubscriberInterface
class TaskMovedDateSubscriber extends \Core\Base implements EventSubscriberInterface
{
public static function getSubscribedEvents()
{

View File

@ -6,7 +6,7 @@ use Event\TaskEvent;
use Model\Task;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class TransitionSubscriber extends Base implements EventSubscriberInterface
class TransitionSubscriber extends \Core\Base implements EventSubscriberInterface
{
public static function getSubscribedEvents()
{

View File

@ -11,7 +11,7 @@ use Model\File;
use Model\Subtask;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class WebhookSubscriber extends Base implements EventSubscriberInterface
class WebhookSubscriber extends \Core\Base implements EventSubscriberInterface
{
public static function getSubscribedEvents()
{

View File

@ -3,15 +3,15 @@
</div>
<h3><?= t('Choose an event') ?></h3>
<form method="post" action="<?= $this->u('action', 'params', array('project_id' => $project['id'])) ?>">
<form method="post" action="<?= $this->url->href('action', 'params', array('project_id' => $project['id'])) ?>">
<?= $this->formCsrf() ?>
<?= $this->form->csrf() ?>
<?= $this->formHidden('project_id', $values) ?>
<?= $this->formHidden('action_name', $values) ?>
<?= $this->form->hidden('project_id', $values) ?>
<?= $this->form->hidden('action_name', $values) ?>
<?= $this->formLabel(t('Event'), 'event_name') ?>
<?= $this->formSelect('event_name', $events, $values) ?><br/>
<?= $this->form->label(t('Event'), 'event_name') ?>
<?= $this->form->select('event_name', $events, $values) ?><br/>
<div class="form-help">
<?= t('When the selected event occurs execute the corresponding action.') ?>
@ -20,6 +20,6 @@
<div class="form-actions">
<input type="submit" value="<?= t('Next step') ?>" class="btn btn-blue"/>
<?= t('or') ?>
<?= $this->a(t('cancel'), 'action', 'index', array('project_id' => $project['id'])) ?>
<?= $this->url->link(t('cancel'), 'action', 'index', array('project_id' => $project['id'])) ?>
</div>
</form>

View File

@ -15,25 +15,25 @@
<?php foreach ($actions as $action): ?>
<tr>
<td><?= $this->inList($action['event_name'], $available_events) ?></td>
<td><?= $this->inList($action['action_name'], $available_actions) ?></td>
<td><?= $this->text->in($action['event_name'], $available_events) ?></td>
<td><?= $this->text->in($action['action_name'], $available_actions) ?></td>
<td>
<ul>
<?php foreach ($action['params'] as $param): ?>
<li>
<?= $this->inList($param['name'], $available_params) ?> =
<?= $this->text->in($param['name'], $available_params) ?> =
<strong>
<?php if ($this->contains($param['name'], 'column_id')): ?>
<?= $this->inList($param['value'], $columns_list) ?>
<?php elseif ($this->contains($param['name'], 'user_id')): ?>
<?= $this->inList($param['value'], $users_list) ?>
<?php elseif ($this->contains($param['name'], 'project_id')): ?>
<?= $this->inList($param['value'], $projects_list) ?>
<?php elseif ($this->contains($param['name'], 'color_id')): ?>
<?= $this->inList($param['value'], $colors_list) ?>
<?php elseif ($this->contains($param['name'], 'category_id')): ?>
<?= $this->inList($param['value'], $categories_list) ?>
<?php elseif ($this->contains($param['name'], 'label')): ?>
<?php if ($this->text->contains($param['name'], 'column_id')): ?>
<?= $this->text->in($param['value'], $columns_list) ?>
<?php elseif ($this->text->contains($param['name'], 'user_id')): ?>
<?= $this->text->in($param['value'], $users_list) ?>
<?php elseif ($this->text->contains($param['name'], 'project_id')): ?>
<?= $this->text->in($param['value'], $projects_list) ?>
<?php elseif ($this->text->contains($param['name'], 'color_id')): ?>
<?= $this->text->in($param['value'], $colors_list) ?>
<?php elseif ($this->text->contains($param['name'], 'category_id')): ?>
<?= $this->text->in($param['value'], $categories_list) ?>
<?php elseif ($this->text->contains($param['name'], 'label')): ?>
<?= $this->e($param['value']) ?>
<?php endif ?>
</strong>
@ -42,7 +42,7 @@
</ul>
</td>
<td>
<?= $this->a(t('Remove'), 'action', 'confirm', array('project_id' => $project['id'], 'action_id' => $action['id'])) ?>
<?= $this->url->link(t('Remove'), 'action', 'confirm', array('project_id' => $project['id'], 'action_id' => $action['id'])) ?>
</td>
</tr>
<?php endforeach ?>
@ -51,12 +51,12 @@
<?php endif ?>
<h3><?= t('Add an action') ?></h3>
<form method="post" action="<?= $this->u('action', 'event', array('project_id' => $project['id'])) ?>" class="listing">
<?= $this->formCsrf() ?>
<?= $this->formHidden('project_id', $values) ?>
<form method="post" action="<?= $this->url->href('action', 'event', array('project_id' => $project['id'])) ?>" class="listing">
<?= $this->form->csrf() ?>
<?= $this->form->hidden('project_id', $values) ?>
<?= $this->formLabel(t('Action'), 'action_name') ?>
<?= $this->formSelect('action_name', $available_actions, $values) ?><br/>
<?= $this->form->label(t('Action'), 'action_name') ?>
<?= $this->form->select('action_name', $available_actions, $values) ?><br/>
<div class="form-actions">
<input type="submit" value="<?= t('Next step') ?>" class="btn btn-blue"/>

View File

@ -3,34 +3,34 @@
</div>
<h3><?= t('Define action parameters') ?></h3>
<form method="post" action="<?= $this->u('action', 'create', array('project_id' => $project['id'])) ?>" autocomplete="off">
<form method="post" action="<?= $this->url->href('action', 'create', array('project_id' => $project['id'])) ?>" autocomplete="off">
<?= $this->formCsrf() ?>
<?= $this->form->csrf() ?>
<?= $this->formHidden('project_id', $values) ?>
<?= $this->formHidden('event_name', $values) ?>
<?= $this->formHidden('action_name', $values) ?>
<?= $this->form->hidden('project_id', $values) ?>
<?= $this->form->hidden('event_name', $values) ?>
<?= $this->form->hidden('action_name', $values) ?>
<?php foreach ($action_params as $param_name => $param_desc): ?>
<?php if ($this->contains($param_name, 'column_id')): ?>
<?= $this->formLabel($param_desc, $param_name) ?>
<?= $this->formSelect('params['.$param_name.']', $columns_list, $values) ?><br/>
<?php elseif ($this->contains($param_name, 'user_id')): ?>
<?= $this->formLabel($param_desc, $param_name) ?>
<?= $this->formSelect('params['.$param_name.']', $users_list, $values) ?><br/>
<?php elseif ($this->contains($param_name, 'project_id')): ?>
<?= $this->formLabel($param_desc, $param_name) ?>
<?= $this->formSelect('params['.$param_name.']', $projects_list, $values) ?><br/>
<?php elseif ($this->contains($param_name, 'color_id')): ?>
<?= $this->formLabel($param_desc, $param_name) ?>
<?= $this->formSelect('params['.$param_name.']', $colors_list, $values) ?><br/>
<?php elseif ($this->contains($param_name, 'category_id')): ?>
<?= $this->formLabel($param_desc, $param_name) ?>
<?= $this->formSelect('params['.$param_name.']', $categories_list, $values) ?><br/>
<?php elseif ($this->contains($param_name, 'label')): ?>
<?= $this->formLabel($param_desc, $param_name) ?>
<?= $this->formText('params['.$param_name.']', $values) ?>
<?php if ($this->text->contains($param_name, 'column_id')): ?>
<?= $this->form->label($param_desc, $param_name) ?>
<?= $this->form->select('params['.$param_name.']', $columns_list, $values) ?><br/>
<?php elseif ($this->text->contains($param_name, 'user_id')): ?>
<?= $this->form->label($param_desc, $param_name) ?>
<?= $this->form->select('params['.$param_name.']', $users_list, $values) ?><br/>
<?php elseif ($this->text->contains($param_name, 'project_id')): ?>
<?= $this->form->label($param_desc, $param_name) ?>
<?= $this->form->select('params['.$param_name.']', $projects_list, $values) ?><br/>
<?php elseif ($this->text->contains($param_name, 'color_id')): ?>
<?= $this->form->label($param_desc, $param_name) ?>
<?= $this->form->select('params['.$param_name.']', $colors_list, $values) ?><br/>
<?php elseif ($this->text->contains($param_name, 'category_id')): ?>
<?= $this->form->label($param_desc, $param_name) ?>
<?= $this->form->select('params['.$param_name.']', $categories_list, $values) ?><br/>
<?php elseif ($this->text->contains($param_name, 'label')): ?>
<?= $this->form->label($param_desc, $param_name) ?>
<?= $this->form->text('params['.$param_name.']', $values) ?>
<?php endif ?>
<?php endforeach ?>
@ -38,6 +38,6 @@
<div class="form-actions">
<input type="submit" value="<?= t('Save this action') ?>" class="btn btn-blue"/>
<?= t('or') ?>
<?= $this->a(t('cancel'), 'action', 'index', array('project_id' => $project['id'])) ?>
<?= $this->url->link(t('cancel'), 'action', 'index', array('project_id' => $project['id'])) ?>
</div>
</form>

View File

@ -4,12 +4,12 @@
<div class="confirm">
<p class="alert alert-info">
<?= t('Do you really want to remove this action: "%s"?', $this->inList($action['event_name'], $available_events).'/'.$this->inList($action['action_name'], $available_actions)) ?>
<?= t('Do you really want to remove this action: "%s"?', $this->text->in($action['event_name'], $available_events).'/'.$this->text->in($action['action_name'], $available_actions)) ?>
</p>
<div class="form-actions">
<?= $this->a(t('Yes'), 'action', 'remove', array('project_id' => $project['id'], 'action_id' => $action['id']), true, 'btn btn-red') ?>
<?= $this->url->link(t('Yes'), 'action', 'remove', array('project_id' => $project['id'], 'action_id' => $action['id']), true, 'btn btn-red') ?>
<?= t('or') ?>
<?= $this->a(t('cancel'), 'action', 'index', array('project_id' => $project['id'])) ?>
<?= $this->url->link(t('cancel'), 'action', 'index', array('project_id' => $project['id'])) ?>
</div>
</div>

View File

@ -6,24 +6,24 @@
<p class="alert"><?= t('Not enough data to show the graph.') ?></p>
<?php else: ?>
<section id="analytic-burndown">
<div id="chart" data-url="<?= $this->u('analytic', 'burndown', array('project_id' => $project['id'], 'from' => $values['from'], 'to' => $values['to'])) ?>"></div>
<div id="chart" data-url="<?= $this->url->href('analytic', 'burndown', array('project_id' => $project['id'], 'from' => $values['from'], 'to' => $values['to'])) ?>"></div>
</section>
<?php endif ?>
<hr/>
<form method="post" class="form-inline" action="<?= $this->u('analytic', 'burndown', array('project_id' => $project['id'])) ?>" autocomplete="off">
<form method="post" class="form-inline" action="<?= $this->url->href('analytic', 'burndown', array('project_id' => $project['id'])) ?>" autocomplete="off">
<?= $this->formCsrf() ?>
<?= $this->form->csrf() ?>
<div class="form-inline-group">
<?= $this->formLabel(t('Start Date'), 'from') ?>
<?= $this->formText('from', $values, array(), array('required', 'placeholder="'.$this->inList($date_format, $date_formats).'"'), 'form-date') ?>
<?= $this->form->label(t('Start Date'), 'from') ?>
<?= $this->form->text('from', $values, array(), array('required', 'placeholder="'.$this->text->in($date_format, $date_formats).'"'), 'form-date') ?>
</div>
<div class="form-inline-group">
<?= $this->formLabel(t('End Date'), 'to') ?>
<?= $this->formText('to', $values, array(), array('required', 'placeholder="'.$this->inList($date_format, $date_formats).'"'), 'form-date') ?>
<?= $this->form->label(t('End Date'), 'to') ?>
<?= $this->form->text('to', $values, array(), array('required', 'placeholder="'.$this->text->in($date_format, $date_formats).'"'), 'form-date') ?>
</div>
<div class="form-inline-group">

View File

@ -6,24 +6,24 @@
<p class="alert"><?= t('Not enough data to show the graph.') ?></p>
<?php else: ?>
<section id="analytic-cfd">
<div id="chart" data-url="<?= $this->u('analytic', 'cfd', array('project_id' => $project['id'], 'from' => $values['from'], 'to' => $values['to'])) ?>"></div>
<div id="chart" data-url="<?= $this->url->href('analytic', 'cfd', array('project_id' => $project['id'], 'from' => $values['from'], 'to' => $values['to'])) ?>"></div>
</section>
<?php endif ?>
<hr/>
<form method="post" class="form-inline" action="<?= $this->u('analytic', 'cfd', array('project_id' => $project['id'])) ?>" autocomplete="off">
<form method="post" class="form-inline" action="<?= $this->url->href('analytic', 'cfd', array('project_id' => $project['id'])) ?>" autocomplete="off">
<?= $this->formCsrf() ?>
<?= $this->form->csrf() ?>
<div class="form-inline-group">
<?= $this->formLabel(t('Start Date'), 'from') ?>
<?= $this->formText('from', $values, array(), array('required', 'placeholder="'.$this->inList($date_format, $date_formats).'"'), 'form-date') ?>
<?= $this->form->label(t('Start Date'), 'from') ?>
<?= $this->form->text('from', $values, array(), array('required', 'placeholder="'.$this->text->in($date_format, $date_formats).'"'), 'form-date') ?>
</div>
<div class="form-inline-group">
<?= $this->formLabel(t('End Date'), 'to') ?>
<?= $this->formText('to', $values, array(), array('required', 'placeholder="'.$this->inList($date_format, $date_formats).'"'), 'form-date') ?>
<?= $this->form->label(t('End Date'), 'to') ?>
<?= $this->form->text('to', $values, array(), array('required', 'placeholder="'.$this->text->in($date_format, $date_formats).'"'), 'form-date') ?>
</div>
<div class="form-inline-group">

View File

@ -1,10 +1,10 @@
<?= $this->js('assets/js/vendor/d3.v3.4.8.min.js') ?>
<?= $this->js('assets/js/vendor/dimple.v2.1.2.min.js') ?>
<?= $this->asset->js('assets/js/vendor/d3.v3.4.8.min.js') ?>
<?= $this->asset->js('assets/js/vendor/dimple.v2.1.2.min.js') ?>
<section id="main">
<div class="page-header">
<ul>
<li><i class="fa fa-table fa-fw"></i><?= $this->a(t('Back to the board'), 'board', 'show', array('project_id' => $project['id'])) ?></li>
<li><i class="fa fa-table fa-fw"></i><?= $this->url->link(t('Back to the board'), 'board', 'show', array('project_id' => $project['id'])) ?></li>
</ul>
</div>
<section class="sidebar-container" id="analytic-section">

View File

@ -2,16 +2,16 @@
<h2><?= t('Reportings') ?></h2>
<ul>
<li>
<?= $this->a(t('Task distribution'), 'analytic', 'tasks', array('project_id' => $project['id'])) ?>
<?= $this->url->link(t('Task distribution'), 'analytic', 'tasks', array('project_id' => $project['id'])) ?>
</li>
<li>
<?= $this->a(t('User repartition'), 'analytic', 'users', array('project_id' => $project['id'])) ?>
<?= $this->url->link(t('User repartition'), 'analytic', 'users', array('project_id' => $project['id'])) ?>
</li>
<li>
<?= $this->a(t('Cumulative flow diagram'), 'analytic', 'cfd', array('project_id' => $project['id'])) ?>
<?= $this->url->link(t('Cumulative flow diagram'), 'analytic', 'cfd', array('project_id' => $project['id'])) ?>
</li>
<li>
<?= $this->a(t('Burndown chart'), 'analytic', 'burndown', array('project_id' => $project['id'])) ?>
<?= $this->url->link(t('Burndown chart'), 'analytic', 'burndown', array('project_id' => $project['id'])) ?>
</li>
</ul>
</div>

View File

@ -7,7 +7,7 @@
<?php else: ?>
<section id="analytic-task-repartition">
<div id="chart" data-url="<?= $this->u('analytic', 'tasks', array('project_id' => $project['id'])) ?>"></div>
<div id="chart" data-url="<?= $this->url->href('analytic', 'tasks', array('project_id' => $project['id'])) ?>"></div>
<table>
<tr>

View File

@ -7,7 +7,7 @@
<?php else: ?>
<section id="analytic-user-repartition">
<div id="chart" data-url="<?= $this->u('analytic', 'users', array('project_id' => $project['id'])) ?>"></div>
<div id="chart" data-url="<?= $this->url->href('analytic', 'users', array('project_id' => $project['id'])) ?>"></div>
<table>
<tr>

View File

@ -1,14 +1,14 @@
<section id="main">
<div class="page-header page-header-mobile">
<ul>
<?php if ($this->userSession->isAdmin()): ?>
<li><i class="fa fa-plus fa-fw"></i><?= $this->a(t('New project'), 'project', 'create') ?></li>
<?php if ($this->user->isAdmin()): ?>
<li><i class="fa fa-plus fa-fw"></i><?= $this->url->link(t('New project'), 'project', 'create') ?></li>
<?php endif ?>
<li><i class="fa fa-lock fa-fw"></i><?= $this->a(t('New private project'), 'project', 'create', array('private' => 1)) ?></li>
<li><i class="fa fa-folder fa-fw"></i><?= $this->a(t('Project management'), 'project', 'index') ?></li>
<?php if ($this->userSession->isAdmin()): ?>
<li><i class="fa fa-user fa-fw"></i><?= $this->a(t('User management'), 'user', 'index') ?></li>
<li><i class="fa fa-cog fa-fw"></i><?= $this->a(t('Settings'), 'config', 'index') ?></li>
<li><i class="fa fa-lock fa-fw"></i><?= $this->url->link(t('New private project'), 'project', 'create', array('private' => 1)) ?></li>
<li><i class="fa fa-folder fa-fw"></i><?= $this->url->link(t('Project management'), 'project', 'index') ?></li>
<?php if ($this->user->isAdmin()): ?>
<li><i class="fa fa-user fa-fw"></i><?= $this->url->link(t('User management'), 'user', 'index') ?></li>
<li><i class="fa fa-cog fa-fw"></i><?= $this->url->link(t('Settings'), 'config', 'index') ?></li>
<?php endif ?>
<li>
<span class="dropdown">
@ -45,9 +45,9 @@
<div class="dashboard-right-column">
<div id="dashboard-calendar">
<div id="user-calendar"
data-check-url="<?= $this->u('calendar', 'user') ?>"
data-check-url="<?= $this->url->href('calendar', 'user') ?>"
data-user-id="<?= $user_id ?>"
data-save-url="<?= $this->u('calendar', 'save') ?>"
data-save-url="<?= $this->url->href('calendar', 'save') ?>"
>
</div>
</div>

View File

@ -11,18 +11,18 @@
<?php foreach ($paginator->getCollection() as $project): ?>
<tr>
<td>
<?= $this->a('#'.$project['id'], 'board', 'show', array('project_id' => $project['id']), false, 'dashboard-table-link') ?>
<?= $this->url->link('#'.$project['id'], 'board', 'show', array('project_id' => $project['id']), false, 'dashboard-table-link') ?>
</td>
<td>
<?php if ($this->isManager($project['id'])): ?>
<?= $this->a('<i class="fa fa-cog"></i>', 'project', 'show', array('project_id' => $project['id']), false, 'dashboard-table-link', t('Settings')) ?>&nbsp;
<?php if ($this->user->isManager($project['id'])): ?>
<?= $this->url->link('<i class="fa fa-cog"></i>', 'project', 'show', array('project_id' => $project['id']), false, 'dashboard-table-link', t('Settings')) ?>&nbsp;
<?php endif ?>
<?= $this->a('<i class="fa fa-calendar"></i>', 'calendar', 'show', array('project_id' => $project['id']), false, 'dashboard-table-link', t('Calendar')) ?>&nbsp;
<?= $this->url->link('<i class="fa fa-calendar"></i>', 'calendar', 'show', array('project_id' => $project['id']), false, 'dashboard-table-link', t('Calendar')) ?>&nbsp;
<?= $this->a($this->e($project['name']), 'board', 'show', array('project_id' => $project['id'])) ?>
<?= $this->url->link($this->e($project['name']), 'board', 'show', array('project_id' => $project['id'])) ?>
<?php if (! empty($project['description'])): ?>
<span class="column-tooltip" title='<?= $this->e($this->markdown($project['description'])) ?>'>
<span class="column-tooltip" title='<?= $this->e($this->text->markdown($project['description'])) ?>'>
<i class="fa fa-info-circle"></i>
</span>
<?php endif ?>

View File

@ -13,16 +13,16 @@
<?php foreach ($paginator->getCollection() as $subtask): ?>
<tr>
<td class="task-table color-<?= $subtask['color_id'] ?>">
<?= $this->a('#'.$subtask['task_id'], 'task', 'show', array('task_id' => $subtask['task_id'], 'project_id' => $subtask['project_id'])) ?>
<?= $this->url->link('#'.$subtask['task_id'], 'task', 'show', array('task_id' => $subtask['task_id'], 'project_id' => $subtask['project_id'])) ?>
</td>
<td>
<?= $this->a($this->e($subtask['project_name']), 'board', 'show', array('project_id' => $subtask['project_id'])) ?>
<?= $this->url->link($this->e($subtask['project_name']), 'board', 'show', array('project_id' => $subtask['project_id'])) ?>
</td>
<td>
<?= $this->a($this->e($subtask['task_name']), 'task', 'show', array('task_id' => $subtask['task_id'], 'project_id' => $subtask['project_id'])) ?>
<?= $this->url->link($this->e($subtask['task_name']), 'task', 'show', array('task_id' => $subtask['task_id'], 'project_id' => $subtask['project_id'])) ?>
</td>
<td>
<?= $this->toggleSubtaskStatus($subtask, 'dashboard') ?>
<?= $this->subtask->toggleStatus($subtask, 'dashboard') ?>
</td>
<td>
<?php if (! empty($subtask['time_spent'])): ?>

View File

@ -13,13 +13,13 @@
<?php foreach ($paginator->getCollection() as $task): ?>
<tr>
<td class="task-table color-<?= $task['color_id'] ?>">
<?= $this->a('#'.$task['id'], 'task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])) ?>
<?= $this->url->link('#'.$task['id'], 'task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])) ?>
</td>
<td>
<?= $this->a($this->e($task['project_name']), 'board', 'show', array('project_id' => $task['project_id'])) ?>
<?= $this->url->link($this->e($task['project_name']), 'board', 'show', array('project_id' => $task['project_id'])) ?>
</td>
<td>
<?= $this->a($this->e($task['title']), 'task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])) ?>
<?= $this->url->link($this->e($task['title']), 'task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])) ?>
</td>
<td>
<?php if (! empty($task['time_spent'])): ?>

View File

@ -4,24 +4,24 @@
<p class="alert alert-error"><?= $this->e($errors['login']) ?></p>
<?php endif ?>
<form method="post" action="<?= $this->u('auth', 'check', array('redirect_query' => $redirect_query)) ?>">
<form method="post" action="<?= $this->url->href('auth', 'check', array('redirect_query' => $redirect_query)) ?>">
<?= $this->formCsrf() ?>
<?= $this->form->csrf() ?>
<?= $this->formLabel(t('Username'), 'username') ?>
<?= $this->formText('username', $values, $errors, array('autofocus', 'required')) ?><br/>
<?= $this->form->label(t('Username'), 'username') ?>
<?= $this->form->text('username', $values, $errors, array('autofocus', 'required')) ?><br/>
<?= $this->formLabel(t('Password'), 'password') ?>
<?= $this->formPassword('password', $values, $errors, array('required')) ?>
<?= $this->form->label(t('Password'), 'password') ?>
<?= $this->form->password('password', $values, $errors, array('required')) ?>
<?= $this->formCheckbox('remember_me', t('Remember Me'), 1) ?><br/>
<?= $this->form->checkbox('remember_me', t('Remember Me'), 1) ?><br/>
<?php if (GOOGLE_AUTH): ?>
<?= $this->a(t('Login with my Google Account'), 'user', 'google') ?>
<?= $this->url->link(t('Login with my Google Account'), 'user', 'google') ?>
<?php endif ?>
<?php if (GITHUB_AUTH): ?>
<?= $this->a(t('Login with my GitHub Account'), 'user', 'gitHub') ?>
<?= $this->url->link(t('Login with my GitHub Account'), 'user', 'gitHub') ?>
<?php endif ?>
<div class="form-actions">

View File

@ -1,20 +1,20 @@
<section id="main">
<section>
<h3><?= t('Change assignee for the task "%s"', $values['title']) ?></h3>
<form method="post" action="<?= $this->u('board', 'updateAssignee', array('task_id' => $values['id'], 'project_id' => $values['project_id'])) ?>">
<form method="post" action="<?= $this->url->href('board', 'updateAssignee', array('task_id' => $values['id'], 'project_id' => $values['project_id'])) ?>">
<?= $this->formCsrf() ?>
<?= $this->form->csrf() ?>
<?= $this->formHidden('id', $values) ?>
<?= $this->formHidden('project_id', $values) ?>
<?= $this->form->hidden('id', $values) ?>
<?= $this->form->hidden('project_id', $values) ?>
<?= $this->formLabel(t('Assignee'), 'owner_id') ?>
<?= $this->formSelect('owner_id', $users_list, $values, array(), array('autofocus')) ?><br/>
<?= $this->form->label(t('Assignee'), 'owner_id') ?>
<?= $this->form->select('owner_id', $users_list, $values, array(), array('autofocus')) ?><br/>
<div class="form-actions">
<input type="submit" value="<?= t('Save') ?>" class="btn btn-blue"/>
<?= t('or') ?>
<?= $this->a(t('cancel'), 'board', 'show', array('project_id' => $project['id']), false, 'close-popover') ?>
<?= $this->url->link(t('cancel'), 'board', 'show', array('project_id' => $project['id']), false, 'close-popover') ?>
</div>
</form>
</section>

View File

@ -1,20 +1,20 @@
<section id="main">
<section>
<h3><?= t('Change category for the task "%s"', $values['title']) ?></h3>
<form method="post" action="<?= $this->u('board', 'updateCategory', array('task_id' => $values['id'], 'project_id' => $values['project_id'])) ?>">
<form method="post" action="<?= $this->url->href('board', 'updateCategory', array('task_id' => $values['id'], 'project_id' => $values['project_id'])) ?>">
<?= $this->formCsrf() ?>
<?= $this->form->csrf() ?>
<?= $this->formHidden('id', $values) ?>
<?= $this->formHidden('project_id', $values) ?>
<?= $this->form->hidden('id', $values) ?>
<?= $this->form->hidden('project_id', $values) ?>
<?= $this->formLabel(t('Category'), 'category_id') ?>
<?= $this->formSelect('category_id', $categories_list, $values) ?><br/>
<?= $this->form->label(t('Category'), 'category_id') ?>
<?= $this->form->select('category_id', $categories_list, $values) ?><br/>
<div class="form-actions">
<input type="submit" value="<?= t('Save') ?>" class="btn btn-blue"/>
<?= t('or') ?>
<?= $this->a(t('cancel'), 'board', 'show', array('project_id' => $project['id']), false, 'close-popover') ?>
<?= $this->url->link(t('cancel'), 'board', 'show', array('project_id' => $project['id']), false, 'close-popover') ?>
</div>
</form>
</section>

View File

@ -6,7 +6,7 @@
<div class="comment-inner">
<div class="markdown">
<?= $this->markdown($comment['comment']) ?>
<?= $this->text->markdown($comment['comment']) ?>
</div>
</div>
<?php endforeach ?>

View File

@ -1,5 +1,5 @@
<section class="tooltip-large">
<div class="markdown">
<?= $this->markdown($task['description']) ?>
<?= $this->text->markdown($task['description']) ?>
</div>
</section>

View File

@ -8,8 +8,8 @@
<?= $this->e($file['name']) ?>
</td>
<td>
<i class="fa fa-download"></i> <?= $this->a(t('download'), 'file', 'download', array('task_id' => $task['id'], 'project_id' => $task['project_id'], 'file_id' => $file['id'])) ?>
<i class="fa fa-eye"></i> <?= $this->a(t('open'), 'file', 'open', array('task_id' => $task['id'], 'project_id' => $task['project_id'], 'file_id' => $file['id']), false, 'popover') ?>
<i class="fa fa-download"></i> <?= $this->url->link(t('download'), 'file', 'download', array('task_id' => $task['id'], 'project_id' => $task['project_id'], 'file_id' => $file['id'])) ?>
<i class="fa fa-eye"></i> <?= $this->url->link(t('open'), 'file', 'open', array('task_id' => $task['id'], 'project_id' => $task['project_id'], 'file_id' => $file['id']), false, 'popover') ?>
</td>
</tr>
<?php endforeach ?>
@ -18,11 +18,11 @@
<?php foreach ($files as $file): ?>
<tr>
<td>
<i class="fa <?= $this->getFileIcon($file['name']) ?> fa-fw"></i>
<i class="fa <?= $this->file->icon($file['name']) ?> fa-fw"></i>
<?= $this->e($file['name']) ?>
</td>
<td>
<i class="fa fa-download"></i> <?= $this->a(t('download'), 'file', 'download', array('task_id' => $task['id'], 'project_id' => $task['project_id'], 'file_id' => $file['id'])) ?>
<i class="fa fa-download"></i> <?= $this->url->link(t('download'), 'file', 'download', array('task_id' => $task['id'], 'project_id' => $task['project_id'], 'file_id' => $file['id'])) ?>
</td>
</tr>
<?php endforeach ?>

View File

@ -23,37 +23,37 @@
</li>
<li>
<i class="fa fa-search fa-fw"></i>
<?= $this->a(t('Search'), 'project', 'search', array('project_id' => $project['id'])) ?>
<?= $this->url->link(t('Search'), 'project', 'search', array('project_id' => $project['id'])) ?>
</li>
<li>
<i class="fa fa-check-square-o fa-fw"></i>
<?= $this->a(t('Completed tasks'), 'project', 'tasks', array('project_id' => $project['id'])) ?>
<?= $this->url->link(t('Completed tasks'), 'project', 'tasks', array('project_id' => $project['id'])) ?>
</li>
<li>
<i class="fa fa-dashboard fa-fw"></i>
<?= $this->a(t('Activity'), 'project', 'activity', array('project_id' => $project['id'])) ?>
<?= $this->url->link(t('Activity'), 'project', 'activity', array('project_id' => $project['id'])) ?>
</li>
<li>
<i class="fa fa-calendar fa-fw"></i>
<?= $this->a(t('Calendar'), 'calendar', 'show', array('project_id' => $project['id'])) ?>
<?= $this->url->link(t('Calendar'), 'calendar', 'show', array('project_id' => $project['id'])) ?>
</li>
<?php if ($project['is_public']): ?>
<li>
<i class="fa fa-share-alt fa-fw"></i> <?= $this->a(t('Public link'), 'board', 'readonly', array('token' => $project['token']), false, '', '', true) ?>
<i class="fa fa-share-alt fa-fw"></i> <?= $this->url->link(t('Public link'), 'board', 'readonly', array('token' => $project['token']), false, '', '', true) ?>
</li>
<?php endif ?>
<?php if ($this->acl->isManagerActionAllowed($project['id'])): ?>
<?php if ($this->user->isManager($project['id'])): ?>
<li>
<i class="fa fa-line-chart fa-fw"></i>
<?= $this->a(t('Analytics'), 'analytic', 'tasks', array('project_id' => $project['id'])) ?>
<?= $this->url->link(t('Analytics'), 'analytic', 'tasks', array('project_id' => $project['id'])) ?>
</li>
<li>
<i class="fa fa-pie-chart fa-fw"></i>
<?= $this->a(t('Budget'), 'budget', 'index', array('project_id' => $project['id'])) ?>
<?= $this->url->link(t('Budget'), 'budget', 'index', array('project_id' => $project['id'])) ?>
</li>
<li>
<i class="fa fa-cog fa-fw"></i>
<?= $this->a(t('Configure'), 'project', 'show', array('project_id' => $project['id'])) ?>
<?= $this->url->link(t('Configure'), 'project', 'show', array('project_id' => $project['id'])) ?>
</li>
<?php endif ?>
</ul>
@ -61,10 +61,10 @@
</span>
</li>
<li>
<?= $this->formSelect('user_id', $users, array(), array(), array('data-placeholder="'.t('Filter by user').'"', 'data-notfound="'.t('No results match:').'"'), 'apply-filters chosen-select') ?>
<?= $this->form->select('user_id', $users, array(), array(), array('data-placeholder="'.t('Filter by user').'"', 'data-notfound="'.t('No results match:').'"'), 'apply-filters chosen-select') ?>
</li>
<li>
<?= $this->formSelect('category_id', $categories, array(), array(), array('data-placeholder="'.t('Filter by category').'"', 'data-notfound="'.t('No results match:').'"'), 'apply-filters chosen-select') ?>
<?= $this->form->select('category_id', $categories, array(), array(), array('data-placeholder="'.t('Filter by category').'"', 'data-notfound="'.t('No results match:').'"'), 'apply-filters chosen-select') ?>
</li>
<li>
<select id="more-filters" multiple data-placeholder="<?= t('More filters') ?>" data-notfound="<?= t('No results match:') ?>" class="apply-filters hide-mobile">

View File

@ -6,9 +6,9 @@
class="board-project-<?= $project['id'] ?>"
data-project-id="<?= $project['id'] ?>"
data-check-interval="<?= $board_private_refresh_interval ?>"
data-save-url="<?= $this->u('board', 'save', array('project_id' => $project['id'])) ?>"
data-check-url="<?= $this->u('board', 'check', array('project_id' => $project['id'], 'timestamp' => time())) ?>"
data-task-creation-url="<?= $this->u('task', 'create', array('project_id' => $project['id'])) ?>"
data-save-url="<?= $this->url->href('board', 'save', array('project_id' => $project['id'])) ?>"
data-check-url="<?= $this->url->href('board', 'check', array('project_id' => $project['id'], 'timestamp' => time())) ?>"
data-task-creation-url="<?= $this->url->href('task', 'create', array('project_id' => $project['id'])) ?>"
>
<?php endif ?>

View File

@ -1,7 +1,7 @@
<section id="tooltip-subtasks">
<?php foreach ($subtasks as $subtask): ?>
<?= $this->toggleSubtaskStatus($subtask, 'board') ?>
<?= $this->e(empty($subtask['username']) ? '' : ' ['.$this->getFullname($subtask).']') ?>
<?= $this->subtask->toggleStatus($subtask, 'board') ?>
<?= $this->e(empty($subtask['username']) ? '' : ' ['.$this->user->getFullname($subtask).']') ?>
<br/>
<?php endforeach ?>
</section>

View File

@ -21,14 +21,14 @@
<th class="board-column">
<?php if (! $not_editable): ?>
<div class="board-add-icon">
<?= $this->a('+', 'task', 'create', array('project_id' => $column['project_id'], 'column_id' => $column['id'], 'swimlane_id' => $swimlane['id']), false, 'task-board-popover', t('Add a new task')) ?>
<?= $this->url->link('+', 'task', 'create', array('project_id' => $column['project_id'], 'column_id' => $column['id'], 'swimlane_id' => $swimlane['id']), false, 'task-board-popover', t('Add a new task')) ?>
</div>
<?php endif ?>
<?= $this->e($column['title']) ?>
<?php if (! $not_editable && ! empty($column['description'])): ?>
<span class="column-tooltip pull-right" title='<?= $this->e($this->markdown($column['description'])) ?>'>
<span class="column-tooltip pull-right" title='<?= $this->e($this->text->markdown($column['description'])) ?>'>
<i class="fa fa-info-circle"></i>
</span>
<?php endif ?>

View File

@ -2,16 +2,16 @@
<div class="task-board-category-container">
<span class="task-board-category">
<?php if ($not_editable): ?>
<?= $this->inList($task['category_id'], $categories_listing) ?>
<?= $this->text->in($task['category_id'], $categories_listing) ?>
<?php else: ?>
<?= $this->a(
$this->inList($task['category_id'], $categories_listing),
<?= $this->url->link(
$this->text->in($task['category_id'], $categories_listing),
'board',
'changeCategory',
array('task_id' => $task['id'], 'project_id' => $task['project_id']),
false,
'task-board-popover' . (isset($categories_description[$task['category_id']]) ? ' column-tooltip' : ''),
isset($categories_description[$task['category_id']]) ? $this->markdown($categories_description[$task['category_id']]) : t('Change category')
isset($categories_description[$task['category_id']]) ? $this->text->markdown($categories_description[$task['category_id']]) : t('Change category')
) ?>
<?php endif ?>
</span>
@ -26,31 +26,31 @@
<?php endif ?>
<?php if ($task['recurrence_status'] == \Model\Task::RECURRING_STATUS_PENDING): ?>
<span title="<?= t('Recurrence') ?>" class="task-board-tooltip" data-href="<?= $this->u('board', 'recurrence', array('task_id' => $task['id'], 'project_id' => $task['project_id'])) ?>"><i class="fa fa-refresh fa-rotate-90"></i></span>
<span title="<?= t('Recurrence') ?>" class="task-board-tooltip" data-href="<?= $this->url->href('board', 'recurrence', array('task_id' => $task['id'], 'project_id' => $task['project_id'])) ?>"><i class="fa fa-refresh fa-rotate-90"></i></span>
<?php endif ?>
<?php if ($task['recurrence_status'] == \Model\Task::RECURRING_STATUS_PROCESSED): ?>
<span title="<?= t('Recurrence') ?>" class="task-board-tooltip" data-href="<?= $this->u('board', 'recurrence', array('task_id' => $task['id'], 'project_id' => $task['project_id'])) ?>"><i class="fa fa-refresh fa-rotate-90 fa-inverse"></i></span>
<span title="<?= t('Recurrence') ?>" class="task-board-tooltip" data-href="<?= $this->url->href('board', 'recurrence', array('task_id' => $task['id'], 'project_id' => $task['project_id'])) ?>"><i class="fa fa-refresh fa-rotate-90 fa-inverse"></i></span>
<?php endif ?>
<?php if (! empty($task['nb_links'])): ?>
<span title="<?= t('Links') ?>" class="task-board-tooltip" data-href="<?= $this->u('board', 'tasklinks', array('task_id' => $task['id'], 'project_id' => $task['project_id'])) ?>"><i class="fa fa-code-fork"></i>&nbsp;<?= $task['nb_links'] ?></span>
<span title="<?= t('Links') ?>" class="task-board-tooltip" data-href="<?= $this->url->href('board', 'tasklinks', array('task_id' => $task['id'], 'project_id' => $task['project_id'])) ?>"><i class="fa fa-code-fork"></i>&nbsp;<?= $task['nb_links'] ?></span>
<?php endif ?>
<?php if (! empty($task['nb_subtasks'])): ?>
<span title="<?= t('Sub-Tasks') ?>" class="task-board-tooltip" data-href="<?= $this->u('board', 'subtasks', array('task_id' => $task['id'], 'project_id' => $task['project_id'])) ?>"><i class="fa fa-bars"></i>&nbsp;<?= round($task['nb_completed_subtasks']/$task['nb_subtasks']*100, 0).'%' ?></span>
<span title="<?= t('Sub-Tasks') ?>" class="task-board-tooltip" data-href="<?= $this->url->href('board', 'subtasks', array('task_id' => $task['id'], 'project_id' => $task['project_id'])) ?>"><i class="fa fa-bars"></i>&nbsp;<?= round($task['nb_completed_subtasks']/$task['nb_subtasks']*100, 0).'%' ?></span>
<?php endif ?>
<?php if (! empty($task['nb_files'])): ?>
<span title="<?= t('Attachments') ?>" class="task-board-tooltip" data-href="<?= $this->u('board', 'attachments', array('task_id' => $task['id'], 'project_id' => $task['project_id'])) ?>"><i class="fa fa-paperclip"></i>&nbsp;<?= $task['nb_files'] ?></span>
<span title="<?= t('Attachments') ?>" class="task-board-tooltip" data-href="<?= $this->url->href('board', 'attachments', array('task_id' => $task['id'], 'project_id' => $task['project_id'])) ?>"><i class="fa fa-paperclip"></i>&nbsp;<?= $task['nb_files'] ?></span>
<?php endif ?>
<?php if (! empty($task['nb_comments'])): ?>
<span title="<?= p($task['nb_comments'], t('%d comment', $task['nb_comments']), t('%d comments', $task['nb_comments'])) ?>" class="task-board-tooltip" data-href="<?= $this->u('board', 'comments', array('task_id' => $task['id'], 'project_id' => $task['project_id'])) ?>"><i class="fa fa-comment-o"></i>&nbsp;<?= $task['nb_comments'] ?></span>
<span title="<?= p($task['nb_comments'], t('%d comment', $task['nb_comments']), t('%d comments', $task['nb_comments'])) ?>" class="task-board-tooltip" data-href="<?= $this->url->href('board', 'comments', array('task_id' => $task['id'], 'project_id' => $task['project_id'])) ?>"><i class="fa fa-comment-o"></i>&nbsp;<?= $task['nb_comments'] ?></span>
<?php endif ?>
<?php if (! empty($task['description'])): ?>
<span title="<?= t('Description') ?>" class="task-board-tooltip" data-href="<?= $this->u('board', 'description', array('task_id' => $task['id'], 'project_id' => $task['project_id'])) ?>">
<span title="<?= t('Description') ?>" class="task-board-tooltip" data-href="<?= $this->url->href('board', 'description', array('task_id' => $task['id'], 'project_id' => $task['project_id'])) ?>">
<i class="fa fa-file-text-o"></i>
</span>
<?php endif ?>

View File

@ -2,15 +2,15 @@
<span>
<a href="#" class="dropdown-menu"><?= '#'.$task['id'] ?></a>
<ul>
<li><i class="fa fa-user"></i> <?= $this->a(t('Change assignee'), 'board', 'changeAssignee', array('task_id' => $task['id'], 'project_id' => $task['project_id']), false, 'task-board-popover') ?></li>
<li><i class="fa fa-tag"></i> <?= $this->a(t('Change category'), 'board', 'changeCategory', array('task_id' => $task['id'], 'project_id' => $task['project_id']), false, 'task-board-popover') ?></li>
<li><i class="fa fa-align-left"></i> <?= $this->a(t('Change description'), 'task', 'description', array('task_id' => $task['id'], 'project_id' => $task['project_id']), false, 'task-board-popover') ?></li>
<li><i class="fa fa-pencil-square-o"></i> <?= $this->a(t('Edit this task'), 'task', 'edit', array('task_id' => $task['id'], 'project_id' => $task['project_id']), false, 'task-board-popover') ?></li>
<li><i class="fa fa-comment-o"></i> <?= $this->a(t('Add a comment'), 'comment', 'create', array('task_id' => $task['id'], 'project_id' => $task['project_id']), false, 'task-board-popover') ?></li>
<li><i class="fa fa-code-fork"></i> <?= $this->a(t('Add a link'), 'tasklink', 'create', array('task_id' => $task['id'], 'project_id' => $task['project_id']), false, 'task-board-popover') ?></li>
<li><i class="fa fa-camera"></i> <?= $this->a(t('Add a screenshot'), 'board', 'screenshot', array('task_id' => $task['id'], 'project_id' => $task['project_id']), false, 'task-board-popover') ?></li>
<li><i class="fa fa-refresh fa-rotate-90"></i> <?= $this->a(t('Edit recurrence'), 'task', 'recurrence', array('task_id' => $task['id'], 'project_id' => $task['project_id']), false, 'task-board-popover') ?></li>
<li><i class="fa fa-close"></i> <?= $this->a(t('Close this task'), 'task', 'close', array('task_id' => $task['id'], 'project_id' => $task['project_id'], 'redirect' => 'board'), false, 'task-board-popover') ?></li>
<li><i class="fa fa-user"></i> <?= $this->url->link(t('Change assignee'), 'board', 'changeAssignee', array('task_id' => $task['id'], 'project_id' => $task['project_id']), false, 'task-board-popover') ?></li>
<li><i class="fa fa-tag"></i> <?= $this->url->link(t('Change category'), 'board', 'changeCategory', array('task_id' => $task['id'], 'project_id' => $task['project_id']), false, 'task-board-popover') ?></li>
<li><i class="fa fa-align-left"></i> <?= $this->url->link(t('Change description'), 'task', 'description', array('task_id' => $task['id'], 'project_id' => $task['project_id']), false, 'task-board-popover') ?></li>
<li><i class="fa fa-pencil-square-o"></i> <?= $this->url->link(t('Edit this task'), 'task', 'edit', array('task_id' => $task['id'], 'project_id' => $task['project_id']), false, 'task-board-popover') ?></li>
<li><i class="fa fa-comment-o"></i> <?= $this->url->link(t('Add a comment'), 'comment', 'create', array('task_id' => $task['id'], 'project_id' => $task['project_id']), false, 'task-board-popover') ?></li>
<li><i class="fa fa-code-fork"></i> <?= $this->url->link(t('Add a link'), 'tasklink', 'create', array('task_id' => $task['id'], 'project_id' => $task['project_id']), false, 'task-board-popover') ?></li>
<li><i class="fa fa-camera"></i> <?= $this->url->link(t('Add a screenshot'), 'board', 'screenshot', array('task_id' => $task['id'], 'project_id' => $task['project_id']), false, 'task-board-popover') ?></li>
<li><i class="fa fa-refresh fa-rotate-90"></i> <?= $this->url->link(t('Edit recurrence'), 'task', 'recurrence', array('task_id' => $task['id'], 'project_id' => $task['project_id']), false, 'task-board-popover') ?></li>
<li><i class="fa fa-close"></i> <?= $this->url->link(t('Close this task'), 'task', 'close', array('task_id' => $task['id'], 'project_id' => $task['project_id'], 'redirect' => 'board'), false, 'task-board-popover') ?></li>
</ul>
</span>
</span>

View File

@ -3,12 +3,12 @@
data-owner-id="<?= $task['owner_id'] ?>"
data-category-id="<?= $task['category_id'] ?>"
data-due-date="<?= $task['date_due'] ?>"
data-task-url="<?= $this->u('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])) ?>">
data-task-url="<?= $this->url->href('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])) ?>">
<?= $this->render('board/task_menu', array('task' => $task)) ?>
<div class="task-board-collapsed" style="display: none">
<?= $this->a($this->e($task['title']), 'task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id']), false, 'task-board-collapsed-title') ?>
<?= $this->url->link($this->e($task['title']), 'task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id']), false, 'task-board-collapsed-title') ?>
</div>
<div class="task-board-expanded">
@ -19,8 +19,8 @@
</span>
<?php endif ?>
<span class="task-board-user <?= $this->userSession->isCurrentUser($task['owner_id']) ? 'task-board-current-user' : '' ?>">
<?= $this->a(
<span class="task-board-user <?= $this->user->isCurrentUser($task['owner_id']) ? 'task-board-current-user' : '' ?>">
<?= $this->url->link(
(! empty($task['owner_id']) ? ($task['assignee_name'] ?: $task['assignee_username']) : t('Nobody assigned')),
'board',
'changeAssignee',
@ -32,12 +32,12 @@
</span>
<div class="task-board-days">
<span title="<?= t('Task age in days')?>" class="task-days-age"><?= $this->getTaskAge($task['date_creation']) ?></span>
<span title="<?= t('Days in this column')?>" class="task-days-incolumn"><?= $this->getTaskAge($task['date_moved']) ?></span>
<span title="<?= t('Task age in days')?>" class="task-days-age"><?= $this->task->age($task['date_creation']) ?></span>
<span title="<?= t('Days in this column')?>" class="task-days-incolumn"><?= $this->task->age($task['date_moved']) ?></span>
</div>
<div class="task-board-title">
<?= $this->a($this->e($task['title']), 'task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id']), false, '', t('View this task')) ?>
<?= $this->url->link($this->e($task['title']), 'task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id']), false, '', t('View this task')) ?>
</div>
<?= $this->render('board/task_footer', array(

View File

@ -1,6 +1,6 @@
<div class="task-board color-<?= $task['color_id'] ?> <?= $task['date_modification'] > time() - $board_highlight_period ? 'task-board-recent' : '' ?>">
<?= $this->a('#'.$task['id'], 'task', 'readonly', array('task_id' => $task['id'], 'token' => $project['token'])) ?>
<?= $this->url->link('#'.$task['id'], 'task', 'readonly', array('task_id' => $task['id'], 'token' => $project['token'])) ?>
<?php if ($task['reference']): ?>
<span class="task-board-reference" title="<?= t('Reference') ?>">
@ -19,7 +19,7 @@
</span>
<div class="task-board-title">
<?= $this->a($this->e($task['title']), 'task', 'readonly', array('task_id' => $task['id'], 'token' => $project['token'])) ?>
<?= $this->url->link($this->e($task['title']), 'task', 'readonly', array('task_id' => $task['id'], 'token' => $project['token'])) ?>
</div>
<?= $this->render('board/task_footer', array(

View File

@ -3,7 +3,7 @@
<?php foreach($links as $link): ?>
<li>
<strong><?= t($link['label']) ?></strong>
<?= $this->a(
<?= $this->url->link(
$this->e('#'.$link['task_id'].' - '.$link['title']),
'task', 'show', array('task_id' => $link['task_id'], 'project_id' => $link['project_id']),
false,

View File

@ -1,8 +1,8 @@
<div class="page-header">
<h2><?= t('Budget') ?></h2>
<ul>
<li><?= $this->a(t('Budget lines'), 'budget', 'create', array('project_id' => $project['id'])) ?></li>
<li><?= $this->a(t('Cost breakdown'), 'budget', 'breakdown', array('project_id' => $project['id'])) ?></li>
<li><?= $this->url->link(t('Budget lines'), 'budget', 'create', array('project_id' => $project['id'])) ?></li>
<li><?= $this->url->link(t('Cost breakdown'), 'budget', 'breakdown', array('project_id' => $project['id'])) ?></li>
</ul>
</div>
@ -20,9 +20,9 @@
</tr>
<?php foreach ($paginator->getCollection() as $record): ?>
<tr>
<td><?= $this->a($this->e($record['task_title']), 'task', 'show', array('project_id' => $project['id'], 'task_id' => $record['task_id'])) ?></td>
<td><?= $this->a($this->e($record['subtask_title']), 'task', 'show', array('project_id' => $project['id'], 'task_id' => $record['task_id'])) ?></td>
<td><?= $this->a($this->e($record['name'] ?: $record['username']), 'user', 'show', array('user_id' => $record['user_id'])) ?></td>
<td><?= $this->url->link($this->e($record['task_title']), 'task', 'show', array('project_id' => $project['id'], 'task_id' => $record['task_id'])) ?></td>
<td><?= $this->url->link($this->e($record['subtask_title']), 'task', 'show', array('project_id' => $project['id'], 'task_id' => $record['task_id'])) ?></td>
<td><?= $this->url->link($this->e($record['name'] ?: $record['username']), 'user', 'show', array('user_id' => $record['user_id'])) ?></td>
<td><?= n($record['cost']) ?></td>
<td><?= n($record['time_spent']).' '.t('hours') ?></td>
<td><?= dt('%B %e, %Y', $record['start']) ?></td>

View File

@ -1,8 +1,8 @@
<div class="page-header">
<h2><?= t('Budget') ?></h2>
<ul>
<li><?= $this->a(t('Budget lines'), 'budget', 'create', array('project_id' => $project['id'])) ?></li>
<li><?= $this->a(t('Cost breakdown'), 'budget', 'breakdown', array('project_id' => $project['id'])) ?></li>
<li><?= $this->url->link(t('Budget lines'), 'budget', 'create', array('project_id' => $project['id'])) ?></li>
<li><?= $this->url->link(t('Cost breakdown'), 'budget', 'breakdown', array('project_id' => $project['id'])) ?></li>
</ul>
</div>
@ -20,7 +20,7 @@
<td><?= dt('%B %e, %Y', strtotime($line['date'])) ?></td>
<td><?= $this->e($line['comment']) ?></td>
<td>
<?= $this->a(t('Remove'), 'budget', 'confirm', array('project_id' => $project['id'], 'budget_id' => $line['id'])) ?>
<?= $this->url->link(t('Remove'), 'budget', 'confirm', array('project_id' => $project['id'], 'budget_id' => $line['id'])) ?>
</td>
</tr>
<?php endforeach ?>
@ -29,21 +29,21 @@
<h3><?= t('New budget line') ?></h3>
<?php endif ?>
<form method="post" action="<?= $this->u('budget', 'save', array('project_id' => $project['id'])) ?>" autocomplete="off">
<form method="post" action="<?= $this->url->href('budget', 'save', array('project_id' => $project['id'])) ?>" autocomplete="off">
<?= $this->formCsrf() ?>
<?= $this->form->csrf() ?>
<?= $this->formHidden('id', $values) ?>
<?= $this->formHidden('project_id', $values) ?>
<?= $this->form->hidden('id', $values) ?>
<?= $this->form->hidden('project_id', $values) ?>
<?= $this->formLabel(t('Amount'), 'amount') ?>
<?= $this->formText('amount', $values, $errors, array('required'), 'form-numeric') ?>
<?= $this->form->label(t('Amount'), 'amount') ?>
<?= $this->form->text('amount', $values, $errors, array('required'), 'form-numeric') ?>
<?= $this->formLabel(t('Date'), 'date') ?>
<?= $this->formText('date', $values, $errors, array('required'), 'form-date') ?>
<?= $this->form->label(t('Date'), 'date') ?>
<?= $this->form->text('date', $values, $errors, array('required'), 'form-date') ?>
<?= $this->formLabel(t('Comment'), 'comment') ?>
<?= $this->formText('comment', $values, $errors) ?>
<?= $this->form->label(t('Comment'), 'comment') ?>
<?= $this->form->text('comment', $values, $errors) ?>
<div class="form-actions">
<input type="submit" value="<?= t('Save') ?>" class="btn btn-blue"/>

View File

@ -1,11 +1,11 @@
<?= $this->js('assets/js/vendor/d3.v3.4.8.min.js') ?>
<?= $this->js('assets/js/vendor/dimple.v2.1.2.min.js') ?>
<?= $this->asset->js('assets/js/vendor/d3.v3.4.8.min.js') ?>
<?= $this->asset->js('assets/js/vendor/dimple.v2.1.2.min.js') ?>
<div class="page-header">
<h2><?= t('Budget') ?></h2>
<ul>
<li><?= $this->a(t('Budget lines'), 'budget', 'create', array('project_id' => $project['id'])) ?></li>
<li><?= $this->a(t('Cost breakdown'), 'budget', 'breakdown', array('project_id' => $project['id'])) ?></li>
<li><?= $this->url->link(t('Budget lines'), 'budget', 'create', array('project_id' => $project['id'])) ?></li>
<li><?= $this->url->link(t('Cost breakdown'), 'budget', 'breakdown', array('project_id' => $project['id'])) ?></li>
</ul>
</div>

View File

@ -6,8 +6,8 @@
<p class="alert alert-info"><?= t('Do you really want to remove this budget line?') ?></p>
<div class="form-actions">
<?= $this->a(t('Yes'), 'budget', 'remove', array('project_id' => $project['id'], 'budget_id' => $budget_id), true, 'btn btn-red') ?>
<?= $this->url->link(t('Yes'), 'budget', 'remove', array('project_id' => $project['id'], 'budget_id' => $budget_id), true, 'btn btn-red') ?>
<?= t('or') ?>
<?= $this->a(t('cancel'), 'budget', 'create', array('project_id' => $project['id'])) ?>
<?= $this->url->link(t('cancel'), 'budget', 'create', array('project_id' => $project['id'])) ?>
</div>
</div>

View File

@ -3,19 +3,19 @@
<ul>
<li>
<i class="fa fa-table fa-fw"></i>
<?= $this->a(t('Back to the board'), 'board', 'show', array('project_id' => $project['id'])) ?>
<?= $this->url->link(t('Back to the board'), 'board', 'show', array('project_id' => $project['id'])) ?>
</li>
<li>
<i class="fa fa-search fa-fw"></i>
<?= $this->a(t('Search'), 'project', 'search', array('project_id' => $project['id'])) ?>
<?= $this->url->link(t('Search'), 'project', 'search', array('project_id' => $project['id'])) ?>
</li>
<li>
<i class="fa fa-check-square-o fa-fw"></i>
<?= $this->a(t('Completed tasks'), 'project', 'tasks', array('project_id' => $project['id'])) ?>
<?= $this->url->link(t('Completed tasks'), 'project', 'tasks', array('project_id' => $project['id'])) ?>
</li>
<li>
<i class="fa fa-dashboard fa-fw"></i>
<?= $this->a(t('Activity'), 'project', 'activity', array('project_id' => $project['id'])) ?>
<?= $this->url->link(t('Activity'), 'project', 'activity', array('project_id' => $project['id'])) ?>
</li>
</ul>
</div>
@ -34,8 +34,8 @@
<div class="sidebar-content">
<div id="calendar"
data-project-id="<?= $project['id'] ?>"
data-save-url="<?= $this->u('calendar', 'save') ?>"
data-check-url="<?= $this->u('calendar', 'project', array('project_id' => $project['id'])) ?>"
data-save-url="<?= $this->url->href('calendar', 'save') ?>"
data-check-url="<?= $this->url->href('calendar', 'project', array('project_id' => $project['id'])) ?>"
data-check-interval="<?= $check_interval ?>"
>
</div>

View File

@ -4,37 +4,37 @@
<?= t('Filter by user') ?>
</li>
<li>
<?= $this->formSelect('owner_id', $users_list, array(), array(), array(), 'calendar-filter') ?>
<?= $this->form->select('owner_id', $users_list, array(), array(), array(), 'calendar-filter') ?>
</li>
<li>
<?= t('Filter by category') ?>
</li>
<li>
<?= $this->formSelect('category_id', $categories_list, array(), array(), array(), 'calendar-filter') ?>
<?= $this->form->select('category_id', $categories_list, array(), array(), array(), 'calendar-filter') ?>
</li>
<li>
<?= t('Filter by column') ?>
</li>
<li>
<?= $this->formSelect('column_id', $columns_list, array(), array(), array(), 'calendar-filter') ?>
<?= $this->form->select('column_id', $columns_list, array(), array(), array(), 'calendar-filter') ?>
</li>
<li>
<?= t('Filter by swimlane') ?>
</li>
<li>
<?= $this->formSelect('swimlane_id', $swimlanes_list, array(), array(), array(), 'calendar-filter') ?>
<?= $this->form->select('swimlane_id', $swimlanes_list, array(), array(), array(), 'calendar-filter') ?>
</li>
<li>
<?= t('Filter by color') ?>
</li>
<li>
<?= $this->formSelect('color_id', $colors_list, array(), array(), array(), 'calendar-filter') ?>
<?= $this->form->select('color_id', $colors_list, array(), array(), array(), 'calendar-filter') ?>
</li>
<li>
<?= t('Filter by status') ?>
</li>
<li>
<?= $this->formSelect('is_active', $status_list, array(), array(), array(), 'calendar-filter') ?>
<?= $this->form->select('is_active', $status_list, array(), array(), array(), 'calendar-filter') ?>
</li>
</ul>
</div>

Some files were not shown because too many files have changed in this diff Show More