0011960: print with 300 dpi by default
[tine20] / tine20 / Tinebase / PersistentFilter.php
1 <?php
2 /**
3  * Tine 2.0
4  *
5  * @package     Tinebase
6  * @subpackage  PersistentFilter
7  * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
8  * @author      Cornelius Weiss <c.weiss@metaways.de>
9  * @copyright   Copyright (c) 2010-2014 Metaways Infosystems GmbH (http://www.metaways.de)
10  */
11
12 /**
13  * persistent filter controller
14  * 
15  * @package     Tinebase
16  * @subpackage  PersistentFilter
17  * 
18  * @todo remove account_id and only use grants to manage shared / personal filters
19  */
20 class Tinebase_PersistentFilter extends Tinebase_Controller_Record_Grants
21 {
22     /**
23      * application name
24      *
25      * @var string
26      */
27     protected $_applicationName = 'Tinebase';
28     
29     /**
30      * check for container ACLs?
31      *
32      * @var boolean
33      */
34     protected $_doContainerACLChecks = FALSE;
35
36     /**
37      * do right checks - can be enabled/disabled by doRightChecks
38      * 
39      * @var boolean
40      */
41     protected $_doRightChecks = FALSE;
42     
43     /**
44      * delete or just set is_delete=1 if record is going to be deleted
45      *
46      * @var boolean
47      */
48     protected $_purgeRecords = FALSE;
49     
50     /**
51      * omit mod log for this records
52      * 
53      * @var boolean
54      */
55     protected $_omitModLog = TRUE;
56     
57     /**
58      * Model name
59      *
60      * @var string
61      */
62     protected $_modelName = 'Tinebase_Model_PersistentFilter';
63     
64     /**
65      * Model name
66      *
67      * @var string
68      */
69     protected $_grantsModel = 'Tinebase_Model_PersistentFilterGrant';
70     
71     /**
72      * @var Tinebase_PersistentFilter
73      */
74     private static $_instance = NULL;
75     
76     /**
77      * the constructor
78      *
79      * don't use the constructor. use the singleton 
80      */
81     private function __construct()
82     {
83         $this->_backend = new Tinebase_PersistentFilter_Backend_Sql();
84         $this->_grantsBackend = new Tinebase_Backend_Sql_Grants(array(
85             'modelName' => $this->_grantsModel,
86             'tableName' => 'filter_acl'
87         ));
88     }
89
90     /**
91      * don't clone. Use the singleton.
92      */
93     private function __clone() 
94     {
95         
96     }
97     
98     /**
99      * singleton
100      *
101      * @return Tinebase_PersistentFilter
102      */
103     public static function getInstance() 
104     {
105         if (self::$_instance === NULL) {
106             self::$_instance = new Tinebase_PersistentFilter();
107         }
108         
109         return self::$_instance;
110     }
111     
112     /**
113      * returns persistent filter identified by id
114      * 
115      * @param  string $_id
116      * @return Tinebase_Model_Filter_FilterGroup
117      */
118     public static function getFilterById($_id)
119     {
120         $persistentFilter = self::getInstance()->get($_id);
121         
122         return $persistentFilter->filters;
123     }
124     
125     /**
126      * helper fn for prefereces
127      * 
128      * @param  string $_appName
129      * @param  string $_accountId
130      * @param  string $_returnDefaultId only return id of default identified by given name
131      * @return array|string filterId => translated name
132      */
133     public static function getPreferenceValues($_appName, $_accountId = null, $_returnDefaultId = null)
134     {
135         $i18n = Tinebase_Translation::getTranslation($_appName);
136         $i18nTinebase = Tinebase_Translation::getTranslation('Tinebase');
137         $pfilters = self::getInstance()->search(new Tinebase_Model_PersistentFilterFilter(array(
138             array('field' => 'application_id', 'operator' => 'equals', 'value' => Tinebase_Application::getInstance()->getApplicationByName($_appName)->getId()),
139             array('field' => 'account_id',     'operator' => 'equals', 'value'  => $_accountId ? $_accountId : Tinebase_Core::getUser()->getId()),
140         )));
141         
142         if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__
143             . ' Got ' . count($pfilters) . ' persistent filters');
144         
145         if (! $_returnDefaultId) {
146             $result = array();
147             foreach ($pfilters as $pfilter) {
148                 $result[] = array($pfilter->getId(), $i18n->translate($pfilter->name));
149             }
150             
151             $result[] = array(
152                 Tinebase_Preference_Abstract::LASTUSEDFILTER,
153                 $i18nTinebase->translate('- The last filter I used -')
154             );
155             return $result;
156         } else {
157             $filter = $pfilters->filter('name', $_returnDefaultId)->getFirstRecord();
158             return $filter ? $filter->getId() : null;
159         }
160     }
161     
162     /**
163      * add one record
164      *
165      * @param   Tinebase_Record_Interface $record
166      * @return  Tinebase_Record_Interface
167      * @throws  Tinebase_Exception_AccessDenied
168      */
169     public function create(Tinebase_Record_Interface $record)
170     {
171         // check first if we already have a filter with this name for this account/application in the db
172         $this->_sanitizeAccountId($record);
173         
174         $existing = $this->search(new Tinebase_Model_PersistentFilterFilter(array(
175             'account_id'        => $record->account_id,
176             'application_id'    => $record->application_id,
177             'name'              => $record->name,
178         )));
179         
180         if (count($existing) > 0) {
181             $record->setId($existing->getFirstRecord()->getId());
182             $result = $this->update($record);
183         } else {
184             $result = parent::create($record);
185         }
186         
187         return $result;
188     }
189     
190     /**
191      * inspect update of one record (before update)
192      *
193      * @param   Tinebase_Record_Interface $record      the update record
194      * @param   Tinebase_Record_Interface $oldRecord   the current persistent record
195      * @return  void
196      */
197     protected function _inspectBeforeUpdate($record, $oldRecord)
198     {
199         $this->_checkManageRightForCurrentUser($record, /* $_throwException = */ true, $oldRecord);
200         $modelName = explode('_', $record->model);
201         $translate = Tinebase_Translation::getTranslation($modelName[0]);
202         // check if filter was shipped.
203         if ($oldRecord->created_by == NULL && $oldRecord->account_id == NULL) {
204             // if shipped, check if values have changed
205             if (($record->account_id !== NULL) || $translate->_($oldRecord->name) != $record->name || $translate->_($oldRecord->description) != $record->description) {
206                 // if values have changed, set created_by to current user, so record is not shipped anymore
207                 $record->created_by = Tinebase_Core::getUser()->getId();
208             }
209         }
210     }
211     
212     /**
213      * set account_id to currentAccount if user has no MANAGE_SHARED_<recordName>_FAVORITES right
214      * 
215      * @param  Tinebase_Record_Interface $record
216      * @return void
217      */
218     protected function _sanitizeAccountId($record)
219     {
220         if (! $record->account_id || ! $this->_belongsToCurrentUser($record)) {
221             if (! $this->_checkManageRightForCurrentUser($record, false)) {
222                 $record->account_id = Tinebase_Core::getUser()->getId();
223             }
224         }
225     }
226     
227     /**
228      * add default grants
229      * 
230      * @param   Tinebase_Record_Interface $record
231      * @param   $boolean $addDuringSetup -> let admin group have all rights instead of user
232      */
233     protected function _setDefaultGrants($record, $addDuringSetup = false)
234     {
235         parent::_setDefaultGrants($record, $addDuringSetup);
236         
237         if (    ! $record->isPersonal()
238              && ! Tinebase_Config::getInstance()->get(Tinebase_Config::ANYONE_ACCOUNT_DISABLED, false) 
239              && in_array(Tinebase_Model_Grants::GRANT_READ, call_user_func($this->_grantsModel . '::getAllGrants'))
240         ) {
241             if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ 
242                 . ' Set read grant for anyone');
243             
244             $record->grants->addRecord(new Tinebase_Model_PersistentFilterGrant(array(
245                 'account_id'       => 0,
246                 'account_type'     => Tinebase_Acl_Rights::ACCOUNT_TYPE_ANYONE,
247                 'record_id'        => $record->getId(),
248                 Tinebase_Model_Grants::GRANT_READ   => true,
249             )));
250         }
251     }
252     
253     /**
254      * checks if filter belongs to current user
255      * 
256      * @param Tinebase_Record_Interface $record
257      * @return boolean
258      */
259     protected function _belongsToCurrentUser($record)
260     {
261         return (is_object(Tinebase_Core::getUser()) && $record->account_id === Tinebase_Core::getUser()->getId());
262     }
263     
264     /**
265      * checks if the current user has the manage shared favorites right for the model of the record
266      * @param Tinebase_Record_Interface $record
267      * @param boolean $_throwException
268      * @param Tinebase_Record_Interface $oldRecord   the current persistent record
269      * @throws Tinebase_Exception_AccessDenied
270      * @return boolean
271      */
272     protected function _checkManageRightForCurrentUser($record, $_throwException = false, $oldRecord = null)
273     {
274         $user = Tinebase_Core::getUser();
275         
276         if (! is_object($user)) {
277             if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__
278                 . ' No valid user found.');
279             return true;
280         }
281         
282         if ($this->_belongsToCurrentUser($record)) {
283             if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__
284                 . ' You always have the right to manage your own filters');
285             return true;
286         }
287         
288         if ($oldRecord && $oldRecord->account_id === $record->account_id && $this->_checkGrant($record, 'update')) {
289             if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__
290                 . ' Edit grant is sufficient to change record if account id does not change');
291             return true;
292         }
293         
294         $existing = $this->search(new Tinebase_Model_PersistentFilterFilter(array(
295             'account_id'        => $record->account_id,
296             'application_id'    => $record->application_id,
297             'name'              => $record->name,
298         )));
299         
300         if ($existing->count() > 0) {
301             $rec = $existing->getFirstRecord();
302         } else {
303             $rec = $record;
304         }
305         
306         $right = $user->hasRight($record->application_id, $this->_getManageSharedRight($rec));
307         if (! $right && $_throwException) {
308             throw new Tinebase_Exception_AccessDenied('You are not allowed to manage shared favorites!'); 
309         }
310
311         return $right;
312     }
313     
314     /**
315      * returns the name of the manage shared right for the record given
316      * @param Tinebase_Record_Interface $record
317      * @return string
318      */
319     protected function _getManageSharedRight($record)
320     {
321         $split = explode('_Model_', str_replace('Filter', '', $record->model));
322         $rightClass = $split[0] . '_Acl_Rights';
323         $rightConstant = 'MANAGE_SHARED_' . strtoupper($split[1]) . '_FAVORITES';
324         
325         return constant($rightClass . '::' . $rightConstant);
326     }
327     
328     /**
329      * inspects delete action
330      *
331      * @param array $_ids
332      * @return array of ids to actually delete
333      */
334     protected function _inspectDelete(array $_ids) 
335     {
336         $recordsToDelete = $this->search(new Tinebase_Model_PersistentFilterFilter(array(array(
337             'field' => 'id', 'operator' => 'in', 'value' => (array)$_ids
338         ))));
339         
340         if (count($recordsToDelete) === 0) {
341             if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ 
342                 . ' No records found.');
343             return array();
344         }
345         
346         foreach ($recordsToDelete as $record) {
347             $this->_checkGrant($record, 'delete');
348             
349             // check if filter is from another user
350             if ($record->account_id !== null && $record->account_id !== Tinebase_Core::getUser()->accountId) {
351                 throw new Tinebase_Exception_AccessDenied('You are not allowed to delete other users\' favorites!');
352             }
353         }
354         
355         if (! Tinebase_Core::getUser()->hasRight($recordsToDelete->getFirstRecord()->application_id, $this->_getManageSharedRight($recordsToDelete->getFirstRecord()))) {
356             foreach ($recordsToDelete as $record) {
357                 if ($record->account_id === null) {
358                     throw new Tinebase_Exception_AccessDenied('You are not allowed to manage shared favorites!');
359                 }
360             }
361         }
362         
363         // delete all persistenfilter prefs with this ids
364         $prefFilter = new Tinebase_Model_PreferenceFilter(array(
365             'name'        => Tinebase_Preference_Abstract::DEFAULTPERSISTENTFILTER,
366             array('field' => 'value', 'operator' => 'in', 'value' => (array) $_ids),
367         ));
368         $prefIds = Tinebase_Core::getPreference()->search($prefFilter, NULL, TRUE);
369         Tinebase_Core::getPreference()->delete($prefIds);
370         
371         return $_ids;
372     }
373 }