public function getItem()
 {
     $task = $this->getTask();
     $owner = $this->getOwner();
     $can_edit = $this->getCanEdit();
     $viewer = $this->getViewer();
     $color_map = ManiphestTaskPriority::getColorMap();
     $bar_color = idx($color_map, $task->getPriority(), 'grey');
     $card = id(new PHUIObjectItemView())->setObject($task)->setUser($viewer)->setObjectName('T' . $task->getID())->setHeader($task->getTitle())->setGrippable($can_edit)->setHref('/T' . $task->getID())->addSigil('project-card')->setDisabled($task->isClosed())->addAction(id(new PHUIListItemView())->setName(pht('Edit'))->setIcon('fa-pencil')->addSigil('edit-project-card')->setHref('/maniphest/task/edit/' . $task->getID() . '/'))->setBarColor($bar_color);
     if ($owner) {
         $card->addHandleIcon($owner, $owner->getName());
     }
     $cover_file = $this->getCoverImageFile();
     if ($cover_file) {
         $card->setCoverImage($cover_file->getBestURI());
     }
     if (ManiphestTaskPoints::getIsEnabled()) {
         $points = $task->getPoints();
         if ($points !== null) {
             $points_tag = id(new PHUITagView())->setType(PHUITagView::TYPE_SHADE)->setShade(PHUITagView::COLOR_GREY)->setSlimShady(true)->setName($points)->addClass('phui-workcard-points');
             $card->addAttribute($points_tag);
         }
     }
     if ($task->isClosed()) {
         $icon = ManiphestTaskStatus::getStatusIcon($task->getStatus());
         $icon = id(new PHUIIconView())->setIcon($icon . ' grey');
         $card->addAttribute($icon);
         $card->setBarColor('grey');
     }
     $project_handles = $this->getProjectHandles();
     // Remove any archived projects from the list.
     if ($project_handles) {
         foreach ($project_handles as $key => $handle) {
             if ($handle->getStatus() == PhabricatorObjectHandle::STATUS_CLOSED) {
                 unset($project_handles[$key]);
             }
         }
     }
     if ($project_handles) {
         $project_handles = array_reverse($project_handles);
         $tag_list = id(new PHUIHandleTagListView())->setSlim(true)->setHandles($project_handles);
         $card->addAttribute($tag_list);
     }
     $card->addClass('phui-workcard');
     return $card;
 }
 private function buildHeaderView(ManiphestTask $task)
 {
     $view = id(new PHUIHeaderView())->setHeader($task->getTitle())->setUser($this->getRequest()->getUser())->setPolicyObject($task);
     $priority_name = ManiphestTaskPriority::getTaskPriorityName($task->getPriority());
     $priority_color = ManiphestTaskPriority::getTaskPriorityColor($task->getPriority());
     $status = $task->getStatus();
     $status_name = ManiphestTaskStatus::renderFullDescription($status, $priority_name, $priority_color);
     $view->addProperty(PHUIHeaderView::PROPERTY_STATUS, $status_name);
     $view->setHeaderIcon(ManiphestTaskStatus::getStatusIcon($task->getStatus()) . ' ' . $priority_color);
     if (ManiphestTaskPoints::getIsEnabled()) {
         $points = $task->getPoints();
         if ($points !== null) {
             $points_name = pht('%s %s', $task->getPoints(), ManiphestTaskPoints::getPointsLabel());
             $tag = id(new PHUITagView())->setName($points_name)->setShade('blue')->setType(PHUITagView::TYPE_SHADE);
             $view->addTag($tag);
         }
     }
     return $view;
 }
 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());
     }
     $fields = 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')));
     if (ManiphestTaskPoints::getIsEnabled()) {
         $points_label = ManiphestTaskPoints::getPointsLabel();
         $action_label = ManiphestTaskPoints::getPointsActionLabel();
         $fields[] = id(new PhabricatorPointsEditField())->setKey('points')->setLabel($points_label)->setDescription(pht('Point value of the task.'))->setConduitDescription(pht('Change the task point value.'))->setConduitTypeDescription(pht('New task point value.'))->setTransactionType(ManiphestTransaction::TYPE_POINTS)->setIsCopyable(true)->setValue($object->getPoints())->setCommentActionLabel($action_label);
     }
     $fields[] = 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')));
     return $fields;
 }
 public function validateOption(PhabricatorConfigOption $option, $value)
 {
     ManiphestTaskPoints::validateConfiguration($value);
 }
 protected function newNavigationMenuItems(PhabricatorProfilePanelConfiguration $config)
 {
     $viewer = $this->getViewer();
     $project = $config->getProfileObject();
     $limit = 250;
     $tasks = id(new ManiphestTaskQuery())->setViewer($viewer)->withEdgeLogicPHIDs(PhabricatorProjectObjectHasProjectEdgeType::EDGECONST, PhabricatorQueryConstraint::OPERATOR_AND, array($project->getPHID()))->setLimit($limit + 1)->execute();
     if (count($tasks) > $limit) {
         return $this->renderError(pht('Too many tasks to compute statistics for (more than %s).', new PhutilNumber($limit)));
     }
     if (!$tasks) {
         return $this->renderError(pht('This milestone has no tasks yet.'));
     }
     $statuses = array();
     $points_done = 0;
     $points_total = 0;
     $no_points = 0;
     foreach ($tasks as $task) {
         $points = $task->getPoints();
         if ($points === null) {
             $no_points++;
             continue;
         }
         if (!$points) {
             continue;
         }
         $status = $task->getStatus();
         if (empty($statuses[$status])) {
             $statuses[$status] = 0;
         }
         $statuses[$status] += $points;
         if (ManiphestTaskStatus::isClosedStatus($status)) {
             $points_done += $points;
         }
         $points_total += $points;
     }
     if ($no_points == count($tasks)) {
         return $this->renderError(pht('No tasks have assigned point values.'));
     }
     if (!$points_total) {
         return $this->renderError(pht('All tasks with assigned point values are worth zero points.'));
     }
     $label = pht('%s of %s %s', new PhutilNumber($points_done), new PhutilNumber($points_total), ManiphestTaskPoints::getPointsLabel());
     $bar = id(new PHUISegmentBarView())->setLabel($label);
     $map = ManiphestTaskStatus::getTaskStatusMap();
     $statuses = array_select_keys($statuses, array_keys($map));
     foreach ($statuses as $status => $points) {
         if (!$points) {
             continue;
         }
         if (!ManiphestTaskStatus::isClosedStatus($status)) {
             continue;
         }
         $color = ManiphestTaskStatus::getStatusColor($status);
         if (!$color) {
             $color = 'sky';
         }
         $tooltip = pht('%s %s', new PhutilNumber($points), ManiphestTaskStatus::getTaskStatusName($status));
         $bar->newSegment()->setWidth($points / $points_total)->setColor($color)->setTooltip($tooltip);
     }
     $bar = phutil_tag('div', array('class' => 'phui-profile-segment-bar'), $bar);
     $item = $this->newItem()->appendChild($bar);
     return array($item);
 }
 public function handleRequest(AphrontRequest $request)
 {
     $viewer = $request->getUser();
     $response = $this->loadProject();
     if ($response) {
         return $response;
     }
     $project = $this->getProject();
     $this->readRequestState();
     $board_uri = $this->getApplicationURI('board/' . $project->getID() . '/');
     $search_engine = id(new ManiphestTaskSearchEngine())->setViewer($viewer)->setBaseURI($board_uri)->setIsBoardView(true);
     if ($request->isFormPost() && !$request->getBool('initialize')) {
         $saved = $search_engine->buildSavedQueryFromRequest($request);
         $search_engine->saveQuery($saved);
         $filter_form = id(new AphrontFormView())->setUser($viewer);
         $search_engine->buildSearchForm($filter_form, $saved);
         if ($search_engine->getErrors()) {
             return $this->newDialog()->setWidth(AphrontDialogView::WIDTH_FULL)->setTitle(pht('Advanced Filter'))->appendChild($filter_form->buildLayoutView())->setErrors($search_engine->getErrors())->setSubmitURI($board_uri)->addSubmitButton(pht('Apply Filter'))->addCancelButton($board_uri);
         }
         return id(new AphrontRedirectResponse())->setURI($this->getURIWithState($search_engine->getQueryResultsPageURI($saved->getQueryKey())));
     }
     $query_key = $request->getURIData('queryKey');
     if (!$query_key) {
         $query_key = 'open';
     }
     $this->queryKey = $query_key;
     $custom_query = null;
     if ($search_engine->isBuiltinQuery($query_key)) {
         $saved = $search_engine->buildSavedQueryFromBuiltin($query_key);
     } else {
         $saved = id(new PhabricatorSavedQueryQuery())->setViewer($viewer)->withQueryKeys(array($query_key))->executeOne();
         if (!$saved) {
             return new Aphront404Response();
         }
         $custom_query = $saved;
     }
     if ($request->getURIData('filter')) {
         $filter_form = id(new AphrontFormView())->setUser($viewer);
         $search_engine->buildSearchForm($filter_form, $saved);
         return $this->newDialog()->setWidth(AphrontDialogView::WIDTH_FULL)->setTitle(pht('Advanced Filter'))->appendChild($filter_form->buildLayoutView())->setSubmitURI($board_uri)->addSubmitButton(pht('Apply Filter'))->addCancelButton($board_uri);
     }
     $task_query = $search_engine->buildQueryFromSavedQuery($saved);
     $select_phids = array($project->getPHID());
     if ($project->getHasSubprojects() || $project->getHasMilestones()) {
         $descendants = id(new PhabricatorProjectQuery())->setViewer($viewer)->withAncestorProjectPHIDs($select_phids)->execute();
         foreach ($descendants as $descendant) {
             $select_phids[] = $descendant->getPHID();
         }
     }
     $tasks = $task_query->withEdgeLogicPHIDs(PhabricatorProjectObjectHasProjectEdgeType::EDGECONST, PhabricatorQueryConstraint::OPERATOR_ANCESTOR, array($select_phids))->setOrder(ManiphestTaskQuery::ORDER_PRIORITY)->setViewer($viewer)->execute();
     $tasks = mpull($tasks, null, 'getPHID');
     $board_phid = $project->getPHID();
     $layout_engine = id(new PhabricatorBoardLayoutEngine())->setViewer($viewer)->setBoardPHIDs(array($board_phid))->setObjectPHIDs(array_keys($tasks))->setFetchAllBoards(true)->executeLayout();
     $columns = $layout_engine->getColumns($board_phid);
     if (!$columns || !$project->getHasWorkboard()) {
         $has_normal_columns = false;
         foreach ($columns as $column) {
             if (!$column->getProxyPHID()) {
                 $has_normal_columns = true;
                 break;
             }
         }
         $can_edit = PhabricatorPolicyFilter::hasCapability($viewer, $project, PhabricatorPolicyCapability::CAN_EDIT);
         if (!$has_normal_columns) {
             if (!$can_edit) {
                 $content = $this->buildNoAccessContent($project);
             } else {
                 $content = $this->buildInitializeContent($project);
             }
         } else {
             if (!$can_edit) {
                 $content = $this->buildDisabledContent($project);
             } else {
                 $content = $this->buildEnableContent($project);
             }
         }
         if ($content instanceof AphrontResponse) {
             return $content;
         }
         $nav = $this->getProfileMenu();
         $nav->selectFilter(PhabricatorProject::PANEL_WORKBOARD);
         $crumbs = $this->buildApplicationCrumbs();
         $crumbs->addTextCrumb(pht('Workboard'));
         return $this->newPage()->setTitle(array($project->getDisplayName(), pht('Workboard')))->setNavigation($nav)->setCrumbs($crumbs)->appendChild($content);
     }
     $task_can_edit_map = id(new PhabricatorPolicyFilter())->setViewer($viewer)->requireCapabilities(array(PhabricatorPolicyCapability::CAN_EDIT))->apply($tasks);
     // If this is a batch edit, select the editable tasks in the chosen column
     // and ship the user into the batch editor.
     $batch_edit = $request->getStr('batch');
     if ($batch_edit) {
         if ($batch_edit !== self::BATCH_EDIT_ALL) {
             $column_id_map = mpull($columns, null, 'getID');
             $batch_column = idx($column_id_map, $batch_edit);
             if (!$batch_column) {
                 return new Aphront404Response();
             }
             $batch_task_phids = $layout_engine->getColumnObjectPHIDs($board_phid, $batch_column->getPHID());
             foreach ($batch_task_phids as $key => $batch_task_phid) {
                 if (empty($task_can_edit_map[$batch_task_phid])) {
                     unset($batch_task_phids[$key]);
                 }
             }
             $batch_tasks = array_select_keys($tasks, $batch_task_phids);
         } else {
             $batch_tasks = $task_can_edit_map;
         }
         if (!$batch_tasks) {
             $cancel_uri = $this->getURIWithState($board_uri);
             return $this->newDialog()->setTitle(pht('No Editable Tasks'))->appendParagraph(pht('The selected column contains no visible tasks which you ' . 'have permission to edit.'))->addCancelButton($board_uri);
         }
         $batch_ids = mpull($batch_tasks, 'getID');
         $batch_ids = implode(',', $batch_ids);
         $batch_uri = new PhutilURI('/maniphest/batch/');
         $batch_uri->setQueryParam('board', $this->id);
         $batch_uri->setQueryParam('batch', $batch_ids);
         return id(new AphrontRedirectResponse())->setURI($batch_uri);
     }
     $board_id = celerity_generate_unique_node_id();
     $board = id(new PHUIWorkboardView())->setUser($viewer)->setID($board_id)->addSigil('jx-workboard')->setMetadata(array('boardPHID' => $project->getPHID()));
     $visible_columns = array();
     $column_phids = array();
     $visible_phids = array();
     foreach ($columns as $column) {
         if (!$this->showHidden) {
             if ($column->isHidden()) {
                 continue;
             }
         }
         $proxy = $column->getProxy();
         if ($proxy && !$proxy->isMilestone()) {
             // TODO: For now, don't show subproject columns because we can't
             // handle tasks with multiple positions yet.
             continue;
         }
         $task_phids = $layout_engine->getColumnObjectPHIDs($board_phid, $column->getPHID());
         $column_tasks = array_select_keys($tasks, $task_phids);
         // If we aren't using "natural" order, reorder the column by the original
         // query order.
         if ($this->sortKey != PhabricatorProjectColumn::ORDER_NATURAL) {
             $column_tasks = array_select_keys($column_tasks, array_keys($tasks));
         }
         $column_phid = $column->getPHID();
         $visible_columns[$column_phid] = $column;
         $column_phids[$column_phid] = $column_tasks;
         foreach ($column_tasks as $phid => $task) {
             $visible_phids[$phid] = $phid;
         }
     }
     $rendering_engine = id(new PhabricatorBoardRenderingEngine())->setViewer($viewer)->setObjects(array_select_keys($tasks, $visible_phids))->setEditMap($task_can_edit_map)->setExcludedProjectPHIDs($select_phids);
     $templates = array();
     $column_maps = array();
     $all_tasks = array();
     foreach ($visible_columns as $column_phid => $column) {
         $column_tasks = $column_phids[$column_phid];
         $panel = id(new PHUIWorkpanelView())->setHeader($column->getDisplayName())->setSubHeader($column->getDisplayType())->addSigil('workpanel');
         $proxy = $column->getProxy();
         if ($proxy) {
             $proxy_id = $proxy->getID();
             $href = $this->getApplicationURI("view/{$proxy_id}/");
             $panel->setHref($href);
         }
         $header_icon = $column->getHeaderIcon();
         if ($header_icon) {
             $panel->setHeaderIcon($header_icon);
         }
         $display_class = $column->getDisplayClass();
         if ($display_class) {
             $panel->addClass($display_class);
         }
         if ($column->isHidden()) {
             $panel->addClass('project-panel-hidden');
         }
         $column_menu = $this->buildColumnMenu($project, $column);
         $panel->addHeaderAction($column_menu);
         $count_tag = id(new PHUITagView())->setType(PHUITagView::TYPE_SHADE)->setShade(PHUITagView::COLOR_BLUE)->addSigil('column-points')->setName(javelin_tag('span', array('sigil' => 'column-points-content'), pht('-')))->setStyle('display: none');
         $panel->setHeaderTag($count_tag);
         $cards = id(new PHUIObjectItemListView())->setUser($viewer)->setFlush(true)->setAllowEmptyList(true)->addSigil('project-column')->setItemClass('phui-workcard')->setMetadata(array('columnPHID' => $column->getPHID(), 'pointLimit' => $column->getPointLimit()));
         foreach ($column_tasks as $task) {
             $object_phid = $task->getPHID();
             $card = $rendering_engine->renderCard($object_phid);
             $templates[$object_phid] = hsprintf('%s', $card->getItem());
             $column_maps[$column_phid][] = $object_phid;
             $all_tasks[$object_phid] = $task;
         }
         $panel->setCards($cards);
         $board->addPanel($panel);
     }
     $behavior_config = array('moveURI' => $this->getApplicationURI('move/' . $project->getID() . '/'), 'createURI' => $this->getCreateURI(), 'uploadURI' => '/file/dropupload/', 'coverURI' => $this->getApplicationURI('cover/'), 'chunkThreshold' => PhabricatorFileStorageEngine::getChunkThreshold(), 'pointsEnabled' => ManiphestTaskPoints::getIsEnabled(), 'boardPHID' => $project->getPHID(), 'order' => $this->sortKey, 'templateMap' => $templates, 'columnMaps' => $column_maps, 'orderMaps' => mpull($all_tasks, 'getWorkboardOrderVectors'), 'propertyMaps' => mpull($all_tasks, 'getWorkboardProperties'), 'boardID' => $board_id, 'projectPHID' => $project->getPHID());
     $this->initBehavior('project-boards', $behavior_config);
     $sort_menu = $this->buildSortMenu($viewer, $this->sortKey);
     $filter_menu = $this->buildFilterMenu($viewer, $custom_query, $search_engine, $query_key);
     $manage_menu = $this->buildManageMenu($project, $this->showHidden);
     $header_link = phutil_tag('a', array('href' => $this->getApplicationURI('profile/' . $project->getID() . '/')), $project->getName());
     $board_box = id(new PHUIBoxView())->appendChild($board)->addClass('project-board-wrapper');
     $nav = $this->getProfileMenu();
     $divider = id(new PHUIListItemView())->setType(PHUIListItemView::TYPE_DIVIDER);
     $fullscreen = $this->buildFullscreenMenu();
     $crumbs = $this->buildApplicationCrumbs();
     $crumbs->addTextCrumb(pht('Workboard'));
     $crumbs->setBorder(true);
     $crumbs->addAction($sort_menu);
     $crumbs->addAction($filter_menu);
     $crumbs->addAction($divider);
     $crumbs->addAction($manage_menu);
     $crumbs->addAction($fullscreen);
     return $this->newPage()->setTitle(array($project->getDisplayName(), pht('Workboard')))->setPageObjectPHIDs(array($project->getPHID()))->setShowFooter(false)->setNavigation($nav)->setCrumbs($crumbs)->addQuicksandConfig(array('boardConfig' => $behavior_config))->appendChild(array($board_box));
 }
 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);
     $owner_phid = $task->getOwnerPHID();
     if ($owner_phid) {
         $assigned_to = $handles->renderHandle($owner_phid)->setShowHovercard(true);
     } else {
         $assigned_to = phutil_tag('em', array(), pht('None'));
     }
     $view->addProperty(pht('Assigned To'), $assigned_to);
     $view->addProperty(pht('Priority'), ManiphestTaskPriority::getTaskPriorityName($task->getPriority()));
     $author = $handles->renderHandle($task->getAuthorPHID())->setShowHovercard(true);
     $view->addProperty(pht('Author'), $author);
     if (ManiphestTaskPoints::getIsEnabled()) {
         $points = $task->getPoints();
         if ($points !== null) {
             $view->addProperty(ManiphestTaskPoints::getPointsLabel(), $task->getPoints());
         }
     }
     $source = $task->getOriginalEmailSource();
     if ($source) {
         $subject = '[T' . $task->getID() . '] ' . $task->getTitle();
         $view->addProperty(pht('From Email'), phutil_tag('a', array('href' => 'mailto:' . $source . '?subject=' . $subject), $source));
     }
     $edge_types = array(ManiphestTaskDependedOnByTaskEdgeType::EDGECONST => pht('Blocks'), ManiphestTaskDependsOnTaskEdgeType::EDGECONST => pht('Blocked By'), ManiphestTaskHasRevisionEdgeType::EDGECONST => pht('Differential Revisions'), ManiphestTaskHasMockEdgeType::EDGECONST => pht('Pholio Mocks'));
     $revisions_commits = array();
     $commit_phids = array_keys($edges[ManiphestTaskHasCommitEdgeType::EDGECONST]);
     if ($commit_phids) {
         $commit_drev = DiffusionCommitHasRevisionEdgeType::EDGECONST;
         $drev_edges = id(new PhabricatorEdgeQuery())->withSourcePHIDs($commit_phids)->withEdgeTypes(array($commit_drev))->execute();
         foreach ($commit_phids as $phid) {
             $revisions_commits[$phid] = $handles->renderHandle($phid)->setShowHovercard(true);
             $revision_phid = key($drev_edges[$phid][$commit_drev]);
             $revision_handle = $handles->getHandleIfExists($revision_phid);
             if ($revision_handle) {
                 $task_drev = ManiphestTaskHasRevisionEdgeType::EDGECONST;
                 unset($edges[$task_drev][$revision_phid]);
                 $revisions_commits[$phid] = hsprintf('%s / %s', $revision_handle->renderHovercardLink($revision_handle->getName()), $revisions_commits[$phid]);
             }
         }
     }
     foreach ($edge_types as $edge_type => $edge_name) {
         if ($edges[$edge_type]) {
             $edge_handles = $viewer->loadHandles(array_keys($edges[$edge_type]));
             $view->addProperty($edge_name, $edge_handles->renderList());
         }
     }
     if ($revisions_commits) {
         $view->addProperty(pht('Commits'), phutil_implode_html(phutil_tag('br'), $revisions_commits));
     }
     $view->invokeWillRenderEvent();
     $field_list->appendFieldsToPropertyList($task, $viewer, $view);
     return $view;
 }
 public function shouldHide()
 {
     switch ($this->getTransactionType()) {
         case PhabricatorTransactions::TYPE_EDGE:
             $commit_phid = $this->getMetadataValue('commitPHID');
             $edge_type = $this->getMetadataValue('edge:type');
             if ($edge_type == ManiphestTaskHasCommitEdgeType::EDGECONST) {
                 if ($commit_phid) {
                     return true;
                 }
             }
             break;
         case self::TYPE_DESCRIPTION:
         case self::TYPE_PRIORITY:
         case self::TYPE_STATUS:
             if ($this->getOldValue() === null) {
                 return true;
             } else {
                 return false;
             }
             break;
         case self::TYPE_SUBPRIORITY:
         case self::TYPE_PARENT:
             return true;
         case self::TYPE_COVER_IMAGE:
             // At least for now, don't show these.
             return true;
         case self::TYPE_POINTS:
             if (!ManiphestTaskPoints::getIsEnabled()) {
                 return true;
             }
     }
     return parent::shouldHide();
 }
    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());
        }
        $column_documentation = pht(<<<EODOCS
You can use this transaction type to create a task into a particular workboard
column, or move an existing task between columns.

The transaction value can be specified in several forms. Some are simpler but
less powerful, while others are more complex and more powerful.

The simplest valid value is a single column PHID:

```lang=json
"PHID-PCOL-1111"
```

This will move the task into that column, or create the task into that column
if you are creating a new task. If the task is currently on the board, it will
be moved out of any exclusive columns. If the task is not currently on the
board, it will be added to the board.

You can also perform multiple moves at the same time by passing a list of
PHIDs:

```lang=json
["PHID-PCOL-2222", "PHID-PCOL-3333"]
```

This is equivalent to performing each move individually.

The most complex and most powerful form uses a dictionary to provide additional
information about the move, including an optional specific position within the
column.

The target column should be identified as `columnPHID`, and you may select a
position by passing either `beforePHID` or `afterPHID`, specifying the PHID of
a task currently in the column that you want to move this task before or after:

```lang=json
[
  {
    "columnPHID": "PHID-PCOL-4444",
    "beforePHID": "PHID-TASK-5555"
  }
]
```

Note that this affects only the "natural" position of the task. The task
position when the board is sorted by some other attribute (like priority)
depends on that attribute value: change a task's priority to move it on
priority-sorted boards.
EODOCS
);
        $column_map = $this->getColumnMap($object);
        $fields = 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 PhabricatorColumnsEditField())->setKey('column')->setLabel(pht('Column'))->setDescription(pht('Create a task in a workboard column.'))->setConduitDescription(pht('Move a task to one or more workboard columns.'))->setConduitTypeDescription(pht('List of columns to move the task to.'))->setConduitDocumentation($column_documentation)->setAliases(array('columnPHID', 'columns', 'columnPHIDs'))->setTransactionType(PhabricatorTransactions::TYPE_COLUMNS)->setIsReorderable(false)->setIsDefaultable(false)->setIsLockable(false)->setCommentActionLabel(pht('Move on Workboard'))->setCommentActionOrder(2000)->setColumnMap($column_map), 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')));
        if (ManiphestTaskPoints::getIsEnabled()) {
            $points_label = ManiphestTaskPoints::getPointsLabel();
            $action_label = ManiphestTaskPoints::getPointsActionLabel();
            $fields[] = id(new PhabricatorPointsEditField())->setKey('points')->setLabel($points_label)->setDescription(pht('Point value of the task.'))->setConduitDescription(pht('Change the task point value.'))->setConduitTypeDescription(pht('New task point value.'))->setTransactionType(ManiphestTransaction::TYPE_POINTS)->setIsCopyable(true)->setValue($object->getPoints())->setCommentActionLabel($action_label);
        }
        $fields[] = 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')));
        return $fields;
    }