Page MenuHomestyx hydra

No OneTemporary

diff --git a/src/applications/maniphest/controller/ManiphestController.php b/src/applications/maniphest/controller/ManiphestController.php
index 87eaf69706..b65811128d 100644
--- a/src/applications/maniphest/controller/ManiphestController.php
+++ b/src/applications/maniphest/controller/ManiphestController.php
@@ -1,70 +1,66 @@
<?php
abstract class ManiphestController extends PhabricatorController {
public function buildApplicationMenu() {
return $this->buildSideNavView(true)->getMenu();
}
- public function buildSideNavView($for_app = false) {
- $user = $this->getRequest()->getUser();
+ public function buildSideNavView() {
+ $viewer = $this->getViewer();
$nav = new AphrontSideNavFilterView();
$nav->setBaseURI(new PhutilURI($this->getApplicationURI()));
- if ($for_app) {
- $nav->addFilter('task/create/', pht('Create Task'));
- }
-
id(new ManiphestTaskSearchEngine())
- ->setViewer($user)
+ ->setViewer($viewer)
->addNavigationItems($nav->getMenu());
- if ($user->isLoggedIn()) {
+ if ($viewer->isLoggedIn()) {
// For now, don't give logged-out users access to reports.
$nav->addLabel(pht('Reports'));
$nav->addFilter('report', pht('Reports'));
}
$nav->selectFilter(null);
return $nav;
}
protected function buildApplicationCrumbs() {
$crumbs = parent::buildApplicationCrumbs();
$crumbs->addAction(
id(new PHUIListItemView())
->setName(pht('Create Task'))
->setHref($this->getApplicationURI('task/create/'))
->setIcon('fa-plus-square'));
return $crumbs;
}
protected function renderSingleTask(ManiphestTask $task) {
$request = $this->getRequest();
$user = $request->getUser();
$phids = $task->getProjectPHIDs();
if ($task->getOwnerPHID()) {
$phids[] = $task->getOwnerPHID();
}
$handles = id(new PhabricatorHandleQuery())
->setViewer($user)
->withPHIDs($phids)
->execute();
$view = id(new ManiphestTaskListView())
->setUser($user)
->setShowSubpriorityControls(!$request->getStr('ungrippable'))
->setShowBatchControls(true)
->setHandles($handles)
->setTasks(array($task));
return $view;
}
}
diff --git a/src/applications/maniphest/controller/ManiphestTaskDetailController.php b/src/applications/maniphest/controller/ManiphestTaskDetailController.php
index 090bdb9bb7..d5fab7f9f5 100644
--- a/src/applications/maniphest/controller/ManiphestTaskDetailController.php
+++ b/src/applications/maniphest/controller/ManiphestTaskDetailController.php
@@ -1,586 +1,590 @@
<?php
final class ManiphestTaskDetailController extends ManiphestController {
public function shouldAllowPublic() {
return true;
}
public function handleRequest(AphrontRequest $request) {
$viewer = $this->getViewer();
$id = $request->getURIData('id');
$e_title = null;
$priority_map = ManiphestTaskPriority::getTaskPriorityMap();
$task = id(new ManiphestTaskQuery())
->setViewer($viewer)
->withIDs(array($id))
->needSubscriberPHIDs(true)
->executeOne();
if (!$task) {
return new Aphront404Response();
}
$workflow = $request->getStr('workflow');
$parent_task = null;
if ($workflow && is_numeric($workflow)) {
$parent_task = id(new ManiphestTaskQuery())
->setViewer($viewer)
->withIDs(array($workflow))
->executeOne();
}
$field_list = PhabricatorCustomField::getObjectFields(
$task,
PhabricatorCustomField::ROLE_VIEW);
$field_list
->setViewer($viewer)
->readFieldsFromStorage($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;
$attached = $task->getAttached();
foreach ($attached as $type => $list) {
foreach ($list as $phid => $info) {
$phids[$phid] = true;
}
}
if ($parent_task) {
$phids[$parent_task->getPHID()] = true;
}
$phids = array_keys($phids);
$handles = $viewer->loadHandles($phids);
$info_view = null;
if ($parent_task) {
$info_view = new PHUIInfoView();
$info_view->setSeverity(PHUIInfoView::SEVERITY_NOTICE);
$info_view->addButton(
id(new PHUIButtonView())
->setTag('a')
->setHref('/maniphest/task/create/?parent='.$parent_task->getID())
->setText(pht('Create Another Subtask')));
$info_view->appendChild(hsprintf(
'Created a subtask of <strong>%s</strong>.',
$handles->renderHandle($parent_task->getPHID())));
} else if ($workflow == 'create') {
$info_view = new PHUIInfoView();
$info_view->setSeverity(PHUIInfoView::SEVERITY_NOTICE);
$info_view->addButton(
id(new PHUIButtonView())
->setTag('a')
->setHref('/maniphest/task/create/?template='.$task->getID())
->setText(pht('Similar Task')));
$info_view->addButton(
id(new PHUIButtonView())
->setTag('a')
->setHref('/maniphest/task/create/')
->setText(pht('Empty Task')));
$info_view->appendChild(pht('New task created. Create another?'));
}
$engine = new PhabricatorMarkupEngine();
$engine->setViewer($viewer);
$engine->setContextObject($task);
$engine->addObject($task, ManiphestTask::MARKUP_FIELD_DESCRIPTION);
$timeline = $this->buildTransactionTimeline(
$task,
new ManiphestTransactionQuery(),
$engine);
$resolution_types = ManiphestTaskStatus::getTaskStatusMap();
$transaction_types = array(
PhabricatorTransactions::TYPE_COMMENT => pht('Comment'),
ManiphestTransaction::TYPE_STATUS => pht('Change Status'),
ManiphestTransaction::TYPE_OWNER => pht('Reassign / Claim'),
PhabricatorTransactions::TYPE_SUBSCRIBERS => pht('Add CCs'),
ManiphestTransaction::TYPE_PRIORITY => pht('Change Priority'),
PhabricatorTransactions::TYPE_EDGE => pht('Associate Projects'),
);
// Remove actions the user doesn't have permission to take.
$requires = array(
ManiphestTransaction::TYPE_OWNER =>
ManiphestEditAssignCapability::CAPABILITY,
ManiphestTransaction::TYPE_PRIORITY =>
ManiphestEditPriorityCapability::CAPABILITY,
PhabricatorTransactions::TYPE_EDGE =>
ManiphestEditProjectsCapability::CAPABILITY,
ManiphestTransaction::TYPE_STATUS =>
ManiphestEditStatusCapability::CAPABILITY,
);
foreach ($transaction_types as $type => $name) {
if (isset($requires[$type])) {
if (!$this->hasApplicationCapability($requires[$type])) {
unset($transaction_types[$type]);
}
}
}
// Don't show an option to change to the current status, or to change to
// the duplicate status explicitly.
unset($resolution_types[$task->getStatus()]);
unset($resolution_types[ManiphestTaskStatus::getDuplicateStatus()]);
// Don't show owner/priority changes for closed tasks, as they don't make
// much sense.
if ($task->isClosed()) {
unset($transaction_types[ManiphestTransaction::TYPE_PRIORITY]);
unset($transaction_types[ManiphestTransaction::TYPE_OWNER]);
}
$default_claim = array(
$viewer->getPHID() => $viewer->getUsername().
' ('.$viewer->getRealName().')',
);
$draft = id(new PhabricatorDraft())->loadOneWhere(
'authorPHID = %s AND draftKey = %s',
$viewer->getPHID(),
$task->getPHID());
if ($draft) {
$draft_text = $draft->getDraft();
} else {
$draft_text = null;
}
$projects_source = new PhabricatorProjectDatasource();
$users_source = new PhabricatorPeopleDatasource();
$mailable_source = new PhabricatorMetaMTAMailableDatasource();
$comment_form = new AphrontFormView();
$comment_form
->setUser($viewer)
->setWorkflow(true)
->setAction('/maniphest/transaction/save/')
->setEncType('multipart/form-data')
->addHiddenInput('taskID', $task->getID())
->appendChild(
id(new AphrontFormSelectControl())
->setLabel(pht('Action'))
->setName('action')
->setOptions($transaction_types)
->setID('transaction-action'))
->appendChild(
id(new AphrontFormSelectControl())
->setLabel(pht('Status'))
->setName('resolution')
->setControlID('resolution')
->setControlStyle('display: none')
->setOptions($resolution_types))
->appendControl(
id(new AphrontFormTokenizerControl())
->setLabel(pht('Assign To'))
->setName('assign_to')
->setControlID('assign_to')
->setControlStyle('display: none')
->setID('assign-tokenizer')
->setDisableBehavior(true)
->setDatasource($users_source))
->appendControl(
id(new AphrontFormTokenizerControl())
->setLabel(pht('CCs'))
->setName('ccs')
->setControlID('ccs')
->setControlStyle('display: none')
->setID('cc-tokenizer')
->setDisableBehavior(true)
->setDatasource($mailable_source))
->appendChild(
id(new AphrontFormSelectControl())
->setLabel(pht('Priority'))
->setName('priority')
->setOptions($priority_map)
->setControlID('priority')
->setControlStyle('display: none')
->setValue($task->getPriority()))
->appendControl(
id(new AphrontFormTokenizerControl())
->setLabel(pht('Projects'))
->setName('projects')
->setControlID('projects')
->setControlStyle('display: none')
->setID('projects-tokenizer')
->setDisableBehavior(true)
->setDatasource($projects_source))
->appendChild(
id(new AphrontFormFileControl())
->setLabel(pht('File'))
->setName('file')
->setControlID('file')
->setControlStyle('display: none'))
->appendChild(
id(new PhabricatorRemarkupControl())
->setUser($viewer)
->setLabel(pht('Comments'))
->setName('comments')
->setValue($draft_text)
->setID('transaction-comments')
->setUser($viewer))
->appendChild(
id(new AphrontFormSubmitControl())
->setValue(pht('Submit')));
$control_map = array(
ManiphestTransaction::TYPE_STATUS => 'resolution',
ManiphestTransaction::TYPE_OWNER => 'assign_to',
PhabricatorTransactions::TYPE_SUBSCRIBERS => 'ccs',
ManiphestTransaction::TYPE_PRIORITY => 'priority',
PhabricatorTransactions::TYPE_EDGE => 'projects',
);
$tokenizer_map = array(
PhabricatorTransactions::TYPE_EDGE => array(
'id' => 'projects-tokenizer',
'src' => $projects_source->getDatasourceURI(),
'placeholder' => $projects_source->getPlaceholderText(),
),
ManiphestTransaction::TYPE_OWNER => array(
'id' => 'assign-tokenizer',
'src' => $users_source->getDatasourceURI(),
'value' => $default_claim,
'limit' => 1,
'placeholder' => $users_source->getPlaceholderText(),
),
PhabricatorTransactions::TYPE_SUBSCRIBERS => array(
'id' => 'cc-tokenizer',
'src' => $mailable_source->getDatasourceURI(),
'placeholder' => $mailable_source->getPlaceholderText(),
),
);
// TODO: Initializing these behaviors for logged out users fatals things.
if ($viewer->isLoggedIn()) {
Javelin::initBehavior('maniphest-transaction-controls', array(
'select' => 'transaction-action',
'controlMap' => $control_map,
'tokenizers' => $tokenizer_map,
));
Javelin::initBehavior('maniphest-transaction-preview', array(
'uri' => '/maniphest/transaction/preview/'.$task->getID().'/',
'preview' => 'transaction-preview',
'comments' => 'transaction-comments',
'action' => 'transaction-action',
'map' => $control_map,
'tokenizers' => $tokenizer_map,
));
}
$is_serious = PhabricatorEnv::getEnvConfig('phabricator.serious-business');
$comment_header = $is_serious
? pht('Add Comment')
: pht('Weigh In');
$preview_panel = phutil_tag_div(
'aphront-panel-preview',
phutil_tag(
'div',
array('id' => 'transaction-preview'),
phutil_tag_div(
'aphront-panel-preview-loading-text',
pht('Loading preview...'))));
$object_name = 'T'.$task->getID();
$actions = $this->buildActionView($task);
$crumbs = $this->buildApplicationCrumbs()
->addTextCrumb($object_name, '/'.$object_name);
$header = $this->buildHeaderView($task);
$properties = $this->buildPropertyView(
$task, $field_list, $edges, $actions, $handles);
$description = $this->buildDescriptionView($task, $engine);
if (!$viewer->isLoggedIn()) {
// TODO: Eventually, everything should run through this. For now, we're
// only using it to get a consistent "Login to Comment" button.
$comment_box = id(new PhabricatorApplicationTransactionCommentView())
->setUser($viewer)
->setRequestURI($request->getRequestURI());
$preview_panel = null;
} else {
$comment_box = id(new PHUIObjectBoxView())
->setFlush(true)
->setHeaderText($comment_header)
->setForm($comment_form);
$timeline->setQuoteTargetID('transaction-comments');
$timeline->setQuoteRef($object_name);
}
$object_box = id(new PHUIObjectBoxView())
->setHeader($header)
->addPropertyList($properties);
if ($description) {
$object_box->addPropertyList($description);
}
- return $this->buildApplicationPage(
- array(
- $crumbs,
- $info_view,
- $object_box,
- $timeline,
- $comment_box,
- $preview_panel,
- ),
- array(
- 'title' => 'T'.$task->getID().' '.$task->getTitle(),
- 'pageObjects' => array($task->getPHID()),
- ));
+ $title = 'T'.$task->getID().' '.$task->getTitle();
+
+ return $this->newPage()
+ ->setTitle($title)
+ ->setCrumbs($crumbs)
+ ->setPageObjectPHIDs(
+ array(
+ $task->getPHID(),
+ ))
+ ->appendChild(
+ array(
+ $info_view,
+ $object_box,
+ $timeline,
+ $comment_box,
+ $preview_panel,
+ ));
}
private function buildHeaderView(ManiphestTask $task) {
$view = id(new PHUIHeaderView())
->setHeader($task->getTitle())
->setUser($this->getRequest()->getUser())
->setPolicyObject($task);
$status = $task->getStatus();
$status_name = ManiphestTaskStatus::renderFullDescription($status);
$view->addProperty(PHUIHeaderView::PROPERTY_STATUS, $status_name);
return $view;
}
private function buildActionView(ManiphestTask $task) {
$viewer = $this->getRequest()->getUser();
$id = $task->getID();
$phid = $task->getPHID();
$can_edit = PhabricatorPolicyFilter::hasCapability(
$viewer,
$task,
PhabricatorPolicyCapability::CAN_EDIT);
$can_create = $viewer->isLoggedIn();
$view = id(new PhabricatorActionListView())
->setUser($viewer)
->setObject($task)
->setObjectURI($this->getRequest()->getRequestURI());
$view->addAction(
id(new PhabricatorActionView())
->setName(pht('Edit Task'))
->setIcon('fa-pencil')
->setHref($this->getApplicationURI("/task/edit/{$id}/"))
->setDisabled(!$can_edit)
->setWorkflow(!$can_edit));
$view->addAction(
id(new PhabricatorActionView())
->setName(pht('Merge Duplicates In'))
->setHref("/search/attach/{$phid}/TASK/merge/")
->setWorkflow(true)
->setIcon('fa-compress')
->setDisabled(!$can_edit)
->setWorkflow(true));
$view->addAction(
id(new PhabricatorActionView())
->setName(pht('Create Subtask'))
->setHref($this->getApplicationURI("/task/create/?parent={$id}"))
->setIcon('fa-level-down')
->setDisabled(!$can_create)
->setWorkflow(!$can_create));
$view->addAction(
id(new PhabricatorActionView())
->setName(pht('Edit Blocking Tasks'))
->setHref("/search/attach/{$phid}/TASK/blocks/")
->setWorkflow(true)
->setIcon('fa-link')
->setDisabled(!$can_edit)
->setWorkflow(true));
return $view;
}
private function buildPropertyView(
ManiphestTask $task,
PhabricatorCustomFieldList $field_list,
array $edges,
PhabricatorActionListView $actions,
$handles) {
$viewer = $this->getRequest()->getUser();
$view = id(new PHUIPropertyListView())
->setUser($viewer)
->setObject($task)
->setActionList($actions);
$view->addProperty(
pht('Assigned To'),
$task->getOwnerPHID()
? $handles->renderHandle($task->getOwnerPHID())
: phutil_tag('em', array(), pht('None')));
$view->addProperty(
pht('Priority'),
ManiphestTaskPriority::getTaskPriorityName($task->getPriority()));
$view->addProperty(
pht('Author'),
$handles->renderHandle($task->getAuthorPHID()));
$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);
$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->renderLink($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));
}
$attached = $task->getAttached();
if (!is_array($attached)) {
$attached = array();
}
$file_infos = idx($attached, PhabricatorFileFilePHIDType::TYPECONST);
if ($file_infos) {
$file_phids = array_keys($file_infos);
// TODO: These should probably be handles or something; clean this up
// as we sort out file attachments.
$files = id(new PhabricatorFileQuery())
->setViewer($viewer)
->withPHIDs($file_phids)
->execute();
$file_view = new PhabricatorFileLinkListView();
$file_view->setFiles($files);
$view->addProperty(
pht('Files'),
$file_view->render());
}
$view->invokeWillRenderEvent();
$field_list->appendFieldsToPropertyList(
$task,
$viewer,
$view);
return $view;
}
private function buildDescriptionView(
ManiphestTask $task,
PhabricatorMarkupEngine $engine) {
$section = null;
if (strlen($task->getDescription())) {
$section = new PHUIPropertyListView();
$section->addSectionHeader(
pht('Description'),
PHUIPropertyListView::ICON_SUMMARY);
$section->addTextContent(
phutil_tag(
'div',
array(
'class' => 'phabricator-remarkup',
),
$engine->getOutput($task, ManiphestTask::MARKUP_FIELD_DESCRIPTION)));
}
return $section;
}
}
diff --git a/src/applications/maniphest/controller/ManiphestTaskEditController.php b/src/applications/maniphest/controller/ManiphestTaskEditController.php
index 5c4a3b4862..e9ce5a567a 100644
--- a/src/applications/maniphest/controller/ManiphestTaskEditController.php
+++ b/src/applications/maniphest/controller/ManiphestTaskEditController.php
@@ -1,756 +1,757 @@
<?php
final class ManiphestTaskEditController extends ManiphestController {
public function handleRequest(AphrontRequest $request) {
$viewer = $this->getViewer();
$id = $request->getURIData('id');
$response_type = $request->getStr('responseType', 'task');
$order = $request->getStr('order', PhabricatorProjectColumn::DEFAULT_ORDER);
$can_edit_assign = $this->hasApplicationCapability(
ManiphestEditAssignCapability::CAPABILITY);
$can_edit_policies = $this->hasApplicationCapability(
ManiphestEditPoliciesCapability::CAPABILITY);
$can_edit_priority = $this->hasApplicationCapability(
ManiphestEditPriorityCapability::CAPABILITY);
$can_edit_projects = $this->hasApplicationCapability(
ManiphestEditProjectsCapability::CAPABILITY);
$can_edit_status = $this->hasApplicationCapability(
ManiphestEditStatusCapability::CAPABILITY);
$can_create_projects = PhabricatorPolicyFilter::hasCapability(
$viewer,
PhabricatorApplication::getByClass('PhabricatorProjectApplication'),
ProjectCreateProjectsCapability::CAPABILITY);
$parent_task = null;
$template_id = null;
if ($id) {
$task = id(new ManiphestTaskQuery())
->setViewer($viewer)
->requireCapabilities(
array(
PhabricatorPolicyCapability::CAN_VIEW,
PhabricatorPolicyCapability::CAN_EDIT,
))
->withIDs(array($id))
->needSubscriberPHIDs(true)
->needProjectPHIDs(true)
->executeOne();
if (!$task) {
return new Aphront404Response();
}
} else {
$task = ManiphestTask::initializeNewTask($viewer);
// We currently do not allow you to set the task status when creating
// a new task, although now that statuses are custom it might make
// sense.
$can_edit_status = false;
// These allow task creation with defaults.
if (!$request->isFormPost()) {
$task->setTitle($request->getStr('title'));
if ($can_edit_projects) {
$projects = $request->getStr('projects');
if ($projects) {
$tokens = $request->getStrList('projects');
$type_project = PhabricatorProjectProjectPHIDType::TYPECONST;
foreach ($tokens as $key => $token) {
if (phid_get_type($token) == $type_project) {
// If this is formatted like a PHID, leave it as-is.
continue;
}
if (preg_match('/^#/', $token)) {
// If this already has a "#", leave it as-is.
continue;
}
// Add a "#" prefix.
$tokens[$key] = '#'.$token;
}
$default_projects = id(new PhabricatorObjectQuery())
->setViewer($viewer)
->withNames($tokens)
->execute();
$default_projects = mpull($default_projects, 'getPHID');
if ($default_projects) {
$task->attachProjectPHIDs($default_projects);
}
}
}
if ($can_edit_priority) {
$priority = $request->getInt('priority');
if ($priority !== null) {
$priority_map = ManiphestTaskPriority::getTaskPriorityMap();
if (isset($priority_map[$priority])) {
$task->setPriority($priority);
}
}
}
$task->setDescription($request->getStr('description'));
if ($can_edit_assign) {
$assign = $request->getStr('assign');
if (strlen($assign)) {
$assign_user = id(new PhabricatorPeopleQuery())
->setViewer($viewer)
->withUsernames(array($assign))
->executeOne();
if (!$assign_user) {
$assign_user = id(new PhabricatorPeopleQuery())
->setViewer($viewer)
->withPHIDs(array($assign))
->executeOne();
}
if ($assign_user) {
$task->setOwnerPHID($assign_user->getPHID());
}
}
}
}
$template_id = $request->getInt('template');
// You can only have a parent task if you're creating a new task.
$parent_id = $request->getInt('parent');
if (strlen($parent_id)) {
$parent_task = id(new ManiphestTaskQuery())
->setViewer($viewer)
->withIDs(array($parent_id))
->executeOne();
if (!$parent_task) {
return new Aphront404Response();
}
if (!$template_id) {
$template_id = $parent_id;
}
}
}
$errors = array();
$e_title = true;
$field_list = PhabricatorCustomField::getObjectFields(
$task,
PhabricatorCustomField::ROLE_EDIT);
$field_list->setViewer($viewer);
$field_list->readFieldsFromStorage($task);
$aux_fields = $field_list->getFields();
$v_space = $task->getSpacePHID();
if ($request->isFormPost()) {
$changes = array();
$new_title = $request->getStr('title');
$new_desc = $request->getStr('description');
$new_status = $request->getStr('status');
$v_space = $request->getStr('spacePHID');
if (!$task->getID()) {
$workflow = 'create';
} else {
$workflow = '';
}
$changes[ManiphestTransaction::TYPE_TITLE] = $new_title;
$changes[ManiphestTransaction::TYPE_DESCRIPTION] = $new_desc;
if ($can_edit_status) {
$changes[ManiphestTransaction::TYPE_STATUS] = $new_status;
} else if (!$task->getID()) {
// Create an initial status transaction for the burndown chart.
// TODO: We can probably remove this once Facts comes online.
$changes[ManiphestTransaction::TYPE_STATUS] = $task->getStatus();
}
$owner_tokenizer = $request->getArr('assigned_to');
$owner_phid = reset($owner_tokenizer);
if (!strlen($new_title)) {
$e_title = pht('Required');
$errors[] = pht('Title is required.');
}
$old_values = array();
foreach ($aux_fields as $aux_arr_key => $aux_field) {
// TODO: This should be buildFieldTransactionsFromRequest() once we
// switch to ApplicationTransactions properly.
$aux_old_value = $aux_field->getOldValueForApplicationTransactions();
$aux_field->readValueFromRequest($request);
$aux_new_value = $aux_field->getNewValueForApplicationTransactions();
// TODO: We're faking a call to the ApplicaitonTransaction validation
// logic here. We need valid objects to pass, but they aren't used
// in a meaningful way. For now, build User objects. Once the Maniphest
// objects exist, this will switch over automatically. This is a big
// hack but shouldn't be long for this world.
$placeholder_editor = id(new PhabricatorUserProfileEditor())
->setActor($viewer);
$field_errors = $aux_field->validateApplicationTransactions(
$placeholder_editor,
PhabricatorTransactions::TYPE_CUSTOMFIELD,
array(
id(new ManiphestTransaction())
->setOldValue($aux_old_value)
->setNewValue($aux_new_value),
));
foreach ($field_errors as $error) {
$errors[] = $error->getMessage();
}
$old_values[$aux_field->getFieldKey()] = $aux_old_value;
}
if ($errors) {
$task->setTitle($new_title);
$task->setDescription($new_desc);
$task->setPriority($request->getInt('priority'));
$task->setOwnerPHID($owner_phid);
$task->attachSubscriberPHIDs($request->getArr('cc'));
$task->attachProjectPHIDs($request->getArr('projects'));
} else {
if ($can_edit_priority) {
$changes[ManiphestTransaction::TYPE_PRIORITY] =
$request->getInt('priority');
}
if ($can_edit_assign) {
$changes[ManiphestTransaction::TYPE_OWNER] = $owner_phid;
}
$changes[PhabricatorTransactions::TYPE_SUBSCRIBERS] =
array('=' => $request->getArr('cc'));
if ($can_edit_projects) {
$projects = $request->getArr('projects');
$changes[PhabricatorTransactions::TYPE_EDGE] =
$projects;
$column_phid = $request->getStr('columnPHID');
// allow for putting a task in a project column at creation -only-
if (!$task->getID() && $column_phid && $projects) {
$column = id(new PhabricatorProjectColumnQuery())
->setViewer($viewer)
->withProjectPHIDs($projects)
->withPHIDs(array($column_phid))
->executeOne();
if ($column) {
$changes[ManiphestTransaction::TYPE_PROJECT_COLUMN] =
array(
'new' => array(
'projectPHID' => $column->getProjectPHID(),
'columnPHIDs' => array($column_phid),
),
'old' => array(
'projectPHID' => $column->getProjectPHID(),
'columnPHIDs' => array(),
),
);
}
}
}
if ($can_edit_policies) {
$changes[PhabricatorTransactions::TYPE_SPACE] = $v_space;
$changes[PhabricatorTransactions::TYPE_VIEW_POLICY] =
$request->getStr('viewPolicy');
$changes[PhabricatorTransactions::TYPE_EDIT_POLICY] =
$request->getStr('editPolicy');
}
$template = new ManiphestTransaction();
$transactions = array();
foreach ($changes as $type => $value) {
$transaction = clone $template;
$transaction->setTransactionType($type);
if ($type == ManiphestTransaction::TYPE_PROJECT_COLUMN) {
$transaction->setNewValue($value['new']);
$transaction->setOldValue($value['old']);
} else if ($type == PhabricatorTransactions::TYPE_EDGE) {
$project_type =
PhabricatorProjectObjectHasProjectEdgeType::EDGECONST;
$transaction
->setMetadataValue('edge:type', $project_type)
->setNewValue(
array(
'=' => array_fuse($value),
));
} else {
$transaction->setNewValue($value);
}
$transactions[] = $transaction;
}
if ($aux_fields) {
foreach ($aux_fields as $aux_field) {
$transaction = clone $template;
$transaction->setTransactionType(
PhabricatorTransactions::TYPE_CUSTOMFIELD);
$aux_key = $aux_field->getFieldKey();
$transaction->setMetadataValue('customfield:key', $aux_key);
$old = idx($old_values, $aux_key);
$new = $aux_field->getNewValueForApplicationTransactions();
$transaction->setOldValue($old);
$transaction->setNewValue($new);
$transactions[] = $transaction;
}
}
if ($transactions) {
$is_new = !$task->getID();
$event = new PhabricatorEvent(
PhabricatorEventType::TYPE_MANIPHEST_WILLEDITTASK,
array(
'task' => $task,
'new' => $is_new,
'transactions' => $transactions,
));
$event->setUser($viewer);
$event->setAphrontRequest($request);
PhutilEventEngine::dispatchEvent($event);
$task = $event->getValue('task');
$transactions = $event->getValue('transactions');
$editor = id(new ManiphestTransactionEditor())
->setActor($viewer)
->setContentSourceFromRequest($request)
->setContinueOnNoEffect(true)
->applyTransactions($task, $transactions);
$event = new PhabricatorEvent(
PhabricatorEventType::TYPE_MANIPHEST_DIDEDITTASK,
array(
'task' => $task,
'new' => $is_new,
'transactions' => $transactions,
));
$event->setUser($viewer);
$event->setAphrontRequest($request);
PhutilEventEngine::dispatchEvent($event);
}
if ($parent_task) {
// TODO: This should be transactional now.
id(new PhabricatorEdgeEditor())
->addEdge(
$parent_task->getPHID(),
ManiphestTaskDependsOnTaskEdgeType::EDGECONST,
$task->getPHID())
->save();
$workflow = $parent_task->getID();
}
if ($request->isAjax()) {
switch ($response_type) {
case 'card':
$owner = null;
if ($task->getOwnerPHID()) {
$owner = id(new PhabricatorHandleQuery())
->setViewer($viewer)
->withPHIDs(array($task->getOwnerPHID()))
->executeOne();
}
$tasks = id(new ProjectBoardTaskCard())
->setViewer($viewer)
->setTask($task)
->setOwner($owner)
->setCanEdit(true)
->getItem();
$column = id(new PhabricatorProjectColumnQuery())
->setViewer($viewer)
->withPHIDs(array($request->getStr('columnPHID')))
->executeOne();
if (!$column) {
return new Aphront404Response();
}
// re-load projects for accuracy as they are not re-loaded via
// the editor
$project_phids = PhabricatorEdgeQuery::loadDestinationPHIDs(
$task->getPHID(),
PhabricatorProjectObjectHasProjectEdgeType::EDGECONST);
$task->attachProjectPHIDs($project_phids);
$remove_from_board = false;
if (!in_array($column->getProjectPHID(), $project_phids)) {
$remove_from_board = true;
}
$positions = id(new PhabricatorProjectColumnPositionQuery())
->setViewer($viewer)
->withColumns(array($column))
->execute();
$task_phids = mpull($positions, 'getObjectPHID');
$column_tasks = id(new ManiphestTaskQuery())
->setViewer($viewer)
->withPHIDs($task_phids)
->execute();
if ($order == PhabricatorProjectColumn::ORDER_NATURAL) {
// TODO: This is a little bit awkward, because PHP and JS use
// slightly different sort order parameters to achieve the same
// effect. It would be good to unify this a bit at some point.
$sort_map = array();
foreach ($positions as $position) {
$sort_map[$position->getObjectPHID()] = array(
-$position->getSequence(),
$position->getID(),
);
}
} else {
$sort_map = mpull(
$column_tasks,
'getPrioritySortVector',
'getPHID');
}
$data = array(
'sortMap' => $sort_map,
'removeFromBoard' => $remove_from_board,
);
break;
case 'task':
default:
$tasks = $this->renderSingleTask($task);
$data = array();
break;
}
return id(new AphrontAjaxResponse())->setContent(
array(
'tasks' => $tasks,
'data' => $data,
));
}
$redirect_uri = '/T'.$task->getID();
if ($workflow) {
$redirect_uri .= '?workflow='.$workflow;
}
return id(new AphrontRedirectResponse())
->setURI($redirect_uri);
}
} else {
if (!$task->getID()) {
$task->attachSubscriberPHIDs(array(
$viewer->getPHID(),
));
if ($template_id) {
$template_task = id(new ManiphestTaskQuery())
->setViewer($viewer)
->withIDs(array($template_id))
->needSubscriberPHIDs(true)
->needProjectPHIDs(true)
->executeOne();
if ($template_task) {
$cc_phids = array_unique(array_merge(
$template_task->getSubscriberPHIDs(),
array($viewer->getPHID())));
$task->attachSubscriberPHIDs($cc_phids);
$task->attachProjectPHIDs($template_task->getProjectPHIDs());
$task->setOwnerPHID($template_task->getOwnerPHID());
$task->setPriority($template_task->getPriority());
$task->setViewPolicy($template_task->getViewPolicy());
$task->setEditPolicy($template_task->getEditPolicy());
$v_space = $template_task->getSpacePHID();
$template_fields = PhabricatorCustomField::getObjectFields(
$template_task,
PhabricatorCustomField::ROLE_EDIT);
$fields = $template_fields->getFields();
foreach ($fields as $key => $field) {
if (!$field->shouldCopyWhenCreatingSimilarTask()) {
unset($fields[$key]);
}
if (empty($aux_fields[$key])) {
unset($fields[$key]);
}
}
if ($fields) {
id(new PhabricatorCustomFieldList($fields))
->setViewer($viewer)
->readFieldsFromStorage($template_task);
foreach ($fields as $key => $field) {
$aux_fields[$key]->setValueFromStorage(
$field->getValueForStorage());
}
}
}
}
}
}
$error_view = null;
if ($errors) {
$error_view = new PHUIInfoView();
$error_view->setErrors($errors);
}
$priority_map = ManiphestTaskPriority::getTaskPriorityMap();
if ($task->getOwnerPHID()) {
$assigned_value = array($task->getOwnerPHID());
} else {
$assigned_value = array();
}
if ($task->getSubscriberPHIDs()) {
$cc_value = $task->getSubscriberPHIDs();
} else {
$cc_value = array();
}
if ($task->getProjectPHIDs()) {
$projects_value = $task->getProjectPHIDs();
} else {
$projects_value = array();
}
$cancel_id = nonempty($task->getID(), $template_id);
if ($cancel_id) {
$cancel_uri = '/T'.$cancel_id;
} else {
$cancel_uri = '/maniphest/';
}
if ($task->getID()) {
$button_name = pht('Save Task');
$header_name = pht('Edit Task');
} else if ($parent_task) {
$cancel_uri = '/T'.$parent_task->getID();
$button_name = pht('Create Task');
$header_name = pht('Create New Subtask');
} else {
$button_name = pht('Create Task');
$header_name = pht('Create New Task');
}
require_celerity_resource('maniphest-task-edit-css');
$project_tokenizer_id = celerity_generate_unique_node_id();
$form = new AphrontFormView();
$form
->setUser($viewer)
->addHiddenInput('template', $template_id)
->addHiddenInput('responseType', $response_type)
->addHiddenInput('order', $order)
->addHiddenInput('ungrippable', $request->getStr('ungrippable'))
->addHiddenInput('columnPHID', $request->getStr('columnPHID'));
if ($parent_task) {
$form
->appendChild(
id(new AphrontFormStaticControl())
->setLabel(pht('Parent Task'))
->setValue($viewer->renderHandle($parent_task->getPHID())))
->addHiddenInput('parent', $parent_task->getID());
}
$form
->appendChild(
id(new AphrontFormTextAreaControl())
->setLabel(pht('Title'))
->setName('title')
->setError($e_title)
->setHeight(AphrontFormTextAreaControl::HEIGHT_VERY_SHORT)
->setValue($task->getTitle()));
if ($can_edit_status) {
// See T4819.
$status_map = ManiphestTaskStatus::getTaskStatusMap();
$dup_status = ManiphestTaskStatus::getDuplicateStatus();
if ($task->getStatus() != $dup_status) {
unset($status_map[$dup_status]);
}
$form
->appendChild(
id(new AphrontFormSelectControl())
->setLabel(pht('Status'))
->setName('status')
->setValue($task->getStatus())
->setOptions($status_map));
}
$policies = id(new PhabricatorPolicyQuery())
->setViewer($viewer)
->setObject($task)
->execute();
if ($can_edit_assign) {
$form->appendControl(
id(new AphrontFormTokenizerControl())
->setLabel(pht('Assigned To'))
->setName('assigned_to')
->setValue($assigned_value)
->setUser($viewer)
->setDatasource(new PhabricatorPeopleDatasource())
->setLimit(1));
}
$form
->appendControl(
id(new AphrontFormTokenizerControl())
->setLabel(pht('CC'))
->setName('cc')
->setValue($cc_value)
->setUser($viewer)
->setDatasource(new PhabricatorMetaMTAMailableDatasource()));
if ($can_edit_priority) {
$form
->appendChild(
id(new AphrontFormSelectControl())
->setLabel(pht('Priority'))
->setName('priority')
->setOptions($priority_map)
->setValue($task->getPriority()));
}
if ($can_edit_policies) {
$form
->appendChild(
id(new AphrontFormPolicyControl())
->setUser($viewer)
->setCapability(PhabricatorPolicyCapability::CAN_VIEW)
->setPolicyObject($task)
->setPolicies($policies)
->setSpacePHID($v_space)
->setName('viewPolicy'))
->appendChild(
id(new AphrontFormPolicyControl())
->setUser($viewer)
->setCapability(PhabricatorPolicyCapability::CAN_EDIT)
->setPolicyObject($task)
->setPolicies($policies)
->setName('editPolicy'));
}
if ($can_edit_projects) {
$caption = null;
if ($can_create_projects) {
$caption = javelin_tag(
'a',
array(
'href' => '/project/create/',
'mustcapture' => true,
'sigil' => 'project-create',
),
pht('Create New Project'));
}
$form
->appendControl(
id(new AphrontFormTokenizerControl())
->setLabel(pht('Projects'))
->setName('projects')
->setValue($projects_value)
->setID($project_tokenizer_id)
->setCaption($caption)
->setDatasource(new PhabricatorProjectDatasource()));
}
$field_list->appendFieldsToForm($form);
require_celerity_resource('phui-info-view-css');
Javelin::initBehavior('project-create', array(
'tokenizerID' => $project_tokenizer_id,
));
$description_control = id(new PhabricatorRemarkupControl())
->setLabel(pht('Description'))
->setName('description')
->setID('description-textarea')
->setValue($task->getDescription())
->setUser($viewer);
$form
->appendChild($description_control);
if ($request->isAjax()) {
$dialog = id(new AphrontDialogView())
->setUser($viewer)
->setWidth(AphrontDialogView::WIDTH_FULL)
->setTitle($header_name)
->appendChild(
array(
$error_view,
$form->buildLayoutView(),
))
->addCancelButton($cancel_uri)
->addSubmitButton($button_name);
return id(new AphrontDialogResponse())->setDialog($dialog);
}
$form
->appendChild(
id(new AphrontFormSubmitControl())
->addCancelButton($cancel_uri)
->setValue($button_name));
$form_box = id(new PHUIObjectBoxView())
->setHeaderText($header_name)
->setFormErrors($errors)
->setForm($form);
$preview = id(new PHUIRemarkupPreviewPanel())
->setHeader(pht('Description Preview'))
->setControlID('description-textarea')
->setPreviewURI($this->getApplicationURI('task/descriptionpreview/'));
if ($task->getID()) {
$page_objects = array($task->getPHID());
} else {
$page_objects = array();
}
$crumbs = $this->buildApplicationCrumbs();
if ($task->getID()) {
$crumbs->addTextCrumb('T'.$task->getID(), '/T'.$task->getID());
}
$crumbs->addTextCrumb($header_name);
- return $this->buildApplicationPage(
- array(
- $crumbs,
- $form_box,
- $preview,
- ),
- array(
- 'title' => $header_name,
- 'pageObjects' => $page_objects,
- ));
+ $title = $header_name;
+
+ return $this->newPage()
+ ->setTitle($title)
+ ->setCrumbs($crumbs)
+ ->setPageObjectPHIDs($page_objects)
+ ->appendChild(
+ array(
+ $form_box,
+ $preview,
+ ));
}
}

File Metadata

Mime Type
text/x-diff
Expires
Wed, Apr 30, 3:05 PM (1 d, 9 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
108739
Default Alt Text
(47 KB)

Event Timeline