Merge branch '2016.11-develop' into 2017.11
[tine20] / tine20 / Calendar / Convert / Event / VCalendar / Factory.php
1 <?php
2 /**
3  * Tine 2.0
4  *
5  * @package     Calendar
6  * @subpackage  Convert
7  * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
8  * @author      Lars Kneschke <l.kneschke@metaways.de>
9  * @copyright   Copyright (c) 2011-2013 Metaways Infosystems GmbH (http://www.metaways.de)
10  */
11
12 /**
13  * calendar VCALENDAR converter factory class
14  *
15  * @package     Calendar
16  * @subpackage  Convert
17  */
18 class Calendar_Convert_Event_VCalendar_Factory
19 {
20     const CLIENT_GENERIC     = 'generic';
21     const CLIENT_IPHONE      = 'iphone';
22     const CLIENT_KDE         = 'kde';
23     const CLIENT_MACOSX      = 'macosx';
24     const CLIENT_THUNDERBIRD = 'thunderbird';
25     const CLIENT_EMCLIENT    = 'emclient';
26     const CLIENT_EMCLIENT7   = 'emclient7';
27     const CLIENT_TINE        = 'tine';
28     const CLIENT_DAVDROID    = 'davdroid';
29     const CLIENT_BUSYCAL         = 'busycal';
30     const CLIENT_CALDAVSYNCHRONIZER = 'caldavsynchronizer';
31     
32     /**
33      * cache parsed user-agent strings
34      * 
35      * @var array
36      */
37     static protected $_parsedUserAgentCache = array();
38     
39     /**
40      * factory function to return a selected vcalendar backend class
41      *
42      * @param   string $_backend
43      * @param   string $_version
44      * @return  Tinebase_Convert_Interface
45      */
46     static public function factory($_backend, $_version = null)
47     {
48         switch ($_backend) {
49             case Calendar_Convert_Event_VCalendar_Factory::CLIENT_GENERIC:
50                 return new Calendar_Convert_Event_VCalendar_Generic($_version);
51                 
52             case Calendar_Convert_Event_VCalendar_Factory::CLIENT_IPHONE:
53                 return new Calendar_Convert_Event_VCalendar_Iphone($_version);
54                 
55             case Calendar_Convert_Event_VCalendar_Factory::CLIENT_BUSYCAL:
56                 return new Calendar_Convert_Event_VCalendar_BusyCal($_version);
57                 
58             case Calendar_Convert_Event_VCalendar_Factory::CLIENT_KDE:
59                 return new Calendar_Convert_Event_VCalendar_KDE($_version);
60
61                 
62             case Calendar_Convert_Event_VCalendar_Factory::CLIENT_MACOSX:
63                 return new Calendar_Convert_Event_VCalendar_MacOSX($_version);
64                 
65             case Calendar_Convert_Event_VCalendar_Factory::CLIENT_THUNDERBIRD:
66                 return new Calendar_Convert_Event_VCalendar_Thunderbird($_version);
67  
68             case Calendar_Convert_Event_VCalendar_Factory::CLIENT_EMCLIENT:
69                 return new Calendar_Convert_Event_VCalendar_EMClient($_version);
70
71             case Calendar_Convert_Event_VCalendar_Factory::CLIENT_EMCLIENT7:
72                 return new Calendar_Convert_Event_VCalendar_EMClient7($_version);
73
74             case Calendar_Convert_Event_VCalendar_Factory::CLIENT_DAVDROID:
75                 return new Calendar_Convert_Event_VCalendar_DavDroid($_version);
76
77             case Calendar_Convert_Event_VCalendar_Factory::CLIENT_CALDAVSYNCHRONIZER:
78                 return new Calendar_Convert_Event_VCalendar_CalDAVSynchronizer($_version);
79
80             case Calendar_Convert_Event_VCalendar_Factory::CLIENT_TINE:
81                 return new Calendar_Convert_Event_VCalendar_Tine($_version);
82         }
83         return new Calendar_Convert_Event_VCalendar_Generic($_version);
84     }
85     
86     /**
87      * parse useragent and return backend and version
88      * 
89      * @return array
90      */
91     static public function parseUserAgent($_userAgent)
92     {
93         if (isset(self::$_parsedUserAgentCache[$_userAgent])) {
94             return self::$_parsedUserAgentCache[$_userAgent];
95         }
96         
97         // MacOS X
98         if (preg_match(Calendar_Convert_Event_VCalendar_MacOSX::HEADER_MATCH, $_userAgent, $matches)) {
99             $backend = Calendar_Convert_Event_VCalendar_Factory::CLIENT_MACOSX;
100             $version = $matches['version'];
101         
102         // iPhone
103         } elseif (preg_match(Calendar_Convert_Event_VCalendar_Iphone::HEADER_MATCH, $_userAgent, $matches)) {
104             $backend = Calendar_Convert_Event_VCalendar_Factory::CLIENT_IPHONE;
105             $version = $matches['version'];
106         
107         // BusyCal
108         } elseif (preg_match(Calendar_Convert_Event_VCalendar_BusyCal::HEADER_MATCH, $_userAgent, $matches)) {
109             $backend = Calendar_Convert_Event_VCalendar_Factory::CLIENT_BUSYCAL;
110             $version = $matches['version'];
111                 
112         // KDE
113         } elseif (preg_match(Calendar_Convert_Event_VCalendar_KDE::HEADER_MATCH, $_userAgent, $matches)) {
114             $backend = Calendar_Convert_Event_VCalendar_Factory::CLIENT_KDE;
115             $version = $matches['version'];
116         
117         // Thunderbird
118         } elseif (preg_match(Calendar_Convert_Event_VCalendar_Thunderbird::HEADER_MATCH, $_userAgent, $matches)) {
119             $backend = Calendar_Convert_Event_VCalendar_Factory::CLIENT_THUNDERBIRD;
120             $version = $matches['version'];
121
122         // EMClient 7 calendar
123         } elseif (preg_match(Calendar_Convert_Event_VCalendar_EMClient7::HEADER_MATCH, $_userAgent, $matches) && (floor($matches['version']) >= 7)) {
124             $backend = Calendar_Convert_Event_VCalendar_Factory::CLIENT_EMCLIENT7;
125             $version = $matches['version'];
126
127         // EMClient
128         } elseif (preg_match(Calendar_Convert_Event_VCalendar_EMClient::HEADER_MATCH, $_userAgent, $matches)) {
129             $backend = Calendar_Convert_Event_VCalendar_Factory::CLIENT_EMCLIENT;
130             $version = $matches['version'];
131
132         // Tine 2.0
133         } elseif (preg_match(Calendar_Convert_Event_VCalendar_Tine::HEADER_MATCH, $_userAgent, $matches)) {
134             $backend = Calendar_Convert_Event_VCalendar_Factory::CLIENT_TINE;
135             $version = $matches['version'];
136
137         // DavDroid
138         } elseif (preg_match(Calendar_Convert_Event_VCalendar_DavDroid::HEADER_MATCH, $_userAgent, $matches)) {
139             $backend = Calendar_Convert_Event_VCalendar_Factory::CLIENT_DAVDROID;
140             $version = $matches['version'];
141
142         // CalDAVSynchronizer
143         } elseif (preg_match(Calendar_Convert_Event_VCalendar_CalDAVSynchronizer::HEADER_MATCH, $_userAgent, $matches)) {
144             $backend = Calendar_Convert_Event_VCalendar_Factory::CLIENT_CALDAVSYNCHRONIZER;
145             $version = $matches['version'];
146         } else {
147             $backend = Calendar_Convert_Event_VCalendar_Factory::CLIENT_GENERIC;
148             $version = null;
149         }
150
151         if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) 
152             Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . " $_userAgent ->  backend: $backend version: $version");
153         
154         self::$_parsedUserAgentCache[$_userAgent] = array($backend, $version);
155         
156         return array($backend, $version);
157     }
158
159     /**
160      * parse useragent and return backend and version
161      *
162      * @param string $_userAgent
163      * @return boolean
164      */
165     static public function supportsSyncToken($_userAgent)
166     {
167         $result = false;
168         if (Tinebase_Config::getInstance()->get(Tinebase_Config::WEBDAV_SYNCTOKEN_ENABLED)) {
169             if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) 
170                 Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' SyncTokenSupport enabled');
171             list($backend, $version) = self::parseUserAgent($_userAgent);
172             switch ($backend) {
173                 case self::CLIENT_MACOSX:
174                     if (version_compare($version, '10.9', '>=')) {
175                         $result = true;
176                     }
177                     break;
178                 case self::CLIENT_THUNDERBIRD:
179                     if (version_compare($version, '4', '>=')) {
180                         $result = true;
181                     }
182                     break;
183             }
184
185             if ($result) {
186                 if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG))
187                     Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ .
188                         ' Client ' . $backend . ' version ' . $version . ' supports SyncToken.');
189             }
190         } else {
191             if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) 
192                 Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' SyncTokenSupport disabled');
193         }
194         return $result;
195     }
196 }