]> CyberLeo.Net >> Repos - Github/sugarcrm.git/blob - modules/vCals/vCal.php
Release 6.5.16
[Github/sugarcrm.git] / modules / vCals / vCal.php
1 <?php
2 if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
3 /*********************************************************************************
4  * SugarCRM Community Edition is a customer relationship management program developed by
5  * SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc.
6  * 
7  * This program is free software; you can redistribute it and/or modify it under
8  * the terms of the GNU Affero General Public License version 3 as published by the
9  * Free Software Foundation with the addition of the following permission added
10  * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
11  * IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
12  * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
13  * 
14  * This program is distributed in the hope that it will be useful, but WITHOUT
15  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16  * FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more
17  * details.
18  * 
19  * You should have received a copy of the GNU Affero General Public License along with
20  * this program; if not, see http://www.gnu.org/licenses or write to the Free
21  * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22  * 02110-1301 USA.
23  * 
24  * You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
25  * SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
26  * 
27  * The interactive user interfaces in modified source and object code versions
28  * of this program must display Appropriate Legal Notices, as required under
29  * Section 5 of the GNU Affero General Public License version 3.
30  * 
31  * In accordance with Section 7(b) of the GNU Affero General Public License version 3,
32  * these Appropriate Legal Notices must retain the display of the "Powered by
33  * SugarCRM" logo. If the display of the logo is not reasonably feasible for
34  * technical reasons, the Appropriate Legal Notices must display the words
35  * "Powered by SugarCRM".
36  ********************************************************************************/
37
38
39 require_once('modules/Calendar/Calendar.php');
40
41 class vCal extends SugarBean {
42         // Stored fields
43         var $id;
44         var $date_modified;
45         var $user_id;
46         var $content;
47         var $deleted;
48         var $type;
49         var $source;
50         var $module_dir = "vCals";
51         var $table_name = "vcals";
52
53         var $object_name = "vCal";
54
55         var $new_schema = true;
56
57         var $field_defs = array(
58         );
59
60         // This is used to retrieve related fields from form posts.
61         var $additional_column_fields = Array();
62
63         const UTC_FORMAT = 'Ymd\THi00\Z';
64     const EOL = "\r\n";
65     const TAB = "\t";
66     const CHARSPERLINE = 75;
67
68         function vCal()
69         {
70
71                 parent::SugarBean();
72                 $this->disable_row_level_security = true;
73         }
74
75         function get_summary_text()
76         {
77                 return "";
78         }
79
80
81         function fill_in_additional_list_fields()
82         {
83         }
84
85         function fill_in_additional_detail_fields()
86         {
87         }
88
89         function get_list_view_data()
90         {
91         }
92
93         // combines all freebusy vcals and returns just the FREEBUSY lines as a string
94         function get_freebusy_lines_cache(&$user_bean)
95         {
96         $ical_array = array();
97                 // First, get the list of IDs.
98                 $query = "SELECT id from vcals where user_id='{$user_bean->id}' AND type='vfb' AND deleted=0";
99                 $vcal_arr = $this->build_related_list($query, new vCal());
100
101                 foreach ($vcal_arr as $focus)
102                 {
103                         if (empty($focus->content))
104                         {
105                                 return '';
106                         }
107
108             $ical_arr = self::create_ical_array_from_string($focus->content);
109             $ical_array = array_merge($ical_array, $ical_arr);
110                 }
111
112         return self::create_ical_string_from_array($ical_array);
113         }
114
115         // query and create the FREEBUSY lines for SugarCRM Meetings and Calls and
116         // return the string
117         function create_sugar_freebusy($user_bean, $start_date_time, $end_date_time)
118         {
119         $ical_array = array();
120                 global $DO_USER_TIME_OFFSET,$timedate;
121
122                 $DO_USER_TIME_OFFSET = true;
123                 if(empty($GLOBALS['current_user']) || empty($GLOBALS['current_user']->id)) {
124                     $GLOBALS['current_user'] = $user_bean;
125                 }
126                 // get activities.. queries Meetings and Calls
127                 $acts_arr =
128                 CalendarActivity::get_activities($user_bean->id,
129                         array("show_calls" => true),
130                         $start_date_time,
131                         $end_date_time,
132                         'freebusy');
133
134                 // loop thru each activity, get start/end time in UTC, and return FREEBUSY strings
135                 foreach($acts_arr as $act)
136                 {
137                         $startTimeUTC = $act->start_time->format(self::UTC_FORMAT);
138                         $endTimeUTC = $act->end_time->format(self::UTC_FORMAT);
139
140             $ical_array[] = array("FREEBUSY", $startTimeUTC ."/". $endTimeUTC);
141                 }
142         return self::create_ical_string_from_array($ical_array);
143
144         }
145
146         // return a freebusy vcal string
147         function get_vcal_freebusy($user_focus,$cached=true)
148         {
149            global $locale, $timedate;
150            $ical_array = array();
151            $ical_array[] = array("BEGIN", "VCALENDAR");
152            $ical_array[] = array("VERSION", "2.0");
153            $ical_array[] = array("PRODID", "-//SugarCRM//SugarCRM Calendar//EN");
154            $ical_array[] = array("BEGIN", "VFREEBUSY");
155
156            $name = $locale->getLocaleFormattedName($user_focus->first_name, $user_focus->last_name);
157            $email = $user_focus->email1;
158
159            // get current date for the user
160            $now_date_time = $timedate->getNow(true);
161
162            // get start date ( 1 day ago )
163            $start_date_time = $now_date_time->get("yesterday");
164
165            // get date 2 months from start date
166                         global $sugar_config;
167                         $timeOffset = 2;
168             if (isset($sugar_config['vcal_time']) && $sugar_config['vcal_time'] != 0 && $sugar_config['vcal_time'] < 13)
169                         {
170                                 $timeOffset = $sugar_config['vcal_time'];
171                         }
172            $end_date_time = $start_date_time->get("+$timeOffset months");
173
174            // get UTC time format
175            $utc_start_time = $start_date_time->asDb();
176            $utc_end_time = $end_date_time->asDb();
177            $utc_now_time = $now_date_time->asDb();
178
179            $ical_array[] = array("ORGANIZER;CN=$name", "VFREEBUSY");
180            $ical_array[] = array("DTSTART", $utc_start_time);
181            $ical_array[] = array("DTEND", $utc_end_time);
182
183            $str = self::create_ical_string_from_array($ical_array);
184
185            // now insert the freebusy lines
186            // retrieve cached freebusy lines from vcals
187                    if ($timeOffset != 0)
188                    {
189            if ($cached == true)
190            {
191              $str .= $this->get_freebusy_lines_cache($user_focus);
192            }
193            // generate freebusy from Meetings and Calls
194            else
195            {
196                $str .= $this->create_sugar_freebusy($user_focus,$start_date_time,$end_date_time);
197                         }
198            }
199
200            // UID:20030724T213406Z-10358-1000-1-12@phoenix
201            $str .= self::fold_ical_lines("DTSTAMP", $utc_now_time) . self::EOL;
202            $str .= "END:VFREEBUSY".self::EOL;
203            $str .= "END:VCALENDAR".self::EOL;
204            return $str;
205
206         }
207
208         // static function:
209         // cache vcals
210         function cache_sugar_vcal(&$user_focus)
211         {
212             self::cache_sugar_vcal_freebusy($user_focus);
213         }
214
215         // static function:
216         // caches vcal for Activities in Sugar database
217         function cache_sugar_vcal_freebusy(&$user_focus)
218         {
219             $focus = new vCal();
220             // set freebusy members and save
221             $arr = array('user_id'=>$user_focus->id,'type'=>'vfb','source'=>'sugar');
222             $focus->retrieve_by_string_fields($arr);
223
224
225             $focus->content = $focus->get_vcal_freebusy($user_focus,false);
226             $focus->type = 'vfb';
227             $focus->date_modified = null;
228             $focus->source = 'sugar';
229             $focus->user_id = $user_focus->id;
230             $focus->save();
231         }
232
233     /*
234      * Lines of text SHOULD NOT be longer than 75 octets, excluding the line break.
235      * Long content lines SHOULD be split into a multiple line representations using a line "folding" technique
236      */
237     public static function fold_ical_lines($key, $value)
238     {
239         $iCalValue = $key . ":" . $value;
240
241         if (strlen($iCalValue) <= self::CHARSPERLINE) {
242             return $iCalValue;
243         }
244
245         $firstchars = substr($iCalValue, 0, self::CHARSPERLINE);
246         $remainingchars = substr($iCalValue, self::CHARSPERLINE);
247         $end = self::EOL . self::TAB;
248
249         $remainingchars = substr(
250             chunk_split(
251                 $end . $remainingchars,
252                 self::CHARSPERLINE + strlen(self::EOL),
253                 $end
254             ),
255             0,
256             -strlen($end) // exclude last EOL and TAB chars
257         );
258
259         return $firstchars . $remainingchars;
260     }
261
262     /**
263      * this function takes an iCal string and converts it to iCal array while following RFC rules
264      */
265     public static function create_ical_array_from_string($ical_string)
266     {
267         $ical_string = preg_replace("/\r\n\s+/", "", $ical_string);
268         $lines = preg_split("/\r?\n/", $ical_string);
269         $ical_array = array();
270
271         foreach ($lines as $line) {
272             $line = self::unescape_ical_chars($line);
273             $line = explode(":", $line, 2);
274             if (count($line) != 2) {
275                 continue;
276             }
277             $ical_array[] = array($line[0], $line[1]);
278         }
279
280         return $ical_array;
281     }
282
283     /**
284      * this function takes an iCal array and converts it to iCal string while following RFC rules
285      */
286     public static function create_ical_string_from_array($ical_array)
287     {
288         $str = "";
289         foreach ($ical_array as $ical) {
290             $str .= self::fold_ical_lines($ical[0], self::escape_ical_chars($ical[1])) . self::EOL;
291         }
292         return $str;
293     }
294
295     /**
296      * escape iCal chars as per RFC 5545: http://tools.ietf.org/html/rfc5545#section-3.3.11
297      *
298      * @param string $string string to escape chars
299      * @return escaped string
300      */
301     public static function escape_ical_chars($string)
302     {
303         $string = str_replace(array("\\", "\r", "\n", ";", ","), array("\\\\", "\\r", "\\n", "\\;", "\\,"), $string);
304         return $string;
305     }
306
307     /**
308      * unescape iCal chars as per RFC 5545: http://tools.ietf.org/html/rfc5545#section-3.3.11
309      *
310      * @param string $string string to escape chars
311      * @return unescaped string
312      */
313     public static function unescape_ical_chars($string)
314     {
315         $string = str_replace(array("\\r", "\\n", "\\;", "\\,", "\\\\"), array("\r", "\n", ";", ",", "\\"), $string);
316         return $string;
317     }
318
319         /**
320          * get ics file content for meeting invite email
321          */
322         public static function get_ical_event(SugarBean $bean, User $user){
323         global $timedate;
324         $ical_array = array();
325
326         $ical_array[] = array("BEGIN", "VCALENDAR");
327         $ical_array[] = array("VERSION", "2.0");
328         $ical_array[] = array("PRODID", "-//SugarCRM//SugarCRM Calendar//EN");
329         $ical_array[] = array("BEGIN", "VEVENT");
330         $ical_array[] = array("UID", $bean->id);
331         $ical_array[] = array("ORGANIZED;CN=" . $user->full_name, $user->email1);
332         $ical_array[] = array("DTSTART", $timedate->fromDb($bean->date_start)->format(self::UTC_FORMAT));
333         $ical_array[] = array("DTEND", $timedate->fromDb($bean->date_end)->format(self::UTC_FORMAT));
334
335         $ical_array[] = array(
336             "DTSTAMP",
337             $GLOBALS['timedate']->getNow(false)->format(self::UTC_FORMAT)
338         );
339         $ical_array[] = array("SUMMARY", $bean->name);
340         $ical_array[] = array("LOCATION", $bean->location);
341
342         $descPrepend = empty($bean->join_url) ? "" : $bean->join_url . self::EOL . self::EOL;
343         $ical_array[] = array("DESCRIPTION", $descPrepend . $bean->description);
344
345         $ical_array[] = array("END", "VEVENT");
346         $ical_array[] = array("END", "VCALENDAR");
347
348         return self::create_ical_string_from_array($ical_array);
349         }
350
351 }
352
353 ?>