Christopher Johnson (WMDE) has uploaded a new change for review.
https://gerrit.wikimedia.org/r/261185
Change subject: fixes several upstream breaking changes current with
10ed33052361be82cbc09884118d65ec0601bd55 27.12.2015 Bug: T122486
......................................................................
fixes several upstream breaking changes
current with 10ed33052361be82cbc09884118d65ec0601bd55 27.12.2015
Bug: T122486
Change-Id: I418d643a0949599ad507071fb14ffb3ff89bf102
---
M src/__phutil_library_map__.php
M src/application/SprintApplication.php
M src/controller/SprintController.php
A src/controller/SprintProjectController.php
M src/controller/SprintProjectProfileController.php
M src/controller/board/SprintBoardTaskEditController.php
A src/controller/board/SprintManiphestEditEngine.php
7 files changed, 654 insertions(+), 813 deletions(-)
git pull ssh://gerrit.wikimedia.org:29418/phabricator/extensions/Sprint
refs/changes/85/261185/1
diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
index 84de703..3fa5040 100644
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -61,7 +61,9 @@
'SprintListController' => 'controller/SprintListController.php',
'SprintListDataProvider' => 'storage/SprintListDataProvider.php',
'SprintListTableView' => 'view/SprintListTableView.php',
+ 'SprintManiphestEditEngine' =>
'controller/board/SprintManiphestEditEngine.php',
'SprintPoints' => 'util/SprintPoints.php',
+ 'SprintProjectController' => 'controller/SprintProjectController.php',
'SprintProjectCustomField' => 'customfield/SprintProjectCustomField.php',
'SprintProjectProfileController' =>
'controller/SprintProjectProfileController.php',
'SprintProjectViewController' =>
'controller/SprintProjectViewController.php',
@@ -131,12 +133,14 @@
'SprintIsSprintField' => 'SprintProjectCustomField',
'SprintListController' => 'SprintController',
'SprintListTableView' => 'Phobject',
+ 'SprintManiphestEditEngine' => 'PhabricatorEditEngine',
'SprintPoints' => 'Phobject',
+ 'SprintProjectController' => 'SprintController',
'SprintProjectCustomField' => array(
'PhabricatorProjectCustomField',
'PhabricatorStandardCustomFieldInterface',
),
- 'SprintProjectProfileController' => 'SprintController',
+ 'SprintProjectProfileController' => 'SprintProjectController',
'SprintProjectViewController' => 'SprintController',
'SprintQuery' => 'SprintDAO',
'SprintQueryTest' => 'SprintTestCase',
diff --git a/src/application/SprintApplication.php
b/src/application/SprintApplication.php
index 336bb86..6d7a58b 100644
--- a/src/application/SprintApplication.php
+++ b/src/application/SprintApplication.php
@@ -72,8 +72,8 @@
// all routes following point to default controllers
'archive/(?P<id>[1-9]\d*)/'
=> 'PhabricatorProjectArchiveController',
- 'details/(?P<id>[1-9]\d*)/'
- => 'PhabricatorProjectEditDetailsController',
+ $this->getEditRoutePattern('edit/')
+ => 'PhabricatorProjectEditController',
'feed/(?P<id>[1-9]\d*)/'
=> 'PhabricatorProjectFeedController',
'icon/(?P<id>[1-9]\d*)/'
diff --git a/src/controller/SprintController.php
b/src/controller/SprintController.php
index 143fc2f..e202a3f 100644
--- a/src/controller/SprintController.php
+++ b/src/controller/SprintController.php
@@ -24,7 +24,7 @@
}
public function buildApplicationMenu() {
- return $this->buildSideNavView($this->getUser(),
+ return $this->buildSprintNavView($this->getUser(),
$this->setApplicationURI(), true)->getMenu();
}
@@ -45,7 +45,7 @@
/**
* @param PhutilURI $uri
*/
- public function buildSideNavView($viewer, $uri, $for_app = false) {
+ public function buildSprintNavView($viewer, $uri, $for_app = false) {
$request = $this->getRequest();
$id = $request->getURIData('id');
$slug = $request->getURIData('slug');
diff --git a/src/controller/SprintProjectController.php
b/src/controller/SprintProjectController.php
new file mode 100644
index 0000000..a3f628f
--- /dev/null
+++ b/src/controller/SprintProjectController.php
@@ -0,0 +1,181 @@
+<?php
+
+abstract class SprintProjectController extends SprintController {
+
+ private $project;
+
+ protected function setProject(PhabricatorProject $project) {
+ $this->project = $project;
+ return $this;
+ }
+
+ protected function getProject() {
+ return $this->project;
+ }
+
+ protected function loadProject() {
+ $viewer = $this->getViewer();
+ $request = $this->getRequest();
+
+ $id = $request->getURIData('id');
+ $slug = $request->getURIData('slug');
+
+ if ($slug) {
+ $normal_slug = PhabricatorSlug::normalizeProjectSlug($slug);
+ $is_abnormal = ($slug !== $normal_slug);
+ $normal_uri = "/tag/{$normal_slug}/";
+ } else {
+ $is_abnormal = false;
+ }
+
+ $query = id(new PhabricatorProjectQuery())
+ ->setViewer($viewer)
+ ->needMembers(true)
+ ->needWatchers(true)
+ ->needImages(true)
+ ->needSlugs(true);
+
+ if ($slug) {
+ $query->withSlugs(array($slug));
+ } else {
+ $query->withIDs(array($id));
+ }
+
+ $policy_exception = null;
+ try {
+ $project = $query->executeOne();
+ } catch (PhabricatorPolicyException $ex) {
+ $policy_exception = $ex;
+ $project = null;
+ }
+
+ if (!$project) {
+ // This project legitimately does not exist, so just 404 the user.
+ if (!$policy_exception) {
+ return new Aphront404Response();
+ }
+
+ // Here, the project exists but the user can't see it. If they are
+ // using a non-canonical slug to view the project, redirect to the
+ // canonical slug. If they're already using the canonical slug, rethrow
+ // the exception to give them the policy error.
+ if ($is_abnormal) {
+ return id(new AphrontRedirectResponse())->setURI($normal_uri);
+ } else {
+ throw $policy_exception;
+ }
+ }
+
+ // The user can view the project, but is using a noncanonical slug.
+ // Redirect to the canonical slug.
+ $primary_slug = $project->getPrimarySlug();
+ if ($slug && ($slug !== $primary_slug)) {
+ $primary_uri = "/tag/{$primary_slug}/";
+ return id(new AphrontRedirectResponse())->setURI($primary_uri);
+ }
+
+ $this->setProject($project);
+
+ return null;
+ }
+
+ public function buildApplicationMenu() {
+ return $this->buildSideNavView(true)->getMenu();
+ }
+
+ public function buildSideNavView($for_app = false) {
+ $project = $this->getProject();
+
+ $nav = new AphrontSideNavFilterView();
+ $nav->setBaseURI(new PhutilURI($this->getApplicationURI()));
+
+ $viewer = $this->getViewer();
+
+ $id = null;
+ if ($for_app) {
+ if ($project) {
+ $id = $project->getID();
+ $nav->addFilter("profile/{$id}/", pht('Profile'));
+ $nav->addFilter("board/{$id}/", pht('Workboard'));
+ $nav->addFilter("members/{$id}/", pht('Members'));
+ $nav->addFilter("feed/{$id}/", pht('Feed'));
+ $nav->addFilter("details/{$id}/", pht('Edit Details'));
+ }
+ $nav->addFilter('create', pht('Create Project'));
+ }
+
+ if (!$id) {
+ id(new PhabricatorProjectSearchEngine())
+ ->setViewer($viewer)
+ ->addNavigationItems($nav->getMenu());
+ }
+
+ $nav->selectFilter(null);
+
+ return $nav;
+ }
+
+ public function buildIconNavView(PhabricatorProject $project) {
+ $this->setProject($project);
+ $viewer = $this->getViewer();
+ $id = $project->getID();
+ $picture = $project->getProfileImageURI();
+ $name = $project->getName();
+
+ $columns = id(new PhabricatorProjectColumnQuery())
+ ->setViewer($viewer)
+ ->withProjectPHIDs(array($project->getPHID()))
+ ->execute();
+ if ($columns) {
+ $board_icon = 'fa-columns';
+ } else {
+ $board_icon = 'fa-columns grey';
+ }
+
+ $nav = new AphrontSideNavFilterView();
+ $nav->setIconNav(true);
+ $nav->setBaseURI(new PhutilURI($this->getApplicationURI()));
+ $nav->addIcon("profile/{$id}/", $name, null, $picture);
+
+ $class = 'PhabricatorManiphestApplication';
+ if (PhabricatorApplication::isClassInstalledForViewer($class, $viewer)) {
+ $phid = $project->getPHID();
+ $nav->addIcon("board/{$id}/", pht('Workboard'), $board_icon);
+ $query_uri = urisprintf(
+ '/maniphest/?statuses=open()&projects=%s#R',
+ $phid);
+ $nav->addIcon(null, pht('Open Tasks'), 'fa-anchor', null, $query_uri);
+ }
+
+ $nav->addIcon("feed/{$id}/", pht('Feed'), 'fa-newspaper-o');
+ $nav->addIcon("members/{$id}/", pht('Members'), 'fa-group');
+ $nav->addIcon("details/{$id}/", pht('Edit Details'), 'fa-pencil');
+
+ if (PhabricatorEnv::getEnvConfig('phabricator.show-prototypes')) {
+ $nav->addIcon("subprojects/{$id}/", pht('Subprojects'), 'fa-sitemap');
+ $nav->addIcon("milestones/{$id}/", pht('Milestones'), 'fa-map-marker');
+ }
+
+
+ return $nav;
+ }
+
+ protected function buildApplicationCrumbs() {
+ $crumbs = parent::buildApplicationCrumbs();
+
+ $project = $this->getProject();
+ if ($project) {
+ $ancestors = $project->getAncestorProjects();
+ $ancestors = array_reverse($ancestors);
+ $ancestors[] = $project;
+ foreach ($ancestors as $ancestor) {
+ $crumbs->addTextCrumb(
+ $project->getName(),
+ $project->getURI());
+ }
+ }
+
+ return $crumbs;
+ }
+
+}
diff --git a/src/controller/SprintProjectProfileController.php
b/src/controller/SprintProjectProfileController.php
index 05f32a0..4bdd02e 100644
--- a/src/controller/SprintProjectProfileController.php
+++ b/src/controller/SprintProjectProfileController.php
@@ -1,7 +1,7 @@
<?php
final class SprintProjectProfileController
- extends SprintController {
+ extends SprintProjectController {
public function shouldAllowPublic() {
return true;
@@ -10,27 +10,13 @@
public function handleRequest(AphrontRequest $request) {
$viewer = $request->getViewer();
- $query = id(new PhabricatorProjectQuery())
- ->setViewer($viewer)
- ->needMembers(true)
- ->needWatchers(true)
- ->needImages(true)
- ->needSlugs(true);
- $id = $request->getURIData('id');
- $slug = $request->getURIData('slug');
- if ($slug) {
- $query->withSlugs(array($slug));
- } else {
- $query->withIDs(array($id));
+ $response = $this->loadProject();
+ if ($response) {
+ return $response;
}
- $project = $query->executeOne();
- if (!$project) {
- return new Aphront404Response();
- }
- if ($slug && $slug != $project->getPrimarySlug()) {
- return id(new AphrontRedirectResponse())
- ->setURI('/tag/'.$project->getPrimarySlug().'/');
- }
+
+ $project = $this->getProject();
+ $id = $project->getID();
$picture = $project->getProfileImageURI();
@@ -60,15 +46,15 @@
$nav = $this->buildIconNavView($project);
$nav->selectFilter("profile/{$id}/");
- $nav->appendChild($object_box);
- $nav->appendChild($timeline);
+ $crumbs = $this->buildApplicationCrumbs();
- return $this->buildApplicationPage(
- $nav,
- array(
- 'title' => $project->getName(),
- 'pageObjects' => array($project->getPHID()),
- ));
+ return $this->newPage()
+ ->setNavigation($nav)
+ ->setCrumbs($crumbs)
+ ->setTitle($project->getName())
+ ->setPageObjectPHIDs(array($project->getPHID()))
+ ->appendChild($object_box)
+ ->appendChild($timeline);
}
private function buildActionListView(PhabricatorProject $project) {
@@ -79,8 +65,7 @@
$view = id(new PhabricatorActionListView())
->setUser($viewer)
- ->setObject($project)
- ->setObjectURI($request->getRequestURI());
+ ->setObject($project);
$can_edit = PhabricatorPolicyFilter::hasCapability(
$viewer,
@@ -91,7 +76,7 @@
id(new PhabricatorActionView())
->setName(pht('Edit Details'))
->setIcon('fa-pencil')
- ->setHref($this->getApplicationURI("details/{$id}/")));
+ ->setHref($this->getApplicationURI("edit/{$id}/")));
$view->addAction(
id(new PhabricatorActionView())
@@ -217,5 +202,70 @@
return $view;
}
+ protected function loadProject() {
+ $viewer = $this->getViewer();
+ $request = $this->getRequest();
+
+ $id = $request->getURIData('id');
+ $slug = $request->getURIData('slug');
+
+ if ($slug) {
+ $normal_slug = PhabricatorSlug::normalizeProjectSlug($slug);
+ $is_abnormal = ($slug !== $normal_slug);
+ $normal_uri = "/tag/{$normal_slug}/";
+ } else {
+ $is_abnormal = false;
+ }
+
+ $query = id(new PhabricatorProjectQuery())
+ ->setViewer($viewer)
+ ->needMembers(true)
+ ->needWatchers(true)
+ ->needImages(true)
+ ->needSlugs(true);
+
+ if ($slug) {
+ $query->withSlugs(array($slug));
+ } else {
+ $query->withIDs(array($id));
+ }
+
+ $policy_exception = null;
+ try {
+ $project = $query->executeOne();
+ } catch (PhabricatorPolicyException $ex) {
+ $policy_exception = $ex;
+ $project = null;
+ }
+
+ if (!$project) {
+ // This project legitimately does not exist, so just 404 the user.
+ if (!$policy_exception) {
+ return new Aphront404Response();
+ }
+
+ // Here, the project exists but the user can't see it. If they are
+ // using a non-canonical slug to view the project, redirect to the
+ // canonical slug. If they're already using the canonical slug, rethrow
+ // the exception to give them the policy error.
+ if ($is_abnormal) {
+ return id(new AphrontRedirectResponse())->setURI($normal_uri);
+ } else {
+ throw $policy_exception;
+ }
+ }
+
+ // The user can view the project, but is using a noncanonical slug.
+ // Redirect to the canonical slug.
+ $primary_slug = $project->getPrimarySlug();
+ if ($slug && ($slug !== $primary_slug)) {
+ $primary_uri = "/tag/{$primary_slug}/";
+ return id(new AphrontRedirectResponse())->setURI($primary_uri);
+ }
+
+ $this->setProject($project);
+
+ return null;
+ }
}
diff --git a/src/controller/board/SprintBoardTaskEditController.php
b/src/controller/board/SprintBoardTaskEditController.php
index 60529d4..755e95f 100644
--- a/src/controller/board/SprintBoardTaskEditController.php
+++ b/src/controller/board/SprintBoardTaskEditController.php
@@ -3,782 +3,13 @@
final class SprintBoardTaskEditController 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();
- }
-
- $project = $this->getSprintProjectforTask($viewer, $projects);
-
- $tasks = id(new SprintBoardTaskCard())
- ->setViewer($viewer)
- ->setProject($project)
- ->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);
-
- $title = $header_name;
-
- return $this->newPage()
- ->setTitle($title)
- ->setCrumbs($crumbs)
- ->setPageObjectPHIDs($page_objects)
- ->appendChild(
- array(
- $form_box,
- $preview,
- ));
- }
-
- private function getSprintProjectforTask($viewer, $projects) {
- $project = null;
-
- if ($projects) {
- $query = id(new PhabricatorProjectQuery())
- ->setViewer($viewer)
- ->withPHIDs($projects);
- } else {
- return null;
- }
-
- $projects = $query->execute();
-
- foreach ($projects as $project) {
- $sprintquery = id(new SprintQuery())
- ->setPHID($project->getPHID());
- if ($sprintquery->getIsSprint()) {
- return $project;
- }
- }
-
+ return id(new SprintManiphestEditEngine())
+ ->setController($this)
+ ->addContextParameter('ungrippable')
+ ->addContextParameter('responseType')
+ ->addContextParameter('columnPHID')
+ ->addContextParameter('order')
+ ->buildResponse();
}
}
diff --git a/src/controller/board/SprintManiphestEditEngine.php
b/src/controller/board/SprintManiphestEditEngine.php
new file mode 100644
index 0000000..cce13c9
--- /dev/null
+++ b/src/controller/board/SprintManiphestEditEngine.php
@@ -0,0 +1,375 @@
+<?php
+
+final class SprintManiphestEditEngine
+ extends PhabricatorEditEngine {
+
+ const ENGINECONST = 'sprint.maniphest.task';
+
+ public function getEngineName() {
+ return pht('Maniphest Tasks');
+ }
+
+ public function getSummaryHeader() {
+ return pht('Configure Maniphest Task Forms');
+ }
+
+ public function getSummaryText() {
+ return pht('Configure how users create and edit tasks.');
+ }
+
+ public function getEngineApplicationClass() {
+ return 'PhabricatorManiphestApplication';
+ }
+
+ protected function newEditableObject() {
+ return ManiphestTask::initializeNewTask($this->getViewer());
+ }
+
+ protected function newObjectQuery() {
+ return id(new ManiphestTaskQuery());
+ }
+
+ protected function getObjectCreateTitleText($object) {
+ return pht('Create New Task');
+ }
+
+ protected function getObjectEditTitleText($object) {
+ return pht('Edit %s %s', $object->getMonogram(), $object->getTitle());
+ }
+
+ protected function getObjectEditShortText($object) {
+ return $object->getMonogram();
+ }
+
+ protected function getObjectCreateShortText() {
+ return pht('Create Task');
+ }
+
+ protected function getEditorURI() {
+ return $this->getApplication()->getApplicationURI('task/edit/');
+ }
+
+ protected function getCommentViewHeaderText($object) {
+ return pht('Weigh In');
+ }
+
+ protected function getCommentViewButtonText($object) {
+ return pht('Set Sail for Adventure');
+ }
+
+ protected function getObjectViewURI($object) {
+ return '/'.$object->getMonogram();
+ }
+
+ protected function buildCustomEditFields($object) {
+ $status_map = $this->getTaskStatusMap($object);
+ $priority_map = $this->getTaskPriorityMap($object);
+
+ if ($object->isClosed()) {
+ $default_status = ManiphestTaskStatus::getDefaultStatus();
+ } else {
+ $default_status = ManiphestTaskStatus::getDefaultClosedStatus();
+ }
+
+ if ($object->getOwnerPHID()) {
+ $owner_value = array($object->getOwnerPHID());
+ } else {
+ $owner_value = array($this->getViewer()->getPHID());
+ }
+
+ return array(
+ id(new PhabricatorHandlesEditField())
+ ->setKey('parent')
+ ->setLabel(pht('Parent Task'))
+ ->setDescription(pht('Task to make this a subtask of.'))
+ ->setConduitDescription(pht('Create as a subtask of another
task.'))
+ ->setConduitTypeDescription(pht('PHID of the parent task.'))
+ ->setAliases(array('parentPHID'))
+ ->setTransactionType(ManiphestTransaction::TYPE_PARENT)
+ ->setHandleParameterType(new ManiphestTaskListHTTPParameterType())
+ ->setSingleValue(null)
+ ->setIsReorderable(false)
+ ->setIsDefaultable(false)
+ ->setIsLockable(false),
+ id(new PhabricatorHandlesEditField())
+ ->setKey('column')
+ ->setLabel(pht('Column'))
+ ->setDescription(pht('Workboard column to create this task into.'))
+ ->setConduitDescription(pht('Create into a workboard column.'))
+ ->setConduitTypeDescription(pht('PHID of workboard column.'))
+ ->setAliases(array('columnPHID'))
+ ->setTransactionType(ManiphestTransaction::TYPE_COLUMN)
+ ->setSingleValue(null)
+ ->setIsInvisible(true)
+ ->setIsReorderable(false)
+ ->setIsDefaultable(false)
+ ->setIsLockable(false),
+ id(new PhabricatorTextEditField())
+ ->setKey('title')
+ ->setLabel(pht('Title'))
+ ->setDescription(pht('Name of the task.'))
+ ->setConduitDescription(pht('Rename the task.'))
+ ->setConduitTypeDescription(pht('New task name.'))
+ ->setTransactionType(ManiphestTransaction::TYPE_TITLE)
+ ->setIsRequired(true)
+ ->setValue($object->getTitle()),
+ id(new PhabricatorUsersEditField())
+ ->setKey('owner')
+ ->setAliases(array('ownerPHID', 'assign', 'assigned'))
+ ->setLabel(pht('Assigned To'))
+ ->setDescription(pht('User who is responsible for the task.'))
+ ->setConduitDescription(pht('Reassign the task.'))
+ ->setConduitTypeDescription(
+ pht('New task owner, or `null` to unassign.'))
+ ->setTransactionType(ManiphestTransaction::TYPE_OWNER)
+ ->setIsCopyable(true)
+ ->setSingleValue($object->getOwnerPHID())
+ ->setCommentActionLabel(pht('Assign / Claim'))
+ ->setCommentActionValue($owner_value),
+ id(new PhabricatorSelectEditField())
+ ->setKey('status')
+ ->setLabel(pht('Status'))
+ ->setDescription(pht('Status of the task.'))
+ ->setConduitDescription(pht('Change the task status.'))
+ ->setConduitTypeDescription(pht('New task status constant.'))
+ ->setTransactionType(ManiphestTransaction::TYPE_STATUS)
+ ->setIsCopyable(true)
+ ->setValue($object->getStatus())
+ ->setOptions($status_map)
+ ->setCommentActionLabel(pht('Change Status'))
+ ->setCommentActionValue($default_status),
+ id(new PhabricatorSelectEditField())
+ ->setKey('priority')
+ ->setLabel(pht('Priority'))
+ ->setDescription(pht('Priority of the task.'))
+ ->setConduitDescription(pht('Change the priority of the task.'))
+ ->setConduitTypeDescription(pht('New task priority constant.'))
+ ->setTransactionType(ManiphestTransaction::TYPE_PRIORITY)
+ ->setIsCopyable(true)
+ ->setValue($object->getPriority())
+ ->setOptions($priority_map)
+ ->setCommentActionLabel(pht('Change Priority')),
+ id(new PhabricatorRemarkupEditField())
+ ->setKey('description')
+ ->setLabel(pht('Description'))
+ ->setDescription(pht('Task description.'))
+ ->setConduitDescription(pht('Update the task description.'))
+ ->setConduitTypeDescription(pht('New task description.'))
+ ->setTransactionType(ManiphestTransaction::TYPE_DESCRIPTION)
+ ->setValue($object->getDescription())
+ ->setPreviewPanel(
+ id(new PHUIRemarkupPreviewPanel())
+ ->setHeader(pht('Description Preview'))),
+ );
+ }
+
+ private function getTaskStatusMap(ManiphestTask $task) {
+ $status_map = ManiphestTaskStatus::getTaskStatusMap();
+
+ $current_status = $task->getStatus();
+
+ // If the current status is something we don't recognize (maybe an older
+ // status which was deleted), put a dummy entry in the status map so that
+ // saving the form doesn't destroy any data by accident.
+ if (idx($status_map, $current_status) === null) {
+ $status_map[$current_status] = pht('<Unknown: %s>', $current_status);
+ }
+
+ $dup_status = ManiphestTaskStatus::getDuplicateStatus();
+ foreach ($status_map as $status => $status_name) {
+ // Always keep the task's current status.
+ if ($status == $current_status) {
+ continue;
+ }
+
+ // Don't allow tasks to be changed directly into "Closed, Duplicate"
+ // status. Instead, you have to merge them. See T4819.
+ if ($status == $dup_status) {
+ unset($status_map[$status]);
+ continue;
+ }
+
+ // Don't let new or existing tasks be moved into a disabled status.
+ if (ManiphestTaskStatus::isDisabledStatus($status)) {
+ unset($status_map[$status]);
+ continue;
+ }
+ }
+
+ return $status_map;
+ }
+
+ private function getTaskPriorityMap(ManiphestTask $task) {
+ $priority_map = ManiphestTaskPriority::getTaskPriorityMap();
+ $current_priority = $task->getPriority();
+
+ // If the current value isn't a legitimate one, put it in the dropdown
+ // anyway so saving the form doesn't cause a side effects.
+ if (idx($priority_map, $current_priority) === null) {
+ $priority_map[$current_priority] = pht(
+ '<Unknown: %s>',
+ $current_priority);
+ }
+
+ foreach ($priority_map as $priority => $priority_name) {
+ // Always keep the current priority.
+ if ($priority == $current_priority) {
+ continue;
+ }
+
+ if (ManiphestTaskPriority::isDisabledPriority($priority)) {
+ unset($priority_map[$priority]);
+ continue;
+ }
+ }
+
+ return $priority_map;
+ }
+
+ protected function newEditResponse(
+ AphrontRequest $request,
+ $object,
+ array $xactions) {
+
+ if ($request->isAjax()) {
+ // Reload the task to make sure we pick up the final task state.
+ $viewer = $this->getViewer();
+ $task = id(new ManiphestTaskQuery())
+ ->setViewer($viewer)
+ ->withIDs(array($object->getID()))
+ ->needSubscriberPHIDs(true)
+ ->needProjectPHIDs(true)
+ ->executeOne();
+
+ switch ($request->getStr('responseType')) {
+ case 'card':
+ return $this->buildCardResponse($task);
+ default:
+ return $this->buildListResponse($task);
+ }
+
+ }
+
+ return parent::newEditResponse($request, $object, $xactions);
+ }
+
+ private function buildListResponse(ManiphestTask $task) {
+ $controller = $this->getController();
+
+ $payload = array(
+ 'tasks' => $controller->renderSingleTask($task),
+ 'data' => array(),
+ );
+
+ return id(new AphrontAjaxResponse())->setContent($payload);
+ }
+
+ private function buildCardResponse(ManiphestTask $task) {
+ $controller = $this->getController();
+ $request = $controller->getRequest();
+ $viewer = $request->getViewer();
+
+ $column_phid = $request->getStr('columnPHID');
+ $order = $request->getStr('order');
+
+ $column = id(new PhabricatorProjectColumnQuery())
+ ->setViewer($viewer)
+ ->withPHIDs(array($column_phid))
+ ->executeOne();
+ if (!$column) {
+ return new Aphront404Response();
+ }
+
+ // If the workboard's project has been removed from the card's project
+ // list, we are going to remove it from the board completely.
+ $project_map = array_fuse($task->getProjectPHIDs());
+ $remove_card = empty($project_map[$column->getProjectPHID()]);
+
+ $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(
+ 'removeFromBoard' => $remove_card,
+ 'sortMap' => $sort_map,
+ );
+
+ // TODO: This should just use HandlePool once we get through the EditEngine
+ // transition.
+ $owner = null;
+ if ($task->getOwnerPHID()) {
+ $owner = id(new PhabricatorHandleQuery())
+ ->setViewer($viewer)
+ ->withPHIDs(array($task->getOwnerPHID()))
+ ->executeOne();
+ }
+
+ $projects = $request->getArr('projectPHIDs');
+ $project = $this->getSprintProjectforTask($viewer, $projects);
+
+ $tasks = id(new SprintBoardTaskCard())
+ ->setViewer($viewer)
+ ->setProject($project)
+ ->setTask($task)
+ ->setOwner($owner)
+ ->setCanEdit(true)
+ ->getItem();
+
+ $payload = array(
+ 'tasks' => $tasks,
+ 'data' => $data,
+ );
+
+ return id(new AphrontAjaxResponse())->setContent($payload);
+ }
+
+ private function getSprintProjectforTask($viewer, $projects) {
+ $project = null;
+
+ if ($projects) {
+ $query = id(new PhabricatorProjectQuery())
+ ->setViewer($viewer)
+ ->withPHIDs($projects);
+ } else {
+ return null;
+ }
+
+ $projects = $query->execute();
+
+ foreach ($projects as $project) {
+ $sprintquery = id(new SprintQuery())
+ ->setPHID($project->getPHID());
+ if ($sprintquery->getIsSprint()) {
+ return $project;
+ }
+ }
+
+ }
+
+
+}
--
To view, visit https://gerrit.wikimedia.org/r/261185
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I418d643a0949599ad507071fb14ffb3ff89bf102
Gerrit-PatchSet: 1
Gerrit-Project: phabricator/extensions/Sprint
Gerrit-Branch: master
Gerrit-Owner: Christopher Johnson (WMDE) <[email protected]>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits