public function handleRequest(AphrontRequest $request) { $user = $request->getUser(); $phid = $request->getURIData('phid'); $attach_type = $request->getURIData('type'); $action = $request->getURIData('action', self::ACTION_ATTACH); $handle = id(new PhabricatorHandleQuery())->setViewer($user)->withPHIDs(array($phid))->executeOne(); $object_type = $handle->getType(); $object = id(new PhabricatorObjectQuery())->setViewer($user)->withPHIDs(array($phid))->executeOne(); if (!$object) { return new Aphront404Response(); } $edge_type = null; switch ($action) { case self::ACTION_EDGE: case self::ACTION_DEPENDENCIES: case self::ACTION_BLOCKS: case self::ACTION_ATTACH: $edge_type = $this->getEdgeType($object_type, $attach_type); break; } if ($request->isFormPost()) { $phids = explode(';', $request->getStr('phids')); $phids = array_filter($phids); $phids = array_values($phids); if ($edge_type) { if (!$object instanceof PhabricatorApplicationTransactionInterface) { throw new Exception(pht('Expected object ("%s") to implement interface "%s".', get_class($object), 'PhabricatorApplicationTransactionInterface')); } $old_phids = PhabricatorEdgeQuery::loadDestinationPHIDs($phid, $edge_type); $add_phids = $phids; $rem_phids = array_diff($old_phids, $add_phids); $txn_editor = $object->getApplicationTransactionEditor()->setActor($user)->setContentSourceFromRequest($request)->setContinueOnMissingFields(true)->setContinueOnNoEffect(true); $txn_template = $object->getApplicationTransactionTemplate()->setTransactionType(PhabricatorTransactions::TYPE_EDGE)->setMetadataValue('edge:type', $edge_type)->setNewValue(array('+' => array_fuse($add_phids), '-' => array_fuse($rem_phids))); try { $txn_editor->applyTransactions($object->getApplicationTransactionObject(), array($txn_template)); } catch (PhabricatorEdgeCycleException $ex) { $this->raiseGraphCycleException($ex); } return id(new AphrontReloadResponse())->setURI($handle->getURI()); } else { return $this->performMerge($object, $handle, $phids); } } else { if ($edge_type) { $phids = PhabricatorEdgeQuery::loadDestinationPHIDs($phid, $edge_type); } else { // This is a merge. $phids = array(); } } $strings = $this->getStrings($attach_type, $action); $handles = $this->loadViewerHandles($phids); $obj_dialog = new PhabricatorObjectSelectorDialog(); $obj_dialog->setUser($user)->setHandles($handles)->setFilters($this->getFilters($strings, $attach_type))->setSelectedFilter($strings['selected'])->setExcluded($phid)->setCancelURI($handle->getURI())->setSearchURI('/search/select/' . $attach_type . '/' . $action . '/')->setTitle($strings['title'])->setHeader($strings['header'])->setButtonText($strings['button'])->setInstructions($strings['instructions']); $dialog = $obj_dialog->buildDialog(); return id(new AphrontDialogResponse())->setDialog($dialog); }
public function processRequest() { $request = $this->getRequest(); $user = $request->getUser(); $handle_data = new PhabricatorObjectHandleData(array($this->phid)); $handles = $handle_data->loadHandles(); $handle = $handles[$this->phid]; $object_type = $handle->getType(); $attach_type = $this->type; $objects = $handle_data->loadObjects(); $object = idx($objects, $this->phid); if (!$object) { return new Aphront404Response(); } if ($request->isFormPost()) { $phids = explode(';', $request->getStr('phids')); $phids = array_filter($phids); $phids = array_values($phids); switch ($this->action) { case self::ACTION_MERGE: return $this->performMerge($object, $handle, $phids); case self::ACTION_DEPENDENCIES: case self::ACTION_ATTACH: $two_way = true; if ($this->action == self::ACTION_DEPENDENCIES) { $two_way = false; $this->detectGraphCycles($object, $attach_type, $phids); } $editor = new PhabricatorObjectAttachmentEditor($object_type, $object); $editor->setUser($this->getRequest()->getUser()); $editor->attachObjects($attach_type, $phids, $two_way); return id(new AphrontReloadResponse())->setURI($handle->getURI()); default: throw new Exception("Unsupported attach action."); } } else { switch ($this->action) { case self::ACTION_ATTACH: case self::ACTION_DEPENDENCIES: $phids = $object->getAttachedPHIDs($attach_type); break; default: $phids = array(); break; } } $strings = $this->getStrings(); $handles = id(new PhabricatorObjectHandleData($phids))->loadHandles(); $obj_dialog = new PhabricatorObjectSelectorDialog(); $obj_dialog->setUser($user)->setHandles($handles)->setFilters(array('assigned' => 'Assigned to Me', 'created' => 'Created By Me', 'open' => 'All Open ' . $strings['target_plural_noun'], 'all' => 'All ' . $strings['target_plural_noun']))->setSelectedFilter($strings['selected'])->setCancelURI($handle->getURI())->setSearchURI('/search/select/' . $attach_type . '/')->setTitle($strings['title'])->setHeader($strings['header'])->setButtonText($strings['button'])->setInstructions($strings['instructions']); $dialog = $obj_dialog->buildDialog(); return id(new AphrontDialogResponse())->setDialog($dialog); }
public function processRequest() { $request = $this->getRequest(); $user = $request->getUser(); $handle_data = new PhabricatorObjectHandleData(array($this->phid)); $handles = $handle_data->loadHandles(); $handle = $handles[$this->phid]; $object_type = $handle->getType(); $attach_type = $this->type; $objects = $handle_data->loadObjects(); $object = idx($objects, $this->phid); if (!$object) { return new Aphront404Response(); } $edge_type = null; switch ($this->action) { case self::ACTION_EDGE: case self::ACTION_DEPENDENCIES: case self::ACTION_ATTACH: $edge_type = $this->getEdgeType($object_type, $attach_type); break; } if ($request->isFormPost()) { $phids = explode(';', $request->getStr('phids')); $phids = array_filter($phids); $phids = array_values($phids); if ($edge_type) { $old_phids = PhabricatorEdgeQuery::loadDestinationPHIDs($this->phid, $edge_type); $add_phids = $phids; $rem_phids = array_diff($old_phids, $add_phids); $editor = id(new PhabricatorEdgeEditor()); $editor->setUser($user); foreach ($add_phids as $phid) { $editor->addEdge($this->phid, $edge_type, $phid); } foreach ($rem_phids as $phid) { $editor->removeEdge($this->phid, $edge_type, $phid); } try { $editor->save(); } catch (PhabricatorEdgeCycleException $ex) { $this->raiseGraphCycleException($ex); } return id(new AphrontReloadResponse())->setURI($handle->getURI()); } else { return $this->performMerge($object, $handle, $phids); } } else { if ($edge_type) { $phids = PhabricatorEdgeQuery::loadDestinationPHIDs($this->phid, $edge_type); } else { // This is a merge. $phids = array(); } } $strings = $this->getStrings(); $handles = $this->loadViewerHandles($phids); $obj_dialog = new PhabricatorObjectSelectorDialog(); $obj_dialog->setUser($user)->setHandles($handles)->setFilters(array('assigned' => 'Assigned to Me', 'created' => 'Created By Me', 'open' => 'All Open ' . $strings['target_plural_noun'], 'all' => 'All ' . $strings['target_plural_noun']))->setSelectedFilter($strings['selected'])->setExcluded($this->phid)->setCancelURI($handle->getURI())->setSearchURI('/search/select/' . $attach_type . '/')->setTitle($strings['title'])->setHeader($strings['header'])->setButtonText($strings['button'])->setInstructions($strings['instructions']); $dialog = $obj_dialog->buildDialog(); return id(new AphrontDialogResponse())->setDialog($dialog); }
public function processRequest() { $request = $this->getRequest(); $user = $request->getUser(); $handle_data = new PhabricatorObjectHandleData(array($this->phid)); $handles = $handle_data->loadHandles(); $handle = $handles[$this->phid]; $object_phid = $this->phid; $object_type = $handle->getType(); $attach_type = $this->type; $objects = $handle_data->loadObjects(); $object = idx($objects, $this->phid); if (!$object) { return new Aphront404Response(); } if ($request->isFormPost()) { $phids = explode(';', $request->getStr('phids')); $phids = array_filter($phids); $phids = array_values($phids); switch ($this->action) { case self::ACTION_MERGE: return $this->performMerge($object, $handle, $phids); case self::ACTION_ATTACH: // Fall through to the workflow below. break; default: throw new Exception("Unsupported attach action."); } // sort() so that removing [X, Y] and then adding [Y, X] is correctly // detected as a no-op. sort($phids); $old_phids = $object->getAttachedPHIDs($attach_type); sort($old_phids); if (($phids || $old_phids) && $phids !== $old_phids) { $all_phids = array_merge($phids, $old_phids); $attach_objs = id(new PhabricatorObjectHandleData($all_phids))->loadObjects(); // Remove PHIDs which don't actually exist, to prevent silliness. $phids = array_keys(array_select_keys($attach_objs, $phids)); if ($phids) { $phids = array_combine($phids, $phids); } // Update the primary object. switch ($object_type) { case PhabricatorPHIDConstants::PHID_TYPE_DREV: $object->setAttachedPHIDs($attach_type, $phids); $object->save(); break; case PhabricatorPHIDConstants::PHID_TYPE_TASK: $this->applyTaskTransaction($object, $attach_type, $phids); break; } // Loop through all of the attached/detached objects and update them. foreach ($attach_objs as $phid => $attach_obj) { $attached_phids = $attach_obj->getAttachedPHIDs($object_type); // Figure out if we're attaching or detaching this object. if (isset($phids[$phid])) { $attached_phids[] = $object_phid; } else { $attached_phids = array_fill_keys($attached_phids, true); unset($attached_phids[$object_phid]); $attached_phids = array_keys($attached_phids); } switch ($attach_type) { case PhabricatorPHIDConstants::PHID_TYPE_DREV: $attach_obj->setAttachedPHIDs($object_type, $attached_phids); $attach_obj->save(); break; case PhabricatorPHIDConstants::PHID_TYPE_TASK: $this->applyTaskTransaction($attach_obj, $object_type, $attached_phids); break; } } } return id(new AphrontReloadResponse())->setURI($handle->getURI()); } else { switch ($this->action) { case self::ACTION_ATTACH: $phids = $object->getAttachedPHIDs($attach_type); break; default: $phids = array(); break; } } switch ($this->type) { case PhabricatorPHIDConstants::PHID_TYPE_DREV: $noun = 'Revisions'; $selected = 'created'; break; case PhabricatorPHIDConstants::PHID_TYPE_TASK: $noun = 'Tasks'; $selected = 'assigned'; break; } switch ($this->action) { case self::ACTION_ATTACH: $dialog_title = "Manage Attached {$noun}"; $header_text = "Currently Attached {$noun}"; $button_text = "Save {$noun}"; $instructions = null; break; case self::ACTION_MERGE: $dialog_title = "Merge Duplicate Tasks"; $header_text = "Tasks To Merge"; $button_text = "Merge {$noun}"; $instructions = "These tasks will be merged into the current task and then closed. " . "The current task (\"" . phutil_escape_html($handle->getName()) . "\") " . "will grow stronger."; break; } $handles = id(new PhabricatorObjectHandleData($phids))->loadHandles(); $obj_dialog = new PhabricatorObjectSelectorDialog(); $obj_dialog->setUser($user)->setHandles($handles)->setFilters(array('assigned' => 'Assigned to Me', 'created' => 'Created By Me', 'open' => 'All Open ' . $noun, 'all' => 'All ' . $noun))->setSelectedFilter($selected)->setCancelURI($handle->getURI())->setSearchURI('/search/select/' . $attach_type . '/')->setTitle($dialog_title)->setHeader($header_text)->setButtonText($button_text)->setInstructions($instructions); $dialog = $obj_dialog->buildDialog(); return id(new AphrontDialogResponse())->setDialog($dialog); }