/**
  * Get priorities for moving a task before or after another task.
  */
 public static function getAdjacentSubpriority(ManiphestTask $dst, $is_after, $allow_recursion = true)
 {
     $query = id(new ManiphestTaskQuery())->setViewer(PhabricatorUser::getOmnipotentUser())->setOrder(ManiphestTaskQuery::ORDER_PRIORITY)->withPriorities(array($dst->getPriority()))->setLimit(1);
     if ($is_after) {
         $query->setAfterID($dst->getID());
     } else {
         $query->setBeforeID($dst->getID());
     }
     $adjacent = $query->executeOne();
     $base = $dst->getSubpriority();
     $step = (double) (2 << 32);
     // If we find an adjacent task, we average the two subpriorities and
     // return the result.
     if ($adjacent) {
         $epsilon = 0.01;
         // If the adjacent task has a subpriority that is identical or very
         // close to the task we're looking at, we're going to move it and all
         // tasks with the same subpriority a little farther down the subpriority
         // scale.
         if ($allow_recursion && abs($adjacent->getSubpriority() - $base) < $epsilon) {
             $conn_w = $adjacent->establishConnection('w');
             $min = $adjacent->getSubpriority() - $epsilon;
             $max = $adjacent->getSubpriority() + $epsilon;
             // Get all of the tasks with the similar subpriorities to the adjacent
             // task, including the adjacent task itself.
             $query = id(new ManiphestTaskQuery())->setViewer(PhabricatorUser::getOmnipotentUser())->withPriorities(array($adjacent->getPriority()))->withSubpriorityBetween($min, $max);
             if (!$is_after) {
                 $query->setOrderVector(array('-priority', '-subpriority', '-id'));
             } else {
                 $query->setOrderVector(array('priority', 'subpriority', 'id'));
             }
             $shift_all = $query->execute();
             $shift_last = last($shift_all);
             // Select the most extreme subpriority in the result set as the
             // base value.
             $shift_base = head($shift_all)->getSubpriority();
             // Find the subpriority before or after the task at the end of the
             // block.
             list($shift_pri, $shift_sub) = self::getAdjacentSubpriority($shift_last, $is_after, $allow_recursion = false);
             $delta = $shift_sub - $shift_base;
             $count = count($shift_all);
             $shift = array();
             $cursor = 1;
             foreach ($shift_all as $shift_task) {
                 $shift_target = $shift_base + $cursor / $count * $delta;
                 $cursor++;
                 queryfx($conn_w, 'UPDATE %T SET subpriority = %f WHERE id = %d', $adjacent->getTableName(), $shift_target, $shift_task->getID());
                 // If we're shifting the adjacent task, update it.
                 if ($shift_task->getID() == $adjacent->getID()) {
                     $adjacent->setSubpriority($shift_target);
                 }
                 // If we're shifting the original target task, update the base
                 // subpriority.
                 if ($shift_task->getID() == $dst->getID()) {
                     $base = $shift_target;
                 }
             }
         }
         $sub = ($adjacent->getSubpriority() + $base) / 2;
     } else {
         // Otherwise, we take a step away from the target's subpriority and
         // use that.
         if ($is_after) {
             $sub = $base - $step;
         } else {
             $sub = $base + $step;
         }
     }
     return array($dst->getPriority(), $sub);
 }
Example #2
0
 private function comparePriorityTo(ManiphestTask $other)
 {
     $upri = $this->getPriority();
     $vpri = $other->getPriority();
     if ($upri != $vpri) {
         return $upri - $vpri;
     }
     $usub = $this->getSubpriority();
     $vsub = $other->getSubpriority();
     if ($usub != $vsub) {
         return $usub - $vsub;
     }
     $uid = $this->getID();
     $vid = $other->getID();
     if ($uid != $vid) {
         return $uid - $vid;
     }
     return 0;
 }