/**
  * Partial re-order of backlog items plus update of children
  *
  * Define the priorities of some children of a given Backlog Item
  *
  * <br>
  * Example:
  * <pre>
  * "order": {
  *   "ids" : [123, 789, 1001],
  *   "direction": "before",
  *   "compared_to": 456
  * }
  * </pre>
  *
  * <br>
  * Resulting order will be: <pre>[…, 123, 789, 1001, 456, …]</pre>
  *
  * <br>
  * Add example:
  * <pre>
  * "add": [
  *   {
  *     "id": 34
  *     "remove_from": 56
  *   },
  *   ...
  * ]
  * </pre>
  *
  * <br>
  * Will remove element id 34 from 56 children and add it to current backlog_items children
  *
  * @url PATCH {id}/children
  *
  * @param int                                                   $id    Id of the Backlog Item
  * @param \Tuleap\AgileDashboard\REST\v1\OrderRepresentation    $order Order of the children {@from body}
  * @param array                                                 $add   Ids to add to backlog_items content  {@from body}
  *
  * @throws 400
  * @throws 404
  * @throws 409
  */
 protected function patch($id, OrderRepresentation $order = null, array $add = null)
 {
     $artifact = $this->getArtifact($id);
     $user = $this->getCurrentUser();
     try {
         $indexed_children_ids = $this->getChildrenArtifactIds($user, $artifact);
         if ($add) {
             $this->resources_patcher->startTransaction();
             $to_add = $this->resources_patcher->removeArtifactFromSource($user, $add);
             if (count($to_add)) {
                 $validator = new PatchAddRemoveValidator($indexed_children_ids, new PatchAddBacklogItemsValidator($this->artifact_factory, $this->tracker_factory->getPossibleChildren($artifact->getTracker()), $id));
                 $backlog_items_ids = $validator->validate($id, array(), $to_add);
                 $this->artifactlink_updater->updateArtifactLinks($user, $artifact, $backlog_items_ids, array());
                 $indexed_children_ids = array_flip($backlog_items_ids);
             }
             $this->resources_patcher->commit();
         }
         if ($order) {
             $order->checkFormat($order);
             $order_validator = new OrderValidator($indexed_children_ids);
             $order_validator->validate($order);
             $this->resources_patcher->updateArtifactPriorities($order, $id, null);
         }
     } catch (IdsFromBodyAreNotUniqueException $exception) {
         throw new RestException(409, $exception->getMessage());
     } catch (OrderIdOutOfBoundException $exception) {
         throw new RestException(409, $exception->getMessage());
     } catch (ArtifactCannotBeChildrenOfException $exception) {
         throw new RestException(409, $exception->getMessage());
     } catch (Tracker_Artifact_Exception_CannotRankWithMyself $exception) {
         throw new RestException(400, $exception->getMessage());
     } catch (\Exception $exception) {
         throw new RestException(400, $exception->getMessage());
     }
 }
Example #2
0
 /**
  * Partial re-order of Kanban items
  *
  * Partial re-order of Kanban items
  *
  * <pre>
  * /!\ Kanban REST routes are under construction and subject to changes /!\
  * </pre>
  *
  * @url PATCH {id}/items
  *
  * @param int                                                    $id    Id of the Kanban
  * @param int                                                    $column_id Id of the column the item belongs to {@from query}
  * @param \Tuleap\AgileDashboard\REST\v1\OrderRepresentation     $order Order of the items {@from body}
  * @param \Tuleap\AgileDashboard\REST\v1\Kanban\KanbanAddRepresentation $add   Ids to add to the column {@from body}
  */
 protected function patchItems($id, $column_id, OrderRepresentation $order = null, KanbanAddRepresentation $add = null)
 {
     $current_user = UserManager::instance()->getCurrentUser();
     $kanban = $this->kanban_factory->getKanban($current_user, $id);
     if (!$this->columnIsInTracker($kanban, $current_user, $column_id)) {
         throw new RestException(404);
     }
     if ($add) {
         $add->checkFormat();
         $this->validateIdsInAddAreInKanbanTracker($kanban, $add);
         $this->resources_patcher->startTransaction();
         try {
             $this->moveArtifactsInColumn($kanban, $current_user, $add, $column_id);
             $this->resources_patcher->commit();
         } catch (Tracker_NoChangeException $exception) {
             $this->resources_patcher->rollback();
         } catch (Tracker_Workflow_GlobalRulesViolationException $exception) {
             $this->resources_patcher->rollback();
             throw new RestException(400, $exception->getMessage());
         } catch (Exception $exception) {
             $this->resources_patcher->rollback();
             throw new RestException(500, $exception->getMessage());
         }
     }
     if ($order) {
         $order->checkFormat();
         $kanban_column_items = $this->getItemsInColumn($kanban->getTrackerId(), $column_id);
         $order_validator = new OrderValidator($kanban_column_items);
         try {
             $order_validator->validate($order);
         } catch (IdsFromBodyAreNotUniqueException $exception) {
             throw new RestException(409, $exception->getMessage());
         } catch (OrderIdOutOfBoundException $exception) {
             throw new RestException(409, $exception->getMessage());
         } catch (Exception $exception) {
             throw new RestException(500, $exception->getMessage());
         }
         $this->resources_patcher->updateArtifactPriorities($order, Tracker_Artifact_PriorityHistoryChange::NO_CONTEXT, $this->getProjectIdForKanban($kanban));
     }
     if ($add || $order) {
         $this->statistics_aggregator->addCardDragAndDropHit($this->getProjectIdForKanban($kanban));
         $this->sendMessageForDroppingItem($current_user, $kanban, $order, $add, $column_id);
     }
 }
 public function patch(PFUser $user, Project $project, OrderRepresentationBase $order = null, array $add = null)
 {
     $this->checkIfUserCanChangePrioritiesInMilestone($user, $project);
     if ($add) {
         try {
             $this->resources_patcher->removeArtifactFromSource($user, $add);
         } catch (\Exception $exception) {
             throw new RestException(400, $exception->getMessage());
         }
     }
     if ($order) {
         $order->checkFormat($order);
         $all_ids = array_merge(array($order->compared_to), $order->ids);
         $this->validateArtifactIdsAreInUnassignedTopBacklog($all_ids, $user, $project);
         try {
             $this->resources_patcher->updateArtifactPriorities($order, self::TOP_BACKLOG_IDENTIFIER, $project->getId());
         } catch (Tracker_Artifact_Exception_CannotRankWithMyself $exception) {
             throw new RestException(400, $exception->getMessage());
         }
     }
 }
 /**
  * Partial re-order of milestone backlog relative to one element.
  *
  * <br>
  * Example:
  * <pre>
  * "order": {
  *   "ids" : [123, 789, 1001],
  *   "direction": "before",
  *   "compared_to": 456
  * },
  * "add": {
  *   [123]
  * }
  * </pre>
  *
  * <br>
  * Resulting order will be: <pre>[…, 123, 789, 1001, 456, …]</pre>
  *
  * <br>
  * Add example:
  * <pre>
  * "add": [
  *   {
  *     "id": 34
  *     "remove_from": 56
  *   },
  *   ...
  * ]
  * </pre>
  *
  * <br>
  * Will remove element id 34 from milestone 56 backlog and add it to current backlog
  *
  * @url PATCH {id}/backlog
  *
  * @param int                                                $id    Id of the milestone Item
  * @param \Tuleap\AgileDashboard\REST\v1\OrderRepresentation $order Order of the children {@from body}
  * @param array                                              $add    Ids to add/move to milestone backlog {@from body}
  *
  * @throw 400
  * @throw 403
  * @throw 404
  * @throw 409
  */
 protected function patchBacklog($id, OrderRepresentation $order = null, array $add = null)
 {
     $user = $this->getCurrentUser();
     $milestone = $this->getMilestoneById($user, $id);
     $this->checkIfUserCanChangePrioritiesInMilestone($milestone, $user);
     $to_add = array();
     try {
         if ($add) {
             $this->resources_patcher->startTransaction();
             $to_add = $this->resources_patcher->removeArtifactFromSource($user, $add);
             if (count($to_add)) {
                 $valid_to_add = $this->milestone_validator->validateArtifactIdsCanBeAddedToBacklog($to_add, $milestone, $user);
                 $this->addMissingElementsToBacklog($milestone, $user, $valid_to_add);
             }
             $this->resources_patcher->commit();
         }
     } catch (Tracker_NoChangeException $exception) {
         // nothing to do
     } catch (\Exception $exception) {
         throw new RestException(400, $exception->getMessage());
     }
     try {
         if ($order) {
             $order->checkFormat($order);
             $this->milestone_validator->validateArtifactIdsAreInUnplannedMilestone($this->filterOutAddedElements($order, $to_add), $milestone, $user);
             $this->resources_patcher->updateArtifactPriorities($order, $id, $milestone->getProject()->getId());
         }
     } catch (IdsFromBodyAreNotUniqueException $exception) {
         throw new RestException(409, $exception->getMessage());
     } catch (ArtifactIsNotInUnplannedBacklogItemsException $exception) {
         throw new RestException(409, $exception->getMessage());
     } catch (Tracker_Artifact_Exception_CannotRankWithMyself $exception) {
         throw new RestException(400, $exception->getMessage());
     } catch (\Exception $exception) {
         throw new RestException(400, $exception->getMessage());
     }
 }