diff options
Diffstat (limited to 'app/Model')
-rw-r--r-- | app/Model/Acl.php | 2 | ||||
-rw-r--r-- | app/Model/Action.php | 14 | ||||
-rw-r--r-- | app/Model/Base.php | 47 | ||||
-rw-r--r-- | app/Model/Board.php | 16 | ||||
-rw-r--r-- | app/Model/Comment.php | 23 | ||||
-rw-r--r-- | app/Model/File.php | 9 | ||||
-rw-r--r-- | app/Model/GitHub.php | 25 | ||||
-rw-r--r-- | app/Model/Google.php | 20 | ||||
-rw-r--r-- | app/Model/Ldap.php | 3 | ||||
-rw-r--r-- | app/Model/Notification.php | 215 | ||||
-rw-r--r-- | app/Model/Project.php | 36 | ||||
-rw-r--r-- | app/Model/RememberMe.php | 7 | ||||
-rw-r--r-- | app/Model/ReverseProxyAuth.php | 18 | ||||
-rw-r--r-- | app/Model/SubTask.php | 44 | ||||
-rw-r--r-- | app/Model/Task.php | 152 | ||||
-rw-r--r-- | app/Model/User.php | 11 | ||||
-rw-r--r-- | app/Model/Webhook.php | 8 |
17 files changed, 486 insertions, 164 deletions
diff --git a/app/Model/Acl.php b/app/Model/Acl.php index 8a87a6b2..c4b31079 100644 --- a/app/Model/Acl.php +++ b/app/Model/Acl.php @@ -33,7 +33,7 @@ class Acl extends Base 'board' => array('index', 'show', 'assign', 'assigntask', 'save', 'check'), 'project' => array('tasks', 'index', 'forbidden', 'search'), 'user' => array('index', 'edit', 'update', 'forbidden', 'logout', 'index', 'unlinkgoogle', 'unlinkgithub'), - 'config' => array('index', 'removeremembermetoken'), + 'config' => array('index', 'removeremembermetoken', 'notifications'), 'comment' => array('create', 'save', 'confirm', 'remove', 'update', 'edit', 'forbidden'), 'file' => array('create', 'save', 'download', 'confirm', 'remove', 'open', 'image'), 'subtask' => array('create', 'save', 'edit', 'update', 'confirm', 'remove'), diff --git a/app/Model/Action.php b/app/Model/Action.php index 25e72f58..effe8707 100644 --- a/app/Model/Action.php +++ b/app/Model/Action.php @@ -224,25 +224,25 @@ class Action extends Base switch ($name) { case 'TaskClose': $className = '\Action\TaskClose'; - return new $className($project_id, new Task($this->db, $this->event)); + return new $className($project_id, new Task($this->registry)); case 'TaskAssignCurrentUser': $className = '\Action\TaskAssignCurrentUser'; - return new $className($project_id, new Task($this->db, $this->event), new Acl($this->db, $this->event)); + return new $className($project_id, new Task($this->registry), new Acl($this->registry)); case 'TaskAssignSpecificUser': $className = '\Action\TaskAssignSpecificUser'; - return new $className($project_id, new Task($this->db, $this->event)); + return new $className($project_id, new Task($this->registry)); case 'TaskDuplicateAnotherProject': $className = '\Action\TaskDuplicateAnotherProject'; - return new $className($project_id, new Task($this->db, $this->event)); + return new $className($project_id, new Task($this->registry)); case 'TaskAssignColorUser': $className = '\Action\TaskAssignColorUser'; - return new $className($project_id, new Task($this->db, $this->event)); + return new $className($project_id, new Task($this->registry)); case 'TaskAssignColorCategory': $className = '\Action\TaskAssignColorCategory'; - return new $className($project_id, new Task($this->db, $this->event)); + return new $className($project_id, new Task($this->registry)); case 'TaskAssignCategoryColor': $className = '\Action\TaskAssignCategoryColor'; - return new $className($project_id, new Task($this->db, $this->event)); + return new $className($project_id, new Task($this->registry)); default: throw new LogicException('Action not found: '.$name); } diff --git a/app/Model/Base.php b/app/Model/Base.php index 66185aeb..92578ffc 100644 --- a/app/Model/Base.php +++ b/app/Model/Base.php @@ -17,6 +17,8 @@ require __DIR__.'/../../vendor/SimpleValidator/Validators/Email.php'; require __DIR__.'/../../vendor/SimpleValidator/Validators/Numeric.php'; use Core\Event; +use Core\Tool; +use Core\Registry; use PicoDb\Database; /** @@ -24,6 +26,21 @@ use PicoDb\Database; * * @package model * @author Frederic Guillot + * + * @property \Model\Acl $acl + * @property \Model\Action $action + * @property \Model\Board $board + * @property \Model\Category $category + * @property \Model\Comment $comment + * @property \Model\Config $config + * @property \Model\File $file + * @property \Model\LastLogin $lastLogin + * @property \Model\Ldap $ldap + * @property \Model\Notification $notification + * @property \Model\Project $project + * @property \Model\SubTask $subTask + * @property \Model\Task $task + * @property \Model\User $user */ abstract class Base { @@ -44,15 +61,35 @@ abstract class Base protected $event; /** + * Registry instance + * + * @access protected + * @var \Core\Registry + */ + protected $registry; + + /** * Constructor * * @access public - * @param \PicoDb\Database $db Database instance - * @param \Core\Event $event Event dispatcher instance + * @param \Core\Registry $registry Registry instance + */ + public function __construct(Registry $registry) + { + $this->registry = $registry; + $this->db = $this->registry->shared('db'); + $this->event = $this->registry->shared('event'); + } + + /** + * Load automatically models + * + * @access public + * @param string $name Model name + * @return mixed */ - public function __construct(Database $db, Event $event) + public function __get($name) { - $this->db = $db; - $this->event = $event; + return Tool::loadModel($this->registry, $name); } } diff --git a/app/Model/Board.php b/app/Model/Board.php index a4e0a345..168b185f 100644 --- a/app/Model/Board.php +++ b/app/Model/Board.php @@ -24,17 +24,18 @@ class Board extends Base * Save task positions for each column * * @access public - * @param array $values [['task_id' => X, 'column_id' => X, 'position' => X], ...] + * @param array $positions [['task_id' => X, 'column_id' => X, 'position' => X], ...] + * @param integer $selected_task_id The selected task id * @return boolean */ - public function saveTasksPosition(array $values) + public function saveTasksPosition(array $positions, $selected_task_id) { - $taskModel = new Task($this->db, $this->event); - $this->db->startTransaction(); - foreach ($values as $value) { - if (! $taskModel->move($value['task_id'], $value['column_id'], $value['position'])) { + foreach ($positions as $value) { + + // We trigger events only for the selected task + if (! $this->task->move($value['task_id'], $value['column_id'], $value['position'], $value['task_id'] == $selected_task_id)) { $this->db->cancelTransaction(); return false; } @@ -201,8 +202,7 @@ class Board extends Base $filters[] = array('column' => 'project_id', 'operator' => 'eq', 'value' => $project_id); $filters[] = array('column' => 'is_active', 'operator' => 'eq', 'value' => Task::STATUS_OPEN); - $taskModel = new Task($this->db, $this->event); - $tasks = $taskModel->find($filters); + $tasks = $this->task->find($filters); foreach ($columns as &$column) { diff --git a/app/Model/Comment.php b/app/Model/Comment.php index b5102070..b849fc23 100644 --- a/app/Model/Comment.php +++ b/app/Model/Comment.php @@ -21,6 +21,14 @@ class Comment extends Base const TABLE = 'comments'; /** + * Events + * + * @var string + */ + const EVENT_UPDATE = 'comment.update'; + const EVENT_CREATE = 'comment.create'; + + /** * Get all comments for a given task * * @access public @@ -95,7 +103,14 @@ class Comment extends Base { $values['date'] = time(); - return $this->db->table(self::TABLE)->save($values); + if ($this->db->table(self::TABLE)->save($values)) { + + $values['id'] = $this->db->getConnection()->getLastId(); + $this->event->trigger(self::EVENT_CREATE, $values); + return true; + } + + return false; } /** @@ -107,10 +122,14 @@ class Comment extends Base */ public function update(array $values) { - return $this->db + $result = $this->db ->table(self::TABLE) ->eq('id', $values['id']) ->update(array('comment' => $values['comment'])); + + $this->event->trigger(self::EVENT_UPDATE, $values); + + return $result; } /** diff --git a/app/Model/File.php b/app/Model/File.php index 2a793217..d5a0c7cd 100644 --- a/app/Model/File.php +++ b/app/Model/File.php @@ -25,6 +25,13 @@ class File extends Base const BASE_PATH = 'data/files/'; /** + * Events + * + * @var string + */ + const EVENT_CREATE = 'file.create'; + + /** * Get a file by the id * * @access public @@ -82,6 +89,8 @@ class File extends Base */ public function create($task_id, $name, $path, $is_image) { + $this->event->trigger(self::EVENT_CREATE, array('task_id' => $task_id, 'name' => $name)); + return $this->db->table(self::TABLE)->save(array( 'task_id' => $task_id, 'name' => $name, diff --git a/app/Model/GitHub.php b/app/Model/GitHub.php index 3380218d..bf4f4c51 100644 --- a/app/Model/GitHub.php +++ b/app/Model/GitHub.php @@ -26,22 +26,19 @@ class GitHub extends Base */
public function authenticate($github_id)
{
- $userModel = new User($this->db, $this->event);
-
- $user = $userModel->getByGitHubId($github_id);
+ $user = $this->user->getByGitHubId($github_id);
if ($user) {
// Create the user session
- $userModel->updateSession($user);
+ $this->user->updateSession($user);
// Update login history
- $lastLogin = new LastLogin($this->db, $this->event);
- $lastLogin->create(
+ $this->lastLogin->create(
LastLogin::AUTH_GITHUB,
$user['id'],
- $userModel->getIpAddress(),
- $userModel->getUserAgent()
+ $this->user->getIpAddress(),
+ $this->user->getUserAgent()
);
return true;
@@ -59,9 +56,7 @@ class GitHub extends Base */
public function unlink($user_id)
{
- $userModel = new User($this->db, $this->event);
-
- return $userModel->update(array(
+ return $this->user->update(array(
'id' => $user_id,
'github_id' => '',
));
@@ -78,9 +73,7 @@ class GitHub extends Base */
public function updateUser($user_id, array $profile)
{
- $userModel = new User($this->db, $this->event);
-
- return $userModel->update(array(
+ return $this->user->update(array(
'id' => $user_id,
'github_id' => $profile['id'],
'email' => $profile['email'],
@@ -141,7 +134,7 @@ class GitHub extends Base try {
$gitHubService = $this->getService();
$gitHubService->requestAccessToken($code);
-
+
return json_decode($gitHubService->request('user'), true);
}
catch (TokenResponseException $e) {
@@ -150,7 +143,7 @@ class GitHub extends Base return false;
}
-
+
/**
* Revokes this user's GitHub tokens for Kanboard
*
diff --git a/app/Model/Google.php b/app/Model/Google.php index f5beb8f8..cca4f668 100644 --- a/app/Model/Google.php +++ b/app/Model/Google.php @@ -27,21 +27,19 @@ class Google extends Base */ public function authenticate($google_id) { - $userModel = new User($this->db, $this->event); - $user = $userModel->getByGoogleId($google_id); + $user = $this->user->getByGoogleId($google_id); if ($user) { // Create the user session - $userModel->updateSession($user); + $this->user->updateSession($user); // Update login history - $lastLogin = new LastLogin($this->db, $this->event); - $lastLogin->create( + $this->lastLogin->create( LastLogin::AUTH_GOOGLE, $user['id'], - $userModel->getIpAddress(), - $userModel->getUserAgent() + $this->user->getIpAddress(), + $this->user->getUserAgent() ); return true; @@ -59,9 +57,7 @@ class Google extends Base */ public function unlink($user_id) { - $userModel = new User($this->db, $this->event); - - return $userModel->update(array( + return $this->user->update(array( 'id' => $user_id, 'google_id' => '', )); @@ -77,9 +73,7 @@ class Google extends Base */ public function updateUser($user_id, array $profile) { - $userModel = new User($this->db, $this->event); - - return $userModel->update(array( + return $this->user->update(array( 'id' => $user_id, 'google_id' => $profile['id'], 'email' => $profile['email'], diff --git a/app/Model/Ldap.php b/app/Model/Ldap.php index dabcd5ff..007f7171 100644 --- a/app/Model/Ldap.php +++ b/app/Model/Ldap.php @@ -73,8 +73,7 @@ class Ldap extends Base */ public function create($username, $name, $email) { - $userModel = new User($this->db, $this->event); - $user = $userModel->getByUsername($username); + $user = $this->user->getByUsername($username); // There is an existing user account if ($user) { diff --git a/app/Model/Notification.php b/app/Model/Notification.php new file mode 100644 index 00000000..e0f932a4 --- /dev/null +++ b/app/Model/Notification.php @@ -0,0 +1,215 @@ +<?php + +namespace Model; + +use Core\Template; +use Event\TaskNotificationListener; +use Event\CommentNotificationListener; +use Event\FileNotificationListener; +use Event\SubTaskNotificationListener; +use Swift_Message; +use Swift_Mailer; + +/** + * Notification model + * + * @package model + * @author Frederic Guillot + */ +class Notification extends Base +{ + /** + * SQL table name + * + * @var string + */ + const TABLE = 'user_has_notifications'; + + /** + * Get the list of users to send the notification for a given project + * + * @access public + * @param integer $project_id Project id + * @return array + */ + public function getUsersList($project_id) + { + $users = $this->db->table(User::TABLE) + ->columns('id', 'username', 'name', 'email') + ->eq('notifications_enabled', '1') + ->neq('email', '') + ->findAll(); + + foreach ($users as $index => $user) { + + $projects = $this->db->table(self::TABLE) + ->eq('user_id', $user['id']) + ->findAllByColumn('project_id'); + + // The user have selected only some projects + if (! empty($projects)) { + + // If the user didn't select this project we remove that guy from the list + if (! in_array($project_id, $projects)) { + unset($users[$index]); + } + } + } + + return $users; + } + + /** + * Attach events + * + * @access public + */ + public function attachEvents() + { + $this->event->attach(File::EVENT_CREATE, new FileNotificationListener($this, 'notification_file_creation')); + + $this->event->attach(Comment::EVENT_CREATE, new CommentNotificationListener($this, 'notification_comment_creation')); + $this->event->attach(Comment::EVENT_UPDATE, new CommentNotificationListener($this, 'notification_comment_update')); + + $this->event->attach(SubTask::EVENT_CREATE, new SubTaskNotificationListener($this, 'notification_subtask_creation')); + $this->event->attach(SubTask::EVENT_UPDATE, new SubTaskNotificationListener($this, 'notification_subtask_update')); + + $this->event->attach(Task::EVENT_CREATE, new TaskNotificationListener($this, 'notification_task_creation')); + $this->event->attach(Task::EVENT_UPDATE, new TaskNotificationListener($this, 'notification_task_update')); + $this->event->attach(Task::EVENT_CLOSE, new TaskNotificationListener($this, 'notification_task_close')); + $this->event->attach(Task::EVENT_OPEN, new TaskNotificationListener($this, 'notification_task_open')); + } + + /** + * Send the email notifications + * + * @access public + * @param string $template Template name + * @param array $users List of users + * @param array $data Template data + */ + public function sendEmails($template, array $users, array $data) + { + $transport = $this->registry->shared('mailer'); + $mailer = Swift_Mailer::newInstance($transport); + + $message = Swift_Message::newInstance() + ->setSubject($this->getMailSubject($template, $data)) + ->setFrom(array(MAIL_FROM => 'Kanboard')) + //->setTo(array($user['email'] => $user['name'])) + ->setBody($this->getMailContent($template, $data), 'text/html'); + + foreach ($users as $user) { + $message->setTo(array($user['email'] => $user['name'] ?: $user['username'])); + $mailer->send($message); + } + } + + /** + * Get the mail subject for a given template name + * + * @access public + * @param string $template Template name + * @param array $data Template data + */ + public function getMailSubject($template, array $data) + { + switch ($template) { + case 'notification_file_creation': + return t('[%s][New attachment] %s (#%d)', $data['task']['project_name'], $data['task']['title'], $data['task']['id']); + case 'notification_comment_creation': + return t('[%s][New comment] %s (#%d)', $data['task']['project_name'], $data['task']['title'], $data['task']['id']); + case 'notification_comment_update': + return t('[%s][Comment updated] %s (#%d)', $data['task']['project_name'], $data['task']['title'], $data['task']['id']); + case 'notification_subtask_creation': + return t('[%s][New subtask] %s (#%d)', $data['task']['project_name'], $data['task']['title'], $data['task']['id']); + case 'notification_subtask_update': + return t('[%s][Subtask updated] %s (#%d)', $data['task']['project_name'], $data['task']['title'], $data['task']['id']); + case 'notification_task_creation': + return t('[%s][New task] %s (#%d)', $data['task']['project_name'], $data['task']['title'], $data['task']['id']); + case 'notification_task_update': + return t('[%s][Task updated] %s (#%d)', $data['task']['project_name'], $data['task']['title'], $data['task']['id']); + case 'notification_task_close': + return t('[%s][Task closed] %s (#%d)', $data['task']['project_name'], $data['task']['title'], $data['task']['id']); + case 'notification_task_open': + return t('[%s][Task opened] %s (#%d)', $data['task']['project_name'], $data['task']['title'], $data['task']['id']); + case 'notification_task_due': + return t('[%s][Due tasks]', $data['project']); + } + + return t('[Kanboard] Notification'); + } + + /** + * Get the mail content for a given template name + * + * @access public + * @param string $template Template name + * @param array $data Template data + */ + public function getMailContent($template, array $data) + { + $tpl = new Template; + return $tpl->load($template, $data); + } + + /** + * Save settings for the given user + * + * @access public + * @param integer $user_id User id + * @param array $values Form values + */ + public function saveSettings($user_id, array $values) + { + // Delete all selected projects + $this->db->table(self::TABLE)->eq('user_id', $user_id)->remove(); + + if (isset($values['notifications_enabled']) && $values['notifications_enabled'] == 1) { + + // Activate notifications + $this->db->table(User::TABLE)->eq('id', $user_id)->update(array( + 'notifications_enabled' => '1' + )); + + // Save selected projects + if (! empty($values['projects'])) { + + foreach ($values['projects'] as $project_id => $checkbox_value) { + $this->db->table(self::TABLE)->insert(array( + 'user_id' => $user_id, + 'project_id' => $project_id, + )); + } + } + } + else { + + // Disable notifications + $this->db->table(User::TABLE)->eq('id', $user_id)->update(array( + 'notifications_enabled' => '0' + )); + } + } + + /** + * Read user settings to display the form + * + * @access public + * @param integer $user_id User id + * @return array + */ + public function readSettings($user_id) + { + $values = array(); + $values['notifications_enabled'] = $this->db->table(User::TABLE)->eq('id', $user_id)->findOneColumn('notifications_enabled'); + + $projects = $this->db->table(self::TABLE)->eq('user_id', $user_id)->findAllByColumn('project_id'); + + foreach ($projects as $project_id) { + $values['project_'.$project_id] = true; + } + + return $values; + } +} diff --git a/app/Model/Project.php b/app/Model/Project.php index f598c96f..63458fa3 100644 --- a/app/Model/Project.php +++ b/app/Model/Project.php @@ -55,10 +55,9 @@ class Project extends Base public function getUsersList($project_id, $prepend_unassigned = true, $prepend_everybody = false) { $allowed_users = $this->getAllowedUsers($project_id); - $userModel = new User($this->db, $this->event); if (empty($allowed_users)) { - $allowed_users = $userModel->getList(); + $allowed_users = $this->user->getList(); } if ($prepend_unassigned) { @@ -103,8 +102,7 @@ class Project extends Base 'not_allowed' => array(), ); - $userModel = new User($this->db, $this->event); - $all_users = $userModel->getList(); + $all_users = $this->user->getList(); $users['allowed'] = $this->getAllowedUsers($project_id); @@ -253,27 +251,23 @@ class Project extends Base ->asc('name') ->findAll(); - $boardModel = new Board($this->db, $this->event); - $taskModel = new Task($this->db, $this->event); - $aclModel = new Acl($this->db, $this->event); - foreach ($projects as $pkey => &$project) { - if ($check_permissions && ! $this->isUserAllowed($project['id'], $aclModel->getUserId())) { + if ($check_permissions && ! $this->isUserAllowed($project['id'], $this->acl->getUserId())) { unset($projects[$pkey]); } else { - $columns = $boardModel->getcolumns($project['id']); + $columns = $this->board->getcolumns($project['id']); $project['nb_active_tasks'] = 0; foreach ($columns as &$column) { - $column['nb_active_tasks'] = $taskModel->countByColumnId($project['id'], $column['id']); + $column['nb_active_tasks'] = $this->task->countByColumnId($project['id'], $column['id']); $project['nb_active_tasks'] += $column['nb_active_tasks']; } $project['columns'] = $columns; - $project['nb_tasks'] = $taskModel->countByProjectId($project['id']); + $project['nb_tasks'] = $this->task->countByProjectId($project['id']); $project['nb_inactive_tasks'] = $project['nb_tasks'] - $project['nb_active_tasks']; } } @@ -416,9 +410,8 @@ class Project extends Base */ public function copyBoardFromAnotherProject($project_from, $project_to) { - $boardModel = new Board($this->db, $this->event); $columns = $this->db->table(Board::TABLE)->eq('project_id', $project_from)->asc('position')->findAllByColumn('title'); - return $boardModel->create($project_to, $columns); + return $this->board->create($project_to, $columns); } /** @@ -431,8 +424,7 @@ class Project extends Base */ public function copyCategoriesFromAnotherProject($project_from, $project_to) { - $categoryModel = new Category($this->db, $this->event); - $categoriesTemplate = $categoryModel->getAll($project_from); + $categoriesTemplate = $this->category->getAll($project_from); foreach ($categoriesTemplate as $category) { @@ -478,8 +470,7 @@ class Project extends Base */ public function copyActionsFromAnotherProject($project_from, $project_to) { - $actionModel = new Action($this->db, $this->event); - $actionTemplate = $actionModel->getAllByProject($project_from); + $actionTemplate = $this->action->getAllByProject($project_from); foreach ($actionTemplate as $action) { @@ -522,13 +513,11 @@ class Project extends Base case 'project_id': return $project_to; case 'category_id': - $categoryModel = new Category($this->db, $this->event); - $categoryTemplate = $categoryModel->getById($param['value']); + $categoryTemplate = $this->category->getById($param['value']); $categoryFromNewProject = $this->db->table(Category::TABLE)->eq('project_id', $project_to)->eq('name', $categoryTemplate['name'])->findOne(); return $categoryFromNewProject['id']; case 'column_id': - $boardModel = new Board($this->db, $this->event); - $boardTemplate = $boardModel->getColumn($param['value']); + $boardTemplate = $this->board->getColumn($param['value']); $boardFromNewProject = $this->db->table(Board::TABLE)->eq('project_id', $project_to)->eq('title', $boardTemplate['title'])->findOne(); return $boardFromNewProject['id']; default: @@ -603,8 +592,7 @@ class Project extends Base $project_id = $this->db->getConnection()->getLastId(); - $boardModel = new Board($this->db, $this->event); - $boardModel->create($project_id, array( + $this->board->create($project_id, array( t('Backlog'), t('Ready'), t('Work in progress'), diff --git a/app/Model/RememberMe.php b/app/Model/RememberMe.php index 272b4916..e23ed887 100644 --- a/app/Model/RememberMe.php +++ b/app/Model/RememberMe.php @@ -92,11 +92,8 @@ class RememberMe extends Base ); // Create the session - $user = new User($this->db, $this->event); - $acl = new Acl($this->db, $this->event); - - $user->updateSession($user->getById($record['user_id'])); - $acl->isRememberMe(true); + $this->user->updateSession($this->user->getById($record['user_id'])); + $this->acl->isRememberMe(true); return true; } diff --git a/app/Model/ReverseProxyAuth.php b/app/Model/ReverseProxyAuth.php index 1b9ed06c..14d18ba3 100644 --- a/app/Model/ReverseProxyAuth.php +++ b/app/Model/ReverseProxyAuth.php @@ -23,24 +23,22 @@ class ReverseProxyAuth extends Base if (isset($_SERVER[REVERSE_PROXY_USER_HEADER])) { $login = $_SERVER[REVERSE_PROXY_USER_HEADER]; - $userModel = new User($this->db, $this->event); - $user = $userModel->getByUsername($login); + $user = $this->user->getByUsername($login); if (! $user) { $this->createUser($login); - $user = $userModel->getByUsername($login); + $user = $this->user->getByUsername($login); } // Create the user session - $userModel->updateSession($user); + $this->user->updateSession($user); // Update login history - $lastLogin = new LastLogin($this->db, $this->event); - $lastLogin->create( + $this->lastLogin->create( LastLogin::AUTH_REVERSE_PROXY, $user['id'], - $userModel->getIpAddress(), - $userModel->getUserAgent() + $this->user->getIpAddress(), + $this->user->getUserAgent() ); return true; @@ -58,9 +56,7 @@ class ReverseProxyAuth extends Base */ private function createUser($login) { - $userModel = new User($this->db, $this->event); - - return $userModel->create(array( + return $this->user->create(array( 'email' => strpos($login, '@') !== false ? $login : '', 'username' => $login, 'is_admin' => REVERSE_PROXY_DEFAULT_ADMIN === $login, diff --git a/app/Model/SubTask.php b/app/Model/SubTask.php index 21ccdaac..c7bab44b 100644 --- a/app/Model/SubTask.php +++ b/app/Model/SubTask.php @@ -42,6 +42,14 @@ class SubTask extends Base const STATUS_TODO = 0; /** + * Events + * + * @var string + */ + const EVENT_UPDATE = 'subtask.update'; + const EVENT_CREATE = 'subtask.create'; + + /** * Get available status * * @access public @@ -88,10 +96,27 @@ class SubTask extends Base * * @access public * @param integer $subtask_id Subtask id + * @param bool $more Fetch more data * @return array */ - public function getById($subtask_id) + public function getById($subtask_id, $more = false) { + if ($more) { + + $subtask = $this->db->table(self::TABLE) + ->eq(self::TABLE.'.id', $subtask_id) + ->columns(self::TABLE.'.*', User::TABLE.'.username', User::TABLE.'.name') + ->join(User::TABLE, 'id', 'user_id') + ->findOne(); + + if ($subtask) { + $status = $this->getStatusList(); + $subtask['status_name'] = $status[$subtask['status']]; + } + + return $subtask; + } + return $this->db->table(self::TABLE)->eq('id', $subtask_id)->findOne(); } @@ -116,7 +141,14 @@ class SubTask extends Base $values['time_spent'] = 0; } - return $this->db->table(self::TABLE)->save($values); + $result = $this->db->table(self::TABLE)->save($values); + + if ($result) { + $values['id'] = $this->db->getConnection()->getLastId(); + $this->event->trigger(self::EVENT_CREATE, $values); + } + + return $result; } /** @@ -136,7 +168,13 @@ class SubTask extends Base $values['time_spent'] = 0; } - return $this->db->table(self::TABLE)->eq('id', $values['id'])->save($values); + $result = $this->db->table(self::TABLE)->eq('id', $values['id'])->save($values); + + if ($result) { + $this->event->trigger(self::EVENT_UPDATE, $values); + } + + return $result; } /** diff --git a/app/Model/Task.php b/app/Model/Task.php index 0b2b9cf9..6647f041 100644 --- a/app/Model/Task.php +++ b/app/Model/Task.php @@ -63,6 +63,35 @@ class Task extends Base } /** + * Get a list of due tasks for all projects + * + * @access public + * @return array + */ + public function getTasksDue() + { + $tasks = $this->db->table(self::TABLE) + ->columns( + self::TABLE.'.id', + self::TABLE.'.title', + self::TABLE.'.date_due', + self::TABLE.'.project_id', + Project::TABLE.'.name AS project_name', + User::TABLE.'.username AS assignee_username', + User::TABLE.'.name AS assignee_name' + ) + ->join(Project::TABLE, 'id', 'project_id') + ->join(User::TABLE, 'id', 'owner_id') + ->eq(Project::TABLE.'.is_active', 1) + ->eq(self::TABLE.'.is_active', 1) + ->neq(self::TABLE.'.date_due', '') + ->lte(self::TABLE.'.date_due', mktime(23, 59, 59)) + ->findAll(); + + return $tasks; + } + + /** * Fetch one task * * @access public @@ -182,7 +211,7 @@ class Task extends Base 'tasks.category_id', 'users.username' ) - ->join('users', 'id', 'owner_id'); + ->join(User::TABLE, 'id', 'owner_id'); foreach ($filters as $key => $filter) { @@ -282,8 +311,6 @@ class Task extends Base { $this->db->startTransaction(); - $boardModel = new Board($this->db, $this->event); - // Get the original task $task = $this->getById($task_id); @@ -296,7 +323,7 @@ class Task extends Base $task['owner_id'] = 0; $task['category_id'] = 0; $task['is_active'] = 1; - $task['column_id'] = $boardModel->getFirstColumn($project_id); + $task['column_id'] = $this->board->getFirstColumn($project_id); $task['project_id'] = $project_id; $task['position'] = $this->countByColumnId($task['project_id'], $task['column_id']); @@ -318,17 +345,13 @@ class Task extends Base } /** - * Create a task + * Prepare data before task creation or modification * * @access public - * @param array $values Form values - * @return boolean + * @param array $values Form values */ - public function create(array $values) + public function prepare(array &$values) { - $this->db->startTransaction(); - - // Prepare data if (isset($values['another_task'])) { unset($values['another_task']); } @@ -336,14 +359,30 @@ class Task extends Base if (! empty($values['date_due']) && ! is_numeric($values['date_due'])) { $values['date_due'] = $this->parseDate($values['date_due']); } - else { + + // Force integer fields at 0 (for Postgresql) + if (isset($values['date_due']) && empty($values['date_due'])) { $values['date_due'] = 0; } - if (empty($values['score'])) { + if (isset($values['score']) && empty($values['score'])) { $values['score'] = 0; } + } + /** + * Create a task + * + * @access public + * @param array $values Form values + * @return boolean + */ + public function create(array $values) + { + $this->db->startTransaction(); + + // Prepare data + $this->prepare($values); $values['date_creation'] = time(); $values['position'] = $this->countByColumnId($values['project_id'], $values['column_id']); @@ -368,31 +407,21 @@ class Task extends Base * Update a task * * @access public - * @param array $values Form values + * @param array $values Form values + * @param boolean $trigger_events Flag to trigger events * @return boolean */ - public function update(array $values) + public function update(array $values, $trigger_events = true) { - // Prepare data - if (! empty($values['date_due']) && ! is_numeric($values['date_due'])) { - $values['date_due'] = $this->parseDate($values['date_due']); - } - - // Force integer fields at 0 (for Postgresql) - if (isset($values['date_due']) && empty($values['date_due'])) { - $values['date_due'] = 0; - } - - if (isset($values['score']) && empty($values['score'])) { - $values['score'] = 0; - } - + // Fetch original task $original_task = $this->getById($values['id']); if ($original_task === false) { return false; } + // Prepare data + $this->prepare($values); $updated_task = $values; $updated_task['date_modification'] = time(); unset($updated_task['id']); @@ -400,29 +429,40 @@ class Task extends Base $result = $this->db->table(self::TABLE)->eq('id', $values['id'])->update($updated_task); // Trigger events - if ($result) { - - $events = array( - self::EVENT_CREATE_UPDATE, - self::EVENT_UPDATE, - ); + if ($result && $trigger_events) { + $this->triggerUpdateEvents($original_task, $updated_task); + } - if (isset($values['column_id']) && $original_task['column_id'] != $values['column_id']) { - $events[] = self::EVENT_MOVE_COLUMN; - } - else if (isset($values['position']) && $original_task['position'] != $values['position']) { - $events[] = self::EVENT_MOVE_POSITION; - } + return $result; + } - $event_data = array_merge($original_task, $values); - $event_data['task_id'] = $original_task['id']; + /** + * Trigger events for task modification + * + * @access public + * @param array $original_task Original task data + * @param array $updated_task Updated task data + */ + public function triggerUpdateEvents(array $original_task, array $updated_task) + { + $events = array( + self::EVENT_CREATE_UPDATE, + self::EVENT_UPDATE, + ); - foreach ($events as $event) { - $this->event->trigger($event, $event_data); - } + if (isset($updated_task['column_id']) && $original_task['column_id'] != $updated_task['column_id']) { + $events[] = self::EVENT_MOVE_COLUMN; + } + else if (isset($updated_task['position']) && $original_task['position'] != $updated_task['position']) { + $events[] = self::EVENT_MOVE_POSITION; } - return $result; + $event_data = array_merge($original_task, $updated_task); + $event_data['task_id'] = $original_task['id']; + + foreach ($events as $event) { + $this->event->trigger($event, $event_data); + } } /** @@ -482,8 +522,7 @@ class Task extends Base */ public function remove($task_id) { - $file = new File($this->db, $this->event); - $file->removeAll($task_id); + $this->file->removeAll($task_id); return $this->db->table(self::TABLE)->eq('id', $task_id)->remove(); } @@ -492,20 +531,23 @@ class Task extends Base * Move a task to another column or to another position * * @access public - * @param integer $task_id Task id - * @param integer $column_id Column id - * @param integer $position Position (must be greater than 1) + * @param integer $task_id Task id + * @param integer $column_id Column id + * @param integer $position Position (must be greater than 1) + * @param boolean $trigger_events Flag to trigger events * @return boolean */ - public function move($task_id, $column_id, $position) + public function move($task_id, $column_id, $position, $trigger_events = true) { $this->event->clearTriggeredEvents(); - return $this->update(array( + $values = array( 'id' => $task_id, 'column_id' => $column_id, 'position' => $position, - )); + ); + + return $this->update($values, $trigger_events); } /** diff --git a/app/Model/User.php b/app/Model/User.php index b5744c44..d0e33fd0 100644 --- a/app/Model/User.php +++ b/app/Model/User.php @@ -340,8 +340,7 @@ class User extends Base $this->updateSession($user); // Update login history - $lastLogin = new LastLogin($this->db, $this->event); - $lastLogin->create( + $this->lastLogin->create( $method, $user['id'], $this->getIpAddress(), @@ -350,9 +349,8 @@ class User extends Base // Setup the remember me feature if (! empty($values['remember_me'])) { - $rememberMe = new RememberMe($this->db, $this->event); - $credentials = $rememberMe->create($user['id'], $this->getIpAddress(), $this->getUserAgent()); - $rememberMe->writeCookie($credentials['token'], $credentials['sequence'], $credentials['expiration']); + $credentials = $this->rememberMe->create($user['id'], $this->getIpAddress(), $this->getUserAgent()); + $this->rememberMe->writeCookie($credentials['token'], $credentials['sequence'], $credentials['expiration']); } } else { @@ -384,8 +382,7 @@ class User extends Base // LDAP authentication if (! $authenticated && LDAP_AUTH) { - $ldap = new Ldap($this->db, $this->event); - $authenticated = $ldap->authenticate($username, $password); + $authenticated = $this->ldap->authenticate($username, $password); $method = LastLogin::AUTH_LDAP; } diff --git a/app/Model/Webhook.php b/app/Model/Webhook.php index 679d3edc..872031cc 100644 --- a/app/Model/Webhook.php +++ b/app/Model/Webhook.php @@ -64,11 +64,9 @@ class Webhook extends Base */ public function attachEvents() { - $config = new Config($this->db, $this->event); - - $this->url_task_creation = $config->get('webhooks_url_task_creation'); - $this->url_task_modification = $config->get('webhooks_url_task_modification'); - $this->token = $config->get('webhooks_token'); + $this->url_task_creation = $this->config->get('webhooks_url_task_creation'); + $this->url_task_modification = $this->config->get('webhooks_url_task_modification'); + $this->token = $this->config->get('webhooks_token'); if ($this->url_task_creation) { $this->attachCreateEvents(); |