@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Cancelled recurring events should propogate to real child events

Summary: Ref T8371, Cancelled recurring events should propogate to real child events

Test Plan: Create recurring event, create and exception to a ghost event, cancel recurring event, real ghost event should be treated as cancelled while the recurring event remains cancelled.

Reviewers: epriestley, #blessed_reviewers

Reviewed By: epriestley, #blessed_reviewers

Subscribers: Korvin, epriestley

Maniphest Tasks: T8371

Differential Revision: https://secure.phabricator.com/D13121

+82 -7
+2
src/applications/calendar/controller/PhabricatorCalendarEventViewController.php
··· 28 28 } 29 29 30 30 if ($sequence && $event->getIsRecurring()) { 31 + $parent_event = $event; 31 32 $event = $event->generateNthGhost($sequence, $viewer); 33 + $event->attachParentEvent($parent_event); 32 34 } else if ($sequence) { 33 35 return new Aphront404Response(); 34 36 }
+54 -7
src/applications/calendar/query/PhabricatorCalendarEventQuery.php
··· 12 12 private $isCancelled; 13 13 private $instanceSequencePairs; 14 14 15 - 16 15 private $generateGhosts = false; 17 16 18 17 public function setGenerateGhosts($generate_ghosts) { ··· 108 107 $map = array(); 109 108 $instance_sequence_pairs = array(); 110 109 111 - foreach ($events as $event) { 110 + foreach ($events as $key => $event) { 112 111 $sequence_start = 0; 113 112 $sequence_end = null; 114 113 $duration = $event->getDateTo() - $event->getDateFrom(); 115 114 $end = null; 116 115 117 - if ($event->getIsRecurring() && !$event->getInstanceOfEventPHID()) { 116 + $instance_of = $event->getInstanceOfEventPHID(); 117 + 118 + if ($instance_of == null && $this->isCancelled !== null) { 119 + if ($event->getIsCancelled() != $this->isCancelled) { 120 + unset($events[$key]); 121 + continue; 122 + } 123 + } 124 + 125 + if ($event->getIsRecurring() && $instance_of == null) { 118 126 $frequency = $event->getFrequencyUnit(); 119 127 $modify_key = '+1 '.$frequency; 120 128 ··· 164 172 $instance_sequence_pairs[] = array($event->getPHID(), $index); 165 173 $events[] = $event->generateNthGhost($index, $viewer); 166 174 167 - $key = last_key($events); 168 - $map[$event->getPHID()][$index] = $key; 175 + $last_key = last_key($events); 176 + $map[$event->getPHID()][$index] = $last_key; 169 177 } 170 178 } 171 179 } ··· 308 316 protected function willFilterPage(array $events) { 309 317 $range_start = $this->rangeBegin; 310 318 $range_end = $this->rangeEnd; 319 + $instance_of_event_phids = array(); 320 + $recurring_events = array(); 321 + $viewer = $this->getViewer(); 311 322 312 323 foreach ($events as $key => $event) { 313 324 $event_start = $event->getDateFrom(); ··· 325 336 326 337 foreach ($events as $event) { 327 338 $phids[] = $event->getPHID(); 339 + $instance_of = $event->getInstanceOfEventPHID(); 340 + 341 + if ($instance_of) { 342 + if ($instance_of != $event->getPHID() || $event->getIsGhostEvent()) { 343 + $instance_of_event_phids[] = $event->getInstanceOfEventPHID(); 344 + } 345 + } 346 + } 347 + 348 + if (count($instance_of_event_phids) > 0) { 349 + $recurring_events = id(new PhabricatorCalendarEventQuery()) 350 + ->setViewer($viewer) 351 + ->withPHIDs($instance_of_event_phids) 352 + ->execute(); 353 + 354 + $recurring_events = mpull($recurring_events, null, 'getPHID'); 328 355 } 329 356 330 357 if ($events) { 331 358 $invitees = id(new PhabricatorCalendarEventInviteeQuery()) 332 - ->setViewer($this->getViewer()) 359 + ->setViewer($viewer) 333 360 ->withEventPHIDs($phids) 334 361 ->execute(); 335 362 $invitees = mgroup($invitees, 'getEventPHID'); ··· 337 364 $invitees = array(); 338 365 } 339 366 340 - foreach ($events as $event) { 367 + foreach ($events as $key => $event) { 341 368 $event_invitees = idx($invitees, $event->getPHID(), array()); 342 369 $event->attachInvitees($event_invitees); 370 + 371 + $instance_of = $event->getInstanceOfEventPHID(); 372 + if (!$instance_of) { 373 + continue; 374 + } 375 + $parent = idx($recurring_events, $instance_of); 376 + 377 + // should never get here 378 + if (!$parent) { 379 + unset($events[$key]); 380 + continue; 381 + } 382 + $event->attachParentEvent($parent); 383 + 384 + if ($this->isCancelled !== null) { 385 + if ($event->getIsCancelled() != $this->isCancelled) { 386 + unset($events[$key]); 387 + continue; 388 + } 389 + } 343 390 } 344 391 345 392 $events = msort($events, 'getDateFrom');
+26
src/applications/calendar/storage/PhabricatorCalendarEvent.php
··· 33 33 34 34 const DEFAULT_ICON = 'fa-calendar'; 35 35 36 + private $parentEvent = self::ATTACHABLE; 36 37 private $invitees = self::ATTACHABLE; 37 38 private $appliedViewer; 38 39 ··· 327 328 $uri = $uri.'/'.$this->sequenceIndex; 328 329 } 329 330 return $uri; 331 + } 332 + 333 + public function getParentEvent() { 334 + return $this->assertAttached($this->parentEvent); 335 + } 336 + 337 + public function attachParentEvent($event) { 338 + $this->parentEvent = $event; 339 + return $this; 340 + } 341 + 342 + public function getIsCancelled() { 343 + $instance_of = $this->instanceOfEventPHID; 344 + if ($instance_of != null && $this->getIsParentCancelled()) { 345 + return true; 346 + } 347 + return $this->isCancelled; 348 + } 349 + 350 + public function getIsParentCancelled() { 351 + $recurring_event = $this->getParentEvent(); 352 + if ($recurring_event->getIsCancelled()) { 353 + return true; 354 + } 355 + return false; 330 356 } 331 357 332 358 /* -( Markup Interface )--------------------------------------------------- */