[ Index ]

PHP Cross Reference of Phabricator

title

Body

[close]

/src/applications/maniphest/editor/ -> ManiphestTransactionEditor.php (source)

   1  <?php
   2  
   3  final class ManiphestTransactionEditor
   4    extends PhabricatorApplicationTransactionEditor {
   5  
   6    private $heraldEmailPHIDs = array();
   7  
   8    public function getEditorApplicationClass() {
   9      return 'PhabricatorManiphestApplication';
  10    }
  11  
  12    public function getEditorObjectsDescription() {
  13      return pht('Maniphest Tasks');
  14    }
  15  
  16    public function getTransactionTypes() {
  17      $types = parent::getTransactionTypes();
  18  
  19      $types[] = PhabricatorTransactions::TYPE_COMMENT;
  20      $types[] = PhabricatorTransactions::TYPE_EDGE;
  21      $types[] = ManiphestTransaction::TYPE_PRIORITY;
  22      $types[] = ManiphestTransaction::TYPE_STATUS;
  23      $types[] = ManiphestTransaction::TYPE_TITLE;
  24      $types[] = ManiphestTransaction::TYPE_DESCRIPTION;
  25      $types[] = ManiphestTransaction::TYPE_OWNER;
  26      $types[] = ManiphestTransaction::TYPE_CCS;
  27      $types[] = ManiphestTransaction::TYPE_SUBPRIORITY;
  28      $types[] = ManiphestTransaction::TYPE_PROJECT_COLUMN;
  29      $types[] = ManiphestTransaction::TYPE_MERGED_INTO;
  30      $types[] = ManiphestTransaction::TYPE_MERGED_FROM;
  31      $types[] = ManiphestTransaction::TYPE_UNBLOCK;
  32      $types[] = PhabricatorTransactions::TYPE_VIEW_POLICY;
  33      $types[] = PhabricatorTransactions::TYPE_EDIT_POLICY;
  34  
  35      return $types;
  36    }
  37  
  38    protected function getCustomTransactionOldValue(
  39      PhabricatorLiskDAO $object,
  40      PhabricatorApplicationTransaction $xaction) {
  41  
  42      switch ($xaction->getTransactionType()) {
  43        case ManiphestTransaction::TYPE_PRIORITY:
  44          if ($this->getIsNewObject()) {
  45            return null;
  46          }
  47          return (int)$object->getPriority();
  48        case ManiphestTransaction::TYPE_STATUS:
  49          if ($this->getIsNewObject()) {
  50            return null;
  51          }
  52          return $object->getStatus();
  53        case ManiphestTransaction::TYPE_TITLE:
  54          if ($this->getIsNewObject()) {
  55            return null;
  56          }
  57          return $object->getTitle();
  58        case ManiphestTransaction::TYPE_DESCRIPTION:
  59          if ($this->getIsNewObject()) {
  60            return null;
  61          }
  62          return $object->getDescription();
  63        case ManiphestTransaction::TYPE_OWNER:
  64          return nonempty($object->getOwnerPHID(), null);
  65        case ManiphestTransaction::TYPE_CCS:
  66          return array_values(array_unique($object->getCCPHIDs()));
  67        case ManiphestTransaction::TYPE_PROJECT_COLUMN:
  68          // These are pre-populated.
  69          return $xaction->getOldValue();
  70        case ManiphestTransaction::TYPE_SUBPRIORITY:
  71          return $object->getSubpriority();
  72        case ManiphestTransaction::TYPE_MERGED_INTO:
  73        case ManiphestTransaction::TYPE_MERGED_FROM:
  74          return null;
  75      }
  76    }
  77  
  78    protected function getCustomTransactionNewValue(
  79      PhabricatorLiskDAO $object,
  80      PhabricatorApplicationTransaction $xaction) {
  81  
  82      switch ($xaction->getTransactionType()) {
  83        case ManiphestTransaction::TYPE_PRIORITY:
  84          return (int)$xaction->getNewValue();
  85        case ManiphestTransaction::TYPE_CCS:
  86          return array_values(array_unique($xaction->getNewValue()));
  87        case ManiphestTransaction::TYPE_OWNER:
  88          return nonempty($xaction->getNewValue(), null);
  89        case ManiphestTransaction::TYPE_STATUS:
  90        case ManiphestTransaction::TYPE_TITLE:
  91        case ManiphestTransaction::TYPE_DESCRIPTION:
  92        case ManiphestTransaction::TYPE_SUBPRIORITY:
  93        case ManiphestTransaction::TYPE_PROJECT_COLUMN:
  94        case ManiphestTransaction::TYPE_MERGED_INTO:
  95        case ManiphestTransaction::TYPE_MERGED_FROM:
  96        case ManiphestTransaction::TYPE_UNBLOCK:
  97          return $xaction->getNewValue();
  98      }
  99    }
 100  
 101    protected function transactionHasEffect(
 102      PhabricatorLiskDAO $object,
 103      PhabricatorApplicationTransaction $xaction) {
 104  
 105      $old = $xaction->getOldValue();
 106      $new = $xaction->getNewValue();
 107  
 108      switch ($xaction->getTransactionType()) {
 109        case ManiphestTransaction::TYPE_CCS:
 110          sort($old);
 111          sort($new);
 112          return ($old !== $new);
 113        case ManiphestTransaction::TYPE_PROJECT_COLUMN:
 114          $new_column_phids = $new['columnPHIDs'];
 115          $old_column_phids = $old['columnPHIDs'];
 116          sort($new_column_phids);
 117          sort($old_column_phids);
 118          return ($old !== $new);
 119      }
 120  
 121      return parent::transactionHasEffect($object, $xaction);
 122    }
 123  
 124    protected function applyCustomInternalTransaction(
 125      PhabricatorLiskDAO $object,
 126      PhabricatorApplicationTransaction $xaction) {
 127  
 128      switch ($xaction->getTransactionType()) {
 129        case ManiphestTransaction::TYPE_PRIORITY:
 130          return $object->setPriority($xaction->getNewValue());
 131        case ManiphestTransaction::TYPE_STATUS:
 132          return $object->setStatus($xaction->getNewValue());
 133        case ManiphestTransaction::TYPE_TITLE:
 134          return $object->setTitle($xaction->getNewValue());
 135        case ManiphestTransaction::TYPE_DESCRIPTION:
 136          return $object->setDescription($xaction->getNewValue());
 137        case ManiphestTransaction::TYPE_OWNER:
 138          $phid = $xaction->getNewValue();
 139  
 140          // Update the "ownerOrdering" column to contain the full name of the
 141          // owner, if the task is assigned.
 142  
 143          $handle = null;
 144          if ($phid) {
 145            $handle = id(new PhabricatorHandleQuery())
 146              ->setViewer($this->getActor())
 147              ->withPHIDs(array($phid))
 148              ->executeOne();
 149          }
 150  
 151          if ($handle) {
 152            $object->setOwnerOrdering($handle->getName());
 153          } else {
 154            $object->setOwnerOrdering(null);
 155          }
 156  
 157          return $object->setOwnerPHID($phid);
 158        case ManiphestTransaction::TYPE_CCS:
 159          return $object->setCCPHIDs($xaction->getNewValue());
 160        case ManiphestTransaction::TYPE_SUBPRIORITY:
 161          $data = $xaction->getNewValue();
 162          $new_sub = $this->getNextSubpriority(
 163            $data['newPriority'],
 164            $data['newSubpriorityBase'],
 165            $data['direction']);
 166          $object->setSubpriority($new_sub);
 167          return;
 168        case ManiphestTransaction::TYPE_PROJECT_COLUMN:
 169          // these do external (edge) updates
 170          return;
 171        case ManiphestTransaction::TYPE_MERGED_INTO:
 172          $object->setStatus(ManiphestTaskStatus::getDuplicateStatus());
 173          return;
 174        case ManiphestTransaction::TYPE_MERGED_FROM:
 175          return;
 176      }
 177    }
 178  
 179    protected function expandTransaction(
 180      PhabricatorLiskDAO $object,
 181      PhabricatorApplicationTransaction $xaction) {
 182  
 183      $xactions = parent::expandTransaction($object, $xaction);
 184      switch ($xaction->getTransactionType()) {
 185        case ManiphestTransaction::TYPE_SUBPRIORITY:
 186          $data = $xaction->getNewValue();
 187          $new_pri = $data['newPriority'];
 188          if ($new_pri != $object->getPriority()) {
 189            $xactions[] = id(new ManiphestTransaction())
 190              ->setTransactionType(ManiphestTransaction::TYPE_PRIORITY)
 191              ->setNewValue($new_pri);
 192          }
 193          break;
 194        default:
 195          break;
 196      }
 197  
 198      return $xactions;
 199    }
 200  
 201    protected function applyCustomExternalTransaction(
 202      PhabricatorLiskDAO $object,
 203      PhabricatorApplicationTransaction $xaction) {
 204  
 205      switch ($xaction->getTransactionType()) {
 206        case ManiphestTransaction::TYPE_PROJECT_COLUMN:
 207          $board_phid = idx($xaction->getNewValue(), 'projectPHID');
 208          if (!$board_phid) {
 209            throw new Exception(
 210              pht("Expected 'projectPHID' in column transaction."));
 211          }
 212  
 213          $old_phids = idx($xaction->getOldValue(), 'columnPHIDs', array());
 214          $new_phids = idx($xaction->getNewValue(), 'columnPHIDs', array());
 215          if (count($new_phids) !== 1) {
 216            throw new Exception(
 217              pht("Expected exactly one 'columnPHIDs' in column transaction."));
 218          }
 219  
 220          $columns = id(new PhabricatorProjectColumnQuery())
 221            ->setViewer($this->requireActor())
 222            ->withPHIDs($new_phids)
 223            ->execute();
 224          $columns = mpull($columns, null, 'getPHID');
 225  
 226          $positions = id(new PhabricatorProjectColumnPositionQuery())
 227            ->setViewer($this->requireActor())
 228            ->withObjectPHIDs(array($object->getPHID()))
 229            ->withBoardPHIDs(array($board_phid))
 230            ->execute();
 231  
 232          $before_phid = idx($xaction->getNewValue(), 'beforePHID');
 233          $after_phid = idx($xaction->getNewValue(), 'afterPHID');
 234  
 235          if (!$before_phid && !$after_phid && ($old_phids == $new_phids)) {
 236            // If we are not moving the object between columns and also not
 237            // reordering the position, this is a move on some other order
 238            // (like priority). We can leave the positions untouched and just
 239            // bail, there's no work to be done.
 240            return;
 241          }
 242  
 243          // Otherwise, we're either moving between columns or adjusting the
 244          // object's position in the "natural" ordering, so we do need to update
 245          // some rows.
 246  
 247          // Remove all existing column positions on the board.
 248  
 249          foreach ($positions as $position) {
 250            $position->delete();
 251          }
 252  
 253          // Add the new column positions.
 254  
 255          foreach ($new_phids as $phid) {
 256            $column = idx($columns, $phid);
 257            if (!$column) {
 258              throw new Exception(
 259                pht('No such column "%s" exists!', $phid));
 260            }
 261  
 262            // Load the other object positions in the column. Note that we must
 263            // skip implicit column creation to avoid generating a new position
 264            // if the target column is a backlog column.
 265  
 266            $other_positions = id(new PhabricatorProjectColumnPositionQuery())
 267              ->setViewer($this->requireActor())
 268              ->withColumns(array($column))
 269              ->withBoardPHIDs(array($board_phid))
 270              ->setSkipImplicitCreate(true)
 271              ->execute();
 272            $other_positions = msort($other_positions, 'getOrderingKey');
 273  
 274            // Set up the new position object. We're going to figure out the
 275            // right sequence number and then persist this object with that
 276            // sequence number.
 277            $new_position = id(new PhabricatorProjectColumnPosition())
 278              ->setBoardPHID($board_phid)
 279              ->setColumnPHID($column->getPHID())
 280              ->setObjectPHID($object->getPHID());
 281  
 282            $updates = array();
 283            $sequence = 0;
 284  
 285            // If we're just dropping this into the column without any specific
 286            // position information, put it at the top.
 287            if (!$before_phid && !$after_phid) {
 288              $new_position->setSequence($sequence)->save();
 289              $sequence++;
 290            }
 291  
 292            foreach ($other_positions as $position) {
 293              $object_phid = $position->getObjectPHID();
 294  
 295              // If this is the object we're moving before and we haven't
 296              // saved yet, insert here.
 297              if (($before_phid == $object_phid) && !$new_position->getID()) {
 298                $new_position->setSequence($sequence)->save();
 299                $sequence++;
 300              }
 301  
 302              // This object goes here in the sequence; we might need to update
 303              // the row.
 304              if ($sequence != $position->getSequence()) {
 305                $updates[$position->getID()] = $sequence;
 306              }
 307              $sequence++;
 308  
 309              // If this is the object we're moving after and we haven't saved
 310              // yet, insert here.
 311              if (($after_phid == $object_phid) && !$new_position->getID()) {
 312                $new_position->setSequence($sequence)->save();
 313                $sequence++;
 314              }
 315            }
 316  
 317            // We should have found a place to put it.
 318            if (!$new_position->getID()) {
 319              throw new Exception(
 320                pht('Unable to find a place to insert object on column!'));
 321            }
 322  
 323            // If we changed other objects' column positions, bulk reorder them.
 324  
 325            if ($updates) {
 326              $position = new PhabricatorProjectColumnPosition();
 327              $conn_w = $position->establishConnection('w');
 328  
 329              $pairs = array();
 330              foreach ($updates as $id => $sequence) {
 331                // This is ugly because MySQL gets upset with us if it is
 332                // configured strictly and we attempt inserts which can't work.
 333                // We'll never actually do these inserts since they'll always
 334                // collide (triggering the ON DUPLICATE KEY logic), so we just
 335                // provide dummy values in order to get there.
 336  
 337                $pairs[] = qsprintf(
 338                  $conn_w,
 339                  '(%d, %d, "", "", "")',
 340                  $id,
 341                  $sequence);
 342              }
 343  
 344              queryfx(
 345                $conn_w,
 346                'INSERT INTO %T (id, sequence, boardPHID, columnPHID, objectPHID)
 347                  VALUES %Q ON DUPLICATE KEY UPDATE sequence = VALUES(sequence)',
 348                $position->getTableName(),
 349                implode(', ', $pairs));
 350            }
 351          }
 352          break;
 353        default:
 354          break;
 355      }
 356    }
 357  
 358    protected function applyFinalEffects(
 359      PhabricatorLiskDAO $object,
 360      array $xactions) {
 361  
 362      // When we change the status of a task, update tasks this tasks blocks
 363      // with a message to the effect of "alincoln resolved blocking task Txxx."
 364      $unblock_xaction = null;
 365      foreach ($xactions as $xaction) {
 366        switch ($xaction->getTransactionType()) {
 367          case ManiphestTransaction::TYPE_STATUS:
 368            $unblock_xaction = $xaction;
 369            break;
 370        }
 371      }
 372  
 373      if ($unblock_xaction !== null) {
 374        $blocked_phids = PhabricatorEdgeQuery::loadDestinationPHIDs(
 375          $object->getPHID(),
 376          PhabricatorEdgeConfig::TYPE_TASK_DEPENDED_ON_BY_TASK);
 377        if ($blocked_phids) {
 378          // In theory we could apply these through policies, but that seems a
 379          // little bit surprising. For now, use the actor's vision.
 380          $blocked_tasks = id(new ManiphestTaskQuery())
 381            ->setViewer($this->getActor())
 382            ->withPHIDs($blocked_phids)
 383            ->execute();
 384  
 385          $old = $unblock_xaction->getOldValue();
 386          $new = $unblock_xaction->getNewValue();
 387  
 388          foreach ($blocked_tasks as $blocked_task) {
 389            $unblock_xactions = array();
 390  
 391            $unblock_xactions[] = id(new ManiphestTransaction())
 392              ->setTransactionType(ManiphestTransaction::TYPE_UNBLOCK)
 393              ->setOldValue(array($object->getPHID() => $old))
 394              ->setNewValue(array($object->getPHID() => $new));
 395  
 396            id(new ManiphestTransactionEditor())
 397              ->setActor($this->getActor())
 398              ->setActingAsPHID($this->getActingAsPHID())
 399              ->setContentSource($this->getContentSource())
 400              ->setContinueOnNoEffect(true)
 401              ->setContinueOnMissingFields(true)
 402              ->applyTransactions($blocked_task, $unblock_xactions);
 403          }
 404        }
 405      }
 406  
 407      return $xactions;
 408    }
 409  
 410    protected function shouldSendMail(
 411      PhabricatorLiskDAO $object,
 412      array $xactions) {
 413  
 414      $xactions = mfilter($xactions, 'shouldHide', true);
 415      return $xactions;
 416    }
 417  
 418    protected function getMailSubjectPrefix() {
 419      return PhabricatorEnv::getEnvConfig('metamta.maniphest.subject-prefix');
 420    }
 421  
 422    protected function getMailThreadID(PhabricatorLiskDAO $object) {
 423      return 'maniphest-task-'.$object->getPHID();
 424    }
 425  
 426    protected function getMailTo(PhabricatorLiskDAO $object) {
 427      return array(
 428        $object->getOwnerPHID(),
 429        $this->getActingAsPHID(),
 430      );
 431    }
 432  
 433    protected function getMailCC(PhabricatorLiskDAO $object) {
 434      $phids = array();
 435  
 436      foreach ($object->getCCPHIDs() as $phid) {
 437        $phids[] = $phid;
 438      }
 439  
 440      foreach (parent::getMailCC($object) as $phid) {
 441        $phids[] = $phid;
 442      }
 443  
 444      foreach ($this->heraldEmailPHIDs as $phid) {
 445        $phids[] = $phid;
 446      }
 447  
 448      return $phids;
 449    }
 450  
 451    public function getMailTagsMap() {
 452      return array(
 453        ManiphestTransaction::MAILTAG_STATUS =>
 454          pht("A task's status changes."),
 455        ManiphestTransaction::MAILTAG_OWNER =>
 456          pht("A task's owner changes."),
 457        ManiphestTransaction::MAILTAG_PRIORITY =>
 458          pht("A task's priority changes."),
 459        ManiphestTransaction::MAILTAG_CC =>
 460          pht("A task's subscribers change."),
 461        ManiphestTransaction::MAILTAG_PROJECTS =>
 462          pht("A task's associated projects change."),
 463        ManiphestTransaction::MAILTAG_UNBLOCK =>
 464          pht('One of the tasks a task is blocked by changes status.'),
 465        ManiphestTransaction::MAILTAG_COLUMN =>
 466          pht('A task is moved between columns on a workboard.'),
 467        ManiphestTransaction::MAILTAG_COMMENT =>
 468          pht('Someone comments on a task.'),
 469        ManiphestTransaction::MAILTAG_OTHER =>
 470          pht('Other task activity not listed above occurs.'),
 471      );
 472    }
 473  
 474    protected function buildReplyHandler(PhabricatorLiskDAO $object) {
 475      return id(new ManiphestReplyHandler())
 476        ->setMailReceiver($object);
 477    }
 478  
 479    protected function buildMailTemplate(PhabricatorLiskDAO $object) {
 480      $id = $object->getID();
 481      $title = $object->getTitle();
 482  
 483      return id(new PhabricatorMetaMTAMail())
 484        ->setSubject("T{$id}: {$title}")
 485        ->addHeader('Thread-Topic', "T{$id}: ".$object->getOriginalTitle());
 486    }
 487  
 488    protected function buildMailBody(
 489      PhabricatorLiskDAO $object,
 490      array $xactions) {
 491  
 492      $body = parent::buildMailBody($object, $xactions);
 493  
 494      if ($this->getIsNewObject()) {
 495        $body->addTextSection(
 496          pht('TASK DESCRIPTION'),
 497          $object->getDescription());
 498      }
 499  
 500      $body->addLinkSection(
 501        pht('TASK DETAIL'),
 502        PhabricatorEnv::getProductionURI('/T'.$object->getID()));
 503  
 504  
 505      $board_phids = array();
 506      $type_column = ManiphestTransaction::TYPE_PROJECT_COLUMN;
 507      foreach ($xactions as $xaction) {
 508        if ($xaction->getTransactionType() == $type_column) {
 509          $new = $xaction->getNewValue();
 510          $project_phid = idx($new, 'projectPHID');
 511          if ($project_phid) {
 512            $board_phids[] = $project_phid;
 513          }
 514        }
 515      }
 516  
 517      if ($board_phids) {
 518        $projects = id(new PhabricatorProjectQuery())
 519          ->setViewer($this->requireActor())
 520          ->withPHIDs($board_phids)
 521          ->execute();
 522  
 523        foreach ($projects as $project) {
 524          $body->addLinkSection(
 525            pht('WORKBOARD'),
 526            PhabricatorEnv::getProductionURI(
 527              '/project/board/'.$project->getID().'/'));
 528        }
 529      }
 530  
 531  
 532      return $body;
 533    }
 534  
 535    protected function shouldPublishFeedStory(
 536      PhabricatorLiskDAO $object,
 537      array $xactions) {
 538      return $this->shouldSendMail($object, $xactions);
 539    }
 540  
 541    protected function supportsSearch() {
 542      return true;
 543    }
 544  
 545    protected function shouldApplyHeraldRules(
 546      PhabricatorLiskDAO $object,
 547      array $xactions) {
 548      return true;
 549    }
 550  
 551    protected function buildHeraldAdapter(
 552      PhabricatorLiskDAO $object,
 553      array $xactions) {
 554  
 555      return id(new HeraldManiphestTaskAdapter())
 556        ->setTask($object);
 557    }
 558  
 559    protected function didApplyHeraldRules(
 560      PhabricatorLiskDAO $object,
 561      HeraldAdapter $adapter,
 562      HeraldTranscript $transcript) {
 563  
 564      // TODO: Convert these to transactions. The way Maniphest deals with these
 565      // transactions is currently unconventional and messy.
 566  
 567      $save_again = false;
 568      $cc_phids = $adapter->getCcPHIDs();
 569      if ($cc_phids) {
 570        $existing_cc = $object->getCCPHIDs();
 571        $new_cc = array_unique(array_merge($cc_phids, $existing_cc));
 572        $object->setCCPHIDs($new_cc);
 573        $object->save();
 574      }
 575  
 576      $this->heraldEmailPHIDs = $adapter->getEmailPHIDs();
 577  
 578      $xactions = array();
 579  
 580      $assign_phid = $adapter->getAssignPHID();
 581      if ($assign_phid) {
 582        $xactions[] = id(new ManiphestTransaction())
 583          ->setTransactionType(ManiphestTransaction::TYPE_OWNER)
 584          ->setNewValue($assign_phid);
 585      }
 586  
 587      $project_phids = $adapter->getProjectPHIDs();
 588      if ($project_phids) {
 589        $project_type = PhabricatorProjectObjectHasProjectEdgeType::EDGECONST;
 590        $xactions[] = id(new ManiphestTransaction())
 591          ->setTransactionType(PhabricatorTransactions::TYPE_EDGE)
 592          ->setMetadataValue('edge:type', $project_type)
 593          ->setNewValue(
 594            array(
 595              '+' => array_fuse($project_phids),
 596            ));
 597      }
 598  
 599      return $xactions;
 600    }
 601  
 602    protected function requireCapabilities(
 603      PhabricatorLiskDAO $object,
 604      PhabricatorApplicationTransaction $xaction) {
 605  
 606      parent::requireCapabilities($object, $xaction);
 607  
 608      $app_capability_map = array(
 609        ManiphestTransaction::TYPE_PRIORITY =>
 610          ManiphestEditPriorityCapability::CAPABILITY,
 611        ManiphestTransaction::TYPE_STATUS =>
 612          ManiphestEditStatusCapability::CAPABILITY,
 613        ManiphestTransaction::TYPE_OWNER =>
 614          ManiphestEditAssignCapability::CAPABILITY,
 615        PhabricatorTransactions::TYPE_EDIT_POLICY =>
 616          ManiphestEditPoliciesCapability::CAPABILITY,
 617        PhabricatorTransactions::TYPE_VIEW_POLICY =>
 618          ManiphestEditPoliciesCapability::CAPABILITY,
 619      );
 620  
 621  
 622      $transaction_type = $xaction->getTransactionType();
 623  
 624      $app_capability = null;
 625      if ($transaction_type == PhabricatorTransactions::TYPE_EDGE) {
 626        switch ($xaction->getMetadataValue('edge:type')) {
 627          case PhabricatorProjectObjectHasProjectEdgeType::EDGECONST:
 628            $app_capability = ManiphestEditProjectsCapability::CAPABILITY;
 629            break;
 630        }
 631      } else {
 632        $app_capability = idx($app_capability_map, $transaction_type);
 633      }
 634  
 635      if ($app_capability) {
 636        $app = id(new PhabricatorApplicationQuery())
 637          ->setViewer($this->getActor())
 638          ->withClasses(array('PhabricatorManiphestApplication'))
 639          ->executeOne();
 640        PhabricatorPolicyFilter::requireCapability(
 641          $this->getActor(),
 642          $app,
 643          $app_capability);
 644      }
 645    }
 646  
 647    protected function adjustObjectForPolicyChecks(
 648      PhabricatorLiskDAO $object,
 649      array $xactions) {
 650  
 651      $copy = parent::adjustObjectForPolicyChecks($object, $xactions);
 652      foreach ($xactions as $xaction) {
 653        switch ($xaction->getTransactionType()) {
 654          case ManiphestTransaction::TYPE_OWNER:
 655            $copy->setOwnerPHID($xaction->getNewValue());
 656            break;
 657          default:
 658            continue;
 659        }
 660      }
 661  
 662      return $copy;
 663    }
 664  
 665    private function getNextSubpriority($pri, $sub, $dir = '>') {
 666      switch ($dir) {
 667        case '>':
 668          $order = 'ASC';
 669          break;
 670        case '<':
 671          $order = 'DESC';
 672          break;
 673        default:
 674          throw new Exception('$dir must be ">" or "<".');
 675          break;
 676      }
 677  
 678      if ($sub === null) {
 679        $base = 0;
 680      } else {
 681        $base = $sub;
 682      }
 683  
 684      if ($sub === null) {
 685        $next = id(new ManiphestTask())->loadOneWhere(
 686          'priority = %d ORDER BY subpriority %Q LIMIT 1',
 687          $pri,
 688          $order);
 689        if ($next) {
 690          if ($dir == '>') {
 691            return $next->getSubpriority() - ((double)(2 << 16));
 692          } else {
 693            return $next->getSubpriority() + ((double)(2 << 16));
 694          }
 695        }
 696      } else {
 697        $next = id(new ManiphestTask())->loadOneWhere(
 698          'priority = %d AND subpriority %Q %f ORDER BY subpriority %Q LIMIT 1',
 699          $pri,
 700          $dir,
 701          $sub,
 702          $order);
 703        if ($next) {
 704          return ($sub + $next->getSubpriority()) / 2;
 705        }
 706      }
 707  
 708      if ($dir == '>') {
 709        return $base + (double)(2 << 32);
 710      } else {
 711        return $base - (double)(2 << 32);
 712      }
 713    }
 714  
 715  }


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