mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-15 19:32:40 +01:00
25cc90d632
Summary: Ref T4788. Fixes T9232. This moves the "search for stuff to attach to this object" flow away from hard-coding and legacy constants and toward something more modular and flexible. It also adds an "Edit Commits..." action to Maniphest, resolving T9232. The behavior of the search for commits isn't great right now, but it will improve once these use real ApplicationSearch. Test Plan: Edited a tasks' related commits, mocks, tasks, etc. Reviewers: chad Reviewed By: chad Maniphest Tasks: T4788, T9232 Differential Revision: https://secure.phabricator.com/D16189
177 lines
5.4 KiB
PHP
177 lines
5.4 KiB
PHP
<?php
|
|
|
|
final class PhabricatorSearchRelationshipController
|
|
extends PhabricatorSearchBaseController {
|
|
|
|
public function handleRequest(AphrontRequest $request) {
|
|
$viewer = $this->getViewer();
|
|
|
|
$object = $this->loadRelationshipObject();
|
|
if (!$object) {
|
|
return new Aphront404Response();
|
|
}
|
|
|
|
$relationship = $this->loadRelationship($object);
|
|
if (!$relationship) {
|
|
return new Aphront404Response();
|
|
}
|
|
|
|
$src_phid = $object->getPHID();
|
|
$edge_type = $relationship->getEdgeConstant();
|
|
|
|
$dst_phids = PhabricatorEdgeQuery::loadDestinationPHIDs(
|
|
$src_phid,
|
|
$edge_type);
|
|
|
|
$all_phids = $dst_phids;
|
|
$all_phids[] = $src_phid;
|
|
|
|
$handles = $viewer->loadHandles($all_phids);
|
|
$src_handle = $handles[$src_phid];
|
|
|
|
$done_uri = $src_handle->getURI();
|
|
$initial_phids = $dst_phids;
|
|
|
|
if ($request->isFormPost()) {
|
|
$phids = explode(';', $request->getStr('phids'));
|
|
$phids = array_filter($phids);
|
|
$phids = array_values($phids);
|
|
|
|
$initial_phids = $request->getStrList('initialPHIDs');
|
|
|
|
// Apply the changes as adds and removes relative to the original state
|
|
// of the object when the dialog was rendered so that two users adding
|
|
// relationships at the same time don't race and overwrite one another.
|
|
$add_phids = array_diff($phids, $initial_phids);
|
|
$rem_phids = array_diff($initial_phids, $phids);
|
|
|
|
if ($add_phids) {
|
|
$dst_objects = id(new PhabricatorObjectQuery())
|
|
->setViewer($viewer)
|
|
->withPHIDs($phids)
|
|
->setRaisePolicyExceptions(true)
|
|
->execute();
|
|
$dst_objects = mpull($dst_objects, null, 'getPHID');
|
|
} else {
|
|
$dst_objects = array();
|
|
}
|
|
|
|
try {
|
|
foreach ($add_phids as $add_phid) {
|
|
$dst_object = idx($dst_objects, $add_phid);
|
|
if (!$dst_object) {
|
|
throw new Exception(
|
|
pht(
|
|
'You can not create a relationship to object "%s" because '.
|
|
'the object does not exist or could not be loaded.',
|
|
$add_phid));
|
|
}
|
|
|
|
if (!$relationship->canRelateObjects($object, $dst_object)) {
|
|
throw new Exception(
|
|
pht(
|
|
'You can not create a relationship (of type "%s") to object '.
|
|
'"%s" because it is not the right type of object for this '.
|
|
'relationship.',
|
|
$relationship->getRelationshipConstant(),
|
|
$add_phid));
|
|
}
|
|
}
|
|
} catch (Exception $ex) {
|
|
return $this->newUnrelatableObjectResponse($ex, $done_uri);
|
|
}
|
|
|
|
$editor = $object->getApplicationTransactionEditor()
|
|
->setActor($viewer)
|
|
->setContentSourceFromRequest($request)
|
|
->setContinueOnMissingFields(true)
|
|
->setContinueOnNoEffect(true);
|
|
|
|
$xactions = array();
|
|
$xactions[] = $object->getApplicationTransactionTemplate()
|
|
->setTransactionType(PhabricatorTransactions::TYPE_EDGE)
|
|
->setMetadataValue('edge:type', $edge_type)
|
|
->setNewValue(array(
|
|
'+' => array_fuse($add_phids),
|
|
'-' => array_fuse($rem_phids),
|
|
));
|
|
|
|
try {
|
|
$editor->applyTransactions($object, $xactions);
|
|
|
|
return id(new AphrontRedirectResponse())->setURI($done_uri);
|
|
} catch (PhabricatorEdgeCycleException $ex) {
|
|
return $this->newGraphCycleResponse($ex, $done_uri);
|
|
}
|
|
}
|
|
|
|
$handles = iterator_to_array($handles);
|
|
$handles = array_select_keys($handles, $dst_phids);
|
|
|
|
// TODO: These are hard-coded for now.
|
|
$filters = array(
|
|
'assigned' => pht('Assigned to Me'),
|
|
'created' => pht('Created By Me'),
|
|
'open' => pht('All Open Objects'),
|
|
'all' => pht('All Objects'),
|
|
);
|
|
|
|
$dialog_title = $relationship->getDialogTitleText();
|
|
$dialog_header = $relationship->getDialogHeaderText();
|
|
$dialog_button = $relationship->getDialogButtonText();
|
|
$dialog_instructions = $relationship->getDialogInstructionsText();
|
|
|
|
$source_uri = $relationship->getSourceURI($object);
|
|
|
|
return id(new PhabricatorObjectSelectorDialog())
|
|
->setUser($viewer)
|
|
->setInitialPHIDs($initial_phids)
|
|
->setHandles($handles)
|
|
->setFilters($filters)
|
|
->setSelectedFilter('created')
|
|
->setExcluded($src_phid)
|
|
->setCancelURI($done_uri)
|
|
->setSearchURI($source_uri)
|
|
->setTitle($dialog_title)
|
|
->setHeader($dialog_header)
|
|
->setButtonText($dialog_button)
|
|
->setInstructions($dialog_instructions)
|
|
->buildDialog();
|
|
}
|
|
|
|
private function newGraphCycleResponse(
|
|
PhabricatorEdgeCycleException $ex,
|
|
$done_uri) {
|
|
|
|
$viewer = $this->getViewer();
|
|
$cycle = $ex->getCycle();
|
|
|
|
$handles = $this->loadViewerHandles($cycle);
|
|
$names = array();
|
|
foreach ($cycle as $cycle_phid) {
|
|
$names[] = $handles[$cycle_phid]->getFullName();
|
|
}
|
|
|
|
$message = pht(
|
|
'You can not create that relationship because it would create a '.
|
|
'circular dependency:');
|
|
|
|
$list = implode(" \xE2\x86\x92 ", $names);
|
|
|
|
return $this->newDialog()
|
|
->setTitle(pht('Circular Dependency'))
|
|
->appendParagraph($message)
|
|
->appendParagraph($list)
|
|
->addCancelButton($done_uri);
|
|
}
|
|
|
|
private function newUnrelatableObjectResponse(Exception $ex, $done_uri) {
|
|
$message = $ex->getMessage();
|
|
|
|
return $this->newDialog()
|
|
->setTitle(pht('Invalid Relationship'))
|
|
->appendParagraph($message)
|
|
->addCancelButton($done_uri);
|
|
}
|
|
|
|
}
|