@@ -305,7 +305,7 @@ protected function parseEventForOrganizer(VCalendar $calendar, array $eventInfo,
305305 if (count ($ eventInfo ['instances ' ]) === 0 && count ($ oldEventInfo ['instances ' ]) > 0 ) {
306306 foreach ($ oldEventInfo ['attendees ' ] as $ attendee ) {
307307 $ messages [] = $ this ->generateMessage (
308- $ oldEventInfo ['instances ' ], $ organizerHref , $ organizerName , $ attendee , $ objectId , $ objectType , $ objectSequence , 'CANCEL ' , $ template
308+ $ oldEventInfo ['instances ' ], $ organizerHref , $ organizerName , $ attendee , $ objectId , $ objectType , $ objectSequence , 'CANCEL ' , $ template, true
309309 );
310310 }
311311 return $ messages ;
@@ -314,7 +314,7 @@ protected function parseEventForOrganizer(VCalendar $calendar, array $eventInfo,
314314 if ($ eventInfo ['instances ' ]['master ' ]?->STATUS ?->getValue() === 'CANCELLED ' && $ oldEventInfo ['instances ' ]['master ' ]?->STATUS ?->getValue() !== 'CANCELLED ' ) {
315315 foreach ($ eventInfo ['attendees ' ] as $ attendee ) {
316316 $ messages [] = $ this ->generateMessage (
317- $ eventInfo ['instances ' ], $ organizerHref , $ organizerName , $ attendee , $ objectId , $ objectType , $ objectSequence , 'CANCEL ' , $ template
317+ $ eventInfo ['instances ' ], $ organizerHref , $ organizerName , $ attendee , $ objectId , $ objectType , $ objectSequence , 'CANCEL ' , $ template, true
318318 );
319319 }
320320 return $ messages ;
@@ -328,7 +328,7 @@ protected function parseEventForOrganizer(VCalendar $calendar, array $eventInfo,
328328 $ cancelledNewInstances [] = $ id ;
329329 foreach ($ eventInfo ['attendees ' ] as $ attendee ) {
330330 $ messages [] = $ this ->generateMessage (
331- [$ id => $ instance ], $ organizerHref , $ organizerName , $ attendee , $ objectId , $ objectType , $ objectSequence , 'CANCEL ' , $ template
331+ [$ id => $ instance ], $ organizerHref , $ organizerName , $ attendee , $ objectId , $ objectType , $ objectSequence , 'CANCEL ' , $ template, true
332332 );
333333 }
334334 }
@@ -359,7 +359,7 @@ protected function parseEventForOrganizer(VCalendar $calendar, array $eventInfo,
359359 //get all instances of the attendee was removed from.
360360 $ instances = array_intersect_key ($ oldEventInfo ['instances ' ], array_flip (array_keys ($ oldEventInfo ['attendees ' ][$ attendee ]['instances ' ])));
361361 $ messages [] = $ this ->generateMessage (
362- $ instances , $ organizerHref , $ organizerName , $ oldEventInfo ['attendees ' ][$ attendee ], $ objectId , $ objectType , $ objectSequence , 'CANCEL ' , $ template
362+ $ instances , $ organizerHref , $ organizerName , $ oldEventInfo ['attendees ' ][$ attendee ], $ objectId , $ objectType , $ objectSequence , 'CANCEL ' , $ template, true
363363 );
364364 continue ;
365365 }
@@ -398,8 +398,19 @@ protected function parseEventForOrganizer(VCalendar $calendar, array $eventInfo,
398398 }
399399 }
400400
401+ // determine if this attendee needs to be notified of the change, based on whether
402+ // a significant property changed on the event, or the set of instances they are part of changed
403+ $ oldAttendeeInstances = isset ($ oldEventInfo ['attendees ' ][$ attendee ]) ? array_keys ($ oldEventInfo ['attendees ' ][$ attendee ]['instances ' ]) : [];
404+ $ newAttendeeInstances = array_keys ($ eventInfo ['attendees ' ][$ attendee ]['instances ' ]);
405+
406+ $ significantChange
407+ = $ eventInfo ['attendees ' ][$ attendee ]['forceSend ' ] === 'REQUEST '
408+ || count ($ oldAttendeeInstances ) !== count ($ newAttendeeInstances )
409+ || count (array_diff ($ oldAttendeeInstances , $ newAttendeeInstances )) > 0
410+ || $ oldEventInfo ['significantChangeHash ' ] !== $ eventInfo ['significantChangeHash ' ];
411+
401412 $ messages [] = $ this ->generateMessage (
402- $ instances , $ organizerHref , $ organizerName , $ eventInfo ['attendees ' ][$ attendee ], $ objectId , $ objectType , $ objectSequence , 'REQUEST ' , $ template
413+ $ instances , $ organizerHref , $ organizerName , $ eventInfo ['attendees ' ][$ attendee ], $ objectId , $ objectType , $ objectSequence , 'REQUEST ' , $ template, $ significantChange
403414 );
404415 }
405416
@@ -424,6 +435,8 @@ protected function parseEventForOrganizer(VCalendar $calendar, array $eventInfo,
424435 * @param int $objectSequence The sequence number of the event
425436 * @param string $method The iTip method ('REQUEST', 'CANCEL', 'REPLY', etc.)
426437 * @param VCalendar $template The template calendar object (without event components)
438+ * @param bool $significantChange Whether a property listed in $significantChangeProperties changed,
439+ * or the attendee's set of instances changed
427440 * @return Message The generated iTip message ready to be sent
428441 */
429442 protected function generateMessage (
@@ -436,6 +449,7 @@ protected function generateMessage(
436449 int $ objectSequence ,
437450 string $ method ,
438451 VCalendar $ template ,
452+ bool $ significantChange ,
439453 ): Message {
440454
441455 $ recipientAddress = $ attendee ['href ' ] ?? '' ;
@@ -460,7 +474,7 @@ protected function generateMessage(
460474 $ message ->senderName = $ organizerName ;
461475 $ message ->recipient = $ recipientAddress ;
462476 $ message ->recipientName = $ recipientName ;
463- $ message ->significantChange = true ;
477+ $ message ->significantChange = $ significantChange ;
464478 $ message ->message = $ vObject ;
465479
466480 return $ message ;
0 commit comments