Issues (4069)

Security Analysis    not enabled

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

modules/Calendar/CalendarUtils.php (3 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

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
 * SuiteCRM is an extension to SugarCRM Community Edition developed by Salesagility Ltd.
8
 * Copyright (C) 2011 - 2014 Salesagility Ltd.
9
 *
10
 * This program is free software; you can redistribute it and/or modify it under
11
 * the terms of the GNU Affero General Public License version 3 as published by the
12
 * Free Software Foundation with the addition of the following permission added
13
 * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
14
 * IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
15
 * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
16
 *
17
 * This program is distributed in the hope that it will be useful, but WITHOUT
18
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
19
 * FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more
20
 * details.
21
 *
22
 * You should have received a copy of the GNU Affero General Public License along with
23
 * this program; if not, see http://www.gnu.org/licenses or write to the Free
24
 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
25
 * 02110-1301 USA.
26
 *
27
 * You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
28
 * SW2-130, Cupertino, CA 95014, USA. or at email address [email protected].
29
 *
30
 * The interactive user interfaces in modified source and object code versions
31
 * of this program must display Appropriate Legal Notices, as required under
32
 * Section 5 of the GNU Affero General Public License version 3.
33
 *
34
 * In accordance with Section 7(b) of the GNU Affero General Public License version 3,
35
 * these Appropriate Legal Notices must retain the display of the "Powered by
36
 * SugarCRM" logo and "Supercharged by SuiteCRM" logo. If the display of the logos is not
37
 * reasonably feasible for  technical reasons, the Appropriate Legal Notices must
38
 * display the words  "Powered by SugarCRM" and "Supercharged by SuiteCRM".
39
 ********************************************************************************/
40
41
42
class CalendarUtils {
43
44
	/**
45
	 * Find first day of week according to user's settings
46
	 * @param SugarDateTime $date
47
	 * @return SugarDateTime $date
48
	 */
49
	static function get_first_day_of_week(SugarDateTime $date){
50
		$fdow = $GLOBALS['current_user']->get_first_day_of_week();
51
		if($date->day_of_week < $fdow)
0 ignored issues
show
The property day_of_week does not exist on object<SugarDateTime>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
52
				$date = $date->get('-7 days');
53
		return $date->get_day_by_index_this_week($fdow);
54
	}
55
56
57
	/**
58
	 * Get list of needed fields for modules
59
	 * @return array
60
	 */
61
	static function get_fields(){
62
		return array(
63
			'Meetings' => array(
64
				'name',
65
				'duration_hours',
66
				'duration_minutes',
67
				'status',
68
				'related_to',
69
			),
70
			'Calls' => array(
71
				'name',
72
				'duration_hours',
73
				'duration_minutes',
74
				'status',
75
				'related_to',
76
			),
77
			'Tasks' => array(
78
				'name',
79
				'status',
80
				'related_to',
81
			),
82
		);
83
	}
84
85
	/**
86
	 * Get array of needed time data
87
	 * @param SugarBean $bean
88
	 * @return array
89
	 */
90
	static function get_time_data(SugarBean $bean){
91
					$arr = array();
92
93
					$start_field = "date_start";
94
					$end_field = "date_end";
95
96
					if($bean->object_name == 'Task')
97
						$start_field = $end_field = "date_due";
98
					if(empty($bean->$start_field))
99
						return array();
100
					if(empty($bean->$end_field))
101
						$bean->$end_field = $bean->$start_field;
102
103
					$timestamp = SugarDateTime::createFromFormat($GLOBALS['timedate']->get_date_time_format(),$bean->$start_field,new DateTimeZone('UTC'))->format('U');
104
					$arr['timestamp'] = $timestamp;
105
					$arr['time_start'] = $GLOBALS['timedate']->fromTimestamp($arr['timestamp'])->format($GLOBALS['timedate']->get_time_format());
106
					$date_start = SugarDateTime::createFromFormat($GLOBALS['timedate']->get_date_time_format(),$bean->$start_field,new DateTimeZone('UTC'));
107
					$arr['ts_start'] = $date_start->get("-".$date_start->format("H")." hours -".$date_start->format("i")." minutes -".$date_start->format("s")." seconds")->format('U');
108
					$arr['offset'] = $date_start->format('H') * 3600 + $date_start->format('i') * 60;
109
					$date_end = SugarDateTime::createFromFormat($GLOBALS['timedate']->get_date_time_format(),$bean->$end_field,new DateTimeZone('UTC'));
110
					if($bean->object_name != 'Task')
111
						$date_end->modify("-1 minute");
112
					$arr['ts_end'] = $date_end->get("+1 day")->get("-".$date_end->format("H")." hours -".$date_end->format("i")." minutes -".$date_end->format("s")." seconds")->format('U');
113
					$arr['days'] = ($arr['ts_end'] - $arr['ts_start']) / (3600*24);
114
115
					return $arr;
116
	}
117
118
119
	/**
120
	 * Get array that will be sent back to ajax frontend
121
	 * @param SugarBean $bean
122
	 * @return array
123
	 */
124
	static function get_sendback_array(SugarBean $bean){
125
126
			if(isset($bean->parent_name) && isset($_REQUEST['parent_name']))
127
				$bean->parent_name = $_REQUEST['parent_name'];
128
129
			$users = array();
130
			if($bean->object_name == 'Call')
131
				$users = $bean->get_call_users();
0 ignored issues
show
It seems like you code against a specific sub-type and not the parent class SugarBean as the method get_call_users() does only exist in the following sub-classes of SugarBean: Call. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
132
			else if($bean->object_name == 'Meeting')
133
				$users = $bean->get_meeting_users();
0 ignored issues
show
It seems like you code against a specific sub-type and not the parent class SugarBean as the method get_meeting_users() does only exist in the following sub-classes of SugarBean: Meeting. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
134
			$user_ids = array();
135
			foreach($users as $u)
136
				$user_ids[] = $u->id;
137
138
			$field_list = CalendarUtils::get_fields();
139
			$field_arr = array();
140
			foreach($field_list[$bean->module_dir] as $field){
141
			    if ($field == 'related_to')
142
			    {
143
			        $focus = BeanFactory::getBean($bean->parent_type, $bean->parent_id);
144
			        $field_arr[$field] = $focus->name;
145
			    }
146
			    else
147
			    {
148
			        $field_arr[$field] = $bean->$field;
149
			    }
150
			}
151
152
			$date_field = "date_start";
153
			if($bean->object_name == 'Task')
154
				$date_field = "date_due";
155
156
			$arr = array(
157
				'access' => 'yes',
158
				'type' => strtolower($bean->object_name),
159
				'module_name' => $bean->module_dir,
160
				'user_id' => $GLOBALS['current_user']->id,
161
				'detail' => 1,
162
				'edit' => 1,
163
				'name' => $bean->name,
164
				'record' => $bean->id,
165
				'users' => $user_ids,
166
			);
167
			if(!empty($bean->repeat_parent_id))
168
				$arr['repeat_parent_id'] = $bean->repeat_parent_id;
169
			$arr = array_merge($arr,$field_arr);
170
			$arr = array_merge($arr,CalendarUtils::get_time_data($bean));
171
172
			return $arr;
173
	}
174
175
	/**
176
	 * Get array of repeat data
177
	 * @param SugarBean $bean
178
	 * @return array
179
	 */
180
	 static function get_sendback_repeat_data(SugarBean $bean){
181
	 	if ($bean->module_dir == "Meetings" || $bean->module_dir == "Calls") {
182
	 		if(!empty($bean->repeat_parent_id) || (!empty($bean->repeat_type) && empty($_REQUEST['edit_all_recurrences']))){
183
				if(!empty($bean->repeat_parent_id))
184
					$repeat_parent_id = $bean->repeat_parent_id;
185
				else
186
					$repeat_parent_id = $bean->id;
187
	 			return array("repeat_parent_id" => $repeat_parent_id);
188
	 		}
189
190
	 		$arr = array();
191
	 		if(!empty($bean->repeat_type)){
192
	 			$arr = array(
193
	 				'repeat_type' => $bean->repeat_type,
194
	 				'repeat_interval' => $bean->repeat_interval,
195
	 				'repeat_dow' => $bean->repeat_dow,
196
	 				'repeat_until' => $bean->repeat_until,
197
	 				'repeat_count' => $bean->repeat_count,
198
	 			);
199
	 		}
200
201
	 		// TODO CHECK DATETIME VARIABLE
202
	 		if(!empty($_REQUEST['date_start'])){
203
	 			$date_start = $_REQUEST['date_start'];
204
	 		}else
205
	 			$date_start = $bean->date_start;
206
207
	 		$date = SugarDateTime::createFromFormat($GLOBALS['timedate']->get_date_time_format(),$date_start);
208
		 	$arr = array_merge($arr,array(
209
		 		'current_dow' => $date->format("w"),
210
		 		'default_repeat_until' => $date->get("+1 Month")->format($GLOBALS['timedate']->get_date_format()),
211
		 	));
212
213
		 	return $arr;
214
		}
215
	 	return false;
216
	 }
217
218
	/**
219
	 * Build array of datetimes for recurring meetings
220
	 * @param string $date_start
221
	 * @param array $params
222
	 * @return array
223
	 */
224
	static function build_repeat_sequence($date_start,$params){
225
226
		$arr = array();
227
228
		$type = $params['type'];
229
		$interval = intval($params['interval']);
230
		if($interval < 1)
231
			$interval = 1;
232
233
		if(!empty($params['count'])){
234
			$count = $params['count'];
235
			if($count < 1)
236
				$count = 1;
237
		}else
238
			$count = 0;
239
240
		if(!empty($params['until'])){
241
			$until = $params['until'];
242
		}else
243
			$until = $date_start;
244
245
		if($type == "Weekly"){
246
			$dow = $params['dow'];
247
			if($dow == ""){
248
				return array();
249
			}
250
		}
251
252
		/** 
253
		 * @var SugarDateTime $start Recurrence start date.
254
		 */
255
		$start = SugarDateTime::createFromFormat($GLOBALS['timedate']->get_date_time_format(),$date_start);
256
		/** 
257
		 * @var SugarDateTime $end Recurrence end date. Used if recurrence ends by date.
258
		 */
259
		 
260
		if (!empty($params['until'])) {
261
			$end = SugarDateTime::createFromFormat($GLOBALS['timedate']->get_date_format(), $until);
262
			$end->modify("+1 Day");
263
		} else {
264
			$end = $start;
265
		}
266
		$current = clone $start;
267
268
		$i = 1; // skip the first iteration
269
		$w = $interval; // for week iteration
270
		$last_dow = $start->format("w");
271
272
		$limit = SugarConfig::getInstance()->get('calendar.max_repeat_count',1000);
273
274
		while($i < $count || ($count == 0 && $current->format("U") < $end->format("U"))){
275
			$skip = false;
276
			switch($type){
277
				case "Daily":
278
					$current->modify("+{$interval} Days");
279
					break;
280
				case "Weekly":
281
					$day_index = $last_dow;
282
					for($d = $last_dow + 1; $d <= $last_dow + 7; $d++){
283
						$day_index = $d % 7;
284
						if(strpos($dow,(string)($day_index)) !== false){
285
							break;
286
						}
287
					}
288
					$step = $day_index - $last_dow;
289
					$last_dow = $day_index;
290
					if($step <= 0){
291
						$step += 7;
292
						$w++;
293
					}
294
					if($w % $interval != 0)
295
						$skip = true;
296
297
					$current->modify("+{$step} Days");
298
					break;
299
				case "Monthly":
300
					$current->modify("+{$interval} Months");
301
					break;
302
				case "Yearly":
303
					$current->modify("+{$interval} Years");
304
					break;
305
				default:
306
					return array();
307
			}
308
309
			if($skip)
310
				continue;
311
312
			if(($i < $count || $count == 0 && $current->format("U") < $end->format("U"))  ){
313
				$arr[] = $current->format($GLOBALS['timedate']->get_date_time_format());
314
			}
315
			$i++;
316
317
			if($i > $limit + 100)
318
				break;
319
		}
320
		return $arr;
321
	}
322
323
	/**
324
	 * Save repeat activities
325
	 * @param SugarBean $bean
326
	 * @param array $time_arr array of datetimes
327
	 * @return array
328
	 */
329
	static function save_repeat_activities(SugarBean $bean,$time_arr){
330
331
		// Here we will create single big inserting query for each invitee relationship
332
		// rather than using relationships framework due to performance issues.
333
		// Relationship framework runs very slowly
334
335
		global $db;
336
		$id = $bean->id;
337
		$date_modified = $GLOBALS['timedate']->nowDb();
338
		$lower_name = strtolower($bean->object_name);
339
340
		$qu = "SELECT * FROM {$bean->rel_users_table} WHERE deleted = 0 AND {$lower_name}_id = '{$id}'";
341
		$re = $db->query($qu);
342
		$users_rel_arr = array();
343
		while($ro = $db->fetchByAssoc($re))
344
			$users_rel_arr[] = $ro['user_id'];
345
		$qu_users = "
346
				INSERT INTO {$bean->rel_users_table}
347
				(id,user_id,{$lower_name}_id,date_modified)
348
				VALUES
349
		";
350
		$users_filled = false;
351
352
		$qu = "SELECT * FROM {$bean->rel_contacts_table} WHERE deleted = 0 AND {$lower_name}_id = '{$id}'";
353
		$re = $db->query($qu);
354
		$contacts_rel_arr = array();
355
		while($ro = $db->fetchByAssoc($re))
356
			$contacts_rel_arr[] = $ro['contact_id'];
357
		$qu_contacts = "
358
				INSERT INTO {$bean->rel_contacts_table}
359
				(id,contact_id,{$lower_name}_id,date_modified)
360
				VALUES
361
		";
362
		$contacts_filled = false;
363
364
		$qu = "SELECT * FROM {$bean->rel_leads_table} WHERE deleted = 0 AND {$lower_name}_id = '{$id}'";
365
		$re = $db->query($qu);
366
		$leads_rel_arr = array();
367
		while($ro = $db->fetchByAssoc($re))
368
			$leads_rel_arr[] = $ro['lead_id'];
369
		$qu_leads = "
370
				INSERT INTO {$bean->rel_leads_table}
371
				(id,lead_id,{$lower_name}_id,date_modified)
372
				VALUES
373
		";
374
		$leads_filled = false;
375
376
		$arr = array();
377
		$i = 0;
378
		foreach($time_arr as $date_start){
379
			$clone = $bean;	// we don't use clone keyword cause not necessary
380
			$clone->id = "";
381
			$clone->date_start = $date_start;
382
			// TODO CHECK DATETIME VARIABLE
383
			$date = SugarDateTime::createFromFormat($GLOBALS['timedate']->get_date_time_format(),$date_start);
384
			$date = $date->get("+{$bean->duration_hours} Hours")->get("+{$bean->duration_minutes} Minutes");
385
			$date_end = $date->format($GLOBALS['timedate']->get_date_time_format());
386
			$clone->date_end = $date_end;
387
			$clone->recurring_source = "Sugar";
388
			$clone->repeat_parent_id = $id;
389
			$clone->update_vcal = false;
390
			$clone->save(false);
391
392
			if($clone->id){
393
				foreach($users_rel_arr as $user_id){
394
					if($users_filled)
395
						$qu_users .= ",".PHP_EOL;
396
					$qu_users .= "('".create_guid()."','{$user_id}','{$clone->id}','{$date_modified}')";
397
					$users_filled = true;
398
				}
399
				foreach($contacts_rel_arr as $contact_id){
400
					if($contacts_filled)
401
						$qu_contacts .= ",".PHP_EOL;
402
					$qu_contacts .= "('".create_guid()."','{$contact_id}','{$clone->id}','{$date_modified}')";
403
					$contacts_filled = true;
404
				}
405
				foreach($leads_rel_arr as $lead_id){
406
					if($leads_filled)
407
						$qu_leads .= ",".PHP_EOL;
408
					$qu_leads .= "('".create_guid()."','{$lead_id}','{$clone->id}','{$date_modified}')";
409
					$leads_filled = true;
410
				}
411
				if($i < 44){
412
					$clone->date_start = $date_start;
413
					$clone->date_end = $date_end;
414
					$arr[] = array_merge(array('id' => $clone->id),CalendarUtils::get_time_data($clone));
415
				}
416
				$i++;
417
			}
418
		}
419
		
420
		if ($users_filled) {
421
			$db->query($qu_users);
422
		}
423
		if ($contacts_filled) {
424
			$db->query($qu_contacts);
425
		}		
426
		if ($leads_filled) {
427
			$db->query($qu_leads);
428
		}
429
		
430
		vCal::cache_sugar_vcal($GLOBALS['current_user']);
431
		return $arr;
432
	}
433
434
	/**
435
	 * Delete recurring activities and their invitee relationships
436
	 * @param SugarBean $bean
437
	 */
438
	static function markRepeatDeleted(SugarBean $bean)
439
	{
440
		// we don't use mark_deleted method here because it runs very slowly
441
		global $db;
442
		$date_modified = $GLOBALS['timedate']->nowDb();
443
		if(!empty($GLOBALS['current_user']))
444
			$modified_user_id = $GLOBALS['current_user']->id;
445
		else
446
			$modified_user_id = 1;
447
		$lower_name = strtolower($bean->object_name);
448
449
		$qu = "SELECT id FROM {$bean->table_name} WHERE repeat_parent_id = '{$bean->id}' AND deleted = 0";
450
		$re = $db->query($qu);
451
		while( $ro = $db->fetchByAssoc($re)) {
452
			$id = $ro['id'];
453
			$date_modified = $GLOBALS['timedate']->nowDb();
454
			$db->query("UPDATE {$bean->table_name} SET deleted = 1, date_modified = '{$date_modified}', modified_user_id = '{$modified_user_id}' WHERE id = '{$id}'");
455
			$db->query("UPDATE {$bean->rel_users_table} SET deleted = 1, date_modified = '{$date_modified}' WHERE {$lower_name}_id = '{$id}'");
456
			$db->query("UPDATE {$bean->rel_contacts_table} SET deleted = 1, date_modified = '{$date_modified}' WHERE {$lower_name}_id = '{$id}'");
457
			$db->query("UPDATE {$bean->rel_leads_table} SET deleted = 1, date_modified = '{$date_modified}' WHERE {$lower_name}_id = '{$id}'");
458
		}
459
		vCal::cache_sugar_vcal($GLOBALS['current_user']);
460
	}
461
462
	/**
463
	 * check if meeting has repeat children and pass repeat_parent over to the 2nd meeting in sequence
464
	 * @param SugarBean $bean
465
	 * @param string $beanId
466
	 */
467 3
	static function correctRecurrences(SugarBean $bean, $beanId)
468
	{
469 3
		global $db;
470
		
471 3
		$qu = "SELECT id FROM {$bean->table_name} WHERE repeat_parent_id = '{$beanId}' AND deleted = 0 ORDER BY date_start";
472 3
		$re = $db->query($qu);
473
474 3
		$i = 0;
475 3
		while ($ro = $db->fetchByAssoc($re)) {
476
			$id = $ro['id'];
477
			if($i == 0){
478
				$new_parent_id = $id;
479
				$qu = "UPDATE {$bean->table_name} SET repeat_parent_id = '' AND recurring_source = '' WHERE id = '{$id}'";
480
			}else{
481
				$qu = "UPDATE {$bean->table_name} SET repeat_parent_id = '{$new_parent_id}' WHERE id = '{$id}'";
482
			}
483
			$db->query($qu);
484
      		$i++;
485
		}
486 3
	}
487
488
}
489