#9688: allow to configure default period filter in json frontend
[tine20] / tine20 / Calendar / Frontend / Json.php
1 <?php
2 /**
3  * Tine 2.0
4  * 
5  * @package     Calendar
6  * @subpackage  Frontend
7  * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
8  * @author      Cornelius Weiss <c.weiss@metaways.de>
9  * @copyright   Copyright (c) 2007-2013 Metaways Infosystems GmbH (http://www.metaways.de)
10  */
11
12 /**
13  * json interface for calendar
14  * 
15  * @package     Calendar
16  * @subpackage  Frontend
17  */
18 class Calendar_Frontend_Json extends Tinebase_Frontend_Json_Abstract
19 {
20     /**
21      * app name
22      * 
23      * @var string
24      */
25     protected $_applicationName = 'Calendar';
26     
27     /**
28      * creates an exception instance of a recurring event
29      *
30      * NOTE: deleting persistent exceptions is done via a normal delete action
31      *       and handled in the controller
32      * 
33      * @param  array       $recordData
34      * @param  bool        $deleteInstance
35      * @param  bool        $deleteAllFollowing
36      * @param  bool        $checkBusyConflicts
37      * @return array       exception Event | updated baseEvent
38      * 
39      * @todo replace $_allFollowing param with $range
40      * @deprecated replace with create/update/delete
41      */
42     public function createRecurException($recordData, $deleteInstance, $deleteAllFollowing, $checkBusyConflicts = FALSE)
43     {
44         $event = new Calendar_Model_Event(array(), TRUE);
45         $event->setFromJsonInUsersTimezone($recordData);
46         
47         $returnEvent = Calendar_Controller_Event::getInstance()->createRecurException($event, $deleteInstance, $deleteAllFollowing, $checkBusyConflicts);
48         
49         return $this->getEvent($returnEvent->getId());
50     }
51     
52     /**
53      * deletes existing events
54      *
55      * @param array $_ids
56      * @param string $range
57      * @return string
58      */
59     public function deleteEvents($ids, $range = Calendar_Model_Event::RANGE_THIS)
60     {
61         return $this->_delete($ids, Calendar_Controller_Event::getInstance(), array($range));
62     }
63     
64     /**
65      * deletes existing resources
66      *
67      * @param array $_ids 
68      * @return string
69      */
70     public function deleteResources($ids)
71     {
72         return $this->_delete($ids, Calendar_Controller_Resource::getInstance());
73     }
74     
75     /**
76      * deletes a recur series
77      *
78      * @param  array $recordData
79      * @return void
80      */
81     public function deleteRecurSeries($recordData)
82     {
83         $event = new Calendar_Model_Event(array(), TRUE);
84         $event->setFromJsonInUsersTimezone($recordData);
85         
86         Calendar_Controller_Event::getInstance()->deleteRecurSeries($event);
87         return array('success' => true);
88     }
89     
90     /**
91      * Return a single event
92      *
93      * @param   string $id
94      * @return  array record data
95      */
96     public function getEvent($id)
97     {
98         return $this->_get($id, Calendar_Controller_Event::getInstance());
99     }
100     
101     /**
102      * Returns registry data of the calendar.
103      *
104      * @return mixed array 'variable name' => 'data'
105      * 
106      * @todo move exception handling (no default calender found) to another place?
107      */
108     public function getRegistryData()
109     {
110         $defaultCalendarId = Tinebase_Core::getPreference('Calendar')->getValue(Calendar_Preference::DEFAULTCALENDAR);
111         try {
112             $defaultCalendarArray = Tinebase_Container::getInstance()->getContainerById($defaultCalendarId)->toArray();
113             $defaultCalendarArray['account_grants'] = Tinebase_Container::getInstance()->getGrantsOfAccount(Tinebase_Core::getUser(), $defaultCalendarId)->toArray();
114         } catch (Exception $e) {
115             // remove default cal pref
116             Tinebase_Core::getPreference('Calendar')->deleteUserPref(Calendar_Preference::DEFAULTCALENDAR);
117             $defaultCalendarArray = array();
118         }
119         
120         return array(
121             // registry setting is called defaultContainer to be compatible to the other apps
122             'defaultContainer' => $defaultCalendarArray
123         );
124     }
125     
126     /**
127      * Return a single resouece
128      *
129      * @param   string $id
130      * @return  array record data
131      */
132     public function getResource($id)
133     {
134         return $this->_get($id, Calendar_Controller_Resource::getInstance());
135     }
136     
137     /**
138      * Search for events matching given arguments
139      *
140      * @param  array $_filter
141      * @param  array $_paging
142      * @return array
143      */
144     public function searchEvents($filter, $paging)
145     {
146         $controller = Calendar_Controller_Event::getInstance();
147         
148         $decodedPagination = is_array($paging) ? $paging : Zend_Json::decode($paging);
149         $pagination = new Tinebase_Model_Pagination($decodedPagination);
150         $clientFilter = $filter = $this->_decodeFilter($filter, 'Calendar_Model_EventFilter');
151
152         // find out if fixed calendars should be used
153         $fixedCalendars = Calendar_Config::getInstance()->get(Calendar_Config::FIXED_CALENDARS, new Tinebase_Config_Struct(array()))->toArray();
154         $useFixedCalendars = is_array($fixedCalendars) && ! empty($fixedCalendars);
155         
156         $periodFilter = $filter->getFilter('period');
157         
158         // add period filter per default to prevent endless search
159         if (! $periodFilter) {
160             $periodFilter = $this->_getDefaultPeriodFilter();
161             // periodFilter will be added to fixed filter when using fixed calendars
162             if (! $useFixedCalendars) {
163                 $filter->addFilter($periodFilter);
164             }
165         }
166         
167         // add fixed calendar on demand
168         if ($useFixedCalendars) {
169             $fixed = new Calendar_Model_EventFilter(array(), 'AND');
170             $fixed->addFilter( new Tinebase_Model_Filter_Text('container_id', 'in', $fixedCalendars));
171             
172             $fixed->addFilter($periodFilter);
173             
174             $og = new Calendar_Model_EventFilter(array(), 'OR');
175             $og->addFilterGroup($fixed);
176             $og->addFilterGroup($clientFilter);
177             
178             $filter = new Calendar_Model_EventFilter(array(), 'AND');
179             $filter->addFilterGroup($og);
180         }
181         
182         $records = $controller->search($filter, $pagination, FALSE);
183         
184         $result = $this->_multipleRecordsToJson($records, $clientFilter, $pagination);
185         
186         return array(
187             'results'       => $result,
188             'totalcount'    => count($result),
189             'filter'        => $clientFilter->toArray(TRUE),
190         );
191     }
192     
193     /**
194      * get default period filter
195      * 
196      * @return Calendar_Model_PeriodFilter
197      */
198     protected function _getDefaultPeriodFilter()
199     {
200         $now = Tinebase_DateTime::now()->setTime(0,0,0);
201         
202         $from = $now->getClone()->subMonth(Calendar_Config::getInstance()->get(Calendar_Config::MAX_JSON_DEFAULT_FILTER_PERIOD_FROM, 0));
203         $until = $now->getClone()->addMonth(Calendar_Config::getInstance()->get(Calendar_Config::MAX_JSON_DEFAULT_FILTER_PERIOD_UNTIL, 1));
204         $periodFilter = new Calendar_Model_PeriodFilter(array(
205             'field' => 'period',
206             'operator' => 'within',
207             'value' => array("from" => $from, "until" => $until)
208         ));
209         
210         return $periodFilter;
211     }
212     
213     /**
214      * Search for resources matching given arguments
215      *
216      * @param  array $_filter
217      * @param  array $_paging
218      * @return array
219      */
220     public function searchResources($filter, $paging)
221     {
222         return $this->_search($filter, $paging, Calendar_Controller_Resource::getInstance(), 'Calendar_Model_ResourceFilter');
223     }
224     
225     /**
226      * creates/updates an event / recur
227      *
228      * @param   array   $recordData
229      * @param   bool    $checkBusyConflicts
230      * @param   string  $range
231      * @return  array   created/updated event
232      */
233     public function saveEvent($recordData, $checkBusyConflicts = FALSE, $range = Calendar_Model_Event::RANGE_THIS)
234     {
235         return $this->_save($recordData, Calendar_Controller_Event::getInstance(), 'Event', 'id', array($checkBusyConflicts, $range));
236     }
237     
238     /**
239      * creates/updates a Resource
240      *
241      * @param   array   $recordData
242      * @return  array   created/updated Resource
243      */
244     public function saveResource($recordData)
245     {
246         $recordData['grants'] = new Tinebase_Record_RecordSet('Tinebase_Model_Grants', $recordData['grants']);
247         
248         return $this->_save($recordData, Calendar_Controller_Resource::getInstance(), 'Resource');
249     }
250     
251     /**
252      * sets attendee status for an attender on the given event
253      * 
254      * NOTE: for recur events we implicitly create an exceptions on demand
255      *
256      * @param  array         $eventData
257      * @param  array         $attenderData
258      * @param  string        $authKey
259      * @return array         complete event
260      */
261     public function setAttenderStatus($eventData, $attenderData, $authKey)
262     {
263         $event    = new Calendar_Model_Event($eventData);
264         $attender = new Calendar_Model_Attender($attenderData);
265         
266         Calendar_Controller_Event::getInstance()->attenderStatusUpdate($event, $attender, $authKey);
267         
268         return $this->getEvent($event->getId());
269     }
270     
271     /**
272      * updated a recur series
273      *
274      * @param  array $recordData
275      * @param  bool  $checkBusyConflicts
276      * @noparamyet  JSONstring $returnPeriod NOT IMPLEMENTED YET
277      * @return array 
278      */
279     public function updateRecurSeries($recordData, $checkBusyConflicts = FALSE /*, $returnPeriod*/)
280     {
281         $recurInstance = new Calendar_Model_Event(array(), TRUE);
282         $recurInstance->setFromJsonInUsersTimezone($recordData);
283         
284         //if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) Tinebase_Core::getLogger()->debug(print_r($recurInstance->toArray(), true));
285         
286         $baseEvent = Calendar_Controller_Event::getInstance()->updateRecurSeries($recurInstance, $checkBusyConflicts);
287         
288         return $this->getEvent($baseEvent->getId());
289     }
290     
291     /**
292      * prepares an iMIP (RFC 6047) Message
293      * 
294      * @param array $iMIP
295      * @return array prepared iMIP part
296      */
297     public function iMIPPrepare($iMIP)
298     {
299         $iMIPMessage = $iMIP instanceof Calendar_Model_iMIP ? $iMIP : new Calendar_Model_iMIP($iMIP);
300         $iMIPFrontend = new Calendar_Frontend_iMIP();
301         
302         $iMIPMessage->preconditionsChecked = FALSE;
303         $iMIPFrontend->prepareComponent($iMIPMessage);
304         $iMIPMessage->setTimezone(Tinebase_Core::get(Tinebase_Core::USERTIMEZONE));
305         return $iMIPMessage->toArray();
306     }
307     
308     /**
309      * process an iMIP (RFC 6047) Message
310      * 
311      * @param array  $iMIP
312      * @param string $status
313      * @return array prepared iMIP part
314      */
315     public function iMIPProcess($iMIP, $status=null)
316     {
317         $iMIPMessage = new Calendar_Model_iMIP($iMIP);
318         $iMIPFrontend = new Calendar_Frontend_iMIP();
319         
320         $iMIPFrontend->process($iMIPMessage, $status);
321         
322         return $this->iMIPPrepare($iMIPMessage);
323     }
324 }