Skip to content
Snippets Groups Projects
Commit 26285a09 authored by Christopher Johnson's avatar Christopher Johnson
Browse files

fixes several upstream breaking changes

current with 10ed33052361be82cbc09884118d65ec0601bd55 27.12.2015
See upstream task_T9905

Bug: T122486

Change-Id: I418d643a0949599ad507071fb14ffb3ff89bf102
parent 94442527
No related branches found
No related tags found
No related merge requests found
......@@ -61,7 +61,9 @@ phutil_register_library_map(array(
'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 @@ phutil_register_library_map(array(
'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',
......
......@@ -72,8 +72,8 @@ final class SprintApplication extends PhabricatorApplication {
// 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*)/'
......
......@@ -21,7 +21,7 @@ abstract class SprintConduitAPIMethod extends ConduitAPIMethod {
$project_slugs = $project->getSlugs();
$project_slugs = array_values(mpull($project_slugs, 'getSlug'));
$issprint = $this->isSprint($project->getPHID());
$project_icon = PhabricatorProjectIcon::getAPIName($project->getIcon());
$project_icon = substr($project->getIcon(), 3);
$result[$project->getPHID()] = array(
'id' => $project->getID(),
......@@ -55,7 +55,7 @@ abstract class SprintConduitAPIMethod extends ConduitAPIMethod {
$project_slugs = $project->getSlugs();
$project_slugs = array_values(mpull($project_slugs, 'getSlug'));
$issprint = $this->isSprint($project->getPHID());
$project_icon = PhabricatorProjectIcon::getAPIName($project->getIcon());
$project_icon = substr($project->getIcon(), 3);
$result[$project->getPHID()] = array(
'id' => $project->getID(),
......
......@@ -24,7 +24,7 @@ abstract class SprintController extends PhabricatorController {
}
public function buildApplicationMenu() {
return $this->buildSideNavView($this->getUser(),
return $this->buildSprintNavView($this->getUser(),
$this->setApplicationURI(), true)->getMenu();
}
......@@ -45,7 +45,7 @@ abstract class SprintController extends PhabricatorController {
/**
* @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');
......@@ -169,10 +169,11 @@ abstract class SprintController extends PhabricatorController {
$nav->addIcon("feed/{$id}/", pht('Feed'), 'fa-newspaper-o', null, null);
$nav->addIcon("members/{$id}/", pht('Members'), 'fa-group', null, null);
$nav->addIcon("details/{$id}/", pht('Edit Details'), 'fa-pencil', null, null);
$nav->addIcon("edit/{$id}/", pht('Edit Details'), 'fa-pencil', null, null);
return $nav;
}
protected function isSprint($object) {
$validator = new SprintValidator();
$issprint = call_user_func(array($validator, 'checkForSprint'),
......@@ -182,7 +183,7 @@ abstract class SprintController extends PhabricatorController {
public function getErrorBox($e) {
$error_box = id(new PHUIInfoView())
->setTitle(pht('Burndown could not be rendered for this project'))
->setTitle(pht('Sprint could not be rendered for this project'))
->setErrors(array($e->getMessage()));
return $error_box;
}
......
<?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;
}
}
<?php
final class SprintProjectProfileController
extends SprintController {
extends SprintProjectController {
public function shouldAllowPublic() {
return true;
......@@ -10,28 +10,14 @@ final class SprintProjectProfileController
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));
}
$project = $query->executeOne();
if (!$project) {
return new Aphront404Response();
}
if ($slug && $slug != $project->getPrimarySlug()) {
return id(new AphrontRedirectResponse())
->setURI('/tag/'.$project->getPrimarySlug().'/');
$response = $this->loadProject();
if ($response) {
return $response;
}
$project = $this->getProject();
$id = $project->getID();
$picture = $project->getProfileImageURI();
$header = id(new PHUIHeaderView())
......@@ -60,15 +46,15 @@ final class SprintProjectProfileController
$nav = $this->buildIconNavView($project);
$nav->selectFilter("profile/{$id}/");
$nav->appendChild($object_box);
$nav->appendChild($timeline);
return $this->buildApplicationPage(
$nav,
array(
'title' => $project->getName(),
'pageObjects' => array($project->getPHID()),
));
$crumbs = $this->buildApplicationCrumbs();
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 @@ final class SprintProjectProfileController
$view = id(new PhabricatorActionListView())
->setUser($viewer)
->setObject($project)
->setObjectURI($request->getRequestURI());
->setObject($project);
$can_edit = PhabricatorPolicyFilter::hasCapability(
$viewer,
......@@ -91,7 +76,7 @@ final class SprintProjectProfileController
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())
......@@ -216,6 +201,4 @@ final class SprintProjectProfileController
return $view;
}
}
This diff is collapsed.
<?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;
}
}
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment