Page MenuHomestyx hydra

No OneTemporary

diff --git a/src/applications/maniphest/controller/ManiphestTaskDetailController.php b/src/applications/maniphest/controller/ManiphestTaskDetailController.php
index 2195089d24..c29c7ee9a1 100644
--- a/src/applications/maniphest/controller/ManiphestTaskDetailController.php
+++ b/src/applications/maniphest/controller/ManiphestTaskDetailController.php
@@ -1,368 +1,366 @@
<?php
final class ManiphestTaskDetailController extends ManiphestController {
public function shouldAllowPublic() {
return true;
}
public function handleRequest(AphrontRequest $request) {
$viewer = $this->getViewer();
$id = $request->getURIData('id');
$task = id(new ManiphestTaskQuery())
->setViewer($viewer)
->withIDs(array($id))
->needSubscriberPHIDs(true)
->executeOne();
if (!$task) {
return new Aphront404Response();
}
$field_list = PhabricatorCustomField::getObjectFields(
$task,
PhabricatorCustomField::ROLE_VIEW);
$field_list
->setViewer($viewer)
->readFieldsFromStorage($task);
$edit_engine = id(new ManiphestEditEngine())
->setViewer($viewer)
->setTargetObject($task);
$e_commit = ManiphestTaskHasCommitEdgeType::EDGECONST;
$e_dep_on = ManiphestTaskDependsOnTaskEdgeType::EDGECONST;
$e_dep_by = ManiphestTaskDependedOnByTaskEdgeType::EDGECONST;
$e_rev = ManiphestTaskHasRevisionEdgeType::EDGECONST;
$e_mock = ManiphestTaskHasMockEdgeType::EDGECONST;
$phid = $task->getPHID();
$query = id(new PhabricatorEdgeQuery())
->withSourcePHIDs(array($phid))
->withEdgeTypes(
array(
$e_commit,
$e_dep_on,
$e_dep_by,
$e_rev,
$e_mock,
));
$edges = idx($query->execute(), $phid);
$phids = array_fill_keys($query->getDestinationPHIDs(), true);
if ($task->getOwnerPHID()) {
$phids[$task->getOwnerPHID()] = true;
}
$phids[$task->getAuthorPHID()] = true;
$phids = array_keys($phids);
$handles = $viewer->loadHandles($phids);
$timeline = $this->buildTransactionTimeline(
$task,
new ManiphestTransactionQuery());
$monogram = $task->getMonogram();
$crumbs = $this->buildApplicationCrumbs()
->addTextCrumb($monogram)
->setBorder(true);
$header = $this->buildHeaderView($task);
$details = $this->buildPropertyView($task, $field_list, $edges, $handles);
$description = $this->buildDescriptionView($task);
$curtain = $this->buildCurtain($task, $edit_engine);
$title = pht('%s %s', $monogram, $task->getTitle());
$comment_view = $edit_engine
->buildEditEngineCommentView($task);
$timeline->setQuoteRef($monogram);
$comment_view->setTransactionTimeline($timeline);
$view = id(new PHUITwoColumnView())
->setHeader($header)
->setCurtain($curtain)
->setMainColumn(array(
$timeline,
$comment_view,
))
->addPropertySection(pht('Description'), $description)
->addPropertySection(pht('Details'), $details);
return $this->newPage()
->setTitle($title)
->setCrumbs($crumbs)
->setPageObjectPHIDs(
array(
$task->getPHID(),
))
->appendChild(
array(
$view,
));
}
private function buildHeaderView(ManiphestTask $task) {
$view = id(new PHUIHeaderView())
->setHeader($task->getTitle())
->setUser($this->getRequest()->getUser())
->setPolicyObject($task);
$priority_name = ManiphestTaskPriority::getTaskPriorityName(
$task->getPriority());
$priority_color = ManiphestTaskPriority::getTaskPriorityColor(
$task->getPriority());
$status = $task->getStatus();
$status_name = ManiphestTaskStatus::renderFullDescription(
$status, $priority_name, $priority_color);
$view->addProperty(PHUIHeaderView::PROPERTY_STATUS, $status_name);
$view->setHeaderIcon(ManiphestTaskStatus::getStatusIcon(
$task->getStatus()).' '.$priority_color);
if (ManiphestTaskPoints::getIsEnabled()) {
$points = $task->getPoints();
if ($points !== null) {
$points_name = pht('%s %s',
$task->getPoints(),
ManiphestTaskPoints::getPointsLabel());
$tag = id(new PHUITagView())
->setName($points_name)
->setShade('blue')
->setType(PHUITagView::TYPE_SHADE);
$view->addTag($tag);
}
}
return $view;
}
private function buildCurtain(
ManiphestTask $task,
PhabricatorEditEngine $edit_engine) {
$viewer = $this->getViewer();
$id = $task->getID();
$phid = $task->getPHID();
$can_edit = PhabricatorPolicyFilter::hasCapability(
$viewer,
$task,
PhabricatorPolicyCapability::CAN_EDIT);
$curtain = $this->newCurtainView($task);
$curtain->addAction(
id(new PhabricatorActionView())
->setName(pht('Edit Task'))
->setIcon('fa-pencil')
->setHref($this->getApplicationURI("/task/edit/{$id}/"))
->setDisabled(!$can_edit)
->setWorkflow(!$can_edit));
$edit_config = $edit_engine->loadDefaultEditConfiguration();
$can_create = (bool)$edit_config;
$can_reassign = $edit_engine->hasEditAccessToTransaction(
ManiphestTransaction::TYPE_OWNER);
if ($can_create) {
$form_key = $edit_config->getIdentifier();
$edit_uri = id(new PhutilURI("/task/edit/form/{$form_key}/"))
->setQueryParam('parent', $id)
->setQueryParam('template', $id)
->setQueryParam('status', ManiphestTaskStatus::getDefaultStatus());
$edit_uri = $this->getApplicationURI($edit_uri);
} else {
// TODO: This will usually give us a somewhat-reasonable error page, but
// could be a bit cleaner.
$edit_uri = "/task/edit/{$id}/";
$edit_uri = $this->getApplicationURI($edit_uri);
}
$task_submenu = array();
$task_submenu[] = id(new PhabricatorActionView())
->setName(pht('Create Subtask'))
->setHref($edit_uri)
->setIcon('fa-level-down')
->setDisabled(!$can_create)
->setWorkflow(!$can_create);
$task_submenu[] = id(new PhabricatorActionView())
->setName(pht('Edit Blocking Tasks'))
->setHref("/search/attach/{$phid}/TASK/blocks/")
- ->setWorkflow(true)
->setIcon('fa-link')
->setDisabled(!$can_edit)
->setWorkflow(true);
$task_submenu[] = id(new PhabricatorActionView())
->setName(pht('Merge Duplicates In'))
->setHref("/search/attach/{$phid}/TASK/merge/")
- ->setWorkflow(true)
->setIcon('fa-compress')
->setDisabled(!$can_edit)
->setWorkflow(true);
$curtain->addAction(
id(new PhabricatorActionView())
->setName(pht('Edit Related Tasks...'))
->setIcon('fa-anchor')
->setSubmenu($task_submenu));
$owner_phid = $task->getOwnerPHID();
$author_phid = $task->getAuthorPHID();
$handles = $viewer->loadHandles(array($owner_phid, $author_phid));
if ($owner_phid) {
$image_uri = $handles[$owner_phid]->getImageURI();
$image_href = $handles[$owner_phid]->getURI();
$owner = $viewer->renderHandle($owner_phid)->render();
$content = phutil_tag('strong', array(), $owner);
$assigned_to = id(new PHUIHeadThingView())
->setImage($image_uri)
->setImageHref($image_href)
->setContent($content);
} else {
$assigned_to = phutil_tag('em', array(), pht('None'));
}
$curtain->newPanel()
->setHeaderText(pht('Assigned To'))
->appendChild($assigned_to);
$author_uri = $handles[$author_phid]->getImageURI();
$author_href = $handles[$author_phid]->getURI();
$author = $viewer->renderHandle($author_phid)->render();
$content = phutil_tag('strong', array(), $author);
$date = phabricator_date($task->getDateCreated(), $viewer);
$content = pht('%s, %s', $content, $date);
$authored_by = id(new PHUIHeadThingView())
->setImage($author_uri)
->setImageHref($author_href)
->setContent($content);
$curtain->newPanel()
->setHeaderText(pht('Authored By'))
->appendChild($authored_by);
return $curtain;
}
private function buildPropertyView(
ManiphestTask $task,
PhabricatorCustomFieldList $field_list,
array $edges,
$handles) {
$viewer = $this->getRequest()->getUser();
$view = id(new PHUIPropertyListView())
->setUser($viewer);
$source = $task->getOriginalEmailSource();
if ($source) {
$subject = '[T'.$task->getID().'] '.$task->getTitle();
$view->addProperty(
pht('From Email'),
phutil_tag(
'a',
array(
'href' => 'mailto:'.$source.'?subject='.$subject,
),
$source));
}
$edge_types = array(
ManiphestTaskDependedOnByTaskEdgeType::EDGECONST
=> pht('Blocks'),
ManiphestTaskDependsOnTaskEdgeType::EDGECONST
=> pht('Blocked By'),
ManiphestTaskHasRevisionEdgeType::EDGECONST
=> pht('Differential Revisions'),
ManiphestTaskHasMockEdgeType::EDGECONST
=> pht('Pholio Mocks'),
);
$revisions_commits = array();
$commit_phids = array_keys(
$edges[ManiphestTaskHasCommitEdgeType::EDGECONST]);
if ($commit_phids) {
$commit_drev = DiffusionCommitHasRevisionEdgeType::EDGECONST;
$drev_edges = id(new PhabricatorEdgeQuery())
->withSourcePHIDs($commit_phids)
->withEdgeTypes(array($commit_drev))
->execute();
foreach ($commit_phids as $phid) {
$revisions_commits[$phid] = $handles->renderHandle($phid)
->setShowHovercard(true);
$revision_phid = key($drev_edges[$phid][$commit_drev]);
$revision_handle = $handles->getHandleIfExists($revision_phid);
if ($revision_handle) {
$task_drev = ManiphestTaskHasRevisionEdgeType::EDGECONST;
unset($edges[$task_drev][$revision_phid]);
$revisions_commits[$phid] = hsprintf(
'%s / %s',
$revision_handle->renderHovercardLink($revision_handle->getName()),
$revisions_commits[$phid]);
}
}
}
foreach ($edge_types as $edge_type => $edge_name) {
if ($edges[$edge_type]) {
$edge_handles = $viewer->loadHandles(array_keys($edges[$edge_type]));
$view->addProperty(
$edge_name,
$edge_handles->renderList());
}
}
if ($revisions_commits) {
$view->addProperty(
pht('Commits'),
phutil_implode_html(phutil_tag('br'), $revisions_commits));
}
$field_list->appendFieldsToPropertyList(
$task,
$viewer,
$view);
if ($view->hasAnyProperties()) {
return $view;
}
return null;
}
private function buildDescriptionView(ManiphestTask $task) {
$viewer = $this->getViewer();
$section = null;
$description = $task->getDescription();
if (strlen($description)) {
$section = new PHUIPropertyListView();
$section->addTextContent(
phutil_tag(
'div',
array(
'class' => 'phabricator-remarkup',
),
id(new PHUIRemarkupView($viewer, $description))
->setContextObject($task)));
}
return $section;
}
}
diff --git a/src/applications/pholio/event/PholioActionMenuEventListener.php b/src/applications/pholio/event/PholioActionMenuEventListener.php
index cfa6e39c32..0b563537fa 100644
--- a/src/applications/pholio/event/PholioActionMenuEventListener.php
+++ b/src/applications/pholio/event/PholioActionMenuEventListener.php
@@ -1,51 +1,50 @@
<?php
final class PholioActionMenuEventListener
extends PhabricatorEventListener {
public function register() {
$this->listen(PhabricatorEventType::TYPE_UI_DIDRENDERACTIONS);
}
public function handleEvent(PhutilEvent $event) {
switch ($event->getType()) {
case PhabricatorEventType::TYPE_UI_DIDRENDERACTIONS:
$this->handleActionsEvent($event);
break;
}
}
private function handleActionsEvent(PhutilEvent $event) {
$object = $event->getValue('object');
$actions = null;
if ($object instanceof ManiphestTask) {
$actions = $this->renderTaskItems($event);
}
$this->addActionMenuItems($event, $actions);
}
private function renderTaskItems(PhutilEvent $event) {
if (!$this->canUseApplication($event->getUser())) {
return;
}
$task = $event->getValue('object');
$phid = $task->getPHID();
$can_edit = PhabricatorPolicyFilter::hasCapability(
$event->getUser(),
$task,
PhabricatorPolicyCapability::CAN_EDIT);
return id(new PhabricatorActionView())
->setName(pht('Edit Pholio Mocks'))
->setHref("/search/attach/{$phid}/MOCK/edge/")
- ->setWorkflow(true)
->setIcon('fa-camera-retro')
->setDisabled(!$can_edit)
->setWorkflow(true);
}
}
diff --git a/src/applications/search/controller/PhabricatorSearchAttachController.php b/src/applications/search/controller/PhabricatorSearchAttachController.php
index 2d00ac8bda..a3238cb50d 100644
--- a/src/applications/search/controller/PhabricatorSearchAttachController.php
+++ b/src/applications/search/controller/PhabricatorSearchAttachController.php
@@ -1,325 +1,330 @@
<?php
final class PhabricatorSearchAttachController
extends PhabricatorSearchBaseController {
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)
+ ->requireCapabilities(
+ array(
+ PhabricatorPolicyCapability::CAN_VIEW,
+ PhabricatorPolicyCapability::CAN_EDIT,
+ ))
->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);
}
private function performMerge(
ManiphestTask $task,
PhabricatorObjectHandle $handle,
array $phids) {
$user = $this->getRequest()->getUser();
$response = id(new AphrontReloadResponse())->setURI($handle->getURI());
$phids = array_fill_keys($phids, true);
unset($phids[$task->getPHID()]); // Prevent merging a task into itself.
if (!$phids) {
return $response;
}
$targets = id(new ManiphestTaskQuery())
->setViewer($user)
->requireCapabilities(
array(
PhabricatorPolicyCapability::CAN_VIEW,
PhabricatorPolicyCapability::CAN_EDIT,
))
->withPHIDs(array_keys($phids))
->needSubscriberPHIDs(true)
->needProjectPHIDs(true)
->execute();
if (empty($targets)) {
return $response;
}
$editor = id(new ManiphestTransactionEditor())
->setActor($user)
->setContentSourceFromRequest($this->getRequest())
->setContinueOnNoEffect(true)
->setContinueOnMissingFields(true);
$cc_vector = array();
// since we loaded this via a generic object query, go ahead and get the
// attach the subscriber and project phids now
$task->attachSubscriberPHIDs(
PhabricatorSubscribersQuery::loadSubscribersForPHID($task->getPHID()));
$task->attachProjectPHIDs(
PhabricatorEdgeQuery::loadDestinationPHIDs($task->getPHID(),
PhabricatorProjectObjectHasProjectEdgeType::EDGECONST));
$cc_vector[] = $task->getSubscriberPHIDs();
foreach ($targets as $target) {
$cc_vector[] = $target->getSubscriberPHIDs();
$cc_vector[] = array(
$target->getAuthorPHID(),
$target->getOwnerPHID(),
);
$merged_into_txn = id(new ManiphestTransaction())
->setTransactionType(ManiphestTransaction::TYPE_MERGED_INTO)
->setNewValue($task->getPHID());
$editor->applyTransactions(
$target,
array($merged_into_txn));
}
$all_ccs = array_mergev($cc_vector);
$all_ccs = array_filter($all_ccs);
$all_ccs = array_unique($all_ccs);
$add_ccs = id(new ManiphestTransaction())
->setTransactionType(PhabricatorTransactions::TYPE_SUBSCRIBERS)
->setNewValue(array('=' => $all_ccs));
$merged_from_txn = id(new ManiphestTransaction())
->setTransactionType(ManiphestTransaction::TYPE_MERGED_FROM)
->setNewValue(mpull($targets, 'getPHID'));
$editor->applyTransactions(
$task,
array($add_ccs, $merged_from_txn));
return $response;
}
private function getStrings($attach_type, $action) {
switch ($attach_type) {
case DifferentialRevisionPHIDType::TYPECONST:
$noun = pht('Revisions');
$selected = pht('created');
break;
case ManiphestTaskPHIDType::TYPECONST:
$noun = pht('Tasks');
$selected = pht('assigned');
break;
case PhabricatorRepositoryCommitPHIDType::TYPECONST:
$noun = pht('Commits');
$selected = pht('created');
break;
case PholioMockPHIDType::TYPECONST:
$noun = pht('Mocks');
$selected = pht('created');
break;
}
switch ($action) {
case self::ACTION_EDGE:
case self::ACTION_ATTACH:
$dialog_title = pht('Manage Attached %s', $noun);
$header_text = pht('Currently Attached %s', $noun);
$button_text = pht('Save %s', $noun);
$instructions = null;
break;
case self::ACTION_MERGE:
$dialog_title = pht('Merge Duplicate Tasks');
$header_text = pht('Tasks To Merge');
$button_text = pht('Merge %s', $noun);
$instructions = pht(
'These tasks will be merged into the current task and then closed. '.
'The current task will grow stronger.');
break;
case self::ACTION_DEPENDENCIES:
$dialog_title = pht('Edit Dependencies');
$header_text = pht('Current Dependencies');
$button_text = pht('Save Dependencies');
$instructions = null;
break;
case self::ACTION_BLOCKS:
$dialog_title = pht('Edit Blocking Tasks');
$header_text = pht('Current Blocking Tasks');
$button_text = pht('Save Blocking Tasks');
$instructions = null;
break;
}
return array(
'target_plural_noun' => $noun,
'selected' => $selected,
'title' => $dialog_title,
'header' => $header_text,
'button' => $button_text,
'instructions' => $instructions,
);
}
private function getFilters(array $strings, $attach_type) {
if ($attach_type == PholioMockPHIDType::TYPECONST) {
$filters = array(
'created' => pht('Created By Me'),
'all' => pht('All %s', $strings['target_plural_noun']),
);
} else {
$filters = array(
'assigned' => pht('Assigned to Me'),
'created' => pht('Created By Me'),
'open' => pht('All Open %s', $strings['target_plural_noun']),
'all' => pht('All %s', $strings['target_plural_noun']),
);
}
return $filters;
}
private function getEdgeType($src_type, $dst_type) {
$t_cmit = PhabricatorRepositoryCommitPHIDType::TYPECONST;
$t_task = ManiphestTaskPHIDType::TYPECONST;
$t_drev = DifferentialRevisionPHIDType::TYPECONST;
$t_mock = PholioMockPHIDType::TYPECONST;
$map = array(
$t_cmit => array(
$t_task => DiffusionCommitHasTaskEdgeType::EDGECONST,
),
$t_task => array(
$t_cmit => ManiphestTaskHasCommitEdgeType::EDGECONST,
$t_task => ManiphestTaskDependsOnTaskEdgeType::EDGECONST,
$t_drev => ManiphestTaskHasRevisionEdgeType::EDGECONST,
$t_mock => ManiphestTaskHasMockEdgeType::EDGECONST,
),
$t_drev => array(
$t_drev => DifferentialRevisionDependsOnRevisionEdgeType::EDGECONST,
$t_task => DifferentialRevisionHasTaskEdgeType::EDGECONST,
),
$t_mock => array(
$t_task => PholioMockHasTaskEdgeType::EDGECONST,
),
);
if (empty($map[$src_type][$dst_type])) {
return null;
}
return $map[$src_type][$dst_type];
}
private function raiseGraphCycleException(PhabricatorEdgeCycleException $ex) {
$cycle = $ex->getCycle();
$handles = $this->loadViewerHandles($cycle);
$names = array();
foreach ($cycle as $cycle_phid) {
$names[] = $handles[$cycle_phid]->getFullName();
}
throw new Exception(
pht(
'You can not create that dependency, because it would create a '.
'circular dependency: %s.',
implode(" \xE2\x86\x92 ", $names)));
}
}

File Metadata

Mime Type
text/x-diff
Expires
Thu, Aug 14, 2:47 AM (4 d, 13 h ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
193498
Default Alt Text
(23 KB)

Event Timeline