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;
 }
 public function render()
 {
     if (!$this->user) {
         throw new Exception("Call setUser() before rendering!");
     }
     $task = $this->task;
     $handles = $this->handles;
     require_celerity_resource('maniphest-task-summary-css');
     $pri_class = self::getPriorityClass($task->getPriority());
     $status_map = ManiphestTaskStatus::getTaskStatusMap();
     $batch = null;
     if ($this->showBatchControls) {
         $batch = '<td class="maniphest-task-batch">' . javelin_render_tag('input', array('type' => 'checkbox', 'name' => 'batch[]', 'value' => $task->getID(), 'sigil' => 'maniphest-batch'), null) . '</td>';
     }
     $projects_view = new ManiphestTaskProjectsView();
     $projects_view->setHandles(array_select_keys($this->handles, $task->getProjectPHIDs()));
     $control_class = null;
     $control_sigil = null;
     if ($this->showSubpriorityControls) {
         $control_class = 'maniphest-active-handle';
         $control_sigil = 'maniphest-task-handle';
     }
     $handle = javelin_render_tag('td', array('class' => 'maniphest-task-handle ' . $pri_class . ' ' . $control_class, 'sigil' => $control_sigil), '');
     return javelin_render_tag('table', array('class' => 'maniphest-task-summary', 'sigil' => 'maniphest-task', 'meta' => array('taskID' => $task->getID())), '<tr>' . $handle . $batch . '<td class="maniphest-task-number">' . 'T' . $task->getID() . '</td>' . '<td class="maniphest-task-status">' . idx($status_map, $task->getStatus(), 'Unknown') . '</td>' . '<td class="maniphest-task-owner">' . ($task->getOwnerPHID() ? $handles[$task->getOwnerPHID()]->renderLink() : '<em>None</em>') . '</td>' . '<td class="maniphest-task-name">' . phutil_render_tag('a', array('href' => '/T' . $task->getID()), phutil_escape_html($task->getTitle())) . '</td>' . '<td class="maniphest-task-projects">' . $projects_view->render() . '</td>' . '<td class="maniphest-task-updated">' . phabricator_date($task->getDateModified(), $this->user) . '</td>' . '</tr>');
 }
 public function getEditorValue(PhabricatorUser $viewer, $value)
 {
     $status_map = ManiphestTaskStatus::getTaskStatusMap();
     $value_map = array();
     foreach ($value as $status) {
         $value_map[$status] = idx($status_map, $status, $status);
     }
     return $value_map;
 }
 private function buildResults()
 {
     $results = array();
     $status_map = ManiphestTaskStatus::getTaskStatusMap();
     foreach ($status_map as $value => $name) {
         $results[$value] = id(new PhabricatorTypeaheadResult())->setIcon(ManiphestTaskStatus::getStatusIcon($value))->setPHID($value)->setName($name);
     }
     return $results;
 }
 public function generateTaskStatus()
 {
     $statuses = array_keys(ManiphestTaskStatus::getTaskStatusMap());
     // Make sure 4/5th of all generated Tasks are open
     $random = rand(0, 4);
     if ($random != 0) {
         return ManiphestTaskStatus::getDefaultStatus();
     } else {
         return array_rand($statuses);
     }
 }
 public function render()
 {
     $handles = $this->handles;
     require_celerity_resource('maniphest-task-summary-css');
     $list = new PHUIObjectItemListView();
     if ($this->noDataString) {
         $list->setNoDataString($this->noDataString);
     } else {
         $list->setNoDataString(pht('No tasks.'));
     }
     $status_map = ManiphestTaskStatus::getTaskStatusMap();
     $color_map = ManiphestTaskPriority::getColorMap();
     $priority_map = ManiphestTaskPriority::getTaskPriorityMap();
     if ($this->showBatchControls) {
         Javelin::initBehavior('maniphest-list-editor');
     }
     foreach ($this->tasks as $task) {
         $item = id(new PHUIObjectItemView())->setUser($this->getUser())->setObject($task)->setObjectName('T' . $task->getID())->setHeader($task->getTitle())->setHref('/T' . $task->getID());
         if ($task->getOwnerPHID()) {
             $owner = $handles[$task->getOwnerPHID()];
             $item->addByline(pht('Assigned: %s', $owner->renderLink()));
         }
         $status = $task->getStatus();
         $pri = idx($priority_map, $task->getPriority());
         $status_name = idx($status_map, $task->getStatus());
         $tooltip = pht('%s, %s', $status_name, $pri);
         $icon = ManiphestTaskStatus::getStatusIcon($task->getStatus());
         $color = idx($color_map, $task->getPriority(), 'grey');
         if ($task->isClosed()) {
             $item->setDisabled(true);
             $color = 'grey';
         }
         $item->setStatusIcon($icon . ' ' . $color, $tooltip);
         $item->addIcon('none', phabricator_datetime($task->getDateModified(), $this->getUser()));
         if ($this->showSubpriorityControls) {
             $item->setGrippable(true);
         }
         if ($this->showSubpriorityControls || $this->showBatchControls) {
             $item->addSigil('maniphest-task');
         }
         $project_handles = array_select_keys($handles, array_reverse($task->getProjectPHIDs()));
         $item->addAttribute(id(new PHUIHandleTagListView())->setLimit(4)->setNoDataString(pht('No Projects'))->setSlim(true)->setHandles($project_handles));
         $item->setMetadata(array('taskID' => $task->getID()));
         if ($this->showBatchControls) {
             $href = new PhutilURI('/maniphest/task/edit/' . $task->getID() . '/');
             if (!$this->showSubpriorityControls) {
                 $href->setQueryParam('ungrippable', 'true');
             }
             $item->addAction(id(new PHUIListItemView())->setIcon('fa-pencil')->addSigil('maniphest-edit-task')->setHref($href));
         }
         $list->addItem($item);
     }
     return $list;
 }
 public function processRequest()
 {
     $this->requireApplicationCapability(ManiphestBulkEditCapability::CAPABILITY);
     $request = $this->getRequest();
     $user = $request->getUser();
     $task_ids = $request->getArr('batch');
     $tasks = id(new ManiphestTaskQuery())->setViewer($user)->withIDs($task_ids)->requireCapabilities(array(PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT))->execute();
     $actions = $request->getStr('actions');
     if ($actions) {
         $actions = json_decode($actions, true);
     }
     if ($request->isFormPost() && is_array($actions)) {
         foreach ($tasks as $task) {
             $field_list = PhabricatorCustomField::getObjectFields($task, PhabricatorCustomField::ROLE_EDIT);
             $field_list->readFieldsFromStorage($task);
             $xactions = $this->buildTransactions($actions, $task);
             if ($xactions) {
                 // TODO: Set content source to "batch edit".
                 $editor = id(new ManiphestTransactionEditor())->setActor($user)->setContentSourceFromRequest($request)->setContinueOnNoEffect(true)->setContinueOnMissingFields(true)->applyTransactions($task, $xactions);
             }
         }
         $task_ids = implode(',', mpull($tasks, 'getID'));
         return id(new AphrontRedirectResponse())->setURI('/maniphest/?ids=' . $task_ids);
     }
     $handles = ManiphestTaskListView::loadTaskHandles($user, $tasks);
     $list = new ManiphestTaskListView();
     $list->setTasks($tasks);
     $list->setUser($user);
     $list->setHandles($handles);
     $template = new AphrontTokenizerTemplateView();
     $template = $template->render();
     $projects_source = new PhabricatorProjectDatasource();
     $mailable_source = new PhabricatorMetaMTAMailableDatasource();
     $owner_source = new PhabricatorTypeaheadOwnerDatasource();
     require_celerity_resource('maniphest-batch-editor');
     Javelin::initBehavior('maniphest-batch-editor', array('root' => 'maniphest-batch-edit-form', 'tokenizerTemplate' => $template, 'sources' => array('project' => array('src' => $projects_source->getDatasourceURI(), 'placeholder' => $projects_source->getPlaceholderText()), 'owner' => array('src' => $owner_source->getDatasourceURI(), 'placeholder' => $owner_source->getPlaceholderText(), 'limit' => 1), 'cc' => array('src' => $mailable_source->getDatasourceURI(), 'placeholder' => $mailable_source->getPlaceholderText())), 'input' => 'batch-form-actions', 'priorityMap' => ManiphestTaskPriority::getTaskPriorityMap(), 'statusMap' => ManiphestTaskStatus::getTaskStatusMap()));
     $form = new AphrontFormView();
     $form->setUser($user);
     $form->setID('maniphest-batch-edit-form');
     foreach ($tasks as $task) {
         $form->appendChild(phutil_tag('input', array('type' => 'hidden', 'name' => 'batch[]', 'value' => $task->getID())));
     }
     $form->appendChild(phutil_tag('input', array('type' => 'hidden', 'name' => 'actions', 'id' => 'batch-form-actions')));
     $form->appendChild(phutil_tag('p', array(), pht('These tasks will be edited:')));
     $form->appendChild($list);
     $form->appendChild(id(new AphrontFormInsetView())->setTitle('Actions')->setRightButton(javelin_tag('a', array('href' => '#', 'class' => 'button green', 'sigil' => 'add-action', 'mustcapture' => true), pht('Add Another Action')))->setContent(javelin_tag('table', array('sigil' => 'maniphest-batch-actions', 'class' => 'maniphest-batch-actions-table'), '')))->appendChild(id(new AphrontFormSubmitControl())->setValue(pht('Update Tasks'))->addCancelButton('/maniphest/'));
     $title = pht('Batch Editor');
     $crumbs = $this->buildApplicationCrumbs();
     $crumbs->addTextCrumb($title);
     $form_box = id(new PHUIObjectBoxView())->setHeaderText(pht('Batch Edit Tasks'))->setForm($form);
     return $this->buildApplicationPage(array($crumbs, $form_box), array('title' => $title, 'device' => false));
 }
 private function buildResults()
 {
     $results = array();
     $status_map = ManiphestTaskStatus::getTaskStatusMap();
     foreach ($status_map as $value => $name) {
         $result = id(new PhabricatorTypeaheadResult())->setIcon(ManiphestTaskStatus::getStatusIcon($value))->setPHID($value)->setName($name);
         if (ManiphestTaskStatus::isDisabledStatus($value)) {
             $result->setClosed(pht('Disabled'));
         }
         $results[$value] = $result;
     }
     return $results;
 }
 protected function evaluateFunction($function, array $argv_list)
 {
     $results = array();
     $map = ManiphestTaskStatus::getTaskStatusMap();
     foreach ($argv_list as $argv) {
         foreach ($map as $status => $name) {
             if (ManiphestTaskStatus::isOpenStatus($status)) {
                 $results[] = $status;
             }
         }
     }
     return $results;
 }
 public function render()
 {
     if (!$this->user) {
         throw new Exception("Call setUser() before rendering!");
     }
     $task = $this->task;
     $handles = $this->handles;
     require_celerity_resource('maniphest-task-summary-css');
     $classes = array(ManiphestTaskPriority::PRIORITY_UNBREAK_NOW => 'pri-unbreak', ManiphestTaskPriority::PRIORITY_TRIAGE => 'pri-triage', ManiphestTaskPriority::PRIORITY_HIGH => 'pri-high', ManiphestTaskPriority::PRIORITY_NORMAL => 'pri-normal', ManiphestTaskPriority::PRIORITY_LOW => 'pri-low', ManiphestTaskPriority::PRIORITY_WISH => 'pri-wish');
     $pri_class = idx($classes, $task->getPriority());
     $status_map = ManiphestTaskStatus::getTaskStatusMap();
     return '<table class="maniphest-task-summary">' . '<tr>' . '<td class="maniphest-task-number ' . $pri_class . '">' . 'T' . $task->getID() . '</td>' . '<td class="maniphest-task-status">' . idx($status_map, $task->getStatus(), 'Unknown') . '</td>' . '<td class="maniphest-task-owner">' . ($task->getOwnerPHID() ? $handles[$task->getOwnerPHID()]->renderLink() : '<em>None</em>') . '</td>' . '<td class="maniphest-task-name">' . phutil_render_tag('a', array('href' => '/T' . $task->getID()), phutil_escape_html($task->getTitle())) . '</td>' . '<td class="maniphest-task-priority">' . ManiphestTaskPriority::getTaskPriorityName($task->getPriority()) . '</td>' . '<td class="maniphest-task-updated">' . phabricator_datetime($task->getDateModified(), $this->user) . '</td>' . '</tr>' . '</table>';
 }
 public function getCommandDescription()
 {
     $names = ManiphestTaskStatus::getTaskStatusMap();
     $keywords = ManiphestTaskStatus::getTaskStatusKeywordsMap();
     $table = array();
     $table[] = '| ' . pht('Status') . ' | ' . pht('Keywords');
     $table[] = '|---|---|';
     foreach ($keywords as $status => $words) {
         $words = implode(', ', $words);
         $table[] = '| ' . $names[$status] . ' | ' . $words;
     }
     $table = implode("\n", $table);
     return pht("To change the status of a task, specify the desired status, like " . "`%s`. This table shows the configured names for statuses.\n\n%s\n\n" . "If you specify an invalid status, the command is ignored. This " . "command has no effect if you do not specify a status.", '!status invalid', $table);
 }
 /**
  * @phutil-external-symbol class PHPExcel
  * @phutil-external-symbol class PHPExcel_IOFactory
  * @phutil-external-symbol class PHPExcel_Style_NumberFormat
  * @phutil-external-symbol class PHPExcel_Cell_DataType
  */
 public function buildWorkbook(PHPExcel $workbook, array $tasks, array $handles, PhabricatorUser $user)
 {
     $sheet = $workbook->setActiveSheetIndex(0);
     $sheet->setTitle(pht('Tasks'));
     $widths = array(null, 15, null, 10, 15, 15, 60, 30, 20, 100);
     foreach ($widths as $col => $width) {
         if ($width !== null) {
             $sheet->getColumnDimension($this->col($col))->setWidth($width);
         }
     }
     $status_map = ManiphestTaskStatus::getTaskStatusMap();
     $pri_map = ManiphestTaskPriority::getTaskPriorityMap();
     $date_format = null;
     $rows = array();
     $rows[] = array(pht('ID'), pht('Owner'), pht('Status'), pht('Priority'), pht('Date Created'), pht('Date Updated'), pht('Deadline'), pht('Title'), pht('Projects'), pht('Description'));
     $is_date = array(false, false, false, false, true, true, true, false, false, false);
     $header_format = array('font' => array('bold' => true));
     foreach ($tasks as $task) {
         $task_owner = null;
         if ($task->getOwnerPHID()) {
             $task_owner = $handles[$task->getOwnerPHID()]->getName();
         }
         $projects = array();
         foreach ($task->getProjectPHIDs() as $phid) {
             $projects[] = $handles[$phid]->getName();
         }
         $projects = implode(', ', $projects);
         $custom_fields = PhabricatorCustomField::getObjectFields($task, PhabricatorCustomField::ROLE_VIEW);
         $custom_fields->setViewer($user)->readFieldsFromStorage($task);
         $fields = $custom_fields->getFields();
         $rows[] = array('T' . $task->getID(), $task_owner, idx($status_map, $task->getStatus(), '?'), idx($pri_map, $task->getPriority(), '?'), $this->computeExcelDate($task->getDateCreated()), $this->computeExcelDate($task->getDateModified()), $this->computeExcelDate($fields['std:maniphest:Deadline']->getValueForStorage()), $task->getTitle(), $projects, id(new PhutilUTF8StringTruncator())->setMaximumBytes(512)->truncateString($task->getDescription()));
     }
     foreach ($rows as $row => $cols) {
         foreach ($cols as $col => $spec) {
             $cell_name = $this->col($col) . ($row + 1);
             $cell = $sheet->setCellValue($cell_name, $spec, $return_cell = true);
             if ($row == 0) {
                 $sheet->getStyle($cell_name)->applyFromArray($header_format);
             }
             if ($is_date[$col]) {
                 $code = PHPExcel_Style_NumberFormat::FORMAT_DATE_YYYYMMDD2;
                 $sheet->getStyle($cell_name)->getNumberFormat()->setFormatCode($code);
             } else {
                 $cell->setDataType(PHPExcel_Cell_DataType::TYPE_STRING);
             }
         }
     }
 }
 public function processRequest()
 {
     $request = $this->getRequest();
     $user = $request->getUser();
     $task_ids = $request->getArr('batch');
     $tasks = id(new ManiphestTask())->loadAllWhere('id IN (%Ld)', $task_ids);
     $actions = $request->getStr('actions');
     if ($actions) {
         $actions = json_decode($actions, true);
     }
     if ($request->isFormPost() && is_array($actions)) {
         foreach ($tasks as $task) {
             $xactions = $this->buildTransactions($actions, $task);
             if ($xactions) {
                 $editor = new ManiphestTransactionEditor();
                 $editor->applyTransactions($task, $xactions);
             }
         }
         $task_ids = implode(',', mpull($tasks, 'getID'));
         return id(new AphrontRedirectResponse())->setURI('/maniphest/view/custom/?s=oc&tasks=' . $task_ids);
     }
     $panel = new AphrontPanelView();
     $panel->setHeader('Maniphest Batch Editor');
     $handle_phids = mpull($tasks, 'getOwnerPHID');
     $handles = id(new PhabricatorObjectHandleData($handle_phids))->loadHandles();
     $list = new ManiphestTaskListView();
     $list->setTasks($tasks);
     $list->setUser($user);
     $list->setHandles($handles);
     $template = new AphrontTokenizerTemplateView();
     $template = $template->render();
     require_celerity_resource('maniphest-batch-editor');
     Javelin::initBehavior('maniphest-batch-editor', array('root' => 'maniphest-batch-edit-form', 'tokenizerTemplate' => $template, 'sources' => array('project' => array('src' => '/typeahead/common/projects/', 'placeholder' => 'Type a project name...'), 'owner' => array('src' => '/typeahead/common/searchowner/', 'placeholder' => 'Type a user name...', 'limit' => 1)), 'input' => 'batch-form-actions', 'priorityMap' => ManiphestTaskPriority::getTaskPriorityMap(), 'statusMap' => ManiphestTaskStatus::getTaskStatusMap()));
     $form = new AphrontFormView();
     $form->setUser($user);
     $form->setID('maniphest-batch-edit-form');
     foreach ($tasks as $task) {
         $form->appendChild(phutil_render_tag('input', array('type' => 'hidden', 'name' => 'batch[]', 'value' => $task->getID()), null));
     }
     $form->appendChild(phutil_render_tag('input', array('type' => 'hidden', 'name' => 'actions', 'id' => 'batch-form-actions'), null));
     $form->appendChild('<p>These tasks will be edited:</p>');
     $form->appendChild($list);
     $form->appendChild(id(new AphrontFormInsetView())->setTitle('Actions')->setRightButton(javelin_render_tag('a', array('href' => '#', 'class' => 'button green', 'sigil' => 'add-action', 'mustcapture' => true), 'Add Another Action'))->setContent(javelin_render_tag('table', array('sigil' => 'maniphest-batch-actions', 'class' => 'maniphest-batch-actions-table'), '')))->appendChild(id(new AphrontFormSubmitControl())->setValue('Update Tasks')->addCancelButton('/maniphest/', 'Done'));
     $panel->appendChild($form);
     return $this->buildStandardPageResponse($panel, array('title' => 'Batch Editor'));
 }
 public function buildSearchForm(AphrontFormView $form, PhabricatorSavedQuery $saved)
 {
     $assigned_phids = $saved->getParameter('assignedPHIDs', array());
     $author_phids = $saved->getParameter('authorPHIDs', array());
     $all_project_phids = $saved->getParameter('allProjectPHIDs', array());
     $any_project_phids = $saved->getParameter('anyProjectPHIDs', array());
     $exclude_project_phids = $saved->getParameter('excludeProjectPHIDs', array());
     $user_project_phids = $saved->getParameter('userProjectPHIDs', array());
     $subscriber_phids = $saved->getParameter('subscriberPHIDs', array());
     $all_phids = array_merge($assigned_phids, $author_phids, $all_project_phids, $any_project_phids, $exclude_project_phids, $user_project_phids, $subscriber_phids);
     if ($all_phids) {
         $handles = id(new PhabricatorHandleQuery())->setViewer($this->requireViewer())->withPHIDs($all_phids)->execute();
     } else {
         $handles = array();
     }
     $assigned_handles = array_select_keys($handles, $assigned_phids);
     $author_handles = array_select_keys($handles, $author_phids);
     $all_project_handles = array_select_keys($handles, $all_project_phids);
     $any_project_handles = array_select_keys($handles, $any_project_phids);
     $exclude_project_handles = array_select_keys($handles, $exclude_project_phids);
     $user_project_handles = array_select_keys($handles, $user_project_phids);
     $subscriber_handles = array_select_keys($handles, $subscriber_phids);
     $with_unassigned = $saved->getParameter('withUnassigned');
     $with_no_projects = $saved->getParameter('withNoProject');
     $statuses = $saved->getParameter('statuses', array());
     $statuses = array_fuse($statuses);
     $status_control = id(new AphrontFormCheckboxControl())->setLabel(pht('Status'));
     foreach (ManiphestTaskStatus::getTaskStatusMap() as $status => $name) {
         $status_control->addCheckbox('statuses[]', $status, $name, isset($statuses[$status]));
     }
     $priorities = $saved->getParameter('priorities', array());
     $priorities = array_fuse($priorities);
     $priority_control = id(new AphrontFormCheckboxControl())->setLabel(pht('Priority'));
     foreach (ManiphestTaskPriority::getTaskPriorityMap() as $pri => $name) {
         $priority_control->addCheckbox('priorities[]', $pri, $name, isset($priorities[$pri]));
     }
     $ids = $saved->getParameter('ids', array());
     $builtin_orders = $this->getOrderOptions();
     $custom_orders = $this->getCustomFieldOrderOptions();
     $all_orders = $builtin_orders + $custom_orders;
     $form->appendChild(id(new AphrontFormTokenizerControl())->setDatasource(new PhabricatorPeopleDatasource())->setName('assigned')->setLabel(pht('Assigned To'))->setValue($assigned_handles))->appendChild(id(new AphrontFormCheckboxControl())->addCheckbox('withUnassigned', 1, pht('Show only unassigned tasks.'), $with_unassigned))->appendChild(id(new AphrontFormTokenizerControl())->setDatasource(new PhabricatorProjectDatasource())->setName('allProjects')->setLabel(pht('In All Projects'))->setValue($all_project_handles));
     if (!$this->getIsBoardView()) {
         $form->appendChild(id(new AphrontFormCheckboxControl())->addCheckbox('withNoProject', 1, pht('Show only tasks with no projects.'), $with_no_projects));
     }
     $form->appendChild(id(new AphrontFormTokenizerControl())->setDatasource(new PhabricatorProjectDatasource())->setName('anyProjects')->setLabel(pht('In Any Project'))->setValue($any_project_handles))->appendChild(id(new AphrontFormTokenizerControl())->setDatasource(new PhabricatorProjectDatasource())->setName('excludeProjects')->setLabel(pht('Not In Projects'))->setValue($exclude_project_handles))->appendChild(id(new AphrontFormTokenizerControl())->setDatasource(new PhabricatorPeopleDatasource())->setName('userProjects')->setLabel(pht('In Users\' Projects'))->setValue($user_project_handles))->appendChild(id(new AphrontFormTokenizerControl())->setDatasource(new PhabricatorPeopleDatasource())->setName('authors')->setLabel(pht('Authors'))->setValue($author_handles))->appendChild(id(new AphrontFormTokenizerControl())->setDatasource(new PhabricatorMetaMTAMailableDatasource())->setName('subscribers')->setLabel(pht('Subscribers'))->setValue($subscriber_handles))->appendChild($status_control)->appendChild($priority_control);
     if (!$this->getIsBoardView()) {
         $form->appendChild(id(new AphrontFormSelectControl())->setName('group')->setLabel(pht('Group By'))->setValue($saved->getParameter('group'))->setOptions($this->getGroupOptions()))->appendChild(id(new AphrontFormSelectControl())->setName('order')->setLabel(pht('Order By'))->setValue($saved->getParameter('order'))->setOptions($all_orders));
     }
     $form->appendChild(id(new AphrontFormTextControl())->setName('fulltext')->setLabel(pht('Contains Words'))->setValue($saved->getParameter('fulltext')))->appendChild(id(new AphrontFormTextControl())->setName('ids')->setLabel(pht('Task IDs'))->setValue(implode(', ', $ids)));
     $this->appendCustomFieldsToForm($form, $saved);
     $this->buildDateRange($form, $saved, 'createdStart', pht('Created After'), 'createdEnd', pht('Created Before'));
     $this->buildDateRange($form, $saved, 'modifiedStart', pht('Updated After'), 'modifiedEnd', pht('Updated Before'));
     if (!$this->getIsBoardView()) {
         $form->appendChild(id(new AphrontFormTextControl())->setName('limit')->setLabel(pht('Page Size'))->setValue($saved->getParameter('limit', 100)));
     }
 }
 protected function getDatasourceValueMap()
 {
     return ManiphestTaskStatus::getTaskStatusMap();
 }
 protected function applyRequest(ManiphestTask $task, ConduitAPIRequest $request, $is_new)
 {
     $changes = array();
     if ($is_new) {
         $task->setTitle((string) $request->getValue('title'));
         $task->setDescription((string) $request->getValue('description'));
         $changes[ManiphestTransaction::TYPE_STATUS] = ManiphestTaskStatus::getDefaultStatus();
         $changes[PhabricatorTransactions::TYPE_SUBSCRIBERS] = array('+' => array($request->getUser()->getPHID()));
     } else {
         $comments = $request->getValue('comments');
         if (!$is_new && $comments !== null) {
             $changes[PhabricatorTransactions::TYPE_COMMENT] = null;
         }
         $title = $request->getValue('title');
         if ($title !== null) {
             $changes[ManiphestTransaction::TYPE_TITLE] = $title;
         }
         $desc = $request->getValue('description');
         if ($desc !== null) {
             $changes[ManiphestTransaction::TYPE_DESCRIPTION] = $desc;
         }
         $status = $request->getValue('status');
         if ($status !== null) {
             $valid_statuses = ManiphestTaskStatus::getTaskStatusMap();
             if (!isset($valid_statuses[$status])) {
                 throw id(new ConduitException('ERR-INVALID-PARAMETER'))->setErrorDescription(pht('Status set to invalid value.'));
             }
             $changes[ManiphestTransaction::TYPE_STATUS] = $status;
         }
     }
     $priority = $request->getValue('priority');
     if ($priority !== null) {
         $valid_priorities = ManiphestTaskPriority::getTaskPriorityMap();
         if (!isset($valid_priorities[$priority])) {
             throw id(new ConduitException('ERR-INVALID-PARAMETER'))->setErrorDescription(pht('Priority set to invalid value.'));
         }
         $changes[ManiphestTransaction::TYPE_PRIORITY] = $priority;
     }
     $owner_phid = $request->getValue('ownerPHID');
     if ($owner_phid !== null) {
         $this->validatePHIDList(array($owner_phid), PhabricatorPeopleUserPHIDType::TYPECONST, 'ownerPHID');
         $changes[ManiphestTransaction::TYPE_OWNER] = $owner_phid;
     }
     $ccs = $request->getValue('ccPHIDs');
     if ($ccs !== null) {
         $changes[PhabricatorTransactions::TYPE_SUBSCRIBERS] = array('=' => array_fuse($ccs));
     }
     $transactions = array();
     $view_policy = $request->getValue('viewPolicy');
     if ($view_policy !== null) {
         $transactions[] = id(new ManiphestTransaction())->setTransactionType(PhabricatorTransactions::TYPE_VIEW_POLICY)->setNewValue($view_policy);
     }
     $edit_policy = $request->getValue('editPolicy');
     if ($edit_policy !== null) {
         $transactions[] = id(new ManiphestTransaction())->setTransactionType(PhabricatorTransactions::TYPE_EDIT_POLICY)->setNewValue($edit_policy);
     }
     $project_phids = $request->getValue('projectPHIDs');
     if ($project_phids !== null) {
         $this->validatePHIDList($project_phids, PhabricatorProjectProjectPHIDType::TYPECONST, 'projectPHIDS');
         $project_type = PhabricatorProjectObjectHasProjectEdgeType::EDGECONST;
         $transactions[] = id(new ManiphestTransaction())->setTransactionType(PhabricatorTransactions::TYPE_EDGE)->setMetadataValue('edge:type', $project_type)->setNewValue(array('=' => array_fuse($project_phids)));
     }
     $template = new ManiphestTransaction();
     foreach ($changes as $type => $value) {
         $transaction = clone $template;
         $transaction->setTransactionType($type);
         if ($type == PhabricatorTransactions::TYPE_COMMENT) {
             $transaction->attachComment(id(new ManiphestTransactionComment())->setContent($comments));
         } else {
             $transaction->setNewValue($value);
         }
         $transactions[] = $transaction;
     }
     $field_list = PhabricatorCustomField::getObjectFields($task, PhabricatorCustomField::ROLE_EDIT);
     $field_list->readFieldsFromStorage($task);
     $auxiliary = $request->getValue('auxiliary');
     if ($auxiliary) {
         foreach ($field_list->getFields() as $key => $field) {
             if (!array_key_exists($key, $auxiliary)) {
                 continue;
             }
             $transaction = clone $template;
             $transaction->setTransactionType(PhabricatorTransactions::TYPE_CUSTOMFIELD);
             $transaction->setMetadataValue('customfield:key', $key);
             $transaction->setOldValue($field->getOldValueForApplicationTransactions());
             $transaction->setNewValue($auxiliary[$key]);
             $transactions[] = $transaction;
         }
     }
     if (!$transactions) {
         return;
     }
     $content_source = $request->newContentSource();
     $editor = id(new ManiphestTransactionEditor())->setActor($request->getUser())->setContentSource($content_source)->setContinueOnNoEffect(true);
     if (!$is_new) {
         $editor->setContinueOnMissingFields(true);
     }
     $editor->applyTransactions($task, $transactions);
     // reload the task now that we've done all the fun stuff
     return id(new ManiphestTaskQuery())->setViewer($request->getUser())->withPHIDs(array($task->getPHID()))->needSubscriberPHIDs(true)->needProjectPHIDs(true)->executeOne();
 }
 public function processRequest()
 {
     $request = $this->getRequest();
     $user = $request->getUser();
     $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);
     $parent_task = null;
     $template_id = null;
     if ($this->id) {
         $task = id(new ManiphestTaskQuery())->setViewer($user)->requireCapabilities(array(PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT))->withIDs(array($this->id))->executeOne();
         if (!$task) {
             return new Aphront404Response();
         }
     } else {
         $task = ManiphestTask::initializeNewTask($user);
         // 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($user)->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($user)->withUsernames(array($assign))->executeOne();
                     if (!$assign_user) {
                         $assign_user = id(new PhabricatorPeopleQuery())->setViewer($user)->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 ($parent_id) {
             $parent_task = id(new ManiphestTaskQuery())->setViewer($user)->withIDs(array($parent_id))->executeOne();
             if (!$template_id) {
                 $template_id = $parent_id;
             }
         }
     }
     $errors = array();
     $e_title = true;
     $field_list = PhabricatorCustomField::getObjectFields($task, PhabricatorCustomField::ROLE_EDIT);
     $field_list->setViewer($user);
     $field_list->readFieldsFromStorage($task);
     $aux_fields = $field_list->getFields();
     if ($request->isFormPost()) {
         $changes = array();
         $new_title = $request->getStr('title');
         $new_desc = $request->getStr('description');
         $new_status = $request->getStr('status');
         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 = new PhabricatorUserProfileEditor();
             $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->setCCPHIDs($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[ManiphestTransaction::TYPE_CCS] = $request->getArr('cc');
             if ($can_edit_projects) {
                 $projects = $request->getArr('projects');
                 $changes[ManiphestTransaction::TYPE_PROJECTS] = $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($user)->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_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 == ManiphestTransaction::TYPE_PROJECTS) {
                         // TODO: Gross.
                         $project_type = PhabricatorProjectObjectHasProjectEdgeType::EDGECONST;
                         $transaction->setTransactionType(PhabricatorTransactions::TYPE_EDGE)->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($user);
                 $event->setAphrontRequest($request);
                 PhutilEventEngine::dispatchEvent($event);
                 $task = $event->getValue('task');
                 $transactions = $event->getValue('transactions');
                 $editor = id(new ManiphestTransactionEditor())->setActor($user)->setContentSourceFromRequest($request)->setContinueOnNoEffect(true)->applyTransactions($task, $transactions);
                 $event = new PhabricatorEvent(PhabricatorEventType::TYPE_MANIPHEST_DIDEDITTASK, array('task' => $task, 'new' => $is_new, 'transactions' => $transactions));
                 $event->setUser($user);
                 $event->setAphrontRequest($request);
                 PhutilEventEngine::dispatchEvent($event);
             }
             if ($parent_task) {
                 // TODO: This should be transactional now.
                 id(new PhabricatorEdgeEditor())->addEdge($parent_task->getPHID(), PhabricatorEdgeConfig::TYPE_TASK_DEPENDS_ON_TASK, $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($user)->withPHIDs(array($task->getOwnerPHID()))->executeOne();
                         }
                         $tasks = id(new ProjectBoardTaskCard())->setViewer($user)->setTask($task)->setOwner($owner)->setCanEdit(true)->getItem();
                         $column = id(new PhabricatorProjectColumnQuery())->setViewer($user)->withPHIDs(array($request->getStr('columnPHID')))->executeOne();
                         if (!$column) {
                             return new Aphront404Response();
                         }
                         $positions = id(new PhabricatorProjectColumnPositionQuery())->setViewer($user)->withColumns(array($column))->execute();
                         $task_phids = mpull($positions, 'getObjectPHID');
                         $column_tasks = id(new ManiphestTaskQuery())->setViewer($user)->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 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);
                         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->setCCPHIDs(array($user->getPHID()));
             if ($template_id) {
                 $template_task = id(new ManiphestTaskQuery())->setViewer($user)->withIDs(array($template_id))->executeOne();
                 if ($template_task) {
                     $cc_phids = array_unique(array_merge($template_task->getCCPHIDs(), array($user->getPHID())));
                     $task->setCCPHIDs($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());
                     $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($user)->readFieldsFromStorage($template_task);
                         foreach ($fields as $key => $field) {
                             $aux_fields[$key]->setValueFromStorage($field->getValueForStorage());
                         }
                     }
                 }
             }
         }
     }
     $phids = array_merge(array($task->getOwnerPHID()), $task->getCCPHIDs(), $task->getProjectPHIDs());
     if ($parent_task) {
         $phids[] = $parent_task->getPHID();
     }
     $phids = array_filter($phids);
     $phids = array_unique($phids);
     $handles = $this->loadViewerHandles($phids);
     $error_view = null;
     if ($errors) {
         $error_view = new AphrontErrorView();
         $error_view->setErrors($errors);
     }
     $priority_map = ManiphestTaskPriority::getTaskPriorityMap();
     if ($task->getOwnerPHID()) {
         $assigned_value = array($handles[$task->getOwnerPHID()]);
     } else {
         $assigned_value = array();
     }
     if ($task->getCCPHIDs()) {
         $cc_value = array_select_keys($handles, $task->getCCPHIDs());
     } else {
         $cc_value = array();
     }
     if ($task->getProjectPHIDs()) {
         $projects_value = array_select_keys($handles, $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($user)->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($handles[$parent_task->getPHID()]->getFullName()))->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($user)->setObject($task)->execute();
     if ($can_edit_assign) {
         $form->appendChild(id(new AphrontFormTokenizerControl())->setLabel(pht('Assigned To'))->setName('assigned_to')->setValue($assigned_value)->setUser($user)->setDatasource(new PhabricatorPeopleDatasource())->setLimit(1));
     }
     $form->appendChild(id(new AphrontFormTokenizerControl())->setLabel(pht('CC'))->setName('cc')->setValue($cc_value)->setUser($user)->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($user)->setCapability(PhabricatorPolicyCapability::CAN_VIEW)->setPolicyObject($task)->setPolicies($policies)->setName('viewPolicy'))->appendChild(id(new AphrontFormPolicyControl())->setUser($user)->setCapability(PhabricatorPolicyCapability::CAN_EDIT)->setPolicyObject($task)->setPolicies($policies)->setName('editPolicy'));
     }
     if ($can_edit_projects) {
         $form->appendChild(id(new AphrontFormTokenizerControl())->setLabel(pht('Projects'))->setName('projects')->setValue($projects_value)->setID($project_tokenizer_id)->setCaption(javelin_tag('a', array('href' => '/project/create/', 'mustcapture' => true, 'sigil' => 'project-create'), pht('Create New Project')))->setDatasource(new PhabricatorProjectDatasource()));
     }
     $field_list->appendFieldsToForm($form);
     require_celerity_resource('aphront-error-view-css');
     Javelin::initBehavior('project-create', array('tokenizerID' => $project_tokenizer_id));
     $description_control = new PhabricatorRemarkupControl();
     // "Upsell" creating tasks via email in create flows if the instance is
     // configured for this awesomeness.
     $email_create = PhabricatorEnv::getEnvConfig('metamta.maniphest.public-create-email');
     if (!$task->getID() && $email_create) {
         $email_hint = pht('You can also create tasks by sending an email to: %s', phutil_tag('tt', array(), $email_create));
         $description_control->setCaption($email_hint);
     }
     $description_control->setLabel(pht('Description'))->setName('description')->setID('description-textarea')->setValue($task->getDescription())->setUser($user);
     $form->appendChild($description_control);
     if ($request->isAjax()) {
         $dialog = id(new AphrontDialogView())->setUser($user)->setWidth(AphrontDialogView::WIDTH_FULL)->setTitle($header_name)->appendChild(array($error_view, $form->buildLayoutView()))->addCancelButton($cancel_uri)->addSubmitButton($button_name);
         return id(new AphrontDialogResponse())->setDialog($dialog);
     }
     $form->appendChild(id(new AphrontFormSubmitControl())->addCancelButton($cancel_uri)->setValue($button_name));
     $form_box = id(new PHUIObjectBoxView())->setHeaderText($header_name)->setFormErrors($errors)->setForm($form);
     $preview = id(new PHUIRemarkupPreviewPanel())->setHeader(pht('Description Preview'))->setControlID('description-textarea')->setPreviewURI($this->getApplicationURI('task/descriptionpreview/'));
     if ($task->getID()) {
         $page_objects = array($task->getPHID());
     } else {
         $page_objects = array();
     }
     $crumbs = $this->buildApplicationCrumbs();
     if ($task->getID()) {
         $crumbs->addTextCrumb('T' . $task->getID(), '/T' . $task->getID());
     }
     $crumbs->addTextCrumb($header_name);
     return $this->buildApplicationPage(array($crumbs, $form_box, $preview), array('title' => $header_name, 'pageObjects' => $page_objects));
 }
 private function describeAction($transaction)
 {
     $verb = null;
     $desc = null;
     $classes = array();
     $handles = $this->handles;
     $type = $transaction->getTransactionType();
     $author_phid = $transaction->getAuthorPHID();
     $new = $transaction->getNewValue();
     $old = $transaction->getOldValue();
     switch ($type) {
         case ManiphestTransactionType::TYPE_TITLE:
             $verb = 'Retitled';
             $desc = 'changed the title from ' . $this->renderString($old) . ' to ' . $this->renderString($new);
             break;
         case ManiphestTransactionType::TYPE_DESCRIPTION:
             $verb = 'Edited';
             if ($this->forEmail || $this->getRenderFullSummary()) {
                 $desc = 'updated the task description';
             } else {
                 $desc = 'updated the task description; ' . $this->renderExpandLink($transaction);
             }
             break;
         case ManiphestTransactionType::TYPE_NONE:
             $verb = 'Commented On';
             $desc = 'added a comment';
             break;
         case ManiphestTransactionType::TYPE_OWNER:
             if ($transaction->getAuthorPHID() == $new) {
                 $verb = 'Claimed';
                 $desc = 'claimed this task';
                 $classes[] = 'claimed';
             } else {
                 if (!$new) {
                     $verb = 'Up For Grabs';
                     $desc = 'placed this task up for grabs';
                     $classes[] = 'upforgrab';
                 } else {
                     if (!$old) {
                         $verb = 'Assigned';
                         $desc = 'assigned this task to ' . $this->renderHandles(array($new));
                         $classes[] = 'assigned';
                     } else {
                         $verb = 'Reassigned';
                         $desc = 'reassigned this task from ' . $this->renderHandles(array($old)) . ' to ' . $this->renderHandles(array($new));
                         $classes[] = 'reassigned';
                     }
                 }
             }
             break;
         case ManiphestTransactionType::TYPE_CCS:
             if ($this->preview) {
                 $verb = 'Changed CC';
                 $desc = 'changed CCs..';
                 break;
             }
             $added = array_diff($new, $old);
             $removed = array_diff($old, $new);
             if ($added && !$removed) {
                 $verb = 'Added CC';
                 if (count($added) == 1) {
                     $desc = 'added ' . $this->renderHandles($added) . ' to CC';
                 } else {
                     $desc = 'added CCs: ' . $this->renderHandles($added);
                 }
             } else {
                 if ($removed && !$added) {
                     $verb = 'Removed CC';
                     if (count($removed) == 1) {
                         $desc = 'removed ' . $this->renderHandles($removed) . ' from CC';
                     } else {
                         $desc = 'removed CCs: ' . $this->renderHandles($removed);
                     }
                 } else {
                     $verb = 'Changed CC';
                     $desc = 'changed CCs, added: ' . $this->renderHandles($added) . '; ' . 'removed: ' . $this->renderHandles($removed);
                 }
             }
             break;
         case ManiphestTransactionType::TYPE_PROJECTS:
             if ($this->preview) {
                 $verb = 'Changed Projects';
                 $desc = 'changed projects..';
                 break;
             }
             $added = array_diff($new, $old);
             $removed = array_diff($old, $new);
             if ($added && !$removed) {
                 $verb = 'Added Project';
                 if (count($added) == 1) {
                     $desc = 'added project ' . $this->renderHandles($added);
                 } else {
                     $desc = 'added projects: ' . $this->renderHandles($added);
                 }
             } else {
                 if ($removed && !$added) {
                     $verb = 'Removed Project';
                     if (count($removed) == 1) {
                         $desc = 'removed project ' . $this->renderHandles($removed);
                     } else {
                         $desc = 'removed projectss: ' . $this->renderHandles($removed);
                     }
                 } else {
                     $verb = 'Changed Projects';
                     $desc = 'changed projects, added: ' . $this->renderHandles($added) . '; ' . 'removed: ' . $this->renderHandles($removed);
                 }
             }
             break;
         case ManiphestTransactionType::TYPE_STATUS:
             if ($new == ManiphestTaskStatus::STATUS_OPEN) {
                 if ($old) {
                     $verb = 'Reopened';
                     $desc = 'reopened this task';
                     $classes[] = 'reopened';
                 } else {
                     $verb = 'Created';
                     $desc = 'created this task';
                     $classes[] = 'created';
                 }
             } else {
                 if ($new == ManiphestTaskStatus::STATUS_CLOSED_SPITE) {
                     $verb = 'Spited';
                     $desc = 'closed this task out of spite';
                     $classes[] = 'spited';
                 } else {
                     if ($new == ManiphestTaskStatus::STATUS_CLOSED_DUPLICATE) {
                         $verb = 'Merged';
                         $desc = 'closed this task as a duplicate';
                         $classes[] = 'duplicate';
                     } else {
                         $verb = 'Closed';
                         $full = idx(ManiphestTaskStatus::getTaskStatusMap(), $new, '???');
                         $desc = 'closed this task as "' . $full . '"';
                         $classes[] = 'closed';
                     }
                 }
             }
             break;
         case ManiphestTransactionType::TYPE_PRIORITY:
             $old_name = ManiphestTaskPriority::getTaskPriorityName($old);
             $new_name = ManiphestTaskPriority::getTaskPriorityName($new);
             if ($old == ManiphestTaskPriority::PRIORITY_TRIAGE) {
                 $verb = 'Triaged';
                 $desc = 'triaged this task as "' . $new_name . '" priority';
             } else {
                 if ($old > $new) {
                     $verb = 'Lowered Priority';
                     $desc = 'lowered the priority of this task from "' . $old_name . '" to ' . '"' . $new_name . '"';
                 } else {
                     $verb = 'Raised Priority';
                     $desc = 'raised the priority of this task from "' . $old_name . '" to ' . '"' . $new_name . '"';
                 }
             }
             if ($new == ManiphestTaskPriority::PRIORITY_UNBREAK_NOW) {
                 $classes[] = 'unbreaknow';
             }
             break;
         case ManiphestTransactionType::TYPE_ATTACH:
             if ($this->preview) {
                 $verb = 'Changed Attached';
                 $desc = 'changed attachments..';
                 break;
             }
             $old_raw = nonempty($old, array());
             $new_raw = nonempty($new, array());
             foreach (array(PhabricatorPHIDConstants::PHID_TYPE_DREV, PhabricatorPHIDConstants::PHID_TYPE_TASK, PhabricatorPHIDConstants::PHID_TYPE_FILE) as $type) {
                 $old = array_keys(idx($old_raw, $type, array()));
                 $new = array_keys(idx($new_raw, $type, array()));
                 if ($old != $new) {
                     break;
                 }
             }
             $added = array_diff($new, $old);
             $removed = array_diff($old, $new);
             $add_desc = $this->renderHandles($added);
             $rem_desc = $this->renderHandles($removed);
             switch ($type) {
                 case PhabricatorPHIDConstants::PHID_TYPE_DREV:
                     $singular = 'Differential Revision';
                     $plural = 'Differential Revisions';
                     break;
                 case PhabricatorPHIDConstants::PHID_TYPE_FILE:
                     $singular = 'file';
                     $plural = 'files';
                     break;
                 case PhabricatorPHIDConstants::PHID_TYPE_TASK:
                     $singular = 'Maniphest Task';
                     $plural = 'Maniphest Tasks';
                     $dependency = true;
                     break;
             }
             if ($added && !$removed) {
                 $verb = 'Attached';
                 if (count($added) == 1) {
                     $desc = 'attached ' . $singular . ': ' . $add_desc;
                 } else {
                     $desc = 'attached ' . $plural . ': ' . $add_desc;
                 }
             } else {
                 if ($removed && !$added) {
                     $verb = 'Detached';
                     if (count($removed) == 1) {
                         $desc = 'detached ' . $singular . ': ' . $rem_desc;
                     } else {
                         $desc = 'detached ' . $plural . ': ' . $rem_desc;
                     }
                 } else {
                     $verb = 'Changed Attached';
                     $desc = 'changed attached ' . $plural . ', added: ' . $add_desc . '; ' . 'removed: ' . $rem_desc;
                 }
             }
             break;
         case ManiphestTransactionType::TYPE_AUXILIARY:
             // TODO: This is temporary and hacky! Allow auxiliary fields to
             // customize this.
             $old_esc = phutil_escape_html($old);
             $new_esc = phutil_escape_html($new);
             $aux_key = $transaction->getMetadataValue('aux:key');
             if ($old === null) {
                 $verb = "Set Field";
                 $desc = "set field '{$aux_key}' to '{$new_esc}'";
             } else {
                 if ($new === null) {
                     $verb = "Removed Field";
                     $desc = "removed field '{$aux_key}'";
                 } else {
                     $verb = "Updated Field";
                     $desc = "updated field '{$aux_key}' " . "from '{$old_esc}' to '{$new_esc}'";
                 }
             }
             break;
         default:
             return array($type, ' brazenly ' . $type . "'d", $classes);
     }
     return array($verb, $desc, $classes);
 }
 public function buildWorkbook(PHPExcel $workbook, array $tasks, array $handles, PhabricatorUser $user)
 {
     $sheet = $workbook->setActiveSheetIndex(0);
     $sheet->setTitle(pht('Tasks'));
     // Header Cell
     // title => the displayed header title in the spreadsheet, in row 0
     // width => initial width in pixels for the column, null leaves unspecified
     // celltype => which format the column data should be set as, default is STRING
     //   can be null if it's a date field
     // isDate => there is no date format in the PHPExcel_Cell_DataType, so this is needed
     // cftype => the custom field data type, only specified for custom field headers
     $colHeaders = array(array('title' => pht('ID'), 'width' => null, 'celltype' => PHPExcel_Cell_DataType::TYPE_STRING, 'isDate' => false), array('title' => pht('Owner'), 'width' => 15, 'celltype' => PHPExcel_Cell_DataType::TYPE_STRING, 'isDate' => false), array('title' => pht('Status'), 'width' => null, 'celltype' => PHPExcel_Cell_DataType::TYPE_STRING, 'isDate' => false), array('title' => pht('Priority'), 'width' => 10, 'celltype' => PHPExcel_Cell_DataType::TYPE_STRING, 'isDate' => false), array('title' => pht('Date Created'), 'width' => 15, 'celltype' => null, 'isDate' => true), array('title' => pht('Date Updated'), 'width' => 15, 'celltype' => null, 'isDate' => true), array('title' => pht('Title'), 'width' => 60, 'celltype' => PHPExcel_Cell_DataType::TYPE_STRING, 'isDate' => false), array('title' => pht('Projects'), 'width' => 20, 'celltype' => PHPExcel_Cell_DataType::TYPE_STRING, 'isDate' => false), array('title' => pht('Columns'), 'width' => 20, 'celltype' => PHPExcel_Cell_DataType::TYPE_STRING, 'isDate' => false), array('title' => pht('URI'), 'width' => 30, 'celltype' => PHPExcel_Cell_DataType::TYPE_STRING, 'isDate' => false));
     // Create the custom fields from their configured definition and extract header cell details
     $customFields = id(new ManiphestConfiguredCustomField())->createFields(null);
     $customFieldsHeaderMap = array();
     foreach ($customFields as $customField) {
         // Using the proxy I think is needed due to using ManiphestConfiguredCustomField.createFields
         // That seems to be wrapping the PhabricatorStandardCustomField, but doesn't proxy/delegate the
         // getFieldType() method which is needed here.
         $fieldName = $customField->getProxy()->getFieldName();
         $fieldType = $customField->getProxy()->getFieldType();
         $isDateField = $fieldType == 'date';
         $cellType = PHPExcel_Cell_DataType::TYPE_STRING;
         if ($fieldType == 'int') {
             $cellType = PHPExcel_Cell_DataType::TYPE_NUMERIC;
         }
         $customFieldHeader = array('title' => $fieldName, 'width' => null, 'celltype' => $cellType, 'isDate' => $isDateField, 'cftype' => $fieldType);
         $customFieldsHeaderMap[$fieldName] = $customFieldHeader;
         $colHeaders[] = $customFieldHeader;
     }
     $colHeaders[] = array('title' => pht('Description'), 'width' => 100, 'celltype' => PHPExcel_Cell_DataType::TYPE_STRING, 'isDate' => false);
     $status_map = ManiphestTaskStatus::getTaskStatusMap();
     $pri_map = ManiphestTaskPriority::getTaskPriorityMap();
     $header_format = array('font' => array('bold' => true));
     $rows = array();
     $headerRow = array();
     foreach ($colHeaders as $colIdx => $column) {
         $headerRow[] = $column['title'];
     }
     $rows[] = $headerRow;
     $project_ids_used = array();
     foreach ($tasks as $task) {
         foreach ($task->getProjectPHIDs() as $phid) {
             $project_ids_used[] = $phid;
         }
     }
     $project_ids_used = array_unique($project_ids_used);
     $ppositions = id(new PhabricatorProjectColumnPositionQuery())->setViewer($user)->withObjectPHIDs(mpull($tasks, 'getPHID'))->needColumns(true)->execute();
     $ppositions = mpull($ppositions, null, 'getObjectPHID');
     $task_phid_to_ppositions = array();
     foreach ($tasks as $task) {
         $task_phid = $task->getPHID();
         if (empty($ppositions[$task_phid])) {
             continue;
         }
         if (empty($task_phid_to_ppositions[$task_phid])) {
             $task_phid_to_ppositions[$task_phid] = array();
         }
         $task_phid_to_ppositions[$task_phid][] = $ppositions[$task_phid];
     }
     foreach ($tasks as $task) {
         $task_owner = null;
         if ($task->getOwnerPHID()) {
             $task_owner = $handles[$task->getOwnerPHID()]->getName();
         }
         $projects = array();
         $project_columns = array();
         foreach ($task->getProjectPHIDs() as $phid) {
             $projects[] = $handles[$phid]->getName();
         }
         $projects = implode(', ', $projects);
         $pcolumn_names = array();
         $task_ppositions = $task_phid_to_ppositions[$task->getPHID()];
         foreach ($task_ppositions as $task_position) {
             $pcolumn_names[] = $task_position->getColumn()->getDisplayName();
         }
         $pcolumn_names = implode(', ', $pcolumn_names);
         $row = array('T' . $task->getID(), $task_owner, idx($status_map, $task->getStatus(), '?'), idx($pri_map, $task->getPriority(), '?'), $this->computeExcelDate($task->getDateCreated()), $this->computeExcelDate($task->getDateModified()), $task->getTitle(), $projects, $pcolumn_names, PhabricatorEnv::getProductionURI('/T' . $task->getID()));
         // Query for the custom fields for a specific maniphest task object
         $taskCustomFields = PhabricatorCustomField::getObjectFields($task, PhabricatorCustomField::ROLE_DEFAULT);
         $taskCustomFields->readFieldsFromStorage($task);
         $taskCustomFieldsMap = array();
         foreach ($taskCustomFields->getFields() as $customField) {
             $fieldName = $customField->getFieldName();
             $taskCustomFieldsMap[$fieldName] = $customField;
         }
         // We want to order the items from the task custom field object in the same order
         // which the custom field headers exist in the $colHeaders array
         // So loop over the header map, and pull the populated custom field from the populated map
         foreach ($customFieldsHeaderMap as $fieldName => $customFieldHeader) {
             $customField = $taskCustomFieldsMap[$fieldName];
             if ($customField == null) {
                 $row[] = null;
                 continue;
             }
             $fieldValue = $customField->getProxy()->getFieldValue();
             // option/select-style custom fields have values which are actually the identifier from json spec
             // lookup the display value to be used from the 'getOptions()' on the PhabricatorStandardCustomFieldSelect
             if ($fieldValue !== null && $customFieldHeader['cftype'] == 'select') {
                 $options = $customField->getProxy()->getOptions();
                 $fieldValue = $options[$fieldValue];
             }
             $row[] = $fieldValue;
         }
         $row[] = id(new PhutilUTF8StringTruncator())->setMaximumBytes(512)->truncateString($task->getDescription());
         $rows[] = $row;
     }
     foreach ($rows as $row => $cols) {
         foreach ($cols as $col => $spec) {
             $cell_name = $this->col($col) . ($row + 1);
             $cell = $sheet->setCellValue($cell_name, $spec, $return_cell = true);
             // If the header row only apply the bold-style and width, but do not
             // apply the date-format/data-type since the values will always be string
             if ($row == 0) {
                 $sheet->getStyle($cell_name)->applyFromArray($header_format);
                 $width = $colHeaders[$col]['width'];
                 if ($width !== null) {
                     $sheet->getColumnDimension($this->col($col))->setWidth($width);
                 }
             } else {
                 $is_date = $colHeaders[$col]['isDate'];
                 if ($is_date) {
                     $code = PHPExcel_Style_NumberFormat::FORMAT_DATE_YYYYMMDD2;
                     $sheet->getStyle($cell_name)->getNumberFormat()->setFormatCode($code);
                 } else {
                     $cellType = $colHeaders[$col]['celltype'];
                     if ($cellType == null) {
                         $cellType = PHPExcel_Cell_DataType::TYPE_STRING;
                     }
                     $cell->setDataType($cellType);
                 }
             }
         }
     }
 }
 protected function applyRequest(ManiphestTask $task, ConduitAPIRequest $request, $is_new)
 {
     $changes = array();
     if ($is_new) {
         $task->setTitle((string) $request->getValue('title'));
         $task->setDescription((string) $request->getValue('description'));
         $changes[ManiphestTransactionType::TYPE_STATUS] = ManiphestTaskStatus::STATUS_OPEN;
     } else {
         $comments = $request->getValue('comments');
         if (!$is_new && $comments !== null) {
             $changes[ManiphestTransactionType::TYPE_NONE] = null;
         }
         $title = $request->getValue('title');
         if ($title !== null) {
             $changes[ManiphestTransactionType::TYPE_TITLE] = $title;
         }
         $desc = $request->getValue('description');
         if ($desc !== null) {
             $changes[ManiphestTransactionType::TYPE_DESCRIPTION] = $desc;
         }
         $status = $request->getValue('status');
         if ($status !== null) {
             $valid_statuses = ManiphestTaskStatus::getTaskStatusMap();
             if (!isset($valid_statuses[$status])) {
                 throw id(new ConduitException('ERR-INVALID-PARAMETER'))->setErrorDescription('Status set to invalid value.');
             }
             $changes[ManiphestTransactionType::TYPE_STATUS] = $status;
         }
     }
     $priority = $request->getValue('priority');
     if ($priority !== null) {
         $valid_priorities = ManiphestTaskPriority::getTaskPriorityMap();
         if (!isset($valid_priorities[$priority])) {
             throw id(new ConduitException('ERR-INVALID-PARAMETER'))->setErrorDescription('Priority set to invalid value.');
         }
         $changes[ManiphestTransactionType::TYPE_PRIORITY] = $priority;
     }
     $owner_phid = $request->getValue('ownerPHID');
     if ($owner_phid !== null) {
         $this->validatePHIDList(array($owner_phid), PhabricatorPHIDConstants::PHID_TYPE_USER, 'ownerPHID');
         $changes[ManiphestTransactionType::TYPE_OWNER] = $owner_phid;
     }
     $ccs = $request->getValue('ccPHIDs');
     if ($ccs !== null) {
         $this->validatePHIDList($ccs, PhabricatorPHIDConstants::PHID_TYPE_USER, 'ccPHIDS');
         $changes[ManiphestTransactionType::TYPE_CCS] = $ccs;
     }
     $project_phids = $request->getValue('projectPHIDs');
     if ($project_phids !== null) {
         $this->validatePHIDList($project_phids, PhabricatorPHIDConstants::PHID_TYPE_PROJ, 'projectPHIDS');
         $changes[ManiphestTransactionType::TYPE_PROJECTS] = $project_phids;
     }
     $file_phids = $request->getValue('filePHIDs');
     if ($file_phids !== null) {
         $this->validatePHIDList($file_phids, PhabricatorPHIDConstants::PHID_TYPE_FILE, 'filePHIDS');
         $file_map = array_fill_keys($file_phids, true);
         $attached = $task->getAttached();
         $attached[PhabricatorPHIDConstants::PHID_TYPE_FILE] = $file_map;
         $changes[ManiphestTransactionType::TYPE_ATTACH] = $attached;
     }
     $content_source = PhabricatorContentSource::newForSource(PhabricatorContentSource::SOURCE_CONDUIT, array());
     $template = new ManiphestTransaction();
     $template->setContentSource($content_source);
     $template->setAuthorPHID($request->getUser()->getPHID());
     $transactions = array();
     foreach ($changes as $type => $value) {
         $transaction = clone $template;
         $transaction->setTransactionType($type);
         $transaction->setNewValue($value);
         if ($type == ManiphestTransactionType::TYPE_NONE) {
             $transaction->setComments($comments);
         }
         $transactions[] = $transaction;
     }
     $auxiliary = $request->getValue('auxiliary');
     if ($auxiliary) {
         $task->loadAndAttachAuxiliaryAttributes();
         foreach ($auxiliary as $aux_key => $aux_value) {
             $transaction = clone $template;
             $transaction->setTransactionType(ManiphestTransactionType::TYPE_AUXILIARY);
             $transaction->setMetadataValue('aux:key', $aux_key);
             $transaction->setNewValue($aux_value);
             $transactions[] = $transaction;
         }
     }
     $event = new PhabricatorEvent(PhabricatorEventType::TYPE_MANIPHEST_WILLEDITTASK, array('task' => $task, 'new' => $is_new, 'transactions' => $transactions));
     $event->setUser($request->getUser());
     $event->setConduitRequest($request);
     PhutilEventEngine::dispatchEvent($event);
     $task = $event->getValue('task');
     $transactions = $event->getValue('transactions');
     $editor = new ManiphestTransactionEditor();
     $editor->applyTransactions($task, $transactions);
     $event = new PhabricatorEvent(PhabricatorEventType::TYPE_MANIPHEST_DIDEDITTASK, array('task' => $task, 'new' => $is_new, 'transactions' => $transactions));
     $event->setUser($request->getUser());
     $event->setConduitRequest($request);
     PhutilEventEngine::dispatchEvent($event);
 }
     }
     break;
 case 'taskIDs':
     if ($value) {
         $new_data['ids'] = $value;
     }
     break;
 case 'status':
     $include_open = !empty($value['open']);
     $include_closed = !empty($value['closed']);
     if ($include_open xor $include_closed) {
         if ($include_open) {
             $new_data['statuses'] = array($old_open_status);
         } else {
             $statuses = array();
             foreach (ManiphestTaskStatus::getTaskStatusMap() as $status => $n) {
                 if ($status != $old_open_status) {
                     $statuses[] = $status;
                 }
             }
             $new_data['statuses'] = $statuses;
         }
     }
     break;
 case 'order':
     $map = array('priority' => 'priority', 'updated' => 'updated', 'created' => 'created', 'title' => 'title');
     if (isset($map[$value])) {
         $new_data['order'] = $map[$value];
     } else {
         $new_data['order'] = 'priority';
     }
 public function processRequest()
 {
     $request = $this->getRequest();
     $user = $request->getUser();
     $e_title = null;
     $priority_map = ManiphestTaskPriority::getTaskPriorityMap();
     $task = id(new ManiphestTaskQuery())->setViewer($user)->withIDs(array($this->id))->needSubscriberPHIDs(true)->executeOne();
     if (!$task) {
         return new Aphront404Response();
     }
     $workflow = $request->getStr('workflow');
     $parent_task = null;
     if ($workflow && is_numeric($workflow)) {
         $parent_task = id(new ManiphestTaskQuery())->setViewer($user)->withIDs(array($workflow))->executeOne();
     }
     $field_list = PhabricatorCustomField::getObjectFields($task, PhabricatorCustomField::ROLE_VIEW);
     $field_list->setViewer($user)->readFieldsFromStorage($task);
     $e_commit = ManiphestTaskHasCommitEdgeType::EDGECONST;
     $e_dep_on = ManiphestTaskDependsOnTaskEdgeType::EDGECONST;
     $e_dep_by = ManiphestTaskDependedOnByTaskEdgeType::EDGECONST;
     $e_rev = ManiphestTaskHasRevisionEdgeType::EDGECONST;
     $e_mock = ManiphestTaskHasMockEdgeType::EDGECONST;
     $phid = $task->getPHID();
     $query = id(new PhabricatorEdgeQuery())->withSourcePHIDs(array($phid))->withEdgeTypes(array($e_commit, $e_dep_on, $e_dep_by, $e_rev, $e_mock));
     $edges = idx($query->execute(), $phid);
     $phids = array_fill_keys($query->getDestinationPHIDs(), true);
     if ($task->getOwnerPHID()) {
         $phids[$task->getOwnerPHID()] = true;
     }
     $phids[$task->getAuthorPHID()] = true;
     $attached = $task->getAttached();
     foreach ($attached as $type => $list) {
         foreach ($list as $phid => $info) {
             $phids[$phid] = true;
         }
     }
     if ($parent_task) {
         $phids[$parent_task->getPHID()] = true;
     }
     $phids = array_keys($phids);
     $handles = $user->loadHandles($phids);
     $info_view = null;
     if ($parent_task) {
         $info_view = new PHUIInfoView();
         $info_view->setSeverity(PHUIInfoView::SEVERITY_NOTICE);
         $info_view->addButton(id(new PHUIButtonView())->setTag('a')->setHref('/maniphest/task/create/?parent=' . $parent_task->getID())->setText(pht('Create Another Subtask')));
         $info_view->appendChild(hsprintf('Created a subtask of <strong>%s</strong>.', $handles->renderHandle($parent_task->getPHID())));
     } else {
         if ($workflow == 'create') {
             $info_view = new PHUIInfoView();
             $info_view->setSeverity(PHUIInfoView::SEVERITY_NOTICE);
             $info_view->addButton(id(new PHUIButtonView())->setTag('a')->setHref('/maniphest/task/create/?template=' . $task->getID())->setText(pht('Similar Task')));
             $info_view->addButton(id(new PHUIButtonView())->setTag('a')->setHref('/maniphest/task/create/')->setText(pht('Empty Task')));
             $info_view->appendChild(pht('New task created. Create another?'));
         }
     }
     $engine = new PhabricatorMarkupEngine();
     $engine->setViewer($user);
     $engine->setContextObject($task);
     $engine->addObject($task, ManiphestTask::MARKUP_FIELD_DESCRIPTION);
     $timeline = $this->buildTransactionTimeline($task, new ManiphestTransactionQuery(), $engine);
     $resolution_types = ManiphestTaskStatus::getTaskStatusMap();
     $transaction_types = array(PhabricatorTransactions::TYPE_COMMENT => pht('Comment'), ManiphestTransaction::TYPE_STATUS => pht('Change Status'), ManiphestTransaction::TYPE_OWNER => pht('Reassign / Claim'), PhabricatorTransactions::TYPE_SUBSCRIBERS => pht('Add CCs'), ManiphestTransaction::TYPE_PRIORITY => pht('Change Priority'), PhabricatorTransactions::TYPE_EDGE => pht('Associate Projects'));
     // Remove actions the user doesn't have permission to take.
     $requires = array(ManiphestTransaction::TYPE_OWNER => ManiphestEditAssignCapability::CAPABILITY, ManiphestTransaction::TYPE_PRIORITY => ManiphestEditPriorityCapability::CAPABILITY, PhabricatorTransactions::TYPE_EDGE => ManiphestEditProjectsCapability::CAPABILITY, ManiphestTransaction::TYPE_STATUS => ManiphestEditStatusCapability::CAPABILITY);
     foreach ($transaction_types as $type => $name) {
         if (isset($requires[$type])) {
             if (!$this->hasApplicationCapability($requires[$type])) {
                 unset($transaction_types[$type]);
             }
         }
     }
     // Don't show an option to change to the current status, or to change to
     // the duplicate status explicitly.
     unset($resolution_types[$task->getStatus()]);
     unset($resolution_types[ManiphestTaskStatus::getDuplicateStatus()]);
     // Don't show owner/priority changes for closed tasks, as they don't make
     // much sense.
     if ($task->isClosed()) {
         unset($transaction_types[ManiphestTransaction::TYPE_PRIORITY]);
         unset($transaction_types[ManiphestTransaction::TYPE_OWNER]);
     }
     $default_claim = array($user->getPHID() => $user->getUsername() . ' (' . $user->getRealName() . ')');
     $draft = id(new PhabricatorDraft())->loadOneWhere('authorPHID = %s AND draftKey = %s', $user->getPHID(), $task->getPHID());
     if ($draft) {
         $draft_text = $draft->getDraft();
     } else {
         $draft_text = null;
     }
     $projects_source = new PhabricatorProjectDatasource();
     $users_source = new PhabricatorPeopleDatasource();
     $mailable_source = new PhabricatorMetaMTAMailableDatasource();
     $comment_form = new AphrontFormView();
     $comment_form->setUser($user)->setWorkflow(true)->setAction('/maniphest/transaction/save/')->setEncType('multipart/form-data')->addHiddenInput('taskID', $task->getID())->appendChild(id(new AphrontFormSelectControl())->setLabel(pht('Action'))->setName('action')->setOptions($transaction_types)->setID('transaction-action'))->appendChild(id(new AphrontFormSelectControl())->setLabel(pht('Status'))->setName('resolution')->setControlID('resolution')->setControlStyle('display: none')->setOptions($resolution_types))->appendControl(id(new AphrontFormTokenizerControl())->setLabel(pht('Assign To'))->setName('assign_to')->setControlID('assign_to')->setControlStyle('display: none')->setID('assign-tokenizer')->setDisableBehavior(true)->setDatasource($users_source))->appendControl(id(new AphrontFormTokenizerControl())->setLabel(pht('CCs'))->setName('ccs')->setControlID('ccs')->setControlStyle('display: none')->setID('cc-tokenizer')->setDisableBehavior(true)->setDatasource($mailable_source))->appendChild(id(new AphrontFormSelectControl())->setLabel(pht('Priority'))->setName('priority')->setOptions($priority_map)->setControlID('priority')->setControlStyle('display: none')->setValue($task->getPriority()))->appendControl(id(new AphrontFormTokenizerControl())->setLabel(pht('Projects'))->setName('projects')->setControlID('projects')->setControlStyle('display: none')->setID('projects-tokenizer')->setDisableBehavior(true)->setDatasource($projects_source))->appendChild(id(new AphrontFormFileControl())->setLabel(pht('File'))->setName('file')->setControlID('file')->setControlStyle('display: none'))->appendChild(id(new PhabricatorRemarkupControl())->setUser($user)->setLabel(pht('Comments'))->setName('comments')->setValue($draft_text)->setID('transaction-comments')->setUser($user))->appendChild(id(new AphrontFormSubmitControl())->setValue(pht('Submit')));
     $control_map = array(ManiphestTransaction::TYPE_STATUS => 'resolution', ManiphestTransaction::TYPE_OWNER => 'assign_to', PhabricatorTransactions::TYPE_SUBSCRIBERS => 'ccs', ManiphestTransaction::TYPE_PRIORITY => 'priority', PhabricatorTransactions::TYPE_EDGE => 'projects');
     $tokenizer_map = array(PhabricatorTransactions::TYPE_EDGE => array('id' => 'projects-tokenizer', 'src' => $projects_source->getDatasourceURI(), 'placeholder' => $projects_source->getPlaceholderText()), ManiphestTransaction::TYPE_OWNER => array('id' => 'assign-tokenizer', 'src' => $users_source->getDatasourceURI(), 'value' => $default_claim, 'limit' => 1, 'placeholder' => $users_source->getPlaceholderText()), PhabricatorTransactions::TYPE_SUBSCRIBERS => array('id' => 'cc-tokenizer', 'src' => $mailable_source->getDatasourceURI(), 'placeholder' => $mailable_source->getPlaceholderText()));
     // TODO: Initializing these behaviors for logged out users fatals things.
     if ($user->isLoggedIn()) {
         Javelin::initBehavior('maniphest-transaction-controls', array('select' => 'transaction-action', 'controlMap' => $control_map, 'tokenizers' => $tokenizer_map));
         Javelin::initBehavior('maniphest-transaction-preview', array('uri' => '/maniphest/transaction/preview/' . $task->getID() . '/', 'preview' => 'transaction-preview', 'comments' => 'transaction-comments', 'action' => 'transaction-action', 'map' => $control_map, 'tokenizers' => $tokenizer_map));
     }
     $is_serious = PhabricatorEnv::getEnvConfig('phabricator.serious-business');
     $comment_header = $is_serious ? pht('Add Comment') : pht('Weigh In');
     $preview_panel = phutil_tag_div('aphront-panel-preview', phutil_tag('div', array('id' => 'transaction-preview'), phutil_tag_div('aphront-panel-preview-loading-text', pht('Loading preview...'))));
     $object_name = 'T' . $task->getID();
     $actions = $this->buildActionView($task);
     $crumbs = $this->buildApplicationCrumbs()->addTextCrumb($object_name, '/' . $object_name);
     $header = $this->buildHeaderView($task);
     $properties = $this->buildPropertyView($task, $field_list, $edges, $actions, $handles);
     $description = $this->buildDescriptionView($task, $engine);
     if (!$user->isLoggedIn()) {
         // TODO: Eventually, everything should run through this. For now, we're
         // only using it to get a consistent "Login to Comment" button.
         $comment_box = id(new PhabricatorApplicationTransactionCommentView())->setUser($user)->setRequestURI($request->getRequestURI());
         $preview_panel = null;
     } else {
         $comment_box = id(new PHUIObjectBoxView())->setFlush(true)->setHeaderText($comment_header)->appendChild($comment_form);
         $timeline->setQuoteTargetID('transaction-comments');
         $timeline->setQuoteRef($object_name);
     }
     $object_box = id(new PHUIObjectBoxView())->setHeader($header)->addPropertyList($properties);
     if ($info_view) {
         $object_box->setInfoView($info_view);
     }
     if ($description) {
         $object_box->addPropertyList($description);
     }
     return $this->buildApplicationPage(array($crumbs, $object_box, $timeline, $comment_box, $preview_panel), array('title' => 'T' . $task->getID() . ' ' . $task->getTitle(), 'pageObjects' => array($task->getPHID())));
 }
 private function describeAction($transaction)
 {
     $verb = null;
     $desc = null;
     $classes = array();
     $handles = $this->handles;
     $type = $transaction->getTransactionType();
     $author_phid = $transaction->getAuthorPHID();
     $new = $transaction->getNewValue();
     $old = $transaction->getOldValue();
     switch ($type) {
         case ManiphestTransactionType::TYPE_TITLE:
             $verb = 'Retitled';
             $desc = 'changed the title from ' . $this->renderString($old) . ' to ' . $this->renderString($new);
             break;
         case ManiphestTransactionType::TYPE_DESCRIPTION:
             $verb = 'Edited';
             if ($this->forEmail || $this->getRenderFullSummary()) {
                 $desc = 'updated the task description';
             } else {
                 $desc = 'updated the task description; ' . $this->renderExpandLink($transaction);
             }
             break;
         case ManiphestTransactionType::TYPE_NONE:
             $verb = 'Commented On';
             $desc = 'added a comment';
             break;
         case ManiphestTransactionType::TYPE_OWNER:
             if ($transaction->getAuthorPHID() == $new) {
                 $verb = 'Claimed';
                 $desc = 'claimed this task';
                 $classes[] = 'claimed';
             } else {
                 if (!$new) {
                     $verb = 'Up For Grabs';
                     $desc = 'placed this task up for grabs';
                     $classes[] = 'upforgrab';
                 } else {
                     if (!$old) {
                         $verb = 'Assigned';
                         $desc = 'assigned this task to ' . $this->renderHandles(array($new));
                         $classes[] = 'assigned';
                     } else {
                         $verb = 'Reassigned';
                         $desc = 'reassigned this task from ' . $this->renderHandles(array($old)) . ' to ' . $this->renderHandles(array($new));
                         $classes[] = 'reassigned';
                     }
                 }
             }
             break;
         case ManiphestTransactionType::TYPE_CCS:
             $added = array_diff($new, $old);
             $removed = array_diff($old, $new);
             // can only add in preview so just show placeholder if nothing to add
             if ($this->preview && empty($added)) {
                 $verb = 'Changed CC';
                 $desc = 'changed CCs..';
                 break;
             }
             if ($added && !$removed) {
                 $verb = 'Added CC';
                 if (count($added) == 1) {
                     $desc = 'added ' . $this->renderHandles($added) . ' to CC';
                 } else {
                     $desc = 'added CCs: ' . $this->renderHandles($added);
                 }
             } else {
                 if ($removed && !$added) {
                     $verb = 'Removed CC';
                     if (count($removed) == 1) {
                         $desc = 'removed ' . $this->renderHandles($removed) . ' from CC';
                     } else {
                         $desc = 'removed CCs: ' . $this->renderHandles($removed);
                     }
                 } else {
                     $verb = 'Changed CC';
                     $desc = 'changed CCs, added: ' . $this->renderHandles($added) . '; ' . 'removed: ' . $this->renderHandles($removed);
                 }
             }
             break;
         case ManiphestTransactionType::TYPE_EDGE:
             $edge_type = $transaction->getMetadataValue('edge:type');
             $add = array_diff_key($new, $old);
             $rem = array_diff_key($old, $new);
             if ($add && !$rem) {
                 $verb = $this->getEdgeAddVerb($edge_type);
                 $desc = $this->getEdgeAddList($edge_type, $add);
             } else {
                 if ($rem && !$add) {
                     $verb = $this->getEdgeRemVerb($edge_type);
                     $desc = $this->getEdgeRemList($edge_type, $rem);
                 } else {
                     $verb = $this->getEdgeEditVerb($edge_type);
                     $desc = $this->getEdgeEditList($edge_type, $add, $rem);
                 }
             }
             break;
         case ManiphestTransactionType::TYPE_PROJECTS:
             $added = array_diff($new, $old);
             $removed = array_diff($old, $new);
             // can only add in preview so just show placeholder if nothing to add
             if ($this->preview && empty($added)) {
                 $verb = 'Changed Projects';
                 $desc = 'changed projects..';
                 break;
             }
             if ($added && !$removed) {
                 $verb = 'Added Project';
                 if (count($added) == 1) {
                     $desc = 'added project ' . $this->renderHandles($added);
                 } else {
                     $desc = 'added projects: ' . $this->renderHandles($added);
                 }
             } else {
                 if ($removed && !$added) {
                     $verb = 'Removed Project';
                     if (count($removed) == 1) {
                         $desc = 'removed project ' . $this->renderHandles($removed);
                     } else {
                         $desc = 'removed projects: ' . $this->renderHandles($removed);
                     }
                 } else {
                     $verb = 'Changed Projects';
                     $desc = 'changed projects, added: ' . $this->renderHandles($added) . '; ' . 'removed: ' . $this->renderHandles($removed);
                 }
             }
             break;
         case ManiphestTransactionType::TYPE_STATUS:
             if ($new == ManiphestTaskStatus::STATUS_OPEN) {
                 if ($old) {
                     $verb = 'Reopened';
                     $desc = 'reopened this task';
                     $classes[] = 'reopened';
                 } else {
                     $verb = 'Created';
                     $desc = 'created this task';
                     $classes[] = 'created';
                 }
             } else {
                 if ($new == ManiphestTaskStatus::STATUS_CLOSED_SPITE) {
                     $verb = 'Spited';
                     $desc = 'closed this task out of spite';
                     $classes[] = 'spited';
                 } else {
                     if ($new == ManiphestTaskStatus::STATUS_CLOSED_DUPLICATE) {
                         $verb = 'Merged';
                         $desc = 'closed this task as a duplicate';
                         $classes[] = 'duplicate';
                     } else {
                         $verb = 'Closed';
                         $full = idx(ManiphestTaskStatus::getTaskStatusMap(), $new, '???');
                         $desc = 'closed this task as "' . $full . '"';
                         $classes[] = 'closed';
                     }
                 }
             }
             break;
         case ManiphestTransactionType::TYPE_PRIORITY:
             $old_name = ManiphestTaskPriority::getTaskPriorityName($old);
             $new_name = ManiphestTaskPriority::getTaskPriorityName($new);
             if ($old == ManiphestTaskPriority::PRIORITY_TRIAGE) {
                 $verb = 'Triaged';
                 $desc = 'triaged this task as "' . $new_name . '" priority';
             } else {
                 if ($old > $new) {
                     $verb = 'Lowered Priority';
                     $desc = 'lowered the priority of this task from "' . $old_name . '" to ' . '"' . $new_name . '"';
                 } else {
                     $verb = 'Raised Priority';
                     $desc = 'raised the priority of this task from "' . $old_name . '" to ' . '"' . $new_name . '"';
                 }
             }
             if ($new == ManiphestTaskPriority::PRIORITY_UNBREAK_NOW) {
                 $classes[] = 'unbreaknow';
             }
             break;
         case ManiphestTransactionType::TYPE_ATTACH:
             if ($this->preview) {
                 $verb = 'Changed Attached';
                 $desc = 'changed attachments..';
                 break;
             }
             $old_raw = nonempty($old, array());
             $new_raw = nonempty($new, array());
             foreach (array(PhabricatorPHIDConstants::PHID_TYPE_DREV, PhabricatorPHIDConstants::PHID_TYPE_TASK, PhabricatorPHIDConstants::PHID_TYPE_FILE) as $attach_type) {
                 $old = array_keys(idx($old_raw, $attach_type, array()));
                 $new = array_keys(idx($new_raw, $attach_type, array()));
                 if ($old != $new) {
                     break;
                 }
             }
             $added = array_diff($new, $old);
             $removed = array_diff($old, $new);
             $add_desc = $this->renderHandles($added);
             $rem_desc = $this->renderHandles($removed);
             if ($added && !$removed) {
                 $verb = 'Attached';
                 $desc = 'attached ' . $this->getAttachName($attach_type, count($added)) . ': ' . $add_desc;
             } else {
                 if ($removed && !$added) {
                     $verb = 'Detached';
                     $desc = 'detached ' . $this->getAttachName($attach_type, count($removed)) . ': ' . $rem_desc;
                 } else {
                     $verb = 'Changed Attached';
                     $desc = 'changed attached ' . $this->getAttachName($attach_type, count($added) + count($removed)) . ', added: ' . $add_desc . '; ' . 'removed: ' . $rem_desc;
                 }
             }
             break;
         case ManiphestTransactionType::TYPE_AUXILIARY:
             $aux_key = $transaction->getMetadataValue('aux:key');
             $aux_field = $this->getAuxiliaryField($aux_key);
             $verb = null;
             if ($aux_field) {
                 $verb = $aux_field->renderTransactionEmailVerb($transaction);
             }
             if ($verb === null) {
                 if ($old === null) {
                     $verb = "Set Field";
                 } else {
                     if ($new === null) {
                         $verb = "Removed Field";
                     } else {
                         $verb = "Updated Field";
                     }
                 }
             }
             $desc = null;
             if ($aux_field) {
                 $use_field = $aux_field;
             } else {
                 $use_field = id(new ManiphestAuxiliaryFieldDefaultSpecification())->setFieldType(ManiphestAuxiliaryFieldDefaultSpecification::TYPE_STRING);
             }
             $desc = $use_field->renderTransactionDescription($transaction, $this->forEmail ? ManiphestAuxiliaryFieldSpecification::RENDER_TARGET_TEXT : ManiphestAuxiliaryFieldSpecification::RENDER_TARGET_HTML);
             break;
         default:
             return array($type, ' brazenly ' . $type . "'d", $classes);
     }
     return array($verb, $desc, $classes);
 }
 private function setupEditorBehavior(HeraldRule $rule, array $handles, HeraldAdapter $adapter)
 {
     $serial_conditions = array(array('default', 'default', ''));
     if ($rule->getConditions()) {
         $serial_conditions = array();
         foreach ($rule->getConditions() as $condition) {
             $value = $condition->getValue();
             switch ($condition->getFieldName()) {
                 case HeraldAdapter::FIELD_TASK_PRIORITY:
                     $value_map = array();
                     $priority_map = ManiphestTaskPriority::getTaskPriorityMap();
                     foreach ($value as $priority) {
                         $value_map[$priority] = idx($priority_map, $priority);
                     }
                     $value = $value_map;
                     break;
                 case HeraldAdapter::FIELD_TASK_STATUS:
                     $value_map = array();
                     $status_map = ManiphestTaskStatus::getTaskStatusMap();
                     foreach ($value as $status) {
                         $value_map[$status] = idx($status_map, $status);
                     }
                     $value = $value_map;
                     break;
                 default:
                     if (is_array($value)) {
                         $value_map = array();
                         foreach ($value as $k => $fbid) {
                             $value_map[$fbid] = $handles[$fbid]->getName();
                         }
                         $value = $value_map;
                     }
                     break;
             }
             $serial_conditions[] = array($condition->getFieldName(), $condition->getFieldCondition(), $value);
         }
     }
     $serial_actions = array(array('default', ''));
     if ($rule->getActions()) {
         $serial_actions = array();
         foreach ($rule->getActions() as $action) {
             switch ($action->getAction()) {
                 case HeraldAdapter::ACTION_FLAG:
                 case HeraldAdapter::ACTION_BLOCK:
                     $current_value = $action->getTarget();
                     break;
                 default:
                     if (is_array($action->getTarget())) {
                         $target_map = array();
                         foreach ((array) $action->getTarget() as $fbid) {
                             $target_map[$fbid] = $handles[$fbid]->getName();
                         }
                         $current_value = $target_map;
                     } else {
                         $current_value = $action->getTarget();
                     }
                     break;
             }
             $serial_actions[] = array($action->getAction(), $current_value);
         }
     }
     $all_rules = $this->loadRulesThisRuleMayDependUpon($rule);
     $all_rules = mpull($all_rules, 'getName', 'getPHID');
     asort($all_rules);
     $all_fields = $adapter->getFieldNameMap();
     $all_conditions = $adapter->getConditionNameMap();
     $all_actions = $adapter->getActionNameMap($rule->getRuleType());
     $fields = $adapter->getFields();
     $field_map = array_select_keys($all_fields, $fields);
     // Populate any fields which exist in the rule but which we don't know the
     // names of, so that saving a rule without touching anything doesn't change
     // it.
     foreach ($rule->getConditions() as $condition) {
         $field_name = $condition->getFieldName();
         if (empty($field_map[$field_name])) {
             $field_map[$field_name] = pht('<Unknown Field "%s">', $field_name);
         }
     }
     $actions = $adapter->getActions($rule->getRuleType());
     $action_map = array_select_keys($all_actions, $actions);
     // Populate any actions which exist in the rule but which we don't know the
     // names of, so that saving a rule without touching anything doesn't change
     // it.
     foreach ($rule->getActions() as $action) {
         $action_name = $action->getAction();
         if (empty($action_map[$action_name])) {
             $action_map[$action_name] = pht('<Unknown Action "%s">', $action_name);
         }
     }
     $config_info = array();
     $config_info['fields'] = $field_map;
     $config_info['conditions'] = $all_conditions;
     $config_info['actions'] = $action_map;
     foreach ($config_info['fields'] as $field => $name) {
         try {
             $field_conditions = $adapter->getConditionsForField($field);
         } catch (Exception $ex) {
             $field_conditions = array(HeraldAdapter::CONDITION_UNCONDITIONALLY);
         }
         $config_info['conditionMap'][$field] = $field_conditions;
     }
     foreach ($config_info['fields'] as $field => $fname) {
         foreach ($config_info['conditionMap'][$field] as $condition) {
             $value_type = $adapter->getValueTypeForFieldAndCondition($field, $condition);
             $config_info['values'][$field][$condition] = $value_type;
         }
     }
     $config_info['rule_type'] = $rule->getRuleType();
     foreach ($config_info['actions'] as $action => $name) {
         try {
             $action_value = $adapter->getValueTypeForAction($action, $rule->getRuleType());
         } catch (Exception $ex) {
             $action_value = array(HeraldAdapter::VALUE_NONE);
         }
         $config_info['targets'][$action] = $action_value;
     }
     $changeflag_options = PhabricatorRepositoryPushLog::getHeraldChangeFlagConditionOptions();
     Javelin::initBehavior('herald-rule-editor', array('root' => 'herald-rule-edit-form', 'conditions' => (object) $serial_conditions, 'actions' => (object) $serial_actions, 'select' => array(HeraldAdapter::VALUE_CONTENT_SOURCE => array('options' => PhabricatorContentSource::getSourceNameMap(), 'default' => PhabricatorContentSource::SOURCE_WEB), HeraldAdapter::VALUE_FLAG_COLOR => array('options' => PhabricatorFlagColor::getColorNameMap(), 'default' => PhabricatorFlagColor::COLOR_BLUE), HeraldPreCommitRefAdapter::VALUE_REF_TYPE => array('options' => array(PhabricatorRepositoryPushLog::REFTYPE_BRANCH => pht('branch (git/hg)'), PhabricatorRepositoryPushLog::REFTYPE_TAG => pht('tag (git)'), PhabricatorRepositoryPushLog::REFTYPE_BOOKMARK => pht('bookmark (hg)')), 'default' => PhabricatorRepositoryPushLog::REFTYPE_BRANCH), HeraldPreCommitRefAdapter::VALUE_REF_CHANGE => array('options' => $changeflag_options, 'default' => PhabricatorRepositoryPushLog::CHANGEFLAG_ADD)), 'template' => $this->buildTokenizerTemplates($handles) + array('rules' => $all_rules), 'author' => array($rule->getAuthorPHID() => $handles[$rule->getAuthorPHID()]->getName()), 'info' => $config_info));
 }
Exemple #25
0
 private function renderConditionValueAsText(HeraldCondition $condition, PhabricatorHandleList $handles)
 {
     $value = $condition->getValue();
     if (!is_array($value)) {
         $value = array($value);
     }
     switch ($condition->getFieldName()) {
         case self::FIELD_TASK_PRIORITY:
             $priority_map = ManiphestTaskPriority::getTaskPriorityMap();
             foreach ($value as $index => $val) {
                 $name = idx($priority_map, $val);
                 if ($name) {
                     $value[$index] = $name;
                 }
             }
             break;
         case self::FIELD_TASK_STATUS:
             $status_map = ManiphestTaskStatus::getTaskStatusMap();
             foreach ($value as $index => $val) {
                 $name = idx($status_map, $val);
                 if ($name) {
                     $value[$index] = $name;
                 }
             }
             break;
         case HeraldPreCommitRefAdapter::FIELD_REF_CHANGE:
             $change_map = PhabricatorRepositoryPushLog::getHeraldChangeFlagConditionOptions();
             foreach ($value as $index => $val) {
                 $name = idx($change_map, $val);
                 if ($name) {
                     $value[$index] = $name;
                 }
             }
             break;
         default:
             foreach ($value as $index => $val) {
                 $handle = $handles->getHandleIfExists($val);
                 if ($handle) {
                     $value[$index] = $handle->renderLink();
                 }
             }
             break;
     }
     $value = phutil_implode_html(', ', $value);
     return $value;
 }
 public function processRequest()
 {
     $request = $this->getRequest();
     $user = $request->getUser();
     $files = array();
     $parent_task = null;
     $template_id = null;
     if ($this->id) {
         $task = id(new ManiphestTask())->load($this->id);
         if (!$task) {
             return new Aphront404Response();
         }
     } else {
         $task = new ManiphestTask();
         $task->setPriority(ManiphestTaskPriority::PRIORITY_TRIAGE);
         $task->setAuthorPHID($user->getPHID());
         // These allow task creation with defaults.
         if (!$request->isFormPost()) {
             $task->setTitle($request->getStr('title'));
             $default_projects = $request->getStr('projects');
             if ($default_projects) {
                 $task->setProjectPHIDs(explode(';', $default_projects));
             }
         }
         $file_phids = $request->getArr('files', array());
         if (!$file_phids) {
             // Allow a single 'file' key instead, mostly since Mac OS X urlencodes
             // square brackets in URLs when passed to 'open', so you can't 'open'
             // a URL like '?files[]=xyz' and have PHP interpret it correctly.
             $phid = $request->getStr('file');
             if ($phid) {
                 $file_phids = array($phid);
             }
         }
         if ($file_phids) {
             $files = id(new PhabricatorFile())->loadAllWhere('phid IN (%Ls)', $file_phids);
         }
         $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 ($parent_id) {
             $parent_task = id(new ManiphestTask())->load($parent_id);
         }
     }
     $errors = array();
     $e_title = true;
     $extensions = ManiphestTaskExtensions::newExtensions();
     $aux_fields = $extensions->getAuxiliaryFieldSpecifications();
     if ($request->isFormPost()) {
         $changes = array();
         $new_title = $request->getStr('title');
         $new_desc = $request->getStr('description');
         $new_status = $request->getStr('status');
         $workflow = '';
         if ($task->getID()) {
             if ($new_title != $task->getTitle()) {
                 $changes[ManiphestTransactionType::TYPE_TITLE] = $new_title;
             }
             if ($new_desc != $task->getDescription()) {
                 $changes[ManiphestTransactionType::TYPE_DESCRIPTION] = $new_desc;
             }
             if ($new_status != $task->getStatus()) {
                 $changes[ManiphestTransactionType::TYPE_STATUS] = $new_status;
             }
         } else {
             $task->setTitle($new_title);
             $task->setDescription($new_desc);
             $changes[ManiphestTransactionType::TYPE_STATUS] = ManiphestTaskStatus::STATUS_OPEN;
             $workflow = 'create';
         }
         $owner_tokenizer = $request->getArr('assigned_to');
         $owner_phid = reset($owner_tokenizer);
         if (!strlen($new_title)) {
             $e_title = 'Required';
             $errors[] = 'Title is required.';
         }
         foreach ($aux_fields as $aux_field) {
             $aux_field->setValueFromRequest($request);
             if ($aux_field->isRequired() && !strlen($aux_field->getValue())) {
                 $errors[] = $aux_field->getLabel() . ' is required.';
                 $aux_field->setError('Required');
             }
             if (strlen($aux_field->getValue())) {
                 try {
                     $aux_field->validate();
                 } catch (Exception $e) {
                     $errors[] = $e->getMessage();
                     $aux_field->setError('Invalid');
                 }
             }
         }
         if ($errors) {
             $task->setPriority($request->getInt('priority'));
             $task->setOwnerPHID($owner_phid);
             $task->setCCPHIDs($request->getArr('cc'));
             $task->setProjectPHIDs($request->getArr('projects'));
         } else {
             if ($request->getInt('priority') != $task->getPriority()) {
                 $changes[ManiphestTransactionType::TYPE_PRIORITY] = $request->getInt('priority');
             }
             if ($owner_phid != $task->getOwnerPHID()) {
                 $changes[ManiphestTransactionType::TYPE_OWNER] = $owner_phid;
             }
             if ($request->getArr('cc') != $task->getCCPHIDs()) {
                 $changes[ManiphestTransactionType::TYPE_CCS] = $request->getArr('cc');
             }
             $new_proj_arr = $request->getArr('projects');
             $new_proj_arr = array_values($new_proj_arr);
             sort($new_proj_arr);
             $cur_proj_arr = $task->getProjectPHIDs();
             $cur_proj_arr = array_values($cur_proj_arr);
             sort($cur_proj_arr);
             if ($new_proj_arr != $cur_proj_arr) {
                 $changes[ManiphestTransactionType::TYPE_PROJECTS] = $new_proj_arr;
             }
             if ($files) {
                 $file_map = mpull($files, 'getPHID');
                 $file_map = array_fill_keys($file_map, array());
                 $changes[ManiphestTransactionType::TYPE_ATTACH] = array(PhabricatorPHIDConstants::PHID_TYPE_FILE => $file_map);
             }
             $content_source = PhabricatorContentSource::newForSource(PhabricatorContentSource::SOURCE_WEB, array('ip' => $request->getRemoteAddr()));
             $template = new ManiphestTransaction();
             $template->setAuthorPHID($user->getPHID());
             $template->setContentSource($content_source);
             $transactions = array();
             foreach ($changes as $type => $value) {
                 $transaction = clone $template;
                 $transaction->setTransactionType($type);
                 $transaction->setNewValue($value);
                 $transactions[] = $transaction;
             }
             if ($aux_fields) {
                 $task->loadAndAttachAuxiliaryAttributes();
                 foreach ($aux_fields as $aux_field) {
                     $transaction = clone $template;
                     $transaction->setTransactionType(ManiphestTransactionType::TYPE_AUXILIARY);
                     $aux_key = $aux_field->getAuxiliaryKey();
                     $transaction->setMetadataValue('aux:key', $aux_key);
                     $transaction->setNewValue($aux_field->getValueForStorage());
                     $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($user);
                 $event->setAphrontRequest($request);
                 PhutilEventEngine::dispatchEvent($event);
                 $task = $event->getValue('task');
                 $transactions = $event->getValue('transactions');
                 $editor = new ManiphestTransactionEditor();
                 $editor->setAuxiliaryFields($aux_fields);
                 $editor->applyTransactions($task, $transactions);
                 $event = new PhabricatorEvent(PhabricatorEventType::TYPE_MANIPHEST_DIDEDITTASK, array('task' => $task, 'new' => $is_new, 'transactions' => $transactions));
                 $event->setUser($user);
                 $event->setAphrontRequest($request);
                 PhutilEventEngine::dispatchEvent($event);
             }
             if ($parent_task) {
                 $type_task = PhabricatorPHIDConstants::PHID_TYPE_TASK;
                 // NOTE: It's safe to simply apply this transaction without doing
                 // cycle detection because we know the new task has no children.
                 $new_value = $parent_task->getAttached();
                 $new_value[$type_task][$task->getPHID()] = array();
                 $parent_xaction = clone $template;
                 $attach_type = ManiphestTransactionType::TYPE_ATTACH;
                 $parent_xaction->setTransactionType($attach_type);
                 $parent_xaction->setNewValue($new_value);
                 $editor = new ManiphestTransactionEditor();
                 $editor->setAuxiliaryFields($aux_fields);
                 $editor->applyTransactions($parent_task, array($parent_xaction));
                 $workflow = $parent_task->getID();
             }
             $redirect_uri = '/T' . $task->getID();
             if ($workflow) {
                 $redirect_uri .= '?workflow=' . $workflow;
             }
             return id(new AphrontRedirectResponse())->setURI($redirect_uri);
         }
     } else {
         if (!$task->getID()) {
             $task->setCCPHIDs(array($user->getPHID()));
             if ($template_id) {
                 $template_task = id(new ManiphestTask())->load($template_id);
                 if ($template_task) {
                     $task->setCCPHIDs($template_task->getCCPHIDs());
                     $task->setProjectPHIDs($template_task->getProjectPHIDs());
                     $task->setOwnerPHID($template_task->getOwnerPHID());
                 }
             }
         }
     }
     $phids = array_merge(array($task->getOwnerPHID()), $task->getCCPHIDs(), $task->getProjectPHIDs());
     if ($parent_task) {
         $phids[] = $parent_task->getPHID();
     }
     $phids = array_filter($phids);
     $phids = array_unique($phids);
     $handles = id(new PhabricatorObjectHandleData($phids))->loadHandles($phids);
     $tvalues = mpull($handles, 'getFullName', 'getPHID');
     $error_view = null;
     if ($errors) {
         $error_view = new AphrontErrorView();
         $error_view->setErrors($errors);
         $error_view->setTitle('Form Errors');
     }
     $priority_map = ManiphestTaskPriority::getTaskPriorityMap();
     if ($task->getOwnerPHID()) {
         $assigned_value = array($task->getOwnerPHID() => $handles[$task->getOwnerPHID()]->getFullName());
     } else {
         $assigned_value = array();
     }
     if ($task->getCCPHIDs()) {
         $cc_value = array_select_keys($tvalues, $task->getCCPHIDs());
     } else {
         $cc_value = array();
     }
     if ($task->getProjectPHIDs()) {
         $projects_value = array_select_keys($tvalues, $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 = 'Save Task';
         $header_name = 'Edit Task';
     } else {
         if ($parent_task) {
             $cancel_uri = '/T' . $parent_task->getID();
             $button_name = 'Create Task';
             $header_name = 'Create New Subtask';
         } else {
             $button_name = 'Create Task';
             $header_name = 'Create New Task';
         }
     }
     require_celerity_resource('maniphest-task-edit-css');
     $project_tokenizer_id = celerity_generate_unique_node_id();
     $form = new AphrontFormView();
     $form->setUser($user)->setAction($request->getRequestURI()->getPath())->addHiddenInput('template', $template_id);
     if ($parent_task) {
         $form->appendChild(id(new AphrontFormStaticControl())->setLabel('Parent Task')->setValue($handles[$parent_task->getPHID()]->getFullName()))->addHiddenInput('parent', $parent_task->getID());
     }
     $form->appendChild(id(new AphrontFormTextAreaControl())->setLabel('Title')->setName('title')->setError($e_title)->setHeight(AphrontFormTextAreaControl::HEIGHT_VERY_SHORT)->setValue($task->getTitle()));
     if ($task->getID()) {
         // Only show this in "edit" mode, not "create" mode, since creating a
         // non-open task is kind of silly and it would just clutter up the
         // "create" interface.
         $form->appendChild(id(new AphrontFormSelectControl())->setLabel('Status')->setName('status')->setValue($task->getStatus())->setOptions(ManiphestTaskStatus::getTaskStatusMap()));
     }
     $form->appendChild(id(new AphrontFormTokenizerControl())->setLabel('Assigned To')->setName('assigned_to')->setValue($assigned_value)->setUser($user)->setDatasource('/typeahead/common/users/')->setLimit(1))->appendChild(id(new AphrontFormTokenizerControl())->setLabel('CC')->setName('cc')->setValue($cc_value)->setUser($user)->setDatasource('/typeahead/common/mailable/'))->appendChild(id(new AphrontFormSelectControl())->setLabel('Priority')->setName('priority')->setOptions($priority_map)->setValue($task->getPriority()))->appendChild(id(new AphrontFormTokenizerControl())->setLabel('Projects')->setName('projects')->setValue($projects_value)->setID($project_tokenizer_id)->setCaption(javelin_render_tag('a', array('href' => '/project/create/', 'mustcapture' => true, 'sigil' => 'project-create'), 'Create New Project'))->setDatasource('/typeahead/common/projects/'));
     if ($aux_fields) {
         if (!$request->isFormPost()) {
             $task->loadAndAttachAuxiliaryAttributes();
             foreach ($aux_fields as $aux_field) {
                 $aux_key = $aux_field->getAuxiliaryKey();
                 $value = $task->getAuxiliaryAttribute($aux_key);
                 $aux_field->setValueFromStorage($value);
             }
         }
         foreach ($aux_fields as $aux_field) {
             if ($aux_field->isRequired() && !$aux_field->getError() && !$aux_field->getValue()) {
                 $aux_field->setError(true);
             }
             $aux_control = $aux_field->renderControl();
             $form->appendChild($aux_control);
         }
     }
     require_celerity_resource('aphront-error-view-css');
     Javelin::initBehavior('maniphest-project-create', array('tokenizerID' => $project_tokenizer_id));
     if ($files) {
         $file_display = array();
         foreach ($files as $file) {
             $file_display[] = phutil_escape_html($file->getName());
         }
         $file_display = implode('<br />', $file_display);
         $form->appendChild(id(new AphrontFormMarkupControl())->setLabel('Files')->setValue($file_display));
         foreach ($files as $ii => $file) {
             $form->addHiddenInput('files[' . $ii . ']', $file->getPHID());
         }
     }
     $email_create = PhabricatorEnv::getEnvConfig('metamta.maniphest.public-create-email');
     $email_hint = null;
     if (!$task->getID() && $email_create) {
         $email_hint = 'You can also create tasks by sending an email to: ' . '<tt>' . phutil_escape_html($email_create) . '</tt>';
     }
     $panel_id = celerity_generate_unique_node_id();
     $form->appendChild(id(new AphrontFormTextAreaControl())->setLabel('Description')->setName('description')->setID('description-textarea')->setCaption($email_hint)->setValue($task->getDescription()));
     if (!$task->getID()) {
         $form->appendChild(id(new AphrontFormDragAndDropUploadControl())->setLabel('Attached Files')->setName('files')->setDragAndDropTarget($panel_id)->setActivatedClass('aphront-panel-view-drag-and-drop'));
     }
     $form->appendChild(id(new AphrontFormSubmitControl())->addCancelButton($cancel_uri)->setValue($button_name));
     $panel = new AphrontPanelView();
     $panel->setWidth(AphrontPanelView::WIDTH_FULL);
     $panel->setHeader($header_name);
     $panel->setID($panel_id);
     $panel->appendChild($form);
     $description_preview_panel = '<div class="aphront-panel-preview aphront-panel-preview-full">
     <div class="maniphest-description-preview-header">
       Description Preview
     </div>
     <div id="description-preview">
       <div class="aphront-panel-preview-loading-text">
         Loading preview...
       </div>
     </div>
   </div>';
     Javelin::initBehavior('maniphest-description-preview', array('preview' => 'description-preview', 'textarea' => 'description-textarea', 'uri' => '/maniphest/task/descriptionpreview/'));
     return $this->buildStandardPageResponse(array($error_view, $panel, $description_preview_panel), array('title' => $header_name));
 }
 /**
  * @phutil-external-symbol class PHPExcel
  * @phutil-external-symbol class PHPExcel_IOFactory
  * @phutil-external-symbol class PHPExcel_Style_NumberFormat
  */
 public function processRequest()
 {
     $request = $this->getRequest();
     $user = $request->getUser();
     $ok = @(include_once 'PHPExcel.php');
     if (!$ok) {
         $dialog = new AphrontDialogView();
         $dialog->setUser($user);
         $dialog->setTitle('Excel Export Not Configured');
         $dialog->appendChild('<p>This system does not have PHPExcel installed. This software ' . 'component is required to export tasks to Excel. Have your system ' . 'administrator install it from:</p>' . '<br />' . '<p>' . '<a href="http://www.phpexcel.net/">http://www.phpexcel.net/</a>' . '</p>' . '<br />' . '<p>Your PHP "include_path" needs to be updated to include the ' . 'PHPExcel Classes/ directory.</p>');
         $dialog->addCancelButton('/maniphest/');
         return id(new AphrontDialogResponse())->setDialog($dialog);
     }
     $query = id(new PhabricatorSearchQuery())->loadOneWhere('queryKey = %s', $this->key);
     if (!$query) {
         return new Aphront404Response();
     }
     if (!$request->isDialogFormPost()) {
         $dialog = new AphrontDialogView();
         $dialog->setUser($user);
         $dialog->setTitle('Export Tasks to Excel');
         $dialog->appendChild('<p>Do you want to export the query results to Excel?</p>');
         $dialog->addCancelButton('/maniphest/');
         $dialog->addSubmitButton('Export to Excel');
         return id(new AphrontDialogResponse())->setDialog($dialog);
     }
     $query->setParameter('limit', null);
     $query->setParameter('offset', null);
     $query->setParameter('order', 'p');
     $query->setParameter('group', 'n');
     list($tasks, $handles) = ManiphestTaskListController::loadTasks($query);
     // Ungroup tasks.
     $tasks = array_mergev($tasks);
     $all_projects = array_mergev(mpull($tasks, 'getProjectPHIDs'));
     $project_handles = $this->loadViewerHandles($all_projects);
     $handles += $project_handles;
     $workbook = new PHPExcel();
     $sheet = $workbook->setActiveSheetIndex(0);
     $sheet->setTitle('Tasks');
     $widths = array(null, 15, null, 10, 15, 15, 60, 30, 20, 100);
     foreach ($widths as $col => $width) {
         if ($width !== null) {
             $sheet->getColumnDimension($this->col($col))->setWidth($width);
         }
     }
     $status_map = ManiphestTaskStatus::getTaskStatusMap();
     $pri_map = ManiphestTaskPriority::getTaskPriorityMap();
     $date_format = null;
     $rows = array();
     $rows[] = array('ID', 'Owner', 'Status', 'Priority', 'Date Created', 'Date Updated', 'Title', 'Projects', 'URI', 'Description');
     $is_date = array(false, false, false, false, true, true, false, false, false, false);
     $header_format = array('font' => array('bold' => true));
     foreach ($tasks as $task) {
         $task_owner = null;
         if ($task->getOwnerPHID()) {
             $task_owner = $handles[$task->getOwnerPHID()]->getName();
         }
         $projects = array();
         foreach ($task->getProjectPHIDs() as $phid) {
             $projects[] = $handles[$phid]->getName();
         }
         $projects = implode(', ', $projects);
         $rows[] = array('T' . $task->getID(), $task_owner, idx($status_map, $task->getStatus(), '?'), idx($pri_map, $task->getPriority(), '?'), $this->computeExcelDate($task->getDateCreated()), $this->computeExcelDate($task->getDateModified()), $task->getTitle(), $projects, PhabricatorEnv::getProductionURI('/T' . $task->getID()), phutil_utf8_shorten($task->getDescription(), 512));
     }
     foreach ($rows as $row => $cols) {
         foreach ($cols as $col => $spec) {
             $cell_name = $this->col($col) . ($row + 1);
             $sheet->setCellValue($cell_name, $spec);
             if ($row == 0) {
                 $sheet->getStyle($cell_name)->applyFromArray($header_format);
             }
             if ($is_date[$col]) {
                 $code = PHPExcel_Style_NumberFormat::FORMAT_DATE_YYYYMMDD2;
                 $sheet->getStyle($cell_name)->getNumberFormat()->setFormatCode($code);
             }
         }
     }
     $writer = PHPExcel_IOFactory::createWriter($workbook, 'Excel2007');
     ob_start();
     $writer->save('php://output');
     $data = ob_get_clean();
     $mime = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
     return id(new AphrontFileResponse())->setMimeType($mime)->setDownload('maniphest_tasks_' . date('Ymd') . '.xlsx')->setContent($data);
 }
 public function processRequest()
 {
     $request = $this->getRequest();
     $user = $request->getUser();
     $e_title = null;
     $priority_map = ManiphestTaskPriority::getTaskPriorityMap();
     $task = id(new ManiphestTask())->load($this->id);
     if (!$task) {
         return new Aphront404Response();
     }
     $workflow = $request->getStr('workflow');
     $parent_task = null;
     if ($workflow && is_numeric($workflow)) {
         $parent_task = id(new ManiphestTask())->load($workflow);
     }
     $transactions = id(new ManiphestTransaction())->loadAllWhere('taskID = %d ORDER BY id ASC', $task->getID());
     $e_commit = PhabricatorEdgeConfig::TYPE_TASK_HAS_COMMIT;
     $e_dep_on = PhabricatorEdgeConfig::TYPE_TASK_DEPENDS_ON_TASK;
     $e_dep_by = PhabricatorEdgeConfig::TYPE_TASK_DEPENDED_ON_BY_TASK;
     $e_rev = PhabricatorEdgeConfig::TYPE_TASK_HAS_RELATED_DREV;
     $phid = $task->getPHID();
     $query = id(new PhabricatorEdgeQuery())->withSourcePHIDs(array($phid))->withEdgeTypes(array($e_commit, $e_dep_on, $e_dep_by, $e_rev));
     $edges = $query->execute();
     $commit_phids = array_keys($edges[$phid][$e_commit]);
     $dep_on_tasks = array_keys($edges[$phid][$e_dep_on]);
     $dep_by_tasks = array_keys($edges[$phid][$e_dep_by]);
     $revs = array_keys($edges[$phid][$e_rev]);
     $phids = array_fill_keys($query->getDestinationPHIDs(), true);
     foreach ($transactions as $transaction) {
         foreach ($transaction->extractPHIDs() as $phid) {
             $phids[$phid] = true;
         }
     }
     foreach ($task->getCCPHIDs() as $phid) {
         $phids[$phid] = true;
     }
     foreach ($task->getProjectPHIDs() as $phid) {
         $phids[$phid] = true;
     }
     if ($task->getOwnerPHID()) {
         $phids[$task->getOwnerPHID()] = true;
     }
     $phids[$task->getAuthorPHID()] = true;
     $attached = $task->getAttached();
     foreach ($attached as $type => $list) {
         foreach ($list as $phid => $info) {
             $phids[$phid] = true;
         }
     }
     if ($parent_task) {
         $phids[$parent_task->getPHID()] = true;
     }
     $phids = array_keys($phids);
     $handles = $this->loadViewerHandles($phids);
     $dict = array();
     $dict['Status'] = '<strong>' . ManiphestTaskStatus::getTaskStatusFullName($task->getStatus()) . '</strong>';
     $dict['Assigned To'] = $task->getOwnerPHID() ? $handles[$task->getOwnerPHID()]->renderLink() : '<em>None</em>';
     $dict['Priority'] = ManiphestTaskPriority::getTaskPriorityName($task->getPriority());
     $cc = $task->getCCPHIDs();
     if ($cc) {
         $cc_links = array();
         foreach ($cc as $phid) {
             $cc_links[] = $handles[$phid]->renderLink();
         }
         $dict['CC'] = implode(', ', $cc_links);
     } else {
         $dict['CC'] = '<em>None</em>';
     }
     $dict['Author'] = $handles[$task->getAuthorPHID()]->renderLink();
     $source = $task->getOriginalEmailSource();
     if ($source) {
         $subject = '[T' . $task->getID() . '] ' . $task->getTitle();
         $dict['From Email'] = phutil_render_tag('a', array('href' => 'mailto:' . $source . '?subject=' . $subject), phutil_escape_html($source));
     }
     $projects = $task->getProjectPHIDs();
     if ($projects) {
         $project_links = array();
         foreach ($projects as $phid) {
             $project_links[] = $handles[$phid]->renderLink();
         }
         $dict['Projects'] = implode(', ', $project_links);
     } else {
         $dict['Projects'] = '<em>None</em>';
     }
     $extensions = ManiphestTaskExtensions::newExtensions();
     $aux_fields = $extensions->getAuxiliaryFieldSpecifications();
     if ($aux_fields) {
         $task->loadAndAttachAuxiliaryAttributes();
         foreach ($aux_fields as $aux_field) {
             $aux_key = $aux_field->getAuxiliaryKey();
             $aux_field->setValue($task->getAuxiliaryAttribute($aux_key));
             $value = $aux_field->renderForDetailView();
             if (strlen($value)) {
                 $dict[$aux_field->getLabel()] = $value;
             }
         }
     }
     if ($dep_by_tasks) {
         $dict['Dependent Tasks'] = $this->renderHandleList(array_select_keys($handles, $dep_by_tasks));
     }
     if ($dep_on_tasks) {
         $dict['Depends On'] = $this->renderHandleList(array_select_keys($handles, $dep_on_tasks));
     }
     if ($revs) {
         $dict['Revisions'] = $this->renderHandleList(array_select_keys($handles, $revs));
     }
     if ($commit_phids) {
         $dict['Commits'] = $this->renderHandleList(array_select_keys($handles, $commit_phids));
     }
     $file_infos = idx($attached, PhabricatorPHIDConstants::PHID_TYPE_FILE);
     if ($file_infos) {
         $file_phids = array_keys($file_infos);
         $files = id(new PhabricatorFile())->loadAllWhere('phid IN (%Ls)', $file_phids);
         $views = array();
         foreach ($files as $file) {
             $view = new AphrontFilePreviewView();
             $view->setFile($file);
             $views[] = $view->render();
         }
         $dict['Files'] = implode('', $views);
     }
     $context_bar = null;
     if ($parent_task) {
         $context_bar = new AphrontContextBarView();
         $context_bar->addButton(phutil_render_tag('a', array('href' => '/maniphest/task/create/?parent=' . $parent_task->getID(), 'class' => 'green button'), 'Create Another Subtask'));
         $context_bar->appendChild('Created a subtask of <strong>' . $handles[$parent_task->getPHID()]->renderLink() . '</strong>');
     } else {
         if ($workflow == 'create') {
             $context_bar = new AphrontContextBarView();
             $context_bar->addButton('<label>Create Another:</label>');
             $context_bar->addButton(phutil_render_tag('a', array('href' => '/maniphest/task/create/?template=' . $task->getID(), 'class' => 'green button'), 'Similar Task'));
             $context_bar->addButton(phutil_render_tag('a', array('href' => '/maniphest/task/create/', 'class' => 'green button'), 'Empty Task'));
             $context_bar->appendChild('New task created.');
         }
     }
     $actions = array();
     $action = new AphrontHeadsupActionView();
     $action->setName('Edit Task');
     $action->setURI('/maniphest/task/edit/' . $task->getID() . '/');
     $action->setClass('action-edit');
     $actions[] = $action;
     require_celerity_resource('phabricator-flag-css');
     $flag = PhabricatorFlagQuery::loadUserFlag($user, $task->getPHID());
     if ($flag) {
         $class = PhabricatorFlagColor::getCSSClass($flag->getColor());
         $color = PhabricatorFlagColor::getColorName($flag->getColor());
         $action = new AphrontHeadsupActionView();
         $action->setClass('flag-clear ' . $class);
         $action->setURI('/flag/delete/' . $flag->getID() . '/');
         $action->setName('Remove ' . $color . ' Flag');
         $action->setWorkflow(true);
         $actions[] = $action;
     } else {
         $action = new AphrontHeadsupActionView();
         $action->setClass('phabricator-flag-ghost');
         $action->setURI('/flag/edit/' . $task->getPHID() . '/');
         $action->setName('Flag Task');
         $action->setWorkflow(true);
         $actions[] = $action;
     }
     require_celerity_resource('phabricator-object-selector-css');
     require_celerity_resource('javelin-behavior-phabricator-object-selector');
     $action = new AphrontHeadsupActionView();
     $action->setName('Merge Duplicates');
     $action->setURI('/search/attach/' . $task->getPHID() . '/TASK/merge/');
     $action->setWorkflow(true);
     $action->setClass('action-merge');
     $actions[] = $action;
     $action = new AphrontHeadsupActionView();
     $action->setName('Create Subtask');
     $action->setURI('/maniphest/task/create/?parent=' . $task->getID());
     $action->setClass('action-branch');
     $actions[] = $action;
     $action = new AphrontHeadsupActionView();
     $action->setName('Edit Dependencies');
     $action->setURI('/search/attach/' . $task->getPHID() . '/TASK/dependencies/');
     $action->setWorkflow(true);
     $action->setClass('action-dependencies');
     $actions[] = $action;
     $action = new AphrontHeadsupActionView();
     $action->setName('Edit Differential Revisions');
     $action->setURI('/search/attach/' . $task->getPHID() . '/DREV/');
     $action->setWorkflow(true);
     $action->setClass('action-attach');
     $actions[] = $action;
     $action_list = new AphrontHeadsupActionListView();
     $action_list->setActions($actions);
     $headsup_panel = new AphrontHeadsupView();
     $headsup_panel->setObjectName('T' . $task->getID());
     $headsup_panel->setHeader($task->getTitle());
     $headsup_panel->setActionList($action_list);
     $headsup_panel->setProperties($dict);
     $engine = new PhabricatorMarkupEngine();
     $engine->setViewer($user);
     $engine->addObject($task, ManiphestTask::MARKUP_FIELD_DESCRIPTION);
     foreach ($transactions as $xaction) {
         if ($xaction->hasComments()) {
             $engine->addObject($xaction, ManiphestTransaction::MARKUP_FIELD_BODY);
         }
     }
     $engine->process();
     $headsup_panel->appendChild('<div class="phabricator-remarkup">' . $engine->getOutput($task, ManiphestTask::MARKUP_FIELD_DESCRIPTION) . '</div>');
     $transaction_types = ManiphestTransactionType::getTransactionTypeMap();
     $resolution_types = ManiphestTaskStatus::getTaskStatusMap();
     if ($task->getStatus() == ManiphestTaskStatus::STATUS_OPEN) {
         $resolution_types = array_select_keys($resolution_types, array(ManiphestTaskStatus::STATUS_CLOSED_RESOLVED, ManiphestTaskStatus::STATUS_CLOSED_WONTFIX, ManiphestTaskStatus::STATUS_CLOSED_INVALID, ManiphestTaskStatus::STATUS_CLOSED_SPITE));
     } else {
         $resolution_types = array(ManiphestTaskStatus::STATUS_OPEN => 'Reopened');
         $transaction_types[ManiphestTransactionType::TYPE_STATUS] = 'Reopen Task';
         unset($transaction_types[ManiphestTransactionType::TYPE_PRIORITY]);
         unset($transaction_types[ManiphestTransactionType::TYPE_OWNER]);
     }
     $default_claim = array($user->getPHID() => $user->getUsername() . ' (' . $user->getRealName() . ')');
     $draft = id(new PhabricatorDraft())->loadOneWhere('authorPHID = %s AND draftKey = %s', $user->getPHID(), $task->getPHID());
     if ($draft) {
         $draft_text = $draft->getDraft();
     } else {
         $draft_text = null;
     }
     $is_serious = PhabricatorEnv::getEnvConfig('phabricator.serious-business');
     if ($is_serious) {
         // Prevent tasks from being closed "out of spite" in serious business
         // installs.
         unset($resolution_types[ManiphestTaskStatus::STATUS_CLOSED_SPITE]);
     }
     $comment_form = new AphrontFormView();
     $comment_form->setUser($user)->setAction('/maniphest/transaction/save/')->setEncType('multipart/form-data')->addHiddenInput('taskID', $task->getID())->appendChild(id(new AphrontFormSelectControl())->setLabel('Action')->setName('action')->setOptions($transaction_types)->setID('transaction-action'))->appendChild(id(new AphrontFormSelectControl())->setLabel('Resolution')->setName('resolution')->setControlID('resolution')->setControlStyle('display: none')->setOptions($resolution_types))->appendChild(id(new AphrontFormTokenizerControl())->setLabel('Assign To')->setName('assign_to')->setControlID('assign_to')->setControlStyle('display: none')->setID('assign-tokenizer')->setDisableBehavior(true))->appendChild(id(new AphrontFormTokenizerControl())->setLabel('CCs')->setName('ccs')->setControlID('ccs')->setControlStyle('display: none')->setID('cc-tokenizer')->setDisableBehavior(true))->appendChild(id(new AphrontFormSelectControl())->setLabel('Priority')->setName('priority')->setOptions($priority_map)->setControlID('priority')->setControlStyle('display: none')->setValue($task->getPriority()))->appendChild(id(new AphrontFormTokenizerControl())->setLabel('Projects')->setName('projects')->setControlID('projects')->setControlStyle('display: none')->setID('projects-tokenizer')->setDisableBehavior(true))->appendChild(id(new AphrontFormFileControl())->setLabel('File')->setName('file')->setControlID('file')->setControlStyle('display: none'))->appendChild(id(new PhabricatorRemarkupControl())->setLabel('Comments')->setName('comments')->setValue($draft_text)->setID('transaction-comments'))->appendChild(id(new AphrontFormDragAndDropUploadControl())->setLabel('Attached Files')->setName('files')->setActivatedClass('aphront-panel-view-drag-and-drop'))->appendChild(id(new AphrontFormSubmitControl())->setValue($is_serious ? 'Submit' : 'Avast!'));
     $control_map = array(ManiphestTransactionType::TYPE_STATUS => 'resolution', ManiphestTransactionType::TYPE_OWNER => 'assign_to', ManiphestTransactionType::TYPE_CCS => 'ccs', ManiphestTransactionType::TYPE_PRIORITY => 'priority', ManiphestTransactionType::TYPE_PROJECTS => 'projects', ManiphestTransactionType::TYPE_ATTACH => 'file');
     $tokenizer_map = array(ManiphestTransactionType::TYPE_PROJECTS => array('id' => 'projects-tokenizer', 'src' => '/typeahead/common/projects/', 'ondemand' => PhabricatorEnv::getEnvConfig('tokenizer.ondemand'), 'placeholder' => 'Type a project name...'), ManiphestTransactionType::TYPE_OWNER => array('id' => 'assign-tokenizer', 'src' => '/typeahead/common/users/', 'value' => $default_claim, 'limit' => 1, 'ondemand' => PhabricatorEnv::getEnvConfig('tokenizer.ondemand'), 'placeholder' => 'Type a user name...'), ManiphestTransactionType::TYPE_CCS => array('id' => 'cc-tokenizer', 'src' => '/typeahead/common/mailable/', 'ondemand' => PhabricatorEnv::getEnvConfig('tokenizer.ondemand'), 'placeholder' => 'Type a user or mailing list...'));
     Javelin::initBehavior('maniphest-transaction-controls', array('select' => 'transaction-action', 'controlMap' => $control_map, 'tokenizers' => $tokenizer_map));
     Javelin::initBehavior('maniphest-transaction-preview', array('uri' => '/maniphest/transaction/preview/' . $task->getID() . '/', 'preview' => 'transaction-preview', 'comments' => 'transaction-comments', 'action' => 'transaction-action', 'map' => $control_map, 'tokenizers' => $tokenizer_map));
     $comment_panel = new AphrontPanelView();
     $comment_panel->appendChild($comment_form);
     $comment_panel->addClass('aphront-panel-accent');
     $comment_panel->setHeader($is_serious ? 'Add Comment' : 'Weigh In');
     $preview_panel = '<div class="aphront-panel-preview">
     <div id="transaction-preview">
       <div class="aphront-panel-preview-loading-text">
         Loading preview...
       </div>
     </div>
   </div>';
     $transaction_view = new ManiphestTransactionListView();
     $transaction_view->setTransactions($transactions);
     $transaction_view->setHandles($handles);
     $transaction_view->setUser($user);
     $transaction_view->setAuxiliaryFields($aux_fields);
     $transaction_view->setMarkupEngine($engine);
     PhabricatorFeedStoryNotification::updateObjectNotificationViews($user, $task->getPHID());
     return $this->buildStandardPageResponse(array($context_bar, $headsup_panel, $transaction_view, $comment_panel, $preview_panel), array('title' => 'T' . $task->getID() . ' ' . $task->getTitle(), 'pageObjects' => array($task->getPHID())));
 }
 protected function execute(ConduitAPIRequest $request)
 {
     $results = array('defaultStatus' => ManiphestTaskStatus::getDefaultStatus(), 'defaultClosedStatus' => ManiphestTaskStatus::getDefaultClosedStatus(), 'duplicateStatus' => ManiphestTaskStatus::getDuplicateStatus(), 'openStatuses' => ManiphestTaskStatus::getOpenStatusConstants(), 'closedStatuses' => ManiphestTaskStatus::getClosedStatusConstants(), 'allStatuses' => array_keys(ManiphestTaskStatus::getTaskStatusMap()), 'statusMap' => ManiphestTaskStatus::getTaskStatusMap());
     return $results;
 }
 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);
 }