e31e913fa2cd26517bd444181d5ddc9e298a614d
[tine20] / tine20 / Admin / Controller / Group.php
1 <?php
2 /**
3  * Tine 2.0
4  *
5  * @package     Admin
6  * @subpackage  Controller
7  * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
8  * @author      Lars Kneschke <l.kneschke@metaways.de>
9  * @copyright   Copyright (c) 2007-2009 Metaways Infosystems GmbH (http://www.metaways.de)
10  * 
11  * @todo        make it possible to change default groups
12  * @todo        extend abstract record controller
13  */
14
15 /**
16  * Group Controller for Admin application
17  *
18  * @package     Admin
19  * @subpackage  Controller
20  */
21 class Admin_Controller_Group extends Tinebase_Controller_Abstract
22 {
23     /**
24      * holds the instance of the singleton
25      *
26      * @var Admin_Controller_Group
27      */
28     private static $_instance = NULL;
29         
30     /**
31      * @var Tinebase_SambaSAM_Ldap
32      */
33     protected $_samBackend = NULL;
34
35     /**
36      * the constructor
37      *
38      * don't use the constructor. use the singleton 
39      */
40     private function __construct() 
41     {
42         $this->_applicationName = 'Admin';
43     }
44
45     /**
46      * don't clone. Use the singleton.
47      *
48      */
49     private function __clone() 
50     {
51     }
52
53     /**
54      * the singleton pattern
55      *
56      * @return Admin_Controller_Group
57      */
58     public static function getInstance() 
59     {
60         if (self::$_instance === NULL) {
61             self::$_instance = new Admin_Controller_Group;
62         }
63         
64         return self::$_instance;
65     }
66     
67     /**
68      * get list of groups
69      *
70      * @param string $_filter
71      * @param string $_sort
72      * @param string $_dir
73      * @param int $_start
74      * @param int $_limit
75      * @return Tinebase_Record_RecordSet with record class Tinebase_Model_Group
76      */
77     public function search($filter = NULL, $sort = 'name', $dir = 'ASC', $start = NULL, $limit = NULL)
78     {
79         $this->checkRight('VIEW_ACCOUNTS');
80         
81         return Tinebase_Group::getInstance()->getGroups($filter, $sort, $dir, $start, $limit);
82     }
83    
84     /**
85      * count groups
86      *
87      * @param string $_filter string to search groups for
88      * @return int total group count
89      * 
90      * @todo add checkRight again / but first fix Tinebase_Frontend_Json::searchGroups
91      */
92     public function searchCount($_filter)
93     {
94         //$this->checkRight('VIEW_ACCOUNTS');
95         
96         $groups = Tinebase_Group::getInstance()->getGroups($_filter);
97         $result = count($groups);
98         
99         return $result;
100     }
101     
102     /**
103      * set all groups an user is member of
104      *
105      * @param  mixed  $_userId   the account as integer or Tinebase_Model_User
106      * @param  mixed  $_groupIds
107      * @return array
108      */
109     public function setGroupMemberships($_userId, $_groupIds)
110     {
111         $this->checkRight('MANAGE_ACCOUNTS');
112         
113         if ($_groupIds instanceof Tinebase_Record_RecordSet) {
114             $_groupIds = $_groupIds->getArrayOfIds();
115         }
116         
117         if (count($_groupIds) === 0) {
118             throw new Tinebase_Exception_InvalidArgument('user must belong to at least one group');
119         }
120         
121         $userId = Tinebase_Model_User::convertUserIdToInt($_userId);
122         
123         $groupMemberships = Tinebase_Group::getInstance()->getGroupMemberships($userId);
124         
125         $removeGroupMemberships = array_diff($groupMemberships, $_groupIds);
126         $addGroupMemberships    = array_diff($_groupIds, $groupMemberships);
127         
128         if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__ . ' current groupmemberships: ' . print_r($groupMemberships, true));
129         if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__ . ' new groupmemberships: ' . print_r($_groupIds, true));
130         if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__ . ' added groupmemberships: ' . print_r($addGroupMemberships, true));
131         if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__ . ' removed groupmemberships: ' . print_r($removeGroupMemberships, true));
132         
133         foreach ($addGroupMemberships as $groupId) {
134             $this->addGroupMember($groupId, $userId);
135         }
136         
137         foreach ($removeGroupMemberships as $groupId) {
138             try {
139                 $this->removeGroupMember($groupId, $userId);
140             } catch (Tinebase_Exception_Record_NotDefined $tern) {
141                 if (Tinebase_Core::isLogLevel(Zend_Log::WARN)) Tinebase_Core::getLogger()->warn(__METHOD__ . '::' . __LINE__ 
142                     . ' Could not remove group member from group ' . $groupId . ': ' . $tern);
143             }
144         }
145         
146         return Tinebase_Group::getInstance()->getGroupMemberships($userId);
147     }
148     
149     /**
150      * fetch one group identified by groupid
151      *
152      * @param int $_groupId
153      * @return Tinebase_Model_Group
154      */
155     public function get($_groupId)
156     {
157         $this->checkRight('VIEW_ACCOUNTS');
158         
159         $group = Tinebase_Group::getInstance()->getGroupById($_groupId);
160
161         return $group;
162     }  
163
164    /**
165      * add new group
166      *
167      * @param Tinebase_Model_Group $_group
168      * @param array $_groupMembers
169      * 
170      * @return Tinebase_Model_Group
171      */
172     public function create(Tinebase_Model_Group $_group)
173     {
174         $this->checkRight('MANAGE_ACCOUNTS');
175         
176         // avoid forging group id, get's created in backend
177         unset($_group->id);
178         
179         if (Tinebase_Application::getInstance()->isInstalled('Addressbook') === true) {
180             $list = $this->createOrUpdateList($_group);
181             $_group->list_id = $list->getId();
182         }
183         
184         Tinebase_Timemachine_ModificationLog::setRecordMetaData($_group, 'create');
185         
186         try {
187             $group = Tinebase_Group::getInstance()->addGroup($_group);
188         } catch (Exception $e) {
189             // remove list again, if group creation fails
190             if (isset($list)) {
191                 $listsBackend = new Addressbook_Backend_List();
192                 $listsBackend->delete($list);
193             }
194             throw $e;
195         }
196         
197         if (!empty($_group['members']) ) {
198             Tinebase_Group::getInstance()->setGroupMembers($group->getId(), $_group['members']);
199         }
200         
201         $event = new Admin_Event_CreateGroup();
202         $event->group = $group;
203         Tinebase_Event::fireEvent($event);
204         
205         return $group;
206     }  
207
208    /**
209      * update existing group
210      *
211      * @param Tinebase_Model_Group $_group
212      * @return Tinebase_Model_Group
213      */
214     public function update(Tinebase_Model_Group $_group)
215     {
216         $this->checkRight('MANAGE_ACCOUNTS');
217         
218         // update default user group if name has changed
219         $oldGroup = Tinebase_Group::getInstance()->getGroupById($_group->getId());
220         
221         $defaultGroupName = Tinebase_User::getBackendConfiguration(Tinebase_User::DEFAULT_USER_GROUP_NAME_KEY);
222         if ($oldGroup->name == $defaultGroupName && $oldGroup->name != $_group->name) {
223             Tinebase_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ 
224                 . ' Updated default group name: ' . $oldGroup->name . ' -> ' . $_group->name
225             );
226             Tinebase_User::setBackendConfiguration($_group->name, Tinebase_User::DEFAULT_USER_GROUP_NAME_KEY);
227             Tinebase_User::saveBackendConfiguration();
228         }
229         
230         $transactionId = Tinebase_TransactionManager::getInstance()->startTransaction(Tinebase_Core::getDb());
231         
232         if (Tinebase_Application::getInstance()->isInstalled('Addressbook') === true) {
233             $_group->list_id = $oldGroup->list_id;
234             $list = $this->createOrUpdateList($_group);
235             $_group->list_id = $list->getId();
236         }
237         
238         Tinebase_Timemachine_ModificationLog::setRecordMetaData($_group, 'update', $oldGroup);
239         
240         $group = Tinebase_Group::getInstance()->updateGroup($_group);
241         
242         Tinebase_Group::getInstance()->setGroupMembers($group->getId(), $_group->members);
243         
244         Tinebase_TransactionManager::getInstance()->commitTransaction($transactionId);
245         
246         $event = new Admin_Event_UpdateGroup();
247         $event->group = $group;
248         Tinebase_Event::fireEvent($event);
249         
250         return $group;
251     }
252     
253     /**
254      * add a new groupmember to a group
255      *
256      * @param int $_groupId
257      * @param int $_accountId
258      * @return void
259      */
260     public function addGroupMember($_groupId, $_userId)
261     {
262         $this->checkRight('MANAGE_ACCOUNTS');
263         
264         Tinebase_Group::getInstance()->addGroupMember($_groupId, $_userId);
265         
266         if (Tinebase_Application::getInstance()->isInstalled('Addressbook') === true) {
267             $group = $this->get($_groupId);
268             $user  = Tinebase_User::getInstance()->getUserById($_userId);
269             
270             if (! empty($user->contact_id) && ! empty($group->list_id)) {
271                 if (! Addressbook_Controller_List::getInstance()->exists($group->list_id)) {
272                     if (Tinebase_Core::isLogLevel(Zend_Log::WARN)) Tinebase_Core::getLogger()->warn(__METHOD__ . '::' . __LINE__ 
273                         . ' Could not add member to list ' . $group->list_id . ' (it does not exist)');
274                 } else {
275                     $aclChecking = Addressbook_Controller_List::getInstance()->doContainerACLChecks(FALSE);
276                     Addressbook_Controller_List::getInstance()->addListMember($group->list_id, $user->contact_id);
277                     Addressbook_Controller_List::getInstance()->doContainerACLChecks($aclChecking);
278                 }
279             }
280         }
281         
282         $event = new Admin_Event_AddGroupMember();
283         $event->groupId = $_groupId;
284         $event->userId  = $_userId;
285         Tinebase_Event::fireEvent($event);
286     }
287     
288     /**
289      * remove one groupmember from the group
290      *
291      * @param int $_groupId
292      * @param int $_accountId
293      * @return void
294      */
295     public function removeGroupMember($_groupId, $_userId)
296     {
297         $this->checkRight('MANAGE_ACCOUNTS');
298         
299         Tinebase_Group::getInstance()->removeGroupMember($_groupId, $_userId);
300         
301         if (Tinebase_Application::getInstance()->isInstalled('Addressbook') === true) {
302             $group = $this->get($_groupId);
303             $user  = Tinebase_User::getInstance()->getUserById($_userId);
304             
305             if (!empty($user->contact_id) && !empty($group->list_id)) {
306                 try {
307                     $aclChecking = Addressbook_Controller_List::getInstance()->doContainerACLChecks(FALSE);
308                     Addressbook_Controller_List::getInstance()->removeListMember($group->list_id, $user->contact_id);
309                     Addressbook_Controller_List::getInstance()->doContainerACLChecks($aclChecking);
310                 } catch (Tinebase_Exception_NotFound $tenf) {
311                     if (Tinebase_Core::isLogLevel(Zend_Log::WARN)) 
312                         Tinebase_Core::getLogger()->warn(__METHOD__ . '::' . __LINE__ . ' catched exception: ' . get_class($tenf));
313                     if (Tinebase_Core::isLogLevel(Zend_Log::WARN)) 
314                         Tinebase_Core::getLogger()->warn(__METHOD__ . '::' . __LINE__ . ' ' . $tenf->getMessage());
315                     if (Tinebase_Core::isLogLevel(Zend_Log::INFO)) 
316                         Tinebase_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ . ' ' . $tenf->getTraceAsString());
317                 }
318             }
319         }
320         
321         $event = new Admin_Event_RemoveGroupMember();
322         $event->groupId = $_groupId;
323         $event->userId  = $_userId;
324         Tinebase_Event::fireEvent($event);
325         
326     }
327     
328     /**
329      * delete multiple groups
330      *
331      * @param   array $_groupIds
332      * @return  void
333      */
334     public function delete($_groupIds)
335     {
336         $this->checkRight('MANAGE_ACCOUNTS');
337         
338         // check default user group / can't delete this group
339         $defaultUserGroup = Tinebase_Group::getInstance()->getDefaultGroup();
340         
341         if (in_array($defaultUserGroup->getId(), $_groupIds)) {
342             Tinebase_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ 
343                 . ' Can\'t delete default group: ' . $defaultUserGroup->name
344             );
345             foreach ($_groupIds as $key => $value) {
346                 if ($value == $defaultUserGroup->getId()) {
347                     unset($_groupIds[$key]);
348                 }
349             }
350         }
351         
352         if (empty($_groupIds)) {
353             return;
354         }
355         
356         $eventBefore = new Admin_Event_BeforeDeleteGroup();
357         $eventBefore->groupIds = $_groupIds;
358         Tinebase_Event::fireEvent($eventBefore);
359         
360         if (Tinebase_Application::getInstance()->isInstalled('Addressbook') === true) {
361             $listIds = array();
362             
363             foreach ($_groupIds as $groupId) {
364                 $group = $this->get($groupId);
365                 if (!empty($group->list_id)) {
366                     $listIds[] = $group->list_id;
367                 }
368             }
369             
370             if (!empty($listIds)) {
371                 $listBackend = new Addressbook_Backend_List();
372                 $listBackend->delete($listIds);
373             }
374         }
375         
376         Tinebase_Group::getInstance()->deleteGroups($_groupIds);
377         
378         $event = new Admin_Event_DeleteGroup();
379         $event->groupIds = $_groupIds;
380         Tinebase_Event::fireEvent($event);
381     }
382     
383     /**
384      * get list of groupmembers
385      *
386      * @param int $_groupId
387      * @return array with Tinebase_Model_User arrays
388      */
389     public function getGroupMembers($_groupId)
390     {
391         $result = Tinebase_Group::getInstance()->getGroupMembers($_groupId);
392         
393         return $result;
394     }
395     
396     /**
397      * return all groups an account is member of
398      *
399      * @param mixed $_accountId the account as integer or Tinebase_Model_User
400      * @return array
401      */
402     public function getGroupMemberships($_accountId)
403     {
404         $this->checkRight('VIEW_ACCOUNTS');
405         
406         $result = Tinebase_Group::getInstance()->getGroupMemberships($_accountId);
407         
408         return $result;
409     }
410     
411     /**
412      * create or update list in addressbook sql backend
413      * 
414      * @param  Tinebase_Model_Group  $group
415      * @return Addressbook_Model_List
416      */
417     public function createOrUpdateList(Tinebase_Model_Group $group)
418     {
419         return Addressbook_Controller_List::getInstance()->createOrUpdateByGroup($group);
420     }
421 }