1<?php
2
3namespace Kanboard\Model;
4
5use Kanboard\Core\Base;
6use Kanboard\Core\Security\Role;
7
8/**
9 * Project User Role
10 *
11 * @package  Kanboard\Model
12 * @author   Frederic Guillot
13 */
14class ProjectUserRoleModel extends Base
15{
16    /**
17     * SQL table name
18     *
19     * @var string
20     */
21    const TABLE = 'project_has_users';
22
23    /**
24     * Get the list of active project for the given user
25     *
26     * @access public
27     * @param  integer  $user_id
28     * @return array
29     */
30    public function getActiveProjectsByUser($user_id)
31    {
32        return $this->getProjectsByUser($user_id, array(ProjectModel::ACTIVE));
33    }
34
35    /**
36     * Get the list of project visible for the given user
37     *
38     * @access public
39     * @param  integer  $user_id
40     * @param  array    $status
41     * @return array
42     */
43    public function getProjectsByUser($user_id, $status = array(ProjectModel::ACTIVE, ProjectModel::INACTIVE))
44    {
45        $userProjects = $this->db
46            ->hashtable(ProjectModel::TABLE)
47            ->eq(self::TABLE.'.user_id', $user_id)
48            ->in(ProjectModel::TABLE.'.is_active', $status)
49            ->join(self::TABLE, 'project_id', 'id')
50            ->getAll(ProjectModel::TABLE.'.id', ProjectModel::TABLE.'.name');
51
52        $groupProjects = $this->projectGroupRoleModel->getProjectsByUser($user_id, $status);
53        $projects = $userProjects + $groupProjects;
54
55        asort($projects);
56
57        return $projects;
58    }
59
60    /**
61     * For a given project get the role of the specified user
62     *
63     * @access public
64     * @param  integer  $project_id
65     * @param  integer  $user_id
66     * @return string
67     */
68    public function getUserRole($project_id, $user_id)
69    {
70        $role = $this->db->table(self::TABLE)->eq('user_id', $user_id)->eq('project_id', $project_id)->findOneColumn('role');
71
72        if (empty($role)) {
73            $role = $this->projectGroupRoleModel->getUserRole($project_id, $user_id);
74        }
75
76        return $role;
77    }
78
79    /**
80     * Get all users associated directly to the project
81     *
82     * @access public
83     * @param  integer $project_id
84     * @return array
85     */
86    public function getUsers($project_id)
87    {
88        return $this->db->table(self::TABLE)
89            ->columns(
90                UserModel::TABLE.'.id',
91                UserModel::TABLE.'.username',
92                UserModel::TABLE.'.name',
93                UserModel::TABLE.'.email',
94                self::TABLE.'.role'
95            )
96            ->join(UserModel::TABLE, 'id', 'user_id')
97            ->eq('project_id', $project_id)
98            ->asc(UserModel::TABLE.'.username')
99            ->asc(UserModel::TABLE.'.name')
100            ->findAll();
101    }
102
103    /**
104     * Get all users (fetch users from groups)
105     *
106     * @access public
107     * @param  integer $project_id
108     * @return array
109     */
110    public function getAllUsers($project_id)
111    {
112        $userMembers = $this->getUsers($project_id);
113        $groupMembers = $this->projectGroupRoleModel->getUsers($project_id);
114        $members = array_merge($userMembers, $groupMembers);
115
116        return $this->userModel->prepareList($members);
117    }
118
119    /**
120     * Get users grouped by role
121     *
122     * @access public
123     * @param  integer   $project_id   Project id
124     * @return array
125     */
126    public function getAllUsersGroupedByRole($project_id)
127    {
128        $users = array();
129
130        $userMembers = $this->getUsers($project_id);
131        $groupMembers = $this->projectGroupRoleModel->getUsers($project_id);
132        $members = array_merge($userMembers, $groupMembers);
133
134        foreach ($members as $user) {
135            if (! isset($users[$user['role']])) {
136                $users[$user['role']] = array();
137            }
138
139            $users[$user['role']][$user['id']] = $user['name'] ?: $user['username'];
140        }
141
142        return $users;
143    }
144
145    /**
146     * Get list of users that can be assigned to a task (only Manager and Member)
147     *
148     * @access public
149     * @param  integer $project_id
150     * @return array
151     */
152    public function getAssignableUsers($project_id)
153    {
154        $userMembers = $this->db->table(self::TABLE)
155            ->columns(UserModel::TABLE.'.id', UserModel::TABLE.'.username', UserModel::TABLE.'.name')
156            ->join(UserModel::TABLE, 'id', 'user_id')
157            ->eq(UserModel::TABLE.'.is_active', 1)
158            ->eq(self::TABLE.'.project_id', $project_id)
159            ->neq(self::TABLE.'.role', Role::PROJECT_VIEWER)
160            ->findAll();
161
162        $groupMembers = $this->projectGroupRoleModel->getAssignableUsers($project_id);
163        $members = array_merge($userMembers, $groupMembers);
164
165        return $this->userModel->prepareList($members);
166    }
167
168    /**
169     * Get list of users that can be assigned to a task (only Manager and Member)
170     *
171     * @access public
172     * @param  integer   $project_id    Project id
173     * @param  bool      $unassigned    Prepend the 'Unassigned' value
174     * @param  bool      $everybody     Prepend the 'Everbody' value
175     * @param  bool      $singleUser    If there is only one user return only this user
176     * @return array
177     */
178    public function getAssignableUsersList($project_id, $unassigned = true, $everybody = false, $singleUser = false)
179    {
180        $users = $this->getAssignableUsers($project_id);
181
182        if ($singleUser && count($users) === 1) {
183            return $users;
184        }
185
186        if ($unassigned) {
187            $users = array(t('Unassigned')) + $users;
188        }
189
190        if ($everybody) {
191            $users = array(UserModel::EVERYBODY_ID => t('Everybody')) + $users;
192        }
193
194        return $users;
195    }
196
197    /**
198     * Add a user to the project
199     *
200     * @access public
201     * @param  integer $project_id
202     * @param  integer $user_id
203     * @param  string  $role
204     * @return boolean
205     */
206    public function addUser($project_id, $user_id, $role)
207    {
208        return $this->db->table(self::TABLE)->insert(array(
209            'user_id' => $user_id,
210            'project_id' => $project_id,
211            'role' => $role,
212        ));
213    }
214
215    /**
216     * Remove a user from the project
217     *
218     * @access public
219     * @param  integer $project_id
220     * @param  integer $user_id
221     * @return boolean
222     */
223    public function removeUser($project_id, $user_id)
224    {
225        return $this->db->table(self::TABLE)->eq('user_id', $user_id)->eq('project_id', $project_id)->remove();
226    }
227
228    /**
229     * Change a user role for the project
230     *
231     * @access public
232     * @param  integer $project_id
233     * @param  integer $user_id
234     * @param  string  $role
235     * @return boolean
236     */
237    public function changeUserRole($project_id, $user_id, $role)
238    {
239        return $this->db->table(self::TABLE)
240            ->eq('user_id', $user_id)
241            ->eq('project_id', $project_id)
242            ->update(array(
243                'role' => $role,
244            ));
245    }
246
247    /**
248     * Copy user access from a project to another one
249     *
250     * @param  integer $project_src_id
251     * @param  integer $project_dst_id
252     * @return boolean
253     */
254    public function duplicate($project_src_id, $project_dst_id)
255    {
256        $rows = $this->db->table(self::TABLE)->eq('project_id', $project_src_id)->findAll();
257
258        foreach ($rows as $row) {
259            $result = $this->db->table(self::TABLE)->save(array(
260                'project_id' => $project_dst_id,
261                'user_id' => $row['user_id'],
262                'role' => $row['role'],
263            ));
264
265            if (! $result) {
266                return false;
267            }
268        }
269
270        return true;
271    }
272}
273