[ Index ]

PHP Cross Reference of Phabricator

title

Body

[close]

/src/applications/maniphest/storage/ -> ManiphestTransaction.php (source)

   1  <?php
   2  
   3  final class ManiphestTransaction
   4    extends PhabricatorApplicationTransaction {
   5  
   6    const TYPE_TITLE = 'title';
   7    const TYPE_STATUS = 'status';
   8    const TYPE_DESCRIPTION = 'description';
   9    const TYPE_OWNER  = 'reassign';
  10    const TYPE_CCS = 'ccs';
  11    const TYPE_PROJECTS = 'projects';
  12    const TYPE_PRIORITY = 'priority';
  13    const TYPE_EDGE = 'edge';
  14    const TYPE_SUBPRIORITY = 'subpriority';
  15    const TYPE_PROJECT_COLUMN = 'projectcolumn';
  16    const TYPE_MERGED_INTO = 'mergedinto';
  17    const TYPE_MERGED_FROM = 'mergedfrom';
  18  
  19    const TYPE_UNBLOCK = 'unblock';
  20  
  21    // NOTE: this type is deprecated. Keep it around for legacy installs
  22    // so any transactions render correctly.
  23    const TYPE_ATTACH = 'attach';
  24  
  25  
  26    const MAILTAG_STATUS = 'maniphest-status';
  27    const MAILTAG_OWNER = 'maniphest-owner';
  28    const MAILTAG_PRIORITY = 'maniphest-priority';
  29    const MAILTAG_CC = 'maniphest-cc';
  30    const MAILTAG_PROJECTS = 'maniphest-projects';
  31    const MAILTAG_COMMENT = 'maniphest-comment';
  32    const MAILTAG_COLUMN = 'maniphest-column';
  33    const MAILTAG_UNBLOCK = 'maniphest-unblock';
  34    const MAILTAG_OTHER = 'maniphest-other';
  35  
  36  
  37    public function getApplicationName() {
  38      return 'maniphest';
  39    }
  40  
  41    public function getApplicationTransactionType() {
  42      return ManiphestTaskPHIDType::TYPECONST;
  43    }
  44  
  45    public function getApplicationTransactionCommentObject() {
  46      return new ManiphestTransactionComment();
  47    }
  48  
  49    public function shouldGenerateOldValue() {
  50      switch ($this->getTransactionType()) {
  51        case self::TYPE_PROJECT_COLUMN:
  52        case self::TYPE_EDGE:
  53        case self::TYPE_UNBLOCK:
  54          return false;
  55      }
  56  
  57      return parent::shouldGenerateOldValue();
  58    }
  59  
  60    public function getRemarkupBlocks() {
  61      $blocks = parent::getRemarkupBlocks();
  62  
  63      switch ($this->getTransactionType()) {
  64        case self::TYPE_DESCRIPTION:
  65          $blocks[] = $this->getNewValue();
  66          break;
  67      }
  68  
  69      return $blocks;
  70    }
  71  
  72    public function getRequiredHandlePHIDs() {
  73      $phids = parent::getRequiredHandlePHIDs();
  74  
  75      $new = $this->getNewValue();
  76      $old = $this->getOldValue();
  77  
  78      switch ($this->getTransactionType()) {
  79        case self::TYPE_OWNER:
  80          if ($new) {
  81            $phids[] = $new;
  82          }
  83  
  84          if ($old) {
  85            $phids[] = $old;
  86          }
  87          break;
  88        case self::TYPE_CCS:
  89        case self::TYPE_PROJECTS:
  90          $phids = array_mergev(
  91            array(
  92              $phids,
  93              nonempty($old, array()),
  94              nonempty($new, array()),
  95            ));
  96          break;
  97        case self::TYPE_PROJECT_COLUMN:
  98          $phids[] = $new['projectPHID'];
  99          $phids[] = head($new['columnPHIDs']);
 100          break;
 101        case self::TYPE_MERGED_INTO:
 102          $phids[] = $new;
 103          break;
 104        case self::TYPE_MERGED_FROM:
 105          $phids = array_merge($phids, $new);
 106          break;
 107        case self::TYPE_EDGE:
 108          $phids = array_mergev(
 109            array(
 110              $phids,
 111              array_keys(nonempty($old, array())),
 112              array_keys(nonempty($new, array())),
 113            ));
 114          break;
 115        case self::TYPE_ATTACH:
 116          $old = nonempty($old, array());
 117          $new = nonempty($new, array());
 118          $phids = array_mergev(
 119            array(
 120              $phids,
 121              array_keys(idx($new, 'FILE', array())),
 122              array_keys(idx($old, 'FILE', array())),
 123            ));
 124          break;
 125        case self::TYPE_UNBLOCK:
 126          foreach (array_keys($new) as $phid) {
 127            $phids[] = $phid;
 128          }
 129          break;
 130      }
 131  
 132      return $phids;
 133    }
 134  
 135    public function shouldHide() {
 136      switch ($this->getTransactionType()) {
 137        case self::TYPE_DESCRIPTION:
 138        case self::TYPE_PRIORITY:
 139        case self::TYPE_STATUS:
 140          if ($this->getOldValue() === null) {
 141            return true;
 142          } else {
 143            return false;
 144          }
 145          break;
 146        case self::TYPE_SUBPRIORITY:
 147          return true;
 148        case self::TYPE_PROJECT_COLUMN:
 149          $old_cols = idx($this->getOldValue(), 'columnPHIDs');
 150          $new_cols = idx($this->getNewValue(), 'columnPHIDs');
 151  
 152          $old_cols = array_values($old_cols);
 153          $new_cols = array_values($new_cols);
 154          sort($old_cols);
 155          sort($new_cols);
 156  
 157          return ($old_cols === $new_cols);
 158      }
 159  
 160      return parent::shouldHide();
 161    }
 162  
 163    public function getActionStrength() {
 164      switch ($this->getTransactionType()) {
 165        case self::TYPE_TITLE:
 166          return 1.4;
 167        case self::TYPE_STATUS:
 168          return 1.3;
 169        case self::TYPE_OWNER:
 170          return 1.2;
 171        case self::TYPE_PRIORITY:
 172          return 1.1;
 173      }
 174  
 175      return parent::getActionStrength();
 176    }
 177  
 178  
 179    public function getColor() {
 180      $old = $this->getOldValue();
 181      $new = $this->getNewValue();
 182  
 183      switch ($this->getTransactionType()) {
 184        case self::TYPE_OWNER:
 185          if ($this->getAuthorPHID() == $new) {
 186            return 'green';
 187          } else if (!$new) {
 188            return 'black';
 189          } else if (!$old) {
 190            return 'green';
 191          } else {
 192            return 'green';
 193          }
 194  
 195        case self::TYPE_STATUS:
 196          $color = ManiphestTaskStatus::getStatusColor($new);
 197          if ($color !== null) {
 198            return $color;
 199          }
 200  
 201          if (ManiphestTaskStatus::isOpenStatus($new)) {
 202            return 'green';
 203          } else {
 204            return 'black';
 205          }
 206  
 207        case self::TYPE_PRIORITY:
 208          if ($old == ManiphestTaskPriority::getDefaultPriority()) {
 209            return 'green';
 210          } else if ($old > $new) {
 211            return 'grey';
 212          } else {
 213            return 'yellow';
 214          }
 215  
 216        case self::TYPE_MERGED_FROM:
 217          return 'orange';
 218  
 219        case self::TYPE_MERGED_INTO:
 220          return 'black';
 221      }
 222  
 223      return parent::getColor();
 224    }
 225  
 226    public function getActionName() {
 227      $old = $this->getOldValue();
 228      $new = $this->getNewValue();
 229  
 230      switch ($this->getTransactionType()) {
 231        case self::TYPE_TITLE:
 232          if ($old === null) {
 233            return pht('Created');
 234          }
 235  
 236          return pht('Retitled');
 237  
 238        case self::TYPE_STATUS:
 239          $action = ManiphestTaskStatus::getStatusActionName($new);
 240          if ($action) {
 241            return $action;
 242          }
 243  
 244          $old_closed = ManiphestTaskStatus::isClosedStatus($old);
 245          $new_closed = ManiphestTaskStatus::isClosedStatus($new);
 246  
 247          if ($new_closed && !$old_closed) {
 248            return pht('Closed');
 249          } else if (!$new_closed && $old_closed) {
 250            return pht('Reopened');
 251          } else {
 252            return pht('Changed Status');
 253          }
 254  
 255        case self::TYPE_DESCRIPTION:
 256          return pht('Edited');
 257  
 258        case self::TYPE_OWNER:
 259          if ($this->getAuthorPHID() == $new) {
 260            return pht('Claimed');
 261          } else if (!$new) {
 262            return pht('Up For Grabs');
 263          } else if (!$old) {
 264            return pht('Assigned');
 265          } else {
 266            return pht('Reassigned');
 267          }
 268  
 269        case self::TYPE_CCS:
 270          return pht('Changed CC');
 271  
 272        case self::TYPE_PROJECTS:
 273          return pht('Changed Projects');
 274  
 275        case self::TYPE_PROJECT_COLUMN:
 276          return pht('Changed Project Column');
 277  
 278        case self::TYPE_PRIORITY:
 279          if ($old == ManiphestTaskPriority::getDefaultPriority()) {
 280            return pht('Triaged');
 281          } else if ($old > $new) {
 282            return pht('Lowered Priority');
 283          } else {
 284            return pht('Raised Priority');
 285          }
 286  
 287        case self::TYPE_EDGE:
 288        case self::TYPE_ATTACH:
 289          return pht('Attached');
 290  
 291        case self::TYPE_UNBLOCK:
 292          $old_status = head($old);
 293          $new_status = head($new);
 294  
 295          $old_closed = ManiphestTaskStatus::isClosedStatus($old_status);
 296          $new_closed = ManiphestTaskStatus::isClosedStatus($new_status);
 297  
 298          if ($old_closed && !$new_closed) {
 299            return pht('Block');
 300          } else if (!$old_closed && $new_closed) {
 301            return pht('Unblock');
 302          } else {
 303            return pht('Blocker');
 304          }
 305  
 306        case self::TYPE_MERGED_INTO:
 307        case self::TYPE_MERGED_FROM:
 308          return pht('Merged');
 309  
 310      }
 311  
 312      return parent::getActionName();
 313    }
 314  
 315    public function getIcon() {
 316      $old = $this->getOldValue();
 317      $new = $this->getNewValue();
 318  
 319      switch ($this->getTransactionType()) {
 320        case self::TYPE_OWNER:
 321          return 'fa-user';
 322  
 323        case self::TYPE_CCS:
 324          return 'fa-envelope';
 325  
 326        case self::TYPE_TITLE:
 327          if ($old === null) {
 328            return 'fa-pencil';
 329          }
 330  
 331          return 'fa-pencil';
 332  
 333        case self::TYPE_STATUS:
 334          $action = ManiphestTaskStatus::getStatusIcon($new);
 335          if ($action !== null) {
 336            return $action;
 337          }
 338  
 339          if (ManiphestTaskStatus::isClosedStatus($new)) {
 340            return 'fa-check';
 341          } else {
 342            return 'fa-pencil';
 343          }
 344  
 345        case self::TYPE_DESCRIPTION:
 346          return 'fa-pencil';
 347  
 348        case self::TYPE_PROJECTS:
 349          return 'fa-briefcase';
 350  
 351        case self::TYPE_PROJECT_COLUMN:
 352          return 'fa-columns';
 353  
 354        case self::TYPE_MERGED_INTO:
 355          return 'fa-check';
 356        case self::TYPE_MERGED_FROM:
 357          return 'fa-compress';
 358  
 359        case self::TYPE_PRIORITY:
 360          if ($old == ManiphestTaskPriority::getDefaultPriority()) {
 361            return 'fa-arrow-right';
 362          } else if ($old > $new) {
 363            return 'fa-arrow-down';
 364          } else {
 365            return 'fa-arrow-up';
 366          }
 367  
 368        case self::TYPE_EDGE:
 369        case self::TYPE_ATTACH:
 370          return 'fa-thumb-tack';
 371  
 372        case self::TYPE_UNBLOCK:
 373          return 'fa-shield';
 374  
 375      }
 376  
 377      return parent::getIcon();
 378    }
 379  
 380  
 381  
 382    public function getTitle() {
 383      $author_phid = $this->getAuthorPHID();
 384  
 385      $old = $this->getOldValue();
 386      $new = $this->getNewValue();
 387  
 388      switch ($this->getTransactionType()) {
 389        case self::TYPE_TITLE:
 390          if ($old === null) {
 391            return pht(
 392              '%s created this task.',
 393              $this->renderHandleLink($author_phid));
 394          }
 395          return pht(
 396            '%s changed the title from "%s" to "%s".',
 397            $this->renderHandleLink($author_phid),
 398            $old,
 399            $new);
 400  
 401        case self::TYPE_DESCRIPTION:
 402          return pht(
 403            '%s edited the task description.',
 404            $this->renderHandleLink($author_phid));
 405  
 406        case self::TYPE_STATUS:
 407          $old_closed = ManiphestTaskStatus::isClosedStatus($old);
 408          $new_closed = ManiphestTaskStatus::isClosedStatus($new);
 409  
 410          $old_name = ManiphestTaskStatus::getTaskStatusName($old);
 411          $new_name = ManiphestTaskStatus::getTaskStatusName($new);
 412  
 413          if ($new_closed && !$old_closed) {
 414            if ($new == ManiphestTaskStatus::getDuplicateStatus()) {
 415              return pht(
 416                '%s closed this task as a duplicate.',
 417                $this->renderHandleLink($author_phid));
 418            } else {
 419              return pht(
 420                '%s closed this task as "%s".',
 421                $this->renderHandleLink($author_phid),
 422                $new_name);
 423            }
 424          } else if (!$new_closed && $old_closed) {
 425            return pht(
 426              '%s reopened this task as "%s".',
 427              $this->renderHandleLink($author_phid),
 428              $new_name);
 429          } else {
 430            return pht(
 431              '%s changed the task status from "%s" to "%s".',
 432              $this->renderHandleLink($author_phid),
 433              $old_name,
 434              $new_name);
 435          }
 436  
 437        case self::TYPE_UNBLOCK:
 438          $blocker_phid = key($new);
 439          $old_status = head($old);
 440          $new_status = head($new);
 441  
 442          $old_closed = ManiphestTaskStatus::isClosedStatus($old_status);
 443          $new_closed = ManiphestTaskStatus::isClosedStatus($new_status);
 444  
 445          $old_name = ManiphestTaskStatus::getTaskStatusName($old_status);
 446          $new_name = ManiphestTaskStatus::getTaskStatusName($new_status);
 447  
 448          if ($old_closed && !$new_closed) {
 449            return pht(
 450              '%s reopened blocking task %s as "%s".',
 451              $this->renderHandleLink($author_phid),
 452              $this->renderHandleLink($blocker_phid),
 453              $new_name);
 454          } else if (!$old_closed && $new_closed) {
 455            return pht(
 456              '%s closed blocking task %s as "%s".',
 457              $this->renderHandleLink($author_phid),
 458              $this->renderHandleLink($blocker_phid),
 459              $new_name);
 460          } else {
 461            return pht(
 462              '%s changed the status of blocking task %s from "%s" to "%s".',
 463              $this->renderHandleLink($author_phid),
 464              $this->renderHandleLink($blocker_phid),
 465              $old_name,
 466              $new_name);
 467          }
 468  
 469        case self::TYPE_OWNER:
 470          if ($author_phid == $new) {
 471            return pht(
 472              '%s claimed this task.',
 473              $this->renderHandleLink($author_phid));
 474          } else if (!$new) {
 475            return pht(
 476              '%s placed this task up for grabs.',
 477              $this->renderHandleLink($author_phid));
 478          } else if (!$old) {
 479            return pht(
 480              '%s assigned this task to %s.',
 481              $this->renderHandleLink($author_phid),
 482              $this->renderHandleLink($new));
 483          } else {
 484            return pht(
 485              '%s reassigned this task from %s to %s.',
 486              $this->renderHandleLink($author_phid),
 487              $this->renderHandleLink($old),
 488              $this->renderHandleLink($new));
 489          }
 490  
 491        case self::TYPE_PROJECTS:
 492          $added = array_diff($new, $old);
 493          $removed = array_diff($old, $new);
 494          if ($added && !$removed) {
 495            return pht(
 496              '%s added %d project(s): %s',
 497              $this->renderHandleLink($author_phid),
 498              count($added),
 499              $this->renderHandleList($added));
 500          } else if ($removed && !$added) {
 501            return pht(
 502              '%s removed %d project(s): %s',
 503              $this->renderHandleLink($author_phid),
 504              count($removed),
 505              $this->renderHandleList($removed));
 506          } else if ($removed && $added) {
 507            return pht(
 508              '%s changed project(s), added %d: %s; removed %d: %s',
 509              $this->renderHandleLink($author_phid),
 510              count($added),
 511              $this->renderHandleList($added),
 512              count($removed),
 513              $this->renderHandleList($removed));
 514          } else {
 515            // This is hit when rendering previews.
 516            return pht(
 517              '%s changed projects...',
 518              $this->renderHandleLink($author_phid));
 519          }
 520  
 521        case self::TYPE_PRIORITY:
 522          $old_name = ManiphestTaskPriority::getTaskPriorityName($old);
 523          $new_name = ManiphestTaskPriority::getTaskPriorityName($new);
 524  
 525          if ($old == ManiphestTaskPriority::getDefaultPriority()) {
 526            return pht(
 527              '%s triaged this task as "%s" priority.',
 528              $this->renderHandleLink($author_phid),
 529              $new_name);
 530          } else if ($old > $new) {
 531            return pht(
 532              '%s lowered the priority of this task from "%s" to "%s".',
 533              $this->renderHandleLink($author_phid),
 534              $old_name,
 535              $new_name);
 536          } else {
 537            return pht(
 538              '%s raised the priority of this task from "%s" to "%s".',
 539              $this->renderHandleLink($author_phid),
 540              $old_name,
 541              $new_name);
 542          }
 543  
 544        case self::TYPE_CCS:
 545          // TODO: Remove this when we switch to subscribers. Just reuse the
 546          // code in the parent.
 547          $clone = clone $this;
 548          $clone->setTransactionType(PhabricatorTransactions::TYPE_SUBSCRIBERS);
 549          return $clone->getTitle();
 550  
 551        case self::TYPE_EDGE:
 552          // TODO: Remove this when we switch to real edges. Just reuse the
 553          // code in the parent;
 554          $clone = clone $this;
 555          $clone->setTransactionType(PhabricatorTransactions::TYPE_EDGE);
 556          return $clone->getTitle();
 557  
 558        case self::TYPE_ATTACH:
 559          $old = nonempty($old, array());
 560          $new = nonempty($new, array());
 561          $new = array_keys(idx($new, 'FILE', array()));
 562          $old = array_keys(idx($old, 'FILE', array()));
 563  
 564          $added = array_diff($new, $old);
 565          $removed = array_diff($old, $new);
 566          if ($added && !$removed) {
 567            return pht(
 568              '%s attached %d file(s): %s',
 569              $this->renderHandleLink($author_phid),
 570              count($added),
 571              $this->renderHandleList($added));
 572          } else if ($removed && !$added) {
 573            return pht(
 574              '%s detached %d file(s): %s',
 575              $this->renderHandleLink($author_phid),
 576              count($removed),
 577              $this->renderHandleList($removed));
 578          } else {
 579            return pht(
 580              '%s changed file(s), attached %d: %s; detached %d: %s',
 581              $this->renderHandleLink($author_phid),
 582              count($added),
 583              $this->renderHandleList($added),
 584              count($removed),
 585              $this->renderHandleList($removed));
 586          }
 587  
 588        case self::TYPE_PROJECT_COLUMN:
 589          $project_phid = $new['projectPHID'];
 590          $column_phid = head($new['columnPHIDs']);
 591          return pht(
 592            '%s moved this task to %s on the %s workboard.',
 593            $this->renderHandleLink($author_phid),
 594            $this->renderHandleLink($column_phid),
 595            $this->renderHandleLink($project_phid));
 596          break;
 597  
 598        case self::TYPE_MERGED_INTO:
 599          return pht(
 600            '%s closed this task as a duplicate of %s.',
 601            $this->renderHandleLink($author_phid),
 602            $this->renderHandleLink($new));
 603          break;
 604  
 605        case self::TYPE_MERGED_FROM:
 606          return pht(
 607            '%s merged %d task(s): %s.',
 608            $this->renderHandleLink($author_phid),
 609            count($new),
 610            $this->renderHandleList($new));
 611          break;
 612  
 613  
 614      }
 615  
 616      return parent::getTitle();
 617    }
 618  
 619    public function getTitleForFeed(PhabricatorFeedStory $story) {
 620      $author_phid = $this->getAuthorPHID();
 621      $object_phid = $this->getObjectPHID();
 622  
 623      $old = $this->getOldValue();
 624      $new = $this->getNewValue();
 625  
 626      switch ($this->getTransactionType()) {
 627        case self::TYPE_TITLE:
 628          if ($old === null) {
 629            return pht(
 630              '%s created %s.',
 631              $this->renderHandleLink($author_phid),
 632              $this->renderHandleLink($object_phid));
 633          }
 634  
 635          return pht(
 636            '%s renamed %s from "%s" to "%s".',
 637            $this->renderHandleLink($author_phid),
 638            $this->renderHandleLink($object_phid),
 639            $old,
 640            $new);
 641  
 642        case self::TYPE_DESCRIPTION:
 643          return pht(
 644            '%s edited the description of %s.',
 645            $this->renderHandleLink($author_phid),
 646            $this->renderHandleLink($object_phid));
 647  
 648        case self::TYPE_STATUS:
 649          $old_closed = ManiphestTaskStatus::isClosedStatus($old);
 650          $new_closed = ManiphestTaskStatus::isClosedStatus($new);
 651  
 652          $old_name = ManiphestTaskStatus::getTaskStatusName($old);
 653          $new_name = ManiphestTaskStatus::getTaskStatusName($new);
 654  
 655          if ($new_closed && !$old_closed) {
 656            if ($new == ManiphestTaskStatus::getDuplicateStatus()) {
 657              return pht(
 658                '%s closed %s as a duplicate.',
 659                $this->renderHandleLink($author_phid),
 660                $this->renderHandleLink($object_phid));
 661            } else {
 662              return pht(
 663                '%s closed %s as "%s".',
 664                $this->renderHandleLink($author_phid),
 665                $this->renderHandleLink($object_phid),
 666                $new_name);
 667            }
 668          } else if (!$new_closed && $old_closed) {
 669            return pht(
 670              '%s reopened %s as "%s".',
 671              $this->renderHandleLink($author_phid),
 672              $this->renderHandleLink($object_phid),
 673              $new_name);
 674          } else {
 675            return pht(
 676              '%s changed the status of %s from "%s" to "%s".',
 677              $this->renderHandleLink($author_phid),
 678              $this->renderHandleLink($object_phid),
 679              $old_name,
 680              $new_name);
 681          }
 682  
 683        case self::TYPE_UNBLOCK:
 684          $blocker_phid = key($new);
 685          $old_status = head($old);
 686          $new_status = head($new);
 687  
 688          $old_closed = ManiphestTaskStatus::isClosedStatus($old_status);
 689          $new_closed = ManiphestTaskStatus::isClosedStatus($new_status);
 690  
 691          $old_name = ManiphestTaskStatus::getTaskStatusName($old_status);
 692          $new_name = ManiphestTaskStatus::getTaskStatusName($new_status);
 693  
 694          if ($old_closed && !$new_closed) {
 695            return pht(
 696              '%s reopened %s, a task blocking %s, as "%s".',
 697              $this->renderHandleLink($author_phid),
 698              $this->renderHandleLink($blocker_phid),
 699              $this->renderHandleLink($object_phid),
 700              $new_name);
 701          } else if (!$old_closed && $new_closed) {
 702            return pht(
 703              '%s closed %s, a task blocking %s, as "%s".',
 704              $this->renderHandleLink($author_phid),
 705              $this->renderHandleLink($blocker_phid),
 706              $this->renderHandleLink($object_phid),
 707              $new_name);
 708          } else {
 709            return pht(
 710              '%s changed the status of %s, a task blocking %s, '.
 711              'from "%s" to "%s".',
 712              $this->renderHandleLink($author_phid),
 713              $this->renderHandleLink($blocker_phid),
 714              $this->renderHandleLink($object_phid),
 715              $old_name,
 716              $new_name);
 717          }
 718  
 719        case self::TYPE_OWNER:
 720          if ($author_phid == $new) {
 721            return pht(
 722              '%s claimed %s.',
 723              $this->renderHandleLink($author_phid),
 724              $this->renderHandleLink($object_phid));
 725          } else if (!$new) {
 726            return pht(
 727              '%s placed %s up for grabs.',
 728              $this->renderHandleLink($author_phid),
 729              $this->renderHandleLink($object_phid));
 730          } else if (!$old) {
 731            return pht(
 732              '%s assigned %s to %s.',
 733              $this->renderHandleLink($author_phid),
 734              $this->renderHandleLink($object_phid),
 735              $this->renderHandleLink($new));
 736          } else {
 737            return pht(
 738              '%s reassigned %s from %s to %s.',
 739              $this->renderHandleLink($author_phid),
 740              $this->renderHandleLink($object_phid),
 741              $this->renderHandleLink($old),
 742              $this->renderHandleLink($new));
 743          }
 744  
 745        case self::TYPE_PROJECTS:
 746          $added = array_diff($new, $old);
 747          $removed = array_diff($old, $new);
 748          if ($added && !$removed) {
 749            return pht(
 750              '%s added %d project(s) to %s: %s',
 751              $this->renderHandleLink($author_phid),
 752              count($added),
 753              $this->renderHandleLink($object_phid),
 754              $this->renderHandleList($added));
 755          } else if ($removed && !$added) {
 756            return pht(
 757              '%s removed %d project(s) from %s: %s',
 758              $this->renderHandleLink($author_phid),
 759              count($removed),
 760              $this->renderHandleLink($object_phid),
 761              $this->renderHandleList($removed));
 762          } else if ($removed && $added) {
 763            return pht(
 764              '%s changed project(s) of %s, added %d: %s; removed %d: %s',
 765              $this->renderHandleLink($author_phid),
 766              $this->renderHandleLink($object_phid),
 767              count($added),
 768              $this->renderHandleList($added),
 769              count($removed),
 770              $this->renderHandleList($removed));
 771          }
 772  
 773        case self::TYPE_PRIORITY:
 774          $old_name = ManiphestTaskPriority::getTaskPriorityName($old);
 775          $new_name = ManiphestTaskPriority::getTaskPriorityName($new);
 776  
 777          if ($old == ManiphestTaskPriority::getDefaultPriority()) {
 778            return pht(
 779              '%s triaged %s as "%s" priority.',
 780              $this->renderHandleLink($author_phid),
 781              $this->renderHandleLink($object_phid),
 782              $new_name);
 783          } else if ($old > $new) {
 784            return pht(
 785              '%s lowered the priority of %s from "%s" to "%s".',
 786              $this->renderHandleLink($author_phid),
 787              $this->renderHandleLink($object_phid),
 788              $old_name,
 789              $new_name);
 790          } else {
 791            return pht(
 792              '%s raised the priority of %s from "%s" to "%s".',
 793              $this->renderHandleLink($author_phid),
 794              $this->renderHandleLink($object_phid),
 795              $old_name,
 796              $new_name);
 797          }
 798  
 799        case self::TYPE_CCS:
 800          // TODO: Remove this when we switch to subscribers. Just reuse the
 801          // code in the parent.
 802          $clone = clone $this;
 803          $clone->setTransactionType(PhabricatorTransactions::TYPE_SUBSCRIBERS);
 804          return $clone->getTitleForFeed($story);
 805  
 806        case self::TYPE_EDGE:
 807          // TODO: Remove this when we switch to real edges. Just reuse the
 808          // code in the parent;
 809          $clone = clone $this;
 810          $clone->setTransactionType(PhabricatorTransactions::TYPE_EDGE);
 811          return $clone->getTitleForFeed($story);
 812  
 813        case self::TYPE_ATTACH:
 814          $old = nonempty($old, array());
 815          $new = nonempty($new, array());
 816          $new = array_keys(idx($new, 'FILE', array()));
 817          $old = array_keys(idx($old, 'FILE', array()));
 818  
 819          $added = array_diff($new, $old);
 820          $removed = array_diff($old, $new);
 821          if ($added && !$removed) {
 822            return pht(
 823              '%s attached %d file(s) of %s: %s',
 824              $this->renderHandleLink($author_phid),
 825              $this->renderHandleLink($object_phid),
 826              count($added),
 827              $this->renderHandleList($added));
 828          } else if ($removed && !$added) {
 829            return pht(
 830              '%s detached %d file(s) of %s: %s',
 831              $this->renderHandleLink($author_phid),
 832              $this->renderHandleLink($object_phid),
 833              count($removed),
 834              $this->renderHandleList($removed));
 835          } else {
 836            return pht(
 837              '%s changed file(s) for %s, attached %d: %s; detached %d: %s',
 838              $this->renderHandleLink($author_phid),
 839              $this->renderHandleLink($object_phid),
 840              count($added),
 841              $this->renderHandleList($added),
 842              count($removed),
 843              $this->renderHandleList($removed));
 844          }
 845  
 846        case self::TYPE_PROJECT_COLUMN:
 847          $project_phid = $new['projectPHID'];
 848          $column_phid = head($new['columnPHIDs']);
 849          return pht(
 850            '%s moved %s to %s on the %s workboard.',
 851            $this->renderHandleLink($author_phid),
 852            $this->renderHandleLink($object_phid),
 853            $this->renderHandleLink($column_phid),
 854            $this->renderHandleLink($project_phid));
 855  
 856        case self::TYPE_MERGED_INTO:
 857          return pht(
 858            '%s merged task %s into %s.',
 859            $this->renderHandleLink($author_phid),
 860            $this->renderHandleLink($object_phid),
 861            $this->renderHandleLink($new));
 862  
 863        case self::TYPE_MERGED_FROM:
 864          return pht(
 865            '%s merged %d task(s) %s into %s.',
 866            $this->renderHandleLink($author_phid),
 867            count($new),
 868            $this->renderHandleList($new),
 869            $this->renderHandleLink($object_phid));
 870  
 871      }
 872  
 873      return parent::getTitleForFeed($story);
 874    }
 875  
 876    public function hasChangeDetails() {
 877      switch ($this->getTransactionType()) {
 878        case self::TYPE_DESCRIPTION:
 879          return true;
 880      }
 881      return parent::hasChangeDetails();
 882    }
 883  
 884    public function renderChangeDetails(PhabricatorUser $viewer) {
 885      return $this->renderTextCorpusChangeDetails(
 886        $viewer,
 887        $this->getOldValue(),
 888        $this->getNewValue());
 889    }
 890  
 891    public function getMailTags() {
 892      $tags = array();
 893      switch ($this->getTransactionType()) {
 894        case self::TYPE_STATUS:
 895          $tags[] = self::MAILTAG_STATUS;
 896          break;
 897        case self::TYPE_OWNER:
 898          $tags[] = self::MAILTAG_OWNER;
 899          break;
 900        case self::TYPE_CCS:
 901          $tags[] = self::MAILTAG_CC;
 902          break;
 903        case PhabricatorTransactions::TYPE_EDGE:
 904          switch ($this->getMetadataValue('edge:type')) {
 905            case PhabricatorProjectObjectHasProjectEdgeType::EDGECONST:
 906              $tags[] = self::MAILTAG_PROJECTS;
 907              break;
 908            default:
 909              $tags[] = self::MAILTAG_OTHER;
 910              break;
 911          }
 912          break;
 913        case self::TYPE_PRIORITY:
 914          $tags[] = self::MAILTAG_PRIORITY;
 915          break;
 916        case self::TYPE_UNBLOCK:
 917          $tags[] = self::MAILTAG_UNBLOCK;
 918          break;
 919        case self::TYPE_PROJECT_COLUMN:
 920          $tags[] = self::MAILTAG_COLUMN;
 921          break;
 922        case PhabricatorTransactions::TYPE_COMMENT:
 923          $tags[] = self::MAILTAG_COMMENT;
 924          break;
 925        default:
 926          $tags[] = self::MAILTAG_OTHER;
 927          break;
 928      }
 929      return $tags;
 930    }
 931  
 932    public function getNoEffectDescription() {
 933  
 934      switch ($this->getTransactionType()) {
 935        case self::TYPE_STATUS:
 936          return pht('The task already has the selected status.');
 937        case self::TYPE_OWNER:
 938          return pht('The task already has the selected owner.');
 939        case self::TYPE_PROJECTS:
 940          return pht('The task is already associated with those projects.');
 941        case self::TYPE_PRIORITY:
 942          return pht('The task already has the selected priority.');
 943      }
 944  
 945      return parent::getNoEffectDescription();
 946    }
 947  
 948  }


Generated: Sun Nov 30 09:20:46 2014 Cross-referenced by PHPXref 0.7.1