@@ -35,6 +35,7 @@ public function __construct(
3535 private readonly CalendarFederationConfig $ calendarFederationConfig ,
3636 private readonly IJobList $ jobList ,
3737 private readonly ICloudIdManager $ cloudIdManager ,
38+ private readonly FederatedCalendarInvitationService $ invitationService ,
3839 ) {
3940 }
4041
@@ -122,25 +123,49 @@ public function shareReceived(ICloudFederationShare $share): string {
122123
123124 $ sharedWithPrincipal = 'principals/users/ ' . $ share ->getShareWith ();
124125
125- // Delete existing incoming federated share first
126- $ this ->federatedCalendarMapper ->deleteByUri ($ sharedWithPrincipal , $ calendarUri );
127-
128- $ calendar = new FederatedCalendarEntity ();
129- $ calendar ->setPrincipaluri ($ sharedWithPrincipal );
130- $ calendar ->setUri ($ calendarUri );
131- $ calendar ->setRemoteUrl ($ calendarUrl );
132- $ calendar ->setDisplayName ($ displayName );
133- $ calendar ->setColor ($ color );
134- $ calendar ->setToken ($ share ->getShareSecret ());
135- $ calendar ->setSharedBy ($ share ->getSharedBy ());
136- $ calendar ->setSharedByDisplayName ($ share ->getSharedByDisplayName ());
137- $ calendar ->setPermissions ($ permissions );
138- $ calendar ->setComponents ($ components );
139- $ calendar = $ this ->federatedCalendarMapper ->insert ($ calendar );
140-
141- $ this ->jobList ->add (FederatedCalendarSyncJob::class, [
142- FederatedCalendarSyncJob::ARGUMENT_ID => $ calendar ->getId (),
143- ]);
126+ $ calendar = $ this ->federatedCalendarMapper ->findByUri ($ sharedWithPrincipal , $ calendarUri );
127+ $ isNew = $ calendar === null ;
128+
129+ if ($ calendar === null ) {
130+ $ calendar = new FederatedCalendarEntity ();
131+ $ calendar ->setPrincipaluri ($ sharedWithPrincipal );
132+ $ calendar ->setUri ($ calendarUri );
133+ $ calendar ->setRemoteUrl ($ calendarUrl );
134+ $ calendar ->setDisplayName ($ displayName );
135+ $ calendar ->setColor ($ color );
136+ $ calendar ->setToken ($ share ->getShareSecret ());
137+ $ calendar ->setSharedBy ($ share ->getSharedBy ());
138+ $ calendar ->setSharedByDisplayName ($ share ->getSharedByDisplayName ());
139+ $ calendar ->setPermissions ($ permissions );
140+ $ calendar ->setComponents ($ components );
141+ $ calendar ->setState (FederatedCalendarEntity::STATE_PENDING );
142+ $ calendar = $ this ->federatedCalendarMapper ->insert ($ calendar );
143+ } else {
144+ $ calendar ->setToken ($ share ->getShareSecret ());
145+ $ calendar ->setPermissions ($ permissions );
146+ $ calendar ->setComponents ($ components );
147+ if ($ calendar ->getState () === FederatedCalendarEntity::STATE_PENDING ) {
148+ // The open invitation shows the sharer's metadata, keep it
149+ // fresh. Accepted calendars are not touched as the sharee owns
150+ // the display name and color from that point on.
151+ $ calendar ->setDisplayName ($ displayName );
152+ $ calendar ->setColor ($ color );
153+ $ calendar ->setSharedByDisplayName ($ share ->getSharedByDisplayName ());
154+ }
155+ $ this ->federatedCalendarMapper ->update ($ calendar );
156+ }
157+
158+ if ($ calendar ->getState () === FederatedCalendarEntity::STATE_ACCEPTED ) {
159+ // Re-share of an already accepted calendar: just refresh the data
160+ $ this ->jobList ->add (FederatedCalendarSyncJob::class, [
161+ FederatedCalendarSyncJob::ARGUMENT_ID => $ calendar ->getId (),
162+ ]);
163+ } elseif ($ this ->invitationService ->shouldAutoAccept ($ share ->getOwner (), $ calendar ->getRemoteUrl ())) {
164+ $ this ->invitationService ->accept ($ calendar );
165+ } elseif ($ isNew ) {
166+ // A re-shared pending calendar keeps its original invitation
167+ $ this ->invitationService ->notifyAboutNewShare ($ calendar );
168+ }
144169
145170 return (string )$ calendar ->getId ();
146171 }
@@ -196,6 +221,7 @@ private function handleSyncCalendarNotification(array $notification): array {
196221 $ calendarUrl ,
197222 'principals/users/ ' . $ shareWith ->getUser (),
198223 $ sharedSecret ,
224+ FederatedCalendarEntity::STATE_ACCEPTED ,
199225 );
200226 if (empty ($ calendars )) {
201227 throw new ShareNotFound ('Calendar is not shared with the sharee ' );
0 commit comments