public function testRequestDataAccess()
 {
     $r = new AphrontRequest('http://example.com/', '/');
     $r->setRequestData(array('str_empty' => '', 'str' => 'derp', 'str_true' => 'true', 'str_false' => 'false', 'zero' => '0', 'one' => '1', 'arr_empty' => array(), 'arr_num' => array(1, 2, 3), 'comma' => ',', 'comma_1' => 'a, b', 'comma_2' => ' ,a ,, b ,,,, ,, ', 'comma_3' => '0', 'comma_4' => 'a, a, b, a', 'comma_5' => "a\nb, c\n\nd\n\n\n,\n"));
     $this->assertEqual(1, $r->getInt('one'));
     $this->assertEqual(0, $r->getInt('zero'));
     $this->assertEqual(null, $r->getInt('does-not-exist'));
     $this->assertEqual(0, $r->getInt('str_empty'));
     $this->assertEqual(true, $r->getBool('one'));
     $this->assertEqual(false, $r->getBool('zero'));
     $this->assertEqual(true, $r->getBool('str_true'));
     $this->assertEqual(false, $r->getBool('str_false'));
     $this->assertEqual(true, $r->getBool('str'));
     $this->assertEqual(null, $r->getBool('does-not-exist'));
     $this->assertEqual(false, $r->getBool('str_empty'));
     $this->assertEqual('derp', $r->getStr('str'));
     $this->assertEqual('', $r->getStr('str_empty'));
     $this->assertEqual(null, $r->getStr('does-not-exist'));
     $this->assertEqual(array(), $r->getArr('arr_empty'));
     $this->assertEqual(array(1, 2, 3), $r->getArr('arr_num'));
     $this->assertEqual(null, $r->getArr('str_empty', null));
     $this->assertEqual(null, $r->getArr('str_true', null));
     $this->assertEqual(null, $r->getArr('does-not-exist', null));
     $this->assertEqual(array(), $r->getArr('does-not-exist'));
     $this->assertEqual(array(), $r->getStrList('comma'));
     $this->assertEqual(array('a', 'b'), $r->getStrList('comma_1'));
     $this->assertEqual(array('a', 'b'), $r->getStrList('comma_2'));
     $this->assertEqual(array('0'), $r->getStrList('comma_3'));
     $this->assertEqual(array('a', 'a', 'b', 'a'), $r->getStrList('comma_4'));
     $this->assertEqual(array('a', 'b', 'c', 'd'), $r->getStrList('comma_5'));
     $this->assertEqual(array(), $r->getStrList('does-not-exist'));
     $this->assertEqual(null, $r->getStrList('does-not-exist', null));
     $this->assertEqual(true, $r->getExists('str'));
     $this->assertEqual(false, $r->getExists('does-not-exist'));
 }
 public function buildSavedQueryFromRequest(AphrontRequest $request)
 {
     $saved = new PhabricatorSavedQuery();
     $object_monograms = $request->getStrList('objectMonograms');
     $saved->setParameter('objectMonograms', $object_monograms);
     $ids = $request->getStrList('ids');
     foreach ($ids as $key => $id) {
         if (!$id || !is_numeric($id)) {
             unset($ids[$key]);
         } else {
             $ids[$key] = $id;
         }
     }
     $saved->setParameter('ids', $ids);
     return $saved;
 }
 public function handleRequest(AphrontRequest $request)
 {
     $viewer = $request->getViewer();
     $e_file = true;
     $errors = array();
     if ($request->isDialogFormPost()) {
         $file_phids = $request->getStrList('filePHIDs');
         if ($file_phids) {
             $files = id(new PhabricatorFileQuery())->setViewer($viewer)->withPHIDs($file_phids)->setRaisePolicyExceptions(true)->execute();
         } else {
             $files = array();
         }
         if ($files) {
             $results = array();
             foreach ($files as $file) {
                 $results[] = $file->getDragAndDropDictionary();
             }
             $content = array('files' => $results);
             return id(new AphrontAjaxResponse())->setContent($content);
         } else {
             $e_file = pht('Required');
             $errors[] = pht('You must choose a file to upload.');
         }
     }
     if ($request->getURIData('single')) {
         $allow_multiple = false;
     } else {
         $allow_multiple = true;
     }
     $form = id(new AphrontFormView())->appendChild(id(new PHUIFormFileControl())->setName('filePHIDs')->setLabel(pht('Upload File'))->setAllowMultiple($allow_multiple)->setError($e_file));
     return $this->newDialog()->setTitle(pht('File'))->setErrors($errors)->appendForm($form)->addSubmitButton(pht('Upload'))->addCancelButton('/');
 }
 protected function getParameterValue(AphrontRequest $request, $key)
 {
     $list = $request->getArr($key, null);
     if ($list === null) {
         $list = $request->getStrList($key);
     }
     return $list;
 }
 public function handleRequest(AphrontRequest $request)
 {
     $viewer = $request->getViewer();
     $id = $request->getURIData('id');
     $commit = id(new PhabricatorRepositoryCommit())->load($id);
     if (!$commit) {
         return new Aphront404Response();
     }
     $xactions = array();
     $action = $request->getStr('action');
     if ($action != PhabricatorAuditActionConstants::COMMENT) {
         $action_xaction = id(new PhabricatorAuditTransaction())->setAuthorPHID($viewer->getPHID())->setObjectPHID($commit->getPHID())->setTransactionType(PhabricatorAuditActionConstants::ACTION)->setNewValue($action);
         $auditors = $request->getStrList('auditors');
         if ($action == PhabricatorAuditActionConstants::ADD_AUDITORS && $auditors) {
             $action_xaction->setTransactionType($action);
             $action_xaction->setNewValue(array_fuse($auditors));
         }
         $ccs = $request->getStrList('ccs');
         if ($action == PhabricatorAuditActionConstants::ADD_CCS && $ccs) {
             $action_xaction->setTransactionType(PhabricatorTransactions::TYPE_SUBSCRIBERS);
             // NOTE: This doesn't get processed before use, so just provide fake
             // values.
             $action_xaction->setOldValue(array());
             $action_xaction->setNewValue($ccs);
         }
         $xactions[] = $action_xaction;
     }
     $content = $request->getStr('content');
     if (strlen($content)) {
         $xactions[] = id(new PhabricatorAuditTransaction())->setAuthorPHID($viewer->getPHID())->setObjectPHID($commit->getPHID())->setTransactionType(PhabricatorTransactions::TYPE_COMMENT)->attachComment(id(new PhabricatorAuditTransactionComment())->setContent($content));
     }
     $phids = array();
     foreach ($xactions as $xaction) {
         $phids[] = $xaction->getRequiredHandlePHIDs();
     }
     $phids = array_mergev($phids);
     $handles = $this->loadViewerHandles($phids);
     foreach ($xactions as $xaction) {
         $xaction->setHandles($handles);
     }
     $view = id(new PhabricatorAuditTransactionView())->setIsPreview(true)->setUser($viewer)->setObjectPHID($commit->getPHID())->setTransactions($xactions);
     id(new PhabricatorDraft())->setAuthorPHID($viewer->getPHID())->setDraftKey('diffusion-audit-' . $id)->setDraft($content)->replaceOrDelete();
     return id(new AphrontAjaxResponse())->setContent(hsprintf('%s', $view));
 }
 public function buildSavedQueryFromRequest(AphrontRequest $request)
 {
     $saved = new PhabricatorSavedQuery();
     $saved->setParameter('isStable', $request->getStr('isStable'));
     $saved->setParameter('isUnstable', $request->getStr('isUnstable'));
     $saved->setParameter('isDeprecated', $request->getStr('isDeprecated'));
     $saved->setParameter('applicationNames', $request->getStrList('applicationNames'));
     $saved->setParameter('nameContains', $request->getStr('nameContains'));
     return $saved;
 }
 public function buildSavedQueryFromRequest(AphrontRequest $request)
 {
     $saved = new PhabricatorSavedQuery();
     $saved->setParameter('callsigns', $request->getStrList('callsigns'));
     $saved->setParameter('status', $request->getStr('status'));
     $saved->setParameter('order', $request->getStr('order'));
     $saved->setParameter('hosted', $request->getStr('hosted'));
     $saved->setParameter('types', $request->getArr('types'));
     $saved->setParameter('name', $request->getStr('name'));
     $saved->setParameter('anyProjectPHIDs', $request->getArr('anyProjects'));
     return $saved;
 }
 public function buildSavedQueryFromRequest(AphrontRequest $request)
 {
     $saved = new PhabricatorSavedQuery();
     $saved->setParameter('usernames', $request->getStrList('usernames'));
     $saved->setParameter('nameLike', $request->getStr('nameLike'));
     $saved->setParameter('isAdmin', $request->getStr('isAdmin'));
     $saved->setParameter('isDisabled', $request->getStr('isDisabled'));
     $saved->setParameter('isSystemAgent', $request->getStr('isSystemAgent'));
     $saved->setParameter('needsApproval', $request->getStr('needsApproval'));
     $saved->setParameter('createdStart', $request->getStr('createdStart'));
     $saved->setParameter('createdEnd', $request->getStr('createdEnd'));
     $this->readCustomFieldsFromRequest($request, $saved);
     return $saved;
 }
 public function handleRequest(AphrontRequest $request)
 {
     $viewer = $request->getViewer();
     if (!$request->validateCSRF()) {
         return new Aphront400Response();
     }
     $cancel_uri = $this->getApplicationURI();
     $ids = $request->getStrList('h');
     if ($ids) {
         $files = id(new PhabricatorFileQuery())->setViewer($viewer)->withIDs($ids)->setRaisePolicyExceptions(true)->execute();
     } else {
         $files = array();
     }
     if (!$files) {
         return $this->newDialog()->setTitle(pht('Nothing Uploaded'))->appendParagraph(pht('Drag and drop .ics files to upload them and import them into ' . 'Calendar.'))->addCancelButton($cancel_uri, pht('Done'));
     }
     $engine = new PhabricatorCalendarICSFileImportEngine();
     $imports = array();
     foreach ($files as $file) {
         $import = PhabricatorCalendarImport::initializeNewCalendarImport($viewer, clone $engine);
         $xactions = array();
         $xactions[] = id(new PhabricatorCalendarImportTransaction())->setTransactionType(PhabricatorCalendarImportICSFileTransaction::TRANSACTIONTYPE)->setNewValue($file->getPHID());
         $editor = id(new PhabricatorCalendarImportEditor())->setActor($viewer)->setContinueOnNoEffect(true)->setContinueOnMissingFields(true)->setContentSourceFromRequest($request);
         $editor->applyTransactions($import, $xactions);
         $imports[] = $import;
     }
     $import_phids = mpull($imports, 'getPHID');
     $events = id(new PhabricatorCalendarEventQuery())->setViewer($viewer)->withImportSourcePHIDs($import_phids)->execute();
     if (count($events) == 1) {
         // The user imported exactly one event. This is consistent with dropping
         // a .ics file from an email; just take them to the event.
         $event = head($events);
         $next_uri = $event->getURI();
     } else {
         if (count($imports) > 1) {
             // The user imported multiple different files. Take them to a summary
             // list of generated import activity.
             $source_phids = implode(',', $import_phids);
             $next_uri = '/calendar/import/log/?importSourcePHIDs=' . $source_phids;
         } else {
             // The user imported one file, which had zero or more than one event.
             // Take them to the import detail page.
             $import = head($imports);
             $next_uri = $import->getURI();
         }
     }
     return id(new AphrontRedirectResponse())->setURI($next_uri);
 }
 public function handleRequest(AphrontRequest $request)
 {
     $engine_key = $request->getURIData('engineKey');
     $this->setEngineKey($engine_key);
     $key = $request->getURIData('key');
     $viewer = $this->getViewer();
     $config = id(new PhabricatorEditEngineConfigurationQuery())->setViewer($viewer)->withEngineKeys(array($engine_key))->withIdentifiers(array($key))->requireCapabilities(array(PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT))->executeOne();
     if (!$config) {
         return id(new Aphront404Response());
     }
     $cancel_uri = "/transactions/editengine/{$engine_key}/view/{$key}/";
     $reorder_uri = "/transactions/editengine/{$engine_key}/reorder/{$key}/";
     if ($request->isFormPost()) {
         $xactions = array();
         $key_order = $request->getStrList('keyOrder');
         $type_order = PhabricatorEditEngineConfigurationTransaction::TYPE_ORDER;
         $xactions[] = id(new PhabricatorEditEngineConfigurationTransaction())->setTransactionType($type_order)->setNewValue($key_order);
         $editor = id(new PhabricatorEditEngineConfigurationEditor())->setActor($viewer)->setContentSourceFromRequest($request)->setContinueOnMissingFields(true)->setContinueOnNoEffect(true);
         $editor->applyTransactions($config, $xactions);
         return id(new AphrontRedirectResponse())->setURI($cancel_uri);
     }
     $engine = $config->getEngine();
     $fields = $engine->getFieldsForConfig($config);
     $list_id = celerity_generate_unique_node_id();
     $input_id = celerity_generate_unique_node_id();
     $list = id(new PHUIObjectItemListView())->setUser($viewer)->setID($list_id)->setFlush(true);
     $key_order = array();
     foreach ($fields as $field) {
         if (!$field->getIsReorderable()) {
             continue;
         }
         $label = $field->getLabel();
         $key = $field->getKey();
         if ($label !== null) {
             $header = $label;
         } else {
             $header = $key;
         }
         $item = id(new PHUIObjectItemView())->setHeader($header)->setGrippable(true)->addSigil('editengine-form-field')->setMetadata(array('fieldKey' => $key));
         $list->addItem($item);
         $key_order[] = $key;
     }
     Javelin::initBehavior('editengine-reorder-fields', array('listID' => $list_id, 'inputID' => $input_id, 'reorderURI' => $reorder_uri));
     $note = id(new PHUIInfoView())->appendChild(pht('Drag and drop fields to reorder them.'))->setSeverity(PHUIInfoView::SEVERITY_NOTICE);
     $input = phutil_tag('input', array('type' => 'hidden', 'name' => 'keyOrder', 'value' => implode(', ', $key_order), 'id' => $input_id));
     return $this->newDialog()->setTitle(pht('Reorder Fields'))->setWidth(AphrontDialogView::WIDTH_FORM)->appendChild($note)->appendChild($list)->appendChild($input)->addSubmitButton(pht('Save Changes'))->addCancelButton($cancel_uri);
 }
 protected function processDiffusionRequest(AphrontRequest $request)
 {
     $user = $request->getUser();
     $drequest = $this->diffusionRequest;
     $repository = $drequest->getRepository();
     $repository = id(new PhabricatorRepositoryQuery())->setViewer($user)->requireCapabilities(array(PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT))->withIDs(array($repository->getID()))->executeOne();
     if (!$repository) {
         return new Aphront404Response();
     }
     $edit_uri = $this->getRepositoryControllerURI($repository, 'edit/');
     $v_sources = $repository->getSymbolSources();
     $v_languages = $repository->getSymbolLanguages();
     if ($v_languages) {
         $v_languages = implode(', ', $v_languages);
     }
     $errors = array();
     if ($request->isFormPost()) {
         $v_sources = $request->getArr('sources');
         $v_languages = $request->getStrList('languages');
         $v_languages = array_map('phutil_utf8_strtolower', $v_languages);
         if (!$errors) {
             $xactions = array();
             $template = id(new PhabricatorRepositoryTransaction());
             $type_sources = PhabricatorRepositoryTransaction::TYPE_SYMBOLS_SOURCES;
             $type_lang = PhabricatorRepositoryTransaction::TYPE_SYMBOLS_LANGUAGE;
             $xactions[] = id(clone $template)->setTransactionType($type_sources)->setNewValue($v_sources);
             $xactions[] = id(clone $template)->setTransactionType($type_lang)->setNewValue($v_languages);
             try {
                 id(new PhabricatorRepositoryEditor())->setContinueOnNoEffect(true)->setContentSourceFromRequest($request)->setActor($user)->applyTransactions($repository, $xactions);
                 return id(new AphrontRedirectResponse())->setURI($edit_uri);
             } catch (Exception $ex) {
                 $errors[] = $ex->getMessage();
             }
         }
     }
     $crumbs = $this->buildApplicationCrumbs();
     $crumbs->addTextCrumb(pht('Edit Symbols'));
     $title = pht('Edit %s', $repository->getName());
     $form = id(new AphrontFormView())->setUser($user)->appendRemarkupInstructions($this->getInstructions())->appendChild(id(new AphrontFormTextControl())->setName('languages')->setLabel(pht('Indexed Languages'))->setCaption(pht('File extensions, separate with commas, for example: php, py. ' . 'Leave blank for "any".'))->setValue($v_languages))->appendControl(id(new AphrontFormTokenizerControl())->setName('sources')->setLabel(pht('Uses Symbols From'))->setDatasource(new DiffusionRepositoryDatasource())->setValue($v_sources))->appendChild(id(new AphrontFormSubmitControl())->setValue(pht('Save'))->addCancelButton($edit_uri));
     $object_box = id(new PHUIObjectBoxView())->setHeaderText($title)->setForm($form)->setFormErrors($errors);
     return $this->buildApplicationPage(array($crumbs, $object_box), array('title' => $title));
 }
 protected function getParameterValue(AphrontRequest $request, $key)
 {
     $value = $request->getStrList($key);
     if ($value) {
         return head($value);
     }
     // NOTE: At least for now, we'll attempt to read a direct upload if we
     // miss on a PHID. Currently, PHUIFormFileControl does a client-side
     // upload on workflow forms (which is good) but doesn't have a hook for
     // non-workflow forms (which isn't as good). Giving it a hook is desirable,
     // but complicated. Even if we do hook it, it may be reasonable to keep
     // this code around as a fallback if the client-side JS goes awry.
     $file_key = $this->getFileKey($key);
     if (!$request->getFileExists($file_key)) {
         return null;
     }
     $viewer = $this->getViewer();
     $file = PhabricatorFile::newFromPHPUpload(idx($_FILES, $file_key), array('authorPHID' => $viewer->getPHID(), 'viewPolicy' => PhabricatorPolicies::POLICY_NOONE));
     return $file->getPHID();
 }
 public function handleRequest(AphrontRequest $request)
 {
     $viewer = $this->getViewer();
     $engine_class = $request->getURIData('engine');
     $request->validateCSRF();
     $base_class = 'PhabricatorApplicationSearchEngine';
     if (!is_subclass_of($engine_class, $base_class)) {
         return new Aphront400Response();
     }
     $engine = newv($engine_class, array());
     $engine->setViewer($viewer);
     $queries = $engine->loadAllNamedQueries();
     $queries = mpull($queries, null, 'getQueryKey');
     $order = $request->getStrList('order');
     $queries = array_select_keys($queries, $order) + $queries;
     $sequence = 1;
     foreach ($queries as $query) {
         $query->setSequence($sequence++);
         $query->save();
     }
     return id(new AphrontAjaxResponse());
 }
 public function handleRequest(AphrontRequest $request)
 {
     $viewer = $request->getViewer();
     $id = $request->getURIData('id');
     $panel = id(new PhabricatorDashboardPanelQuery())->setViewer($viewer)->withIDs(array($id))->executeOne();
     if (!$panel) {
         return new Aphront404Response();
     }
     if ($request->isAjax()) {
         $parent_phids = $request->getStrList('parentPanelPHIDs', null);
         if ($parent_phids === null) {
             throw new Exception(pht('Required parameter `parentPanelPHIDs` is not present in ' . 'request.'));
         }
     } else {
         $parent_phids = array();
     }
     $rendered_panel = id(new PhabricatorDashboardPanelRenderingEngine())->setViewer($viewer)->setPanel($panel)->setParentPanelPHIDs($parent_phids)->setHeaderMode($request->getStr('headerMode'))->setDashboardID($request->getInt('dashboardID'))->renderPanel();
     if ($request->isAjax()) {
         return id(new AphrontAjaxResponse())->setContent(array('panelMarkup' => hsprintf('%s', $rendered_panel)));
     }
     $crumbs = $this->buildApplicationCrumbs()->addTextCrumb(pht('Panels'), $this->getApplicationURI('panel/'))->addTextCrumb($panel->getMonogram(), '/' . $panel->getMonogram())->addTextCrumb(pht('Standalone View'));
     $view = id(new PHUIBoxView())->addClass('dashboard-view')->appendChild($rendered_panel);
     return $this->buildApplicationPage(array($crumbs, $view), array('title' => array(pht('Panel'), $panel->getName())));
 }
 public function handleRequest(AphrontRequest $request)
 {
     $viewer = $this->getViewer();
     $server = new PhabricatorOAuthServer();
     $client_phid = $request->getStr('client_id');
     $redirect_uri = $request->getStr('redirect_uri');
     $response_type = $request->getStr('response_type');
     // state is an opaque value the client sent us for their own purposes
     // we just need to send it right back to them in the response!
     $state = $request->getStr('state');
     if (!$client_phid) {
         return $this->buildErrorResponse('invalid_request', pht('Malformed Request'), pht('Required parameter %s was not present in the request.', phutil_tag('strong', array(), 'client_id')));
     }
     // We require that users must be able to see an OAuth application
     // in order to authorize it. This allows an application's visibility
     // policy to be used to restrict authorized users.
     try {
         $client = id(new PhabricatorOAuthServerClientQuery())->setViewer($viewer)->withPHIDs(array($client_phid))->executeOne();
     } catch (PhabricatorPolicyException $ex) {
         $ex->setContext(self::CONTEXT_AUTHORIZE);
         throw $ex;
     }
     $server->setUser($viewer);
     $is_authorized = false;
     $authorization = null;
     $uri = null;
     $name = null;
     // one giant try / catch around all the exciting database stuff so we
     // can return a 'server_error' response if something goes wrong!
     try {
         if (!$client) {
             return $this->buildErrorResponse('invalid_request', pht('Invalid Client Application'), pht('Request parameter %s does not specify a valid client application.', phutil_tag('strong', array(), 'client_id')));
         }
         if ($client->getIsDisabled()) {
             return $this->buildErrorResponse('invalid_request', pht('Application Disabled'), pht('The %s OAuth application has been disabled.', phutil_tag('strong', array(), 'client_id')));
         }
         $name = $client->getName();
         $server->setClient($client);
         if ($redirect_uri) {
             $client_uri = new PhutilURI($client->getRedirectURI());
             $redirect_uri = new PhutilURI($redirect_uri);
             if (!$server->validateSecondaryRedirectURI($redirect_uri, $client_uri)) {
                 return $this->buildErrorResponse('invalid_request', pht('Invalid Redirect URI'), pht('Request parameter %s specifies an invalid redirect URI. ' . 'The redirect URI must be a fully-qualified domain with no ' . 'fragments, and must have the same domain and at least ' . 'the same query parameters as the redirect URI the client ' . 'registered.', phutil_tag('strong', array(), 'redirect_uri')));
             }
             $uri = $redirect_uri;
         } else {
             $uri = new PhutilURI($client->getRedirectURI());
         }
         if (empty($response_type)) {
             return $this->buildErrorResponse('invalid_request', pht('Invalid Response Type'), pht('Required request parameter %s is missing.', phutil_tag('strong', array(), 'response_type')));
         }
         if ($response_type != 'code') {
             return $this->buildErrorResponse('unsupported_response_type', pht('Unsupported Response Type'), pht('Request parameter %s specifies an unsupported response type. ' . 'Valid response types are: %s.', phutil_tag('strong', array(), 'response_type'), implode(', ', array('code'))));
         }
         $requested_scope = $request->getStrList('scope');
         $requested_scope = array_fuse($requested_scope);
         $scope = PhabricatorOAuthServerScope::filterScope($requested_scope);
         // NOTE: We're always requiring a confirmation dialog to redirect.
         // Partly this is a general defense against redirect attacks, and
         // partly this shakes off anchors in the URI (which are not shaken
         // by 302'ing).
         $auth_info = $server->userHasAuthorizedClient($scope);
         list($is_authorized, $authorization) = $auth_info;
         if ($request->isFormPost()) {
             if ($authorization) {
                 $authorization->setScope($scope)->save();
             } else {
                 $authorization = $server->authorizeClient($scope);
             }
             $is_authorized = true;
         }
     } catch (Exception $e) {
         return $this->buildErrorResponse('server_error', pht('Server Error'), pht('The authorization server encountered an unexpected condition ' . 'which prevented it from fulfilling the request.'));
     }
     // When we reach this part of the controller, we can be in two states:
     //
     //   1. The user has not authorized the application yet. We want to
     //      give them an "Authorize this application?" dialog.
     //   2. The user has authorized the application. We want to give them
     //      a "Confirm Login" dialog.
     if ($is_authorized) {
         // The second case is simpler, so handle it first. The user either
         // authorized the application previously, or has just authorized the
         // application. Show them a confirm dialog with a normal link back to
         // the application. This shakes anchors from the URI.
         $unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
         $auth_code = $server->generateAuthorizationCode($uri);
         unset($unguarded);
         $full_uri = $this->addQueryParams($uri, array('code' => $auth_code->getCode(), 'scope' => $authorization->getScopeString(), 'state' => $state));
         if ($client->getIsTrusted()) {
             return id(new AphrontRedirectResponse())->setIsExternal(true)->setURI((string) $full_uri);
         }
         // TODO: It would be nice to give the user more options here, like
         // reviewing permissions, canceling the authorization, or aborting
         // the workflow.
         $dialog = id(new AphrontDialogView())->setUser($viewer)->setTitle(pht('Authenticate: %s', $name))->appendParagraph(pht('This application ("%s") is authorized to use your Phabricator ' . 'credentials. Continue to complete the authentication workflow.', phutil_tag('strong', array(), $name)))->addCancelButton((string) $full_uri, pht('Continue to Application'));
         return id(new AphrontDialogResponse())->setDialog($dialog);
     }
     // Here, we're confirming authorization for the application.
     if ($authorization) {
         $missing_scope = array_diff_key($scope, $authorization->getScope());
     } else {
         $missing_scope = $scope;
     }
     $form = id(new AphrontFormView())->addHiddenInput('client_id', $client_phid)->addHiddenInput('redirect_uri', $redirect_uri)->addHiddenInput('response_type', $response_type)->addHiddenInput('state', $state)->addHiddenInput('scope', $request->getStr('scope'))->setUser($viewer);
     $cancel_msg = pht('The user declined to authorize this application.');
     $cancel_uri = $this->addQueryParams($uri, array('error' => 'access_denied', 'error_description' => $cancel_msg));
     $dialog = $this->newDialog()->setShortTitle(pht('Authorize Access'))->setTitle(pht('Authorize "%s"?', $name))->setSubmitURI($request->getRequestURI()->getPath())->setWidth(AphrontDialogView::WIDTH_FORM)->appendParagraph(pht('Do you want to authorize the external application "%s" to ' . 'access your Phabricator account data, including your primary ' . 'email address?', phutil_tag('strong', array(), $name)))->appendForm($form)->addSubmitButton(pht('Authorize Access'))->addCancelButton((string) $cancel_uri, pht('Do Not Authorize'));
     if ($missing_scope) {
         $dialog->appendParagraph(pht('This application has requested these additional permissions. ' . 'Authorizing it will grant it the permissions it requests:'));
         foreach ($missing_scope as $scope_key => $ignored) {
             // TODO: Once we introduce more scopes, explain them here.
         }
     }
     $unknown_scope = array_diff_key($requested_scope, $scope);
     if ($unknown_scope) {
         $dialog->appendParagraph(pht('This application also requested additional unrecognized ' . 'permissions. These permissions may have existed in an older ' . 'version of Phabricator, or may be from a future version of ' . 'Phabricator. They will not be granted.'));
         $unknown_form = id(new AphrontFormView())->setViewer($viewer)->appendChild(id(new AphrontFormTextControl())->setLabel(pht('Unknown Scope'))->setValue(implode(', ', array_keys($unknown_scope)))->setDisabled(true));
         $dialog->appendForm($unknown_form);
     }
     return $dialog;
 }
 public function handleRequest(AphrontRequest $request)
 {
     $viewer = $this->getViewer();
     $this->requireApplicationCapability(ManiphestBulkEditCapability::CAPABILITY);
     $project = null;
     $board_id = $request->getInt('board');
     if ($board_id) {
         $project = id(new PhabricatorProjectQuery())->setViewer($viewer)->withIDs(array($board_id))->executeOne();
         if (!$project) {
             return new Aphront404Response();
         }
     }
     $task_ids = $request->getArr('batch');
     if (!$task_ids) {
         $task_ids = $request->getStrList('batch');
     }
     $tasks = id(new ManiphestTaskQuery())->setViewer($viewer)->withIDs($task_ids)->requireCapabilities(array(PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT))->needSubscriberPHIDs(true)->needProjectPHIDs(true)->execute();
     if ($project) {
         $cancel_uri = '/project/sprint/board/' . $project->getID() . '/';
         $redirect_uri = $cancel_uri;
     } else {
         $cancel_uri = '/maniphest/';
         $redirect_uri = '/maniphest/?ids=' . implode(',', mpull($tasks, 'getID'));
     }
     $actions = $request->getStr('actions');
     if ($actions) {
         $actions = phutil_json_decode($actions);
     }
     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($viewer)->setContentSourceFromRequest($request)->setContinueOnNoEffect(true)->setContinueOnMissingFields(true)->applyTransactions($task, $xactions);
             }
         }
         return id(new AphrontRedirectResponse())->setURI($redirect_uri);
     }
     $handles = ManiphestTaskListView::loadTaskHandles($viewer, $tasks);
     $list = new ManiphestTaskListView();
     $list->setTasks($tasks);
     $list->setUser($viewer);
     $list->setHandles($handles);
     $template = new AphrontTokenizerTemplateView();
     $template = $template->render();
     $projects_source = new PhabricatorProjectDatasource();
     $mailable_source = new PhabricatorMetaMTAMailableDatasource();
     $mailable_source->setViewer($viewer);
     $owner_source = new ManiphestAssigneeDatasource();
     $owner_source->setViewer($viewer);
     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(), 'browseURI' => $projects_source->getBrowseURI()), 'owner' => array('src' => $owner_source->getDatasourceURI(), 'placeholder' => $owner_source->getPlaceholderText(), 'browseURI' => $owner_source->getBrowseURI(), 'limit' => 1), 'cc' => array('src' => $mailable_source->getDatasourceURI(), 'placeholder' => $mailable_source->getPlaceholderText(), 'browseURI' => $mailable_source->getBrowseURI())), 'input' => 'batch-form-actions', 'priorityMap' => ManiphestTaskPriority::getTaskPriorityMap(), 'statusMap' => ManiphestTaskStatus::getTaskStatusMap()));
     $form = id(new AphrontFormView())->setUser($viewer)->addHiddenInput('board', $board_id)->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(id(new PHUIFormInsetView())->setTitle(pht('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($cancel_uri));
     $title = pht('Batch Editor');
     $crumbs = $this->buildApplicationCrumbs();
     $crumbs->addTextCrumb($title);
     $task_box = id(new PHUIObjectBoxView())->setHeaderText(pht('Selected Tasks'))->setObjectList($list);
     $form_box = id(new PHUIObjectBoxView())->setHeaderText(pht('Batch Editor'))->setForm($form);
     return $this->buildApplicationPage(array($crumbs, $task_box, $form_box), array('title' => $title));
 }
 public function readValueFromRequest(AphrontRequest $request)
 {
     $this->setValue($request->getStrList($this->getFieldKey()));
     return $this;
 }
 public function processRequest(AphrontRequest $request)
 {
     $user = $request->getUser();
     $preferences = $user->loadPreferences();
     $apps = id(new PhabricatorApplicationQuery())->setViewer($user)->withInstalled(true)->withUnlisted(false)->withLaunchable(true)->execute();
     $pinned = $preferences->getPinnedApplications($apps, $user);
     $app_list = array();
     foreach ($pinned as $app) {
         if (isset($apps[$app])) {
             $app_list[$app] = $apps[$app];
         }
     }
     if ($request->getBool('add')) {
         $options = array();
         foreach ($apps as $app) {
             $options[get_class($app)] = $app->getName();
         }
         asort($options);
         unset($options['PhabricatorApplicationsApplication']);
         if ($request->isFormPost()) {
             $pin = $request->getStr('pin');
             if (isset($options[$pin]) && !in_array($pin, $pinned)) {
                 $pinned[] = $pin;
                 $preferences->setPreference(PhabricatorUserPreferences::PREFERENCE_APP_PINNED, $pinned);
                 $preferences->save();
                 return id(new AphrontRedirectResponse())->setURI($this->getPanelURI());
             }
         }
         $options_control = id(new AphrontFormSelectControl())->setName('pin')->setLabel(pht('Application'))->setOptions($options)->setDisabledOptions(array_keys($app_list));
         $form = id(new AphrontFormView())->setUser($user)->addHiddenInput('add', 'true')->appendRemarkupInstructions(pht('Choose an application to pin to your home page.'))->appendChild($options_control);
         $dialog = id(new AphrontDialogView())->setUser($user)->setWidth(AphrontDialogView::WIDTH_FORM)->setTitle(pht('Pin Application'))->appendChild($form->buildLayoutView())->addSubmitButton(pht('Pin Application'))->addCancelButton($this->getPanelURI());
         return id(new AphrontDialogResponse())->setDialog($dialog);
     }
     $unpin = $request->getStr('unpin');
     if ($unpin) {
         $app = idx($apps, $unpin);
         if ($app) {
             if ($request->isFormPost()) {
                 $pinned = array_diff($pinned, array($unpin));
                 $preferences->setPreference(PhabricatorUserPreferences::PREFERENCE_APP_PINNED, $pinned);
                 $preferences->save();
                 return id(new AphrontRedirectResponse())->setURI($this->getPanelURI());
             }
             $dialog = id(new AphrontDialogView())->setUser($user)->setTitle(pht('Unpin Application'))->appendParagraph(pht('Unpin the %s application from your home page?', phutil_tag('strong', array(), $app->getName())))->addSubmitButton(pht('Unpin Application'))->addCanceLButton($this->getPanelURI());
             return id(new AphrontDialogResponse())->setDialog($dialog);
         }
     }
     $order = $request->getStrList('order');
     if ($order && $request->validateCSRF()) {
         $preferences->setPreference(PhabricatorUserPreferences::PREFERENCE_APP_PINNED, $order);
         $preferences->save();
         return id(new AphrontRedirectResponse())->setURI($this->getPanelURI());
     }
     $list_id = celerity_generate_unique_node_id();
     $list = id(new PHUIObjectItemListView())->setUser($user)->setID($list_id);
     Javelin::initBehavior('reorder-applications', array('listID' => $list_id, 'panelURI' => $this->getPanelURI()));
     foreach ($app_list as $key => $application) {
         if ($key == 'PhabricatorApplicationsApplication') {
             continue;
         }
         $icon = $application->getFontIcon();
         if (!$icon) {
             $icon = 'application';
         }
         $icon_view = javelin_tag('span', array('class' => 'phui-icon-view phui-font-fa ' . $icon, 'aural' => false), '');
         $item = id(new PHUIObjectItemView())->setHeader($application->getName())->setImageIcon($icon_view)->addAttribute($application->getShortDescription())->setGrippable(true);
         $item->addAction(id(new PHUIListItemView())->setIcon('fa-times')->setHref($this->getPanelURI() . '?unpin=' . $key)->setWorkflow(true));
         $item->addSigil('pinned-application');
         $item->setMetadata(array('applicationClass' => $key));
         $list->addItem($item);
     }
     $header = id(new PHUIHeaderView())->setHeader(pht('Pinned Applications'))->addActionLink(id(new PHUIButtonView())->setTag('a')->setText(pht('Pin Application'))->setHref($this->getPanelURI() . '?add=true')->setWorkflow(true)->setIcon(id(new PHUIIconView())->setIconFont('fa-thumb-tack')));
     $box = id(new PHUIObjectBoxView())->setHeader($header)->setObjectList($list);
     return $box;
 }
 public function handleRequest(AphrontRequest $request)
 {
     $viewer = $request->getViewer();
     $id = $request->getURIData('id');
     if ($id) {
         $id = $request->getURIData('id');
         $is_new = false;
         $project = id(new PhabricatorProjectQuery())->setViewer($viewer)->withIDs(array($id))->needSlugs(true)->needImages(true)->requireCapabilities(array(PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT))->executeOne();
         if (!$project) {
             return new Aphront404Response();
         }
     } else {
         $is_new = true;
         $this->requireApplicationCapability(ProjectCreateProjectsCapability::CAPABILITY);
         $project = PhabricatorProject::initializeNewProject($viewer);
     }
     $field_list = PhabricatorCustomField::getObjectFields($project, PhabricatorCustomField::ROLE_EDIT);
     $field_list->setViewer($viewer)->readFieldsFromStorage($project);
     $e_name = true;
     $e_slugs = false;
     $e_edit = null;
     $v_name = $project->getName();
     $project_slugs = $project->getSlugs();
     $project_slugs = mpull($project_slugs, 'getSlug', 'getSlug');
     $v_primary_slug = $project->getPrimarySlug();
     unset($project_slugs[$v_primary_slug]);
     $v_slugs = $project_slugs;
     $v_color = $project->getColor();
     $v_icon = $project->getIcon();
     $v_locked = $project->getIsMembershipLocked();
     $validation_exception = null;
     if ($request->isFormPost()) {
         $e_name = null;
         $e_slugs = null;
         $v_name = $request->getStr('name');
         $v_slugs = $request->getStrList('slugs');
         $v_view = $request->getStr('can_view');
         $v_edit = $request->getStr('can_edit');
         $v_join = $request->getStr('can_join');
         $v_color = $request->getStr('color');
         $v_icon = $request->getStr('icon');
         $v_locked = $request->getInt('is_membership_locked', 0);
         $type_name = PhabricatorProjectTransaction::TYPE_NAME;
         $type_slugs = PhabricatorProjectTransaction::TYPE_SLUGS;
         $type_edit = PhabricatorTransactions::TYPE_EDIT_POLICY;
         $type_icon = PhabricatorProjectTransaction::TYPE_ICON;
         $type_color = PhabricatorProjectTransaction::TYPE_COLOR;
         $type_locked = PhabricatorProjectTransaction::TYPE_LOCKED;
         $xactions = array();
         $xactions[] = id(new PhabricatorProjectTransaction())->setTransactionType($type_name)->setNewValue($v_name);
         $xactions[] = id(new PhabricatorProjectTransaction())->setTransactionType($type_slugs)->setNewValue($v_slugs);
         $xactions[] = id(new PhabricatorProjectTransaction())->setTransactionType(PhabricatorTransactions::TYPE_VIEW_POLICY)->setNewValue($v_view);
         $xactions[] = id(new PhabricatorProjectTransaction())->setTransactionType($type_edit)->setNewValue($v_edit);
         $xactions[] = id(new PhabricatorProjectTransaction())->setTransactionType(PhabricatorTransactions::TYPE_JOIN_POLICY)->setNewValue($v_join);
         $xactions[] = id(new PhabricatorProjectTransaction())->setTransactionType($type_icon)->setNewValue($v_icon);
         $xactions[] = id(new PhabricatorProjectTransaction())->setTransactionType($type_color)->setNewValue($v_color);
         $xactions[] = id(new PhabricatorProjectTransaction())->setTransactionType($type_locked)->setNewValue($v_locked);
         $xactions = array_merge($xactions, $field_list->buildFieldTransactionsFromRequest(new PhabricatorProjectTransaction(), $request));
         $editor = id(new PhabricatorProjectTransactionEditor())->setActor($viewer)->setContentSourceFromRequest($request)->setContinueOnNoEffect(true);
         if ($is_new) {
             $xactions[] = id(new PhabricatorProjectTransaction())->setTransactionType(PhabricatorTransactions::TYPE_EDGE)->setMetadataValue('edge:type', PhabricatorProjectProjectHasMemberEdgeType::EDGECONST)->setNewValue(array('+' => array($viewer->getPHID() => $viewer->getPHID())));
         }
         try {
             $editor->applyTransactions($project, $xactions);
             if ($request->isAjax()) {
                 return id(new AphrontAjaxResponse())->setContent(array('phid' => $project->getPHID(), 'name' => $project->getName()));
             }
             $redirect_uri = $this->getApplicationURI('profile/' . $project->getID() . '/');
             return id(new AphrontRedirectResponse())->setURI($redirect_uri);
         } catch (PhabricatorApplicationTransactionValidationException $ex) {
             $validation_exception = $ex;
             $e_name = $ex->getShortMessage($type_name);
             $e_slugs = $ex->getShortMessage($type_slugs);
             $e_edit = $ex->getShortMessage($type_edit);
             $project->setViewPolicy($v_view);
             $project->setEditPolicy($v_edit);
             $project->setJoinPolicy($v_join);
         }
     }
     if ($is_new) {
         $header_name = pht('Create a New Project');
         $title = pht('Create Project');
     } else {
         $header_name = pht('Edit Project');
         $title = pht('Edit Project');
     }
     $policies = id(new PhabricatorPolicyQuery())->setViewer($viewer)->setObject($project)->execute();
     $v_slugs = implode(', ', $v_slugs);
     $form = id(new AphrontFormView())->setUser($viewer)->appendChild(id(new AphrontFormTextControl())->setLabel(pht('Name'))->setName('name')->setValue($v_name)->setError($e_name));
     $field_list->appendFieldsToForm($form);
     $shades = PhabricatorProjectIcon::getColorMap();
     if ($is_new) {
         $icon_uri = $this->getApplicationURI('icon/');
     } else {
         $icon_uri = $this->getApplicationURI('icon/' . $project->getID() . '/');
     }
     $icon_display = PhabricatorProjectIcon::renderIconForChooser($v_icon);
     list($can_lock, $lock_message) = $this->explainApplicationCapability(ProjectCanLockProjectsCapability::CAPABILITY, pht('You can update the Lock Project setting.'), pht('You can not update the Lock Project setting.'));
     $form->appendChild(id(new AphrontFormChooseButtonControl())->setLabel(pht('Icon'))->setName('icon')->setDisplayValue($icon_display)->setButtonText(pht('Choose Icon...'))->setChooseURI($icon_uri)->setValue($v_icon))->appendChild(id(new AphrontFormSelectControl())->setLabel(pht('Color'))->setName('color')->setValue($v_color)->setOptions($shades));
     if (!$is_new) {
         $form->appendChild(id(new AphrontFormStaticControl())->setLabel(pht('Primary Hashtag'))->setCaption(pht('The primary hashtag is derived from the name.'))->setValue($v_primary_slug));
     }
     $form->appendChild(id(new AphrontFormTextControl())->setLabel(pht('Additional Hashtags'))->setCaption(pht('Specify a comma-separated list of additional hashtags.'))->setName('slugs')->setValue($v_slugs)->setError($e_slugs))->appendChild(id(new AphrontFormPolicyControl())->setUser($viewer)->setName('can_view')->setPolicyObject($project)->setPolicies($policies)->setCapability(PhabricatorPolicyCapability::CAN_VIEW))->appendChild(id(new AphrontFormPolicyControl())->setUser($viewer)->setName('can_edit')->setPolicyObject($project)->setPolicies($policies)->setCapability(PhabricatorPolicyCapability::CAN_EDIT)->setError($e_edit))->appendChild(id(new AphrontFormPolicyControl())->setUser($viewer)->setName('can_join')->setCaption(pht('Users who can edit a project can always join a project.'))->setPolicyObject($project)->setPolicies($policies)->setCapability(PhabricatorPolicyCapability::CAN_JOIN))->appendChild(id(new AphrontFormCheckboxControl())->setLabel(pht('Lock Project'))->setDisabled(!$can_lock)->addCheckbox('is_membership_locked', 1, pht('Prevent members from leaving this project.'), $v_locked)->setCaption($lock_message));
     if ($request->isAjax()) {
         $errors = array();
         if ($validation_exception) {
             $errors = mpull($ex->getErrors(), 'getMessage');
         }
         $dialog = id(new AphrontDialogView())->setUser($viewer)->setWidth(AphrontDialogView::WIDTH_FULL)->setTitle($header_name)->setErrors($errors)->appendForm($form)->addSubmitButton($title)->addCancelButton('/project/');
         return id(new AphrontDialogResponse())->setDialog($dialog);
     }
     $form->appendChild(id(new AphrontFormSubmitControl())->addCancelButton($this->getApplicationURI())->setValue(pht('Save')));
     $form_box = id(new PHUIObjectBoxView())->setHeaderText($title)->setValidationException($validation_exception)->setForm($form);
     if (!$is_new) {
         $nav = $this->buildIconNavView($project);
         $nav->selectFilter("details/{$id}/");
         $nav->appendChild($form_box);
     } else {
         $nav = array($form_box);
     }
     return $this->buildApplicationPage($nav, array('title' => $title));
 }
 /**
  * Read a list of items from the request, in either array format or string
  * format:
  *
  *   list[]=item1&list[]=item2
  *   list=item1,item2
  *
  * This provides flexibility when constructing URIs, especially from external
  * sources.
  *
  * @param AphrontRequest  Request to read strings from.
  * @param string          Key to read in the request.
  * @return list<string>   List of values.
  */
 protected function readListFromRequest(AphrontRequest $request, $key)
 {
     $list = $request->getArr($key, null);
     if ($list === null) {
         $list = $request->getStrList($key);
     }
     if (!$list) {
         return array();
     }
     return $list;
 }
 public function processRequest(AphrontRequest $request)
 {
     $viewer = $this->getViewer();
     $preferences = $this->getPreferences();
     $pinned_key = PhabricatorPinnedApplicationsSetting::SETTINGKEY;
     $pinned = $preferences->getSettingValue($pinned_key);
     $apps = id(new PhabricatorApplicationQuery())->setViewer($viewer)->withInstalled(true)->withUnlisted(false)->withLaunchable(true)->execute();
     $app_list = array();
     foreach ($pinned as $app) {
         if (isset($apps[$app])) {
             $app_list[$app] = $apps[$app];
         }
     }
     if ($request->getBool('reset')) {
         if ($request->isFormPost()) {
             $this->writePinnedApplications($preferences, null);
             return id(new AphrontRedirectResponse())->setURI($this->getPanelURI());
         }
         return $this->newDialog()->setTitle(pht('Reset Applications'))->addHiddenInput('reset', 'true')->appendParagraph(pht('Reset pinned applications to their defaults?'))->addSubmitButton(pht('Reset Applications'))->addCancelButton($this->getPanelURI());
     }
     if ($request->getBool('add')) {
         $options = array();
         foreach ($apps as $app) {
             $options[get_class($app)] = $app->getName();
         }
         asort($options);
         unset($options['PhabricatorApplicationsApplication']);
         if ($request->isFormPost()) {
             $pins = $request->getArr('pin');
             $phid = head($pins);
             $app = id(new PhabricatorApplicationQuery())->setViewer($viewer)->withPHIDs(array($phid))->executeOne();
             if ($app) {
                 $pin = get_class($app);
             } else {
                 // This likely means the user submitted an empty form
                 // which will cause nothing to happen.
                 $pin = '';
             }
             if (isset($options[$pin]) && !in_array($pin, $pinned)) {
                 $pinned[] = $pin;
                 $this->writePinnedApplications($preferences, $pinned);
                 return id(new AphrontRedirectResponse())->setURI($this->getPanelURI());
             }
         }
         $options_control = id(new AphrontFormTokenizerControl())->setName('pin')->setLabel(pht('Application'))->setDatasource(new PhabricatorApplicationDatasource())->setLimit(1);
         $form = id(new AphrontFormView())->setViewer($viewer)->addHiddenInput('add', 'true')->appendRemarkupInstructions(pht('Choose an application to pin to your home page.'))->appendControl($options_control);
         return $this->newDialog()->setWidth(AphrontDialogView::WIDTH_FORM)->setTitle(pht('Pin Application'))->appendChild($form->buildLayoutView())->addSubmitButton(pht('Pin Application'))->addCancelButton($this->getPanelURI());
     }
     $unpin = $request->getStr('unpin');
     if ($unpin) {
         $app = idx($apps, $unpin);
         if ($app) {
             if ($request->isFormPost()) {
                 $pinned = array_diff($pinned, array($unpin));
                 $this->writePinnedApplications($preferences, $pinned);
                 return id(new AphrontRedirectResponse())->setURI($this->getPanelURI());
             }
             return $this->newDialog()->setTitle(pht('Unpin Application'))->addHiddenInput('unpin', $unpin)->appendParagraph(pht('Unpin the %s application from your home page?', phutil_tag('strong', array(), $app->getName())))->addSubmitButton(pht('Unpin Application'))->addCancelButton($this->getPanelURI());
         }
     }
     $order = $request->getStrList('order');
     if ($order && $request->validateCSRF()) {
         $this->writePinnedApplications($preferences, $order);
         return id(new AphrontRedirectResponse())->setURI($this->getPanelURI());
     }
     $list_id = celerity_generate_unique_node_id();
     $list = id(new PHUIObjectItemListView())->setViewer($viewer)->setID($list_id);
     Javelin::initBehavior('reorder-applications', array('listID' => $list_id, 'panelURI' => $this->getPanelURI()));
     foreach ($app_list as $key => $application) {
         if ($key == 'PhabricatorApplicationsApplication') {
             continue;
         }
         $icon = $application->getIcon();
         if (!$icon) {
             $icon = 'fa-globe';
         }
         $item = id(new PHUIObjectItemView())->setHeader($application->getName())->setImageIcon($icon)->addAttribute($application->getShortDescription())->setGrippable(true);
         $item->addAction(id(new PHUIListItemView())->setIcon('fa-times')->setHref($this->getPanelURI() . '?unpin=' . $key)->setWorkflow(true));
         $item->addSigil('pinned-application');
         $item->setMetadata(array('applicationClass' => $key));
         $list->addItem($item);
     }
     $header = id(new PHUIHeaderView())->setHeader(pht('Pinned Applications'))->addActionLink(id(new PHUIButtonView())->setTag('a')->setText(pht('Pin Application'))->setHref($this->getPanelURI() . '?add=true')->setWorkflow(true)->setIcon('fa-thumb-tack'))->addActionLink(id(new PHUIButtonView())->setTag('a')->setText(pht('Reset to Defaults'))->setHref($this->getPanelURI() . '?reset=true')->setWorkflow(true)->setIcon('fa-recycle'));
     $box = id(new PHUIObjectBoxView())->setHeader($header)->setObjectList($list);
     return $box;
 }
 protected function getValueFromRequest(AphrontRequest $request, $key)
 {
     return $request->getStrList($key);
 }
 public function handleRequest(AphrontRequest $request)
 {
     $viewer = $this->getViewer();
     $this->requireApplicationCapability(ManiphestBulkEditCapability::CAPABILITY);
     $project = null;
     $board_id = $request->getInt('board');
     if ($board_id) {
         $project = id(new PhabricatorProjectQuery())->setViewer($viewer)->withIDs(array($board_id))->executeOne();
         if (!$project) {
             return new Aphront404Response();
         }
     }
     $task_ids = $request->getArr('batch');
     if (!$task_ids) {
         $task_ids = $request->getStrList('batch');
     }
     if (!$task_ids) {
         throw new Exception(pht('No tasks are selected.'));
     }
     $tasks = id(new ManiphestTaskQuery())->setViewer($viewer)->withIDs($task_ids)->requireCapabilities(array(PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT))->needSubscriberPHIDs(true)->needProjectPHIDs(true)->execute();
     if (!$tasks) {
         throw new Exception(pht("You don't have permission to edit any of the selected tasks."));
     }
     if ($project) {
         $cancel_uri = '/project/board/' . $project->getID() . '/';
         $redirect_uri = $cancel_uri;
     } else {
         $cancel_uri = '/maniphest/';
         $redirect_uri = '/maniphest/?ids=' . implode(',', mpull($tasks, 'getID'));
     }
     $actions = $request->getStr('actions');
     if ($actions) {
         $actions = phutil_json_decode($actions);
     }
     if ($request->isFormPost() && $actions) {
         $job = PhabricatorWorkerBulkJob::initializeNewJob($viewer, new ManiphestTaskEditBulkJobType(), array('taskPHIDs' => mpull($tasks, 'getPHID'), 'actions' => $actions, 'cancelURI' => $cancel_uri, 'doneURI' => $redirect_uri));
         $type_status = PhabricatorWorkerBulkJobTransaction::TYPE_STATUS;
         $xactions = array();
         $xactions[] = id(new PhabricatorWorkerBulkJobTransaction())->setTransactionType($type_status)->setNewValue(PhabricatorWorkerBulkJob::STATUS_CONFIRM);
         $editor = id(new PhabricatorWorkerBulkJobEditor())->setActor($viewer)->setContentSourceFromRequest($request)->setContinueOnMissingFields(true)->applyTransactions($job, $xactions);
         return id(new AphrontRedirectResponse())->setURI($job->getMonitorURI());
     }
     $handles = ManiphestTaskListView::loadTaskHandles($viewer, $tasks);
     $list = new ManiphestTaskListView();
     $list->setTasks($tasks);
     $list->setUser($viewer);
     $list->setHandles($handles);
     $template = new AphrontTokenizerTemplateView();
     $template = $template->render();
     $projects_source = new PhabricatorProjectDatasource();
     $mailable_source = new PhabricatorMetaMTAMailableDatasource();
     $mailable_source->setViewer($viewer);
     $owner_source = new ManiphestAssigneeDatasource();
     $owner_source->setViewer($viewer);
     $spaces_source = id(new PhabricatorSpacesNamespaceDatasource())->setViewer($viewer);
     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(), 'browseURI' => $projects_source->getBrowseURI()), 'owner' => array('src' => $owner_source->getDatasourceURI(), 'placeholder' => $owner_source->getPlaceholderText(), 'browseURI' => $owner_source->getBrowseURI(), 'limit' => 1), 'cc' => array('src' => $mailable_source->getDatasourceURI(), 'placeholder' => $mailable_source->getPlaceholderText(), 'browseURI' => $mailable_source->getBrowseURI()), 'spaces' => array('src' => $spaces_source->getDatasourceURI(), 'placeholder' => $spaces_source->getPlaceholderText(), 'browseURI' => $spaces_source->getBrowseURI(), 'limit' => 1)), 'input' => 'batch-form-actions', 'priorityMap' => ManiphestTaskPriority::getTaskPriorityMap(), 'statusMap' => ManiphestTaskStatus::getTaskStatusMap()));
     $form = id(new AphrontFormView())->setUser($viewer)->addHiddenInput('board', $board_id)->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(id(new PHUIFormInsetView())->setTitle(pht('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($cancel_uri));
     $title = pht('Batch Editor');
     $crumbs = $this->buildApplicationCrumbs();
     $crumbs->addTextCrumb($title);
     $crumbs->setBorder(true);
     $header = id(new PHUIHeaderView())->setHeader(pht('Batch Editor'))->setHeaderIcon('fa-pencil-square-o');
     $task_box = id(new PHUIObjectBoxView())->setHeaderText(pht('Selected Tasks'))->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)->setObjectList($list);
     $form_box = id(new PHUIObjectBoxView())->setHeaderText(pht('Actions'))->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)->setForm($form);
     $view = id(new PHUITwoColumnView())->setHeader($header)->setFooter(array($task_box, $form_box));
     return $this->newPage()->setTitle($title)->setCrumbs($crumbs)->appendChild($view);
 }
 public function handleRequest(AphrontRequest $request)
 {
     $viewer = $this->getViewer();
     $id = $request->getURIData('id');
     $response_type = $request->getStr('responseType', 'task');
     $order = $request->getStr('order', PhabricatorProjectColumn::DEFAULT_ORDER);
     $can_edit_assign = $this->hasApplicationCapability(ManiphestEditAssignCapability::CAPABILITY);
     $can_edit_policies = $this->hasApplicationCapability(ManiphestEditPoliciesCapability::CAPABILITY);
     $can_edit_priority = $this->hasApplicationCapability(ManiphestEditPriorityCapability::CAPABILITY);
     $can_edit_projects = $this->hasApplicationCapability(ManiphestEditProjectsCapability::CAPABILITY);
     $can_edit_status = $this->hasApplicationCapability(ManiphestEditStatusCapability::CAPABILITY);
     $can_create_projects = PhabricatorPolicyFilter::hasCapability($viewer, PhabricatorApplication::getByClass('PhabricatorProjectApplication'), ProjectCreateProjectsCapability::CAPABILITY);
     $parent_task = null;
     $template_id = null;
     if ($id) {
         $task = id(new ManiphestTaskQuery())->setViewer($viewer)->requireCapabilities(array(PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT))->withIDs(array($id))->needSubscriberPHIDs(true)->needProjectPHIDs(true)->executeOne();
         if (!$task) {
             return new Aphront404Response();
         }
     } else {
         $task = ManiphestTask::initializeNewTask($viewer);
         // We currently do not allow you to set the task status when creating
         // a new task, although now that statuses are custom it might make
         // sense.
         $can_edit_status = false;
         // These allow task creation with defaults.
         if (!$request->isFormPost()) {
             $task->setTitle($request->getStr('title'));
             if ($can_edit_projects) {
                 $projects = $request->getStr('projects');
                 if ($projects) {
                     $tokens = $request->getStrList('projects');
                     $type_project = PhabricatorProjectProjectPHIDType::TYPECONST;
                     foreach ($tokens as $key => $token) {
                         if (phid_get_type($token) == $type_project) {
                             // If this is formatted like a PHID, leave it as-is.
                             continue;
                         }
                         if (preg_match('/^#/', $token)) {
                             // If this already has a "#", leave it as-is.
                             continue;
                         }
                         // Add a "#" prefix.
                         $tokens[$key] = '#' . $token;
                     }
                     $default_projects = id(new PhabricatorObjectQuery())->setViewer($viewer)->withNames($tokens)->execute();
                     $default_projects = mpull($default_projects, 'getPHID');
                     if ($default_projects) {
                         $task->attachProjectPHIDs($default_projects);
                     }
                 }
             }
             if ($can_edit_priority) {
                 $priority = $request->getInt('priority');
                 if ($priority !== null) {
                     $priority_map = ManiphestTaskPriority::getTaskPriorityMap();
                     if (isset($priority_map[$priority])) {
                         $task->setPriority($priority);
                     }
                 }
             }
             $task->setDescription($request->getStr('description'));
             if ($can_edit_assign) {
                 $assign = $request->getStr('assign');
                 if (strlen($assign)) {
                     $assign_user = id(new PhabricatorPeopleQuery())->setViewer($viewer)->withUsernames(array($assign))->executeOne();
                     if (!$assign_user) {
                         $assign_user = id(new PhabricatorPeopleQuery())->setViewer($viewer)->withPHIDs(array($assign))->executeOne();
                     }
                     if ($assign_user) {
                         $task->setOwnerPHID($assign_user->getPHID());
                     }
                 }
             }
         }
         $template_id = $request->getInt('template');
         // You can only have a parent task if you're creating a new task.
         $parent_id = $request->getInt('parent');
         if (strlen($parent_id)) {
             $parent_task = id(new ManiphestTaskQuery())->setViewer($viewer)->withIDs(array($parent_id))->executeOne();
             if (!$parent_task) {
                 return new Aphront404Response();
             }
             if (!$template_id) {
                 $template_id = $parent_id;
             }
         }
     }
     $errors = array();
     $e_title = true;
     $field_list = PhabricatorCustomField::getObjectFields($task, PhabricatorCustomField::ROLE_EDIT);
     $field_list->setViewer($viewer);
     $field_list->readFieldsFromStorage($task);
     $aux_fields = $field_list->getFields();
     $v_space = $task->getSpacePHID();
     if ($request->isFormPost()) {
         $changes = array();
         $new_title = $request->getStr('title');
         $new_desc = $request->getStr('description');
         $new_status = $request->getStr('status');
         $v_space = $request->getStr('spacePHID');
         if (!$task->getID()) {
             $workflow = 'create';
         } else {
             $workflow = '';
         }
         $changes[ManiphestTransaction::TYPE_TITLE] = $new_title;
         $changes[ManiphestTransaction::TYPE_DESCRIPTION] = $new_desc;
         if ($can_edit_status) {
             $changes[ManiphestTransaction::TYPE_STATUS] = $new_status;
         } else {
             if (!$task->getID()) {
                 // Create an initial status transaction for the burndown chart.
                 // TODO: We can probably remove this once Facts comes online.
                 $changes[ManiphestTransaction::TYPE_STATUS] = $task->getStatus();
             }
         }
         $owner_tokenizer = $request->getArr('assigned_to');
         $owner_phid = reset($owner_tokenizer);
         if (!strlen($new_title)) {
             $e_title = pht('Required');
             $errors[] = pht('Title is required.');
         }
         $old_values = array();
         foreach ($aux_fields as $aux_arr_key => $aux_field) {
             // TODO: This should be buildFieldTransactionsFromRequest() once we
             // switch to ApplicationTransactions properly.
             $aux_old_value = $aux_field->getOldValueForApplicationTransactions();
             $aux_field->readValueFromRequest($request);
             $aux_new_value = $aux_field->getNewValueForApplicationTransactions();
             // TODO: We're faking a call to the ApplicaitonTransaction validation
             // logic here. We need valid objects to pass, but they aren't used
             // in a meaningful way. For now, build User objects. Once the Maniphest
             // objects exist, this will switch over automatically. This is a big
             // hack but shouldn't be long for this world.
             $placeholder_editor = id(new PhabricatorUserProfileEditor())->setActor($viewer);
             $field_errors = $aux_field->validateApplicationTransactions($placeholder_editor, PhabricatorTransactions::TYPE_CUSTOMFIELD, array(id(new ManiphestTransaction())->setOldValue($aux_old_value)->setNewValue($aux_new_value)));
             foreach ($field_errors as $error) {
                 $errors[] = $error->getMessage();
             }
             $old_values[$aux_field->getFieldKey()] = $aux_old_value;
         }
         if ($errors) {
             $task->setTitle($new_title);
             $task->setDescription($new_desc);
             $task->setPriority($request->getInt('priority'));
             $task->setOwnerPHID($owner_phid);
             $task->attachSubscriberPHIDs($request->getArr('cc'));
             $task->attachProjectPHIDs($request->getArr('projects'));
         } else {
             if ($can_edit_priority) {
                 $changes[ManiphestTransaction::TYPE_PRIORITY] = $request->getInt('priority');
             }
             if ($can_edit_assign) {
                 $changes[ManiphestTransaction::TYPE_OWNER] = $owner_phid;
             }
             $changes[PhabricatorTransactions::TYPE_SUBSCRIBERS] = array('=' => $request->getArr('cc'));
             if ($can_edit_projects) {
                 $projects = $request->getArr('projects');
                 $changes[PhabricatorTransactions::TYPE_EDGE] = $projects;
                 $column_phid = $request->getStr('columnPHID');
                 // allow for putting a task in a project column at creation -only-
                 if (!$task->getID() && $column_phid && $projects) {
                     $column = id(new PhabricatorProjectColumnQuery())->setViewer($viewer)->withProjectPHIDs($projects)->withPHIDs(array($column_phid))->executeOne();
                     if ($column) {
                         $changes[ManiphestTransaction::TYPE_PROJECT_COLUMN] = array('new' => array('projectPHID' => $column->getProjectPHID(), 'columnPHIDs' => array($column_phid)), 'old' => array('projectPHID' => $column->getProjectPHID(), 'columnPHIDs' => array()));
                     }
                 }
             }
             if ($can_edit_policies) {
                 $changes[PhabricatorTransactions::TYPE_SPACE] = $v_space;
                 $changes[PhabricatorTransactions::TYPE_VIEW_POLICY] = $request->getStr('viewPolicy');
                 $changes[PhabricatorTransactions::TYPE_EDIT_POLICY] = $request->getStr('editPolicy');
             }
             $template = new ManiphestTransaction();
             $transactions = array();
             foreach ($changes as $type => $value) {
                 $transaction = clone $template;
                 $transaction->setTransactionType($type);
                 if ($type == ManiphestTransaction::TYPE_PROJECT_COLUMN) {
                     $transaction->setNewValue($value['new']);
                     $transaction->setOldValue($value['old']);
                 } else {
                     if ($type == PhabricatorTransactions::TYPE_EDGE) {
                         $project_type = PhabricatorProjectObjectHasProjectEdgeType::EDGECONST;
                         $transaction->setMetadataValue('edge:type', $project_type)->setNewValue(array('=' => array_fuse($value)));
                     } else {
                         $transaction->setNewValue($value);
                     }
                 }
                 $transactions[] = $transaction;
             }
             if ($aux_fields) {
                 foreach ($aux_fields as $aux_field) {
                     $transaction = clone $template;
                     $transaction->setTransactionType(PhabricatorTransactions::TYPE_CUSTOMFIELD);
                     $aux_key = $aux_field->getFieldKey();
                     $transaction->setMetadataValue('customfield:key', $aux_key);
                     $old = idx($old_values, $aux_key);
                     $new = $aux_field->getNewValueForApplicationTransactions();
                     $transaction->setOldValue($old);
                     $transaction->setNewValue($new);
                     $transactions[] = $transaction;
                 }
             }
             if ($transactions) {
                 $is_new = !$task->getID();
                 $event = new PhabricatorEvent(PhabricatorEventType::TYPE_MANIPHEST_WILLEDITTASK, array('task' => $task, 'new' => $is_new, 'transactions' => $transactions));
                 $event->setUser($viewer);
                 $event->setAphrontRequest($request);
                 PhutilEventEngine::dispatchEvent($event);
                 $task = $event->getValue('task');
                 $transactions = $event->getValue('transactions');
                 $editor = id(new ManiphestTransactionEditor())->setActor($viewer)->setContentSourceFromRequest($request)->setContinueOnNoEffect(true)->applyTransactions($task, $transactions);
                 $event = new PhabricatorEvent(PhabricatorEventType::TYPE_MANIPHEST_DIDEDITTASK, array('task' => $task, 'new' => $is_new, 'transactions' => $transactions));
                 $event->setUser($viewer);
                 $event->setAphrontRequest($request);
                 PhutilEventEngine::dispatchEvent($event);
             }
             if ($parent_task) {
                 // TODO: This should be transactional now.
                 id(new PhabricatorEdgeEditor())->addEdge($parent_task->getPHID(), ManiphestTaskDependsOnTaskEdgeType::EDGECONST, $task->getPHID())->save();
                 $workflow = $parent_task->getID();
             }
             if ($request->isAjax()) {
                 switch ($response_type) {
                     case 'card':
                         $owner = null;
                         if ($task->getOwnerPHID()) {
                             $owner = id(new PhabricatorHandleQuery())->setViewer($viewer)->withPHIDs(array($task->getOwnerPHID()))->executeOne();
                         }
                         $project = $this->getSprintProjectforTask($viewer, $projects);
                         $tasks = id(new SprintBoardTaskCard())->setViewer($viewer)->setProject($project)->setTask($task)->setOwner($owner)->setCanEdit(true)->getItem();
                         $column = id(new PhabricatorProjectColumnQuery())->setViewer($viewer)->withPHIDs(array($request->getStr('columnPHID')))->executeOne();
                         if (!$column) {
                             return new Aphront404Response();
                         }
                         // re-load projects for accuracy as they are not re-loaded via
                         // the editor
                         $project_phids = PhabricatorEdgeQuery::loadDestinationPHIDs($task->getPHID(), PhabricatorProjectObjectHasProjectEdgeType::EDGECONST);
                         $task->attachProjectPHIDs($project_phids);
                         $remove_from_board = false;
                         if (!in_array($column->getProjectPHID(), $project_phids)) {
                             $remove_from_board = true;
                         }
                         $positions = id(new PhabricatorProjectColumnPositionQuery())->setViewer($viewer)->withColumns(array($column))->execute();
                         $task_phids = mpull($positions, 'getObjectPHID');
                         $column_tasks = id(new ManiphestTaskQuery())->setViewer($viewer)->withPHIDs($task_phids)->execute();
                         if ($order == PhabricatorProjectColumn::ORDER_NATURAL) {
                             // TODO: This is a little bit awkward, because PHP and JS use
                             // slightly different sort order parameters to achieve the same
                             // effect. It would be good to unify this a bit at some point.
                             $sort_map = array();
                             foreach ($positions as $position) {
                                 $sort_map[$position->getObjectPHID()] = array(-$position->getSequence(), $position->getID());
                             }
                         } else {
                             $sort_map = mpull($column_tasks, 'getPrioritySortVector', 'getPHID');
                         }
                         $data = array('sortMap' => $sort_map, 'removeFromBoard' => $remove_from_board);
                         break;
                     case 'task':
                     default:
                         $tasks = $this->renderSingleTask($task);
                         $data = array();
                         break;
                 }
                 return id(new AphrontAjaxResponse())->setContent(array('tasks' => $tasks, 'data' => $data));
             }
             $redirect_uri = '/T' . $task->getID();
             if ($workflow) {
                 $redirect_uri .= '?workflow=' . $workflow;
             }
             return id(new AphrontRedirectResponse())->setURI($redirect_uri);
         }
     } else {
         if (!$task->getID()) {
             $task->attachSubscriberPHIDs(array($viewer->getPHID()));
             if ($template_id) {
                 $template_task = id(new ManiphestTaskQuery())->setViewer($viewer)->withIDs(array($template_id))->needSubscriberPHIDs(true)->needProjectPHIDs(true)->executeOne();
                 if ($template_task) {
                     $cc_phids = array_unique(array_merge($template_task->getSubscriberPHIDs(), array($viewer->getPHID())));
                     $task->attachSubscriberPHIDs($cc_phids);
                     $task->attachProjectPHIDs($template_task->getProjectPHIDs());
                     $task->setOwnerPHID($template_task->getOwnerPHID());
                     $task->setPriority($template_task->getPriority());
                     $task->setViewPolicy($template_task->getViewPolicy());
                     $task->setEditPolicy($template_task->getEditPolicy());
                     $v_space = $template_task->getSpacePHID();
                     $template_fields = PhabricatorCustomField::getObjectFields($template_task, PhabricatorCustomField::ROLE_EDIT);
                     $fields = $template_fields->getFields();
                     foreach ($fields as $key => $field) {
                         if (!$field->shouldCopyWhenCreatingSimilarTask()) {
                             unset($fields[$key]);
                         }
                         if (empty($aux_fields[$key])) {
                             unset($fields[$key]);
                         }
                     }
                     if ($fields) {
                         id(new PhabricatorCustomFieldList($fields))->setViewer($viewer)->readFieldsFromStorage($template_task);
                         foreach ($fields as $key => $field) {
                             $aux_fields[$key]->setValueFromStorage($field->getValueForStorage());
                         }
                     }
                 }
             }
         }
     }
     $error_view = null;
     if ($errors) {
         $error_view = new PHUIInfoView();
         $error_view->setErrors($errors);
     }
     $priority_map = ManiphestTaskPriority::getTaskPriorityMap();
     if ($task->getOwnerPHID()) {
         $assigned_value = array($task->getOwnerPHID());
     } else {
         $assigned_value = array();
     }
     if ($task->getSubscriberPHIDs()) {
         $cc_value = $task->getSubscriberPHIDs();
     } else {
         $cc_value = array();
     }
     if ($task->getProjectPHIDs()) {
         $projects_value = $task->getProjectPHIDs();
     } else {
         $projects_value = array();
     }
     $cancel_id = nonempty($task->getID(), $template_id);
     if ($cancel_id) {
         $cancel_uri = '/T' . $cancel_id;
     } else {
         $cancel_uri = '/maniphest/';
     }
     if ($task->getID()) {
         $button_name = pht('Save Task');
         $header_name = pht('Edit Task');
     } else {
         if ($parent_task) {
             $cancel_uri = '/T' . $parent_task->getID();
             $button_name = pht('Create Task');
             $header_name = pht('Create New Subtask');
         } else {
             $button_name = pht('Create Task');
             $header_name = pht('Create New Task');
         }
     }
     require_celerity_resource('maniphest-task-edit-css');
     $project_tokenizer_id = celerity_generate_unique_node_id();
     $form = new AphrontFormView();
     $form->setUser($viewer)->addHiddenInput('template', $template_id)->addHiddenInput('responseType', $response_type)->addHiddenInput('order', $order)->addHiddenInput('ungrippable', $request->getStr('ungrippable'))->addHiddenInput('columnPHID', $request->getStr('columnPHID'));
     if ($parent_task) {
         $form->appendChild(id(new AphrontFormStaticControl())->setLabel(pht('Parent Task'))->setValue($viewer->renderHandle($parent_task->getPHID())))->addHiddenInput('parent', $parent_task->getID());
     }
     $form->appendChild(id(new AphrontFormTextAreaControl())->setLabel(pht('Title'))->setName('title')->setError($e_title)->setHeight(AphrontFormTextAreaControl::HEIGHT_VERY_SHORT)->setValue($task->getTitle()));
     if ($can_edit_status) {
         // See T4819.
         $status_map = ManiphestTaskStatus::getTaskStatusMap();
         $dup_status = ManiphestTaskStatus::getDuplicateStatus();
         if ($task->getStatus() != $dup_status) {
             unset($status_map[$dup_status]);
         }
         $form->appendChild(id(new AphrontFormSelectControl())->setLabel(pht('Status'))->setName('status')->setValue($task->getStatus())->setOptions($status_map));
     }
     $policies = id(new PhabricatorPolicyQuery())->setViewer($viewer)->setObject($task)->execute();
     if ($can_edit_assign) {
         $form->appendControl(id(new AphrontFormTokenizerControl())->setLabel(pht('Assigned To'))->setName('assigned_to')->setValue($assigned_value)->setUser($viewer)->setDatasource(new PhabricatorPeopleDatasource())->setLimit(1));
     }
     $form->appendControl(id(new AphrontFormTokenizerControl())->setLabel(pht('CC'))->setName('cc')->setValue($cc_value)->setUser($viewer)->setDatasource(new PhabricatorMetaMTAMailableDatasource()));
     if ($can_edit_priority) {
         $form->appendChild(id(new AphrontFormSelectControl())->setLabel(pht('Priority'))->setName('priority')->setOptions($priority_map)->setValue($task->getPriority()));
     }
     if ($can_edit_policies) {
         $form->appendChild(id(new AphrontFormPolicyControl())->setUser($viewer)->setCapability(PhabricatorPolicyCapability::CAN_VIEW)->setPolicyObject($task)->setPolicies($policies)->setSpacePHID($v_space)->setName('viewPolicy'))->appendChild(id(new AphrontFormPolicyControl())->setUser($viewer)->setCapability(PhabricatorPolicyCapability::CAN_EDIT)->setPolicyObject($task)->setPolicies($policies)->setName('editPolicy'));
     }
     if ($can_edit_projects) {
         $caption = null;
         if ($can_create_projects) {
             $caption = javelin_tag('a', array('href' => '/project/create/', 'mustcapture' => true, 'sigil' => 'project-create'), pht('Create New Project'));
         }
         $form->appendControl(id(new AphrontFormTokenizerControl())->setLabel(pht('Projects'))->setName('projects')->setValue($projects_value)->setID($project_tokenizer_id)->setCaption($caption)->setDatasource(new PhabricatorProjectDatasource()));
     }
     $field_list->appendFieldsToForm($form);
     require_celerity_resource('phui-info-view-css');
     Javelin::initBehavior('project-create', array('tokenizerID' => $project_tokenizer_id));
     $description_control = id(new PhabricatorRemarkupControl())->setLabel(pht('Description'))->setName('description')->setID('description-textarea')->setValue($task->getDescription())->setUser($viewer);
     $form->appendChild($description_control);
     if ($request->isAjax()) {
         $dialog = id(new AphrontDialogView())->setUser($viewer)->setWidth(AphrontDialogView::WIDTH_FULL)->setTitle($header_name)->appendChild(array($error_view, $form->buildLayoutView()))->addCancelButton($cancel_uri)->addSubmitButton($button_name);
         return id(new AphrontDialogResponse())->setDialog($dialog);
     }
     $form->appendChild(id(new AphrontFormSubmitControl())->addCancelButton($cancel_uri)->setValue($button_name));
     $form_box = id(new PHUIObjectBoxView())->setHeaderText($header_name)->setFormErrors($errors)->setForm($form);
     $preview = id(new PHUIRemarkupPreviewPanel())->setHeader(pht('Description Preview'))->setControlID('description-textarea')->setPreviewURI($this->getApplicationURI('task/descriptionpreview/'));
     if ($task->getID()) {
         $page_objects = array($task->getPHID());
     } else {
         $page_objects = array();
     }
     $crumbs = $this->buildApplicationCrumbs();
     if ($task->getID()) {
         $crumbs->addTextCrumb('T' . $task->getID(), '/T' . $task->getID());
     }
     $crumbs->addTextCrumb($header_name);
     $title = $header_name;
     return $this->newPage()->setTitle($title)->setCrumbs($crumbs)->setPageObjectPHIDs($page_objects)->appendChild(array($form_box, $preview));
 }
 public function readFormValuesFromRequest(AphrontRequest $request)
 {
     $values = array();
     foreach ($this->getPropertyKeys() as $key) {
         switch ($key) {
             case self::KEY_REALNAME_ATTRIBUTES:
                 $values[$key] = $request->getStrList($key, array());
                 break;
             default:
                 $values[$key] = $request->getStr($key);
                 break;
         }
     }
     return $values;
 }
 public function handleRequest(AphrontRequest $request)
 {
     $viewer = $this->getViewer();
     $group_map = $this->getColumnMap();
     $group = explode('.', $request->getStr('group'));
     $group = array_intersect($group, array_keys($group_map));
     $group = array_fuse($group);
     if (empty($group['type'])) {
         $group['type'] = 'type';
     }
     $now = PhabricatorTime::getNow();
     $ago = $now - phutil_units('24 hours in seconds');
     $table = new MultimeterEvent();
     $conn = $table->establishConnection('r');
     $where = array();
     $where[] = qsprintf($conn, 'epoch >= %d AND epoch <= %d', $ago, $now);
     $with = array();
     foreach ($group_map as $key => $column) {
         // Don't let non-admins filter by viewers, this feels a little too
         // invasive of privacy.
         if ($key == 'viewer') {
             if (!$viewer->getIsAdmin()) {
                 continue;
             }
         }
         $with[$key] = $request->getStrList($key);
         if ($with[$key]) {
             $where[] = qsprintf($conn, '%T IN (%Ls)', $column, $with[$key]);
         }
     }
     $where = '(' . implode(') AND (', $where) . ')';
     $data = queryfx_all($conn, 'SELECT *,
       count(*) AS N,
       SUM(sampleRate * resourceCost) AS totalCost,
       SUM(sampleRate * resourceCost) / SUM(sampleRate) AS averageCost
     FROM %T
     WHERE %Q
     GROUP BY %Q
     ORDER BY totalCost DESC, MAX(id) DESC
     LIMIT 100', $table->getTableName(), $where, implode(', ', array_select_keys($group_map, $group)));
     $this->loadDimensions($data);
     $phids = array();
     foreach ($data as $row) {
         $viewer_name = $this->getViewerDimension($row['eventViewerID'])->getName();
         $viewer_phid = $this->getEventViewerPHID($viewer_name);
         if ($viewer_phid) {
             $phids[] = $viewer_phid;
         }
     }
     $handles = $viewer->loadHandles($phids);
     $rows = array();
     foreach ($data as $row) {
         if ($row['N'] == 1) {
             $events_col = $row['id'];
         } else {
             $events_col = $this->renderGroupingLink($group, 'id', pht('%s Event(s)', new PhutilNumber($row['N'])));
         }
         if (isset($group['request'])) {
             $request_col = $row['requestKey'];
             if (!$with['request']) {
                 $request_col = $this->renderSelectionLink('request', $row['requestKey'], $request_col);
             }
         } else {
             $request_col = $this->renderGroupingLink($group, 'request');
         }
         if (isset($group['viewer'])) {
             if ($viewer->getIsAdmin()) {
                 $viewer_col = $this->getViewerDimension($row['eventViewerID'])->getName();
                 $viewer_phid = $this->getEventViewerPHID($viewer_col);
                 if ($viewer_phid) {
                     $viewer_col = $handles[$viewer_phid]->getName();
                 }
                 if (!$with['viewer']) {
                     $viewer_col = $this->renderSelectionLink('viewer', $row['eventViewerID'], $viewer_col);
                 }
             } else {
                 $viewer_col = phutil_tag('em', array(), pht('(Masked)'));
             }
         } else {
             $viewer_col = $this->renderGroupingLink($group, 'viewer');
         }
         if (isset($group['context'])) {
             $context_col = $this->getContextDimension($row['eventContextID'])->getName();
             if (!$with['context']) {
                 $context_col = $this->renderSelectionLink('context', $row['eventContextID'], $context_col);
             }
         } else {
             $context_col = $this->renderGroupingLink($group, 'context');
         }
         if (isset($group['host'])) {
             $host_col = $this->getHostDimension($row['eventHostID'])->getName();
             if (!$with['host']) {
                 $host_col = $this->renderSelectionLink('host', $row['eventHostID'], $host_col);
             }
         } else {
             $host_col = $this->renderGroupingLink($group, 'host');
         }
         if (isset($group['label'])) {
             $label_col = $this->getLabelDimension($row['eventLabelID'])->getName();
             if (!$with['label']) {
                 $label_col = $this->renderSelectionLink('label', $row['eventLabelID'], $label_col);
             }
         } else {
             $label_col = $this->renderGroupingLink($group, 'label');
         }
         if ($with['type']) {
             $type_col = MultimeterEvent::getEventTypeName($row['eventType']);
         } else {
             $type_col = $this->renderSelectionLink('type', $row['eventType'], MultimeterEvent::getEventTypeName($row['eventType']));
         }
         $rows[] = array($events_col, $request_col, $viewer_col, $context_col, $host_col, $type_col, $label_col, MultimeterEvent::formatResourceCost($viewer, $row['eventType'], $row['averageCost']), MultimeterEvent::formatResourceCost($viewer, $row['eventType'], $row['totalCost']), $row['N'] == 1 ? $row['sampleRate'] : '-', phabricator_datetime($row['epoch'], $viewer));
     }
     $table = id(new AphrontTableView($rows))->setHeaders(array(pht('ID'), pht('Request'), pht('Viewer'), pht('Context'), pht('Host'), pht('Type'), pht('Label'), pht('Avg'), pht('Cost'), pht('Rate'), pht('Epoch')))->setColumnClasses(array(null, null, null, null, null, null, 'wide', 'n', 'n', 'n', null));
     $box = id(new PHUIObjectBoxView())->setHeaderText(pht('Samples'))->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)->setTable($table);
     $crumbs = $this->buildApplicationCrumbs();
     $crumbs->addTextCrumb(pht('Samples'), $this->getGroupURI(array(), true));
     $crumbs->setBorder(true);
     $crumb_map = array('host' => pht('By Host'), 'context' => pht('By Context'), 'viewer' => pht('By Viewer'), 'request' => pht('By Request'), 'label' => pht('By Label'), 'id' => pht('By ID'));
     $parts = array();
     foreach ($group as $item) {
         if ($item == 'type') {
             continue;
         }
         $parts[$item] = $item;
         $crumbs->addTextCrumb(idx($crumb_map, $item, $item), $this->getGroupURI($parts, true));
     }
     $header = id(new PHUIHeaderView())->setHeader(pht('Samples (%s - %s)', phabricator_datetime($ago, $viewer), phabricator_datetime($now, $viewer)))->setHeaderIcon('fa-motorcycle');
     $view = id(new PHUITwoColumnView())->setHeader($header)->setFooter($box);
     return $this->newPage()->setTitle(pht('Samples'))->setCrumbs($crumbs)->appendChild($view);
 }
 public function handleRequest(AphrontRequest $request)
 {
     $viewer = $request->getViewer();
     $id = $request->getURIData('id');
     if ($id) {
         $mock = id(new PholioMockQuery())->setViewer($viewer)->needImages(true)->requireCapabilities(array(PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT))->withIDs(array($id))->executeOne();
         if (!$mock) {
             return new Aphront404Response();
         }
         $title = pht('Edit Mock: %s', $mock->getName());
         $header_icon = 'fa-pencil';
         $is_new = false;
         $mock_images = $mock->getImages();
         $files = mpull($mock_images, 'getFile');
         $mock_images = mpull($mock_images, null, 'getFilePHID');
     } else {
         $mock = PholioMock::initializeNewMock($viewer);
         $title = pht('Create Mock');
         $header_icon = 'fa-plus-square';
         $is_new = true;
         $files = array();
         $mock_images = array();
     }
     if ($is_new) {
         $v_projects = array();
     } else {
         $v_projects = PhabricatorEdgeQuery::loadDestinationPHIDs($mock->getPHID(), PhabricatorProjectObjectHasProjectEdgeType::EDGECONST);
         $v_projects = array_reverse($v_projects);
     }
     $e_name = true;
     $e_images = count($mock_images) ? null : true;
     $errors = array();
     $posted_mock_images = array();
     $v_name = $mock->getName();
     $v_desc = $mock->getDescription();
     $v_view = $mock->getViewPolicy();
     $v_edit = $mock->getEditPolicy();
     $v_cc = PhabricatorSubscribersQuery::loadSubscribersForPHID($mock->getPHID());
     $v_space = $mock->getSpacePHID();
     if ($request->isFormPost()) {
         $xactions = array();
         $type_name = PholioTransaction::TYPE_NAME;
         $type_desc = PholioTransaction::TYPE_DESCRIPTION;
         $type_view = PhabricatorTransactions::TYPE_VIEW_POLICY;
         $type_edit = PhabricatorTransactions::TYPE_EDIT_POLICY;
         $type_cc = PhabricatorTransactions::TYPE_SUBSCRIBERS;
         $type_space = PhabricatorTransactions::TYPE_SPACE;
         $v_name = $request->getStr('name');
         $v_desc = $request->getStr('description');
         $v_view = $request->getStr('can_view');
         $v_edit = $request->getStr('can_edit');
         $v_cc = $request->getArr('cc');
         $v_projects = $request->getArr('projects');
         $v_space = $request->getStr('spacePHID');
         $mock_xactions = array();
         $mock_xactions[$type_name] = $v_name;
         $mock_xactions[$type_desc] = $v_desc;
         $mock_xactions[$type_view] = $v_view;
         $mock_xactions[$type_edit] = $v_edit;
         $mock_xactions[$type_cc] = array('=' => $v_cc);
         $mock_xactions[$type_space] = $v_space;
         if (!strlen($request->getStr('name'))) {
             $e_name = pht('Required');
             $errors[] = pht('You must give the mock a name.');
         }
         $file_phids = $request->getArr('file_phids');
         if ($file_phids) {
             $files = id(new PhabricatorFileQuery())->setViewer($viewer)->withPHIDs($file_phids)->execute();
             $files = mpull($files, null, 'getPHID');
             $files = array_select_keys($files, $file_phids);
         } else {
             $files = array();
         }
         if (!$files) {
             $e_images = pht('Required');
             $errors[] = pht('You must add at least one image to the mock.');
         } else {
             $mock->setCoverPHID(head($files)->getPHID());
         }
         foreach ($mock_xactions as $type => $value) {
             $xactions[$type] = id(new PholioTransaction())->setTransactionType($type)->setNewValue($value);
         }
         $order = $request->getStrList('imageOrder');
         $sequence_map = array_flip($order);
         $replaces = $request->getArr('replaces');
         $replaces_map = array_flip($replaces);
         /**
          * Foreach file posted, check to see whether we are replacing an image,
          * adding an image, or simply updating image metadata. Create
          * transactions for these cases as appropos.
          */
         foreach ($files as $file_phid => $file) {
             $replaces_image_phid = null;
             if (isset($replaces_map[$file_phid])) {
                 $old_file_phid = $replaces_map[$file_phid];
                 if ($old_file_phid != $file_phid) {
                     $old_image = idx($mock_images, $old_file_phid);
                     if ($old_image) {
                         $replaces_image_phid = $old_image->getPHID();
                     }
                 }
             }
             $existing_image = idx($mock_images, $file_phid);
             $title = (string) $request->getStr('title_' . $file_phid);
             $description = (string) $request->getStr('description_' . $file_phid);
             $sequence = $sequence_map[$file_phid];
             if ($replaces_image_phid) {
                 $replace_image = id(new PholioImage())->setReplacesImagePHID($replaces_image_phid)->setFilePhid($file_phid)->attachFile($file)->setName(strlen($title) ? $title : $file->getName())->setDescription($description)->setSequence($sequence);
                 $xactions[] = id(new PholioTransaction())->setTransactionType(PholioTransaction::TYPE_IMAGE_REPLACE)->setNewValue($replace_image);
                 $posted_mock_images[] = $replace_image;
             } else {
                 if (!$existing_image) {
                     // this is an add
                     $add_image = id(new PholioImage())->setFilePhid($file_phid)->attachFile($file)->setName(strlen($title) ? $title : $file->getName())->setDescription($description)->setSequence($sequence);
                     $xactions[] = id(new PholioTransaction())->setTransactionType(PholioTransaction::TYPE_IMAGE_FILE)->setNewValue(array('+' => array($add_image)));
                     $posted_mock_images[] = $add_image;
                 } else {
                     $xactions[] = id(new PholioTransaction())->setTransactionType(PholioTransaction::TYPE_IMAGE_NAME)->setNewValue(array($existing_image->getPHID() => $title));
                     $xactions[] = id(new PholioTransaction())->setTransactionType(PholioTransaction::TYPE_IMAGE_DESCRIPTION)->setNewValue(array($existing_image->getPHID() => $description));
                     $xactions[] = id(new PholioTransaction())->setTransactionType(PholioTransaction::TYPE_IMAGE_SEQUENCE)->setNewValue(array($existing_image->getPHID() => $sequence));
                     $posted_mock_images[] = $existing_image;
                 }
             }
         }
         foreach ($mock_images as $file_phid => $mock_image) {
             if (!isset($files[$file_phid]) && !isset($replaces[$file_phid])) {
                 // this is an outright delete
                 $xactions[] = id(new PholioTransaction())->setTransactionType(PholioTransaction::TYPE_IMAGE_FILE)->setNewValue(array('-' => array($mock_image)));
             }
         }
         if (!$errors) {
             $proj_edge_type = PhabricatorProjectObjectHasProjectEdgeType::EDGECONST;
             $xactions[] = id(new PholioTransaction())->setTransactionType(PhabricatorTransactions::TYPE_EDGE)->setMetadataValue('edge:type', $proj_edge_type)->setNewValue(array('=' => array_fuse($v_projects)));
             $mock->openTransaction();
             $editor = id(new PholioMockEditor())->setContentSourceFromRequest($request)->setContinueOnNoEffect(true)->setActor($viewer);
             $xactions = $editor->applyTransactions($mock, $xactions);
             $mock->saveTransaction();
             return id(new AphrontRedirectResponse())->setURI('/M' . $mock->getID());
         }
     }
     if ($id) {
         $submit = id(new AphrontFormSubmitControl())->addCancelButton('/M' . $id)->setValue(pht('Save'));
     } else {
         $submit = id(new AphrontFormSubmitControl())->addCancelButton($this->getApplicationURI())->setValue(pht('Create'));
     }
     $policies = id(new PhabricatorPolicyQuery())->setViewer($viewer)->setObject($mock)->execute();
     // NOTE: Make this show up correctly on the rendered form.
     $mock->setViewPolicy($v_view);
     $mock->setEditPolicy($v_edit);
     $image_elements = array();
     if ($posted_mock_images) {
         $display_mock_images = $posted_mock_images;
     } else {
         $display_mock_images = $mock_images;
     }
     foreach ($display_mock_images as $mock_image) {
         $image_elements[] = id(new PholioUploadedImageView())->setUser($viewer)->setImage($mock_image)->setReplacesPHID($mock_image->getFilePHID());
     }
     $list_id = celerity_generate_unique_node_id();
     $drop_id = celerity_generate_unique_node_id();
     $order_id = celerity_generate_unique_node_id();
     $list_control = phutil_tag('div', array('id' => $list_id, 'class' => 'pholio-edit-list'), $image_elements);
     $drop_control = phutil_tag('a', array('id' => $drop_id, 'class' => 'pholio-edit-drop'), pht('Click here, or drag and drop images to add them to the mock.'));
     $order_control = phutil_tag('input', array('type' => 'hidden', 'name' => 'imageOrder', 'id' => $order_id));
     Javelin::initBehavior('pholio-mock-edit', array('listID' => $list_id, 'dropID' => $drop_id, 'orderID' => $order_id, 'uploadURI' => '/file/dropupload/', 'renderURI' => $this->getApplicationURI('image/upload/'), 'pht' => array('uploading' => pht('Uploading Image...'), 'uploaded' => pht('Upload Complete...'), 'undo' => pht('Undo'), 'removed' => pht('This image will be removed from the mock.'))));
     require_celerity_resource('pholio-edit-css');
     $form = id(new AphrontFormView())->setUser($viewer)->appendChild($order_control)->appendChild(id(new AphrontFormTextControl())->setName('name')->setValue($v_name)->setLabel(pht('Name'))->setError($e_name))->appendChild(id(new PhabricatorRemarkupControl())->setName('description')->setValue($v_desc)->setLabel(pht('Description'))->setUser($viewer))->appendControl(id(new AphrontFormTokenizerControl())->setLabel(pht('Tags'))->setName('projects')->setValue($v_projects)->setDatasource(new PhabricatorProjectDatasource()))->appendControl(id(new AphrontFormTokenizerControl())->setLabel(pht('Subscribers'))->setName('cc')->setValue($v_cc)->setUser($viewer)->setDatasource(new PhabricatorMetaMTAMailableDatasource()))->appendChild(id(new AphrontFormPolicyControl())->setUser($viewer)->setCapability(PhabricatorPolicyCapability::CAN_VIEW)->setPolicyObject($mock)->setPolicies($policies)->setSpacePHID($v_space)->setName('can_view'))->appendChild(id(new AphrontFormPolicyControl())->setUser($viewer)->setCapability(PhabricatorPolicyCapability::CAN_EDIT)->setPolicyObject($mock)->setPolicies($policies)->setName('can_edit'))->appendChild(id(new AphrontFormMarkupControl())->setValue($list_control))->appendChild(id(new AphrontFormMarkupControl())->setValue($drop_control)->setError($e_images))->appendChild($submit);
     $form_box = id(new PHUIObjectBoxView())->setHeaderText(pht('Mock'))->setFormErrors($errors)->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)->setForm($form);
     $crumbs = $this->buildApplicationCrumbs();
     if (!$is_new) {
         $crumbs->addTextCrumb($mock->getMonogram(), '/' . $mock->getMonogram());
     }
     $crumbs->addTextCrumb($title);
     $crumbs->setBorder(true);
     $header = id(new PHUIHeaderView())->setHeader($title)->setHeaderIcon($header_icon);
     $view = id(new PHUITwoColumnView())->setHeader($header)->setFooter($form_box);
     return $this->newPage()->setTitle($title)->setCrumbs($crumbs)->addQuicksandConfig(array('mockEditConfig' => true))->appendChild($view);
 }
 public function handleRequest(AphrontRequest $request)
 {
     $viewer = $this->getViewer();
     $object = $this->loadRelationshipObject();
     if (!$object) {
         return new Aphront404Response();
     }
     $relationship = $this->loadRelationship($object);
     if (!$relationship) {
         return new Aphront404Response();
     }
     $src_phid = $object->getPHID();
     $edge_type = $relationship->getEdgeConstant();
     // If this is a normal relationship, users can remove related objects. If
     // it's a special relationship like a merge, we can't undo it, so we won't
     // prefill the current related objects.
     if ($relationship->canUndoRelationship()) {
         $dst_phids = PhabricatorEdgeQuery::loadDestinationPHIDs($src_phid, $edge_type);
     } else {
         $dst_phids = array();
     }
     $all_phids = $dst_phids;
     $all_phids[] = $src_phid;
     $handles = $viewer->loadHandles($all_phids);
     $src_handle = $handles[$src_phid];
     $done_uri = $src_handle->getURI();
     $initial_phids = $dst_phids;
     $maximum = $relationship->getMaximumSelectionSize();
     if ($request->isFormPost()) {
         $phids = explode(';', $request->getStr('phids'));
         $phids = array_filter($phids);
         $phids = array_values($phids);
         // The UI normally enforces this with Javascript, so this is just a
         // sanity check and does not need to be particularly user-friendly.
         if ($maximum && count($phids) > $maximum) {
             throw new Exception(pht('Too many relationships (%s, of type "%s").', phutil_count($phids), $relationship->getRelationshipConstant()));
         }
         $initial_phids = $request->getStrList('initialPHIDs');
         // Apply the changes as adds and removes relative to the original state
         // of the object when the dialog was rendered so that two users adding
         // relationships at the same time don't race and overwrite one another.
         $add_phids = array_diff($phids, $initial_phids);
         $rem_phids = array_diff($initial_phids, $phids);
         $all_phids = array_merge($add_phids, $rem_phids);
         $capabilities = $relationship->getRequiredRelationshipCapabilities();
         if ($all_phids) {
             $dst_objects = id(new PhabricatorObjectQuery())->setViewer($viewer)->withPHIDs($all_phids)->setRaisePolicyExceptions(true)->requireCapabilities($capabilities)->execute();
             $dst_objects = mpull($dst_objects, null, 'getPHID');
         } else {
             $dst_objects = array();
         }
         try {
             foreach ($add_phids as $add_phid) {
                 $dst_object = idx($dst_objects, $add_phid);
                 if (!$dst_object) {
                     throw new Exception(pht('You can not create a relationship to object "%s" because ' . 'the object does not exist or could not be loaded.', $add_phid));
                 }
                 if ($add_phid == $src_phid) {
                     throw new Exception(pht('You can not create a relationship to object "%s" because ' . 'objects can not be related to themselves.', $add_phid));
                 }
                 if (!$relationship->canRelateObjects($object, $dst_object)) {
                     throw new Exception(pht('You can not create a relationship (of type "%s") to object ' . '"%s" because it is not the right type of object for this ' . 'relationship.', $relationship->getRelationshipConstant(), $add_phid));
                 }
             }
         } catch (Exception $ex) {
             return $this->newUnrelatableObjectResponse($ex, $done_uri);
         }
         $content_source = PhabricatorContentSource::newFromRequest($request);
         $relationship->setContentSource($content_source);
         $editor = $object->getApplicationTransactionEditor()->setActor($viewer)->setContentSource($content_source)->setContinueOnMissingFields(true)->setContinueOnNoEffect(true);
         $xactions = array();
         $xactions[] = $object->getApplicationTransactionTemplate()->setTransactionType(PhabricatorTransactions::TYPE_EDGE)->setMetadataValue('edge:type', $edge_type)->setNewValue(array('+' => array_fuse($add_phids), '-' => array_fuse($rem_phids)));
         $add_objects = array_select_keys($dst_objects, $add_phids);
         $rem_objects = array_select_keys($dst_objects, $rem_phids);
         if ($add_objects || $rem_objects) {
             $more_xactions = $relationship->willUpdateRelationships($object, $add_objects, $rem_objects);
             foreach ($more_xactions as $xaction) {
                 $xactions[] = $xaction;
             }
         }
         try {
             $editor->applyTransactions($object, $xactions);
             if ($add_objects || $rem_objects) {
                 $relationship->didUpdateRelationships($object, $add_objects, $rem_objects);
             }
             return id(new AphrontRedirectResponse())->setURI($done_uri);
         } catch (PhabricatorEdgeCycleException $ex) {
             return $this->newGraphCycleResponse($ex, $done_uri);
         }
     }
     $handles = iterator_to_array($handles);
     $handles = array_select_keys($handles, $dst_phids);
     $dialog_title = $relationship->getDialogTitleText();
     $dialog_header = $relationship->getDialogHeaderText();
     $dialog_button = $relationship->getDialogButtonText();
     $dialog_instructions = $relationship->getDialogInstructionsText();
     $source_uri = $relationship->getSourceURI($object);
     $source = $relationship->newSource();
     $filters = $source->getFilters();
     $selected_filter = $source->getSelectedFilter();
     return id(new PhabricatorObjectSelectorDialog())->setUser($viewer)->setInitialPHIDs($initial_phids)->setHandles($handles)->setFilters($filters)->setSelectedFilter($selected_filter)->setExcluded($src_phid)->setCancelURI($done_uri)->setSearchURI($source_uri)->setTitle($dialog_title)->setHeader($dialog_header)->setButtonText($dialog_button)->setInstructions($dialog_instructions)->setMaximumSelectionSize($maximum)->buildDialog();
 }
 public function handleRequest(AphrontRequest $request)
 {
     $viewer = $this->getViewer();
     $engine_key = $request->getURIData('engineKey');
     $this->setEngineKey($engine_key);
     $type = $request->getURIData('type');
     $is_create = $type == 'create';
     $engine = id(new PhabricatorEditEngineQuery())->setViewer($viewer)->withEngineKeys(array($engine_key))->requireCapabilities(array(PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT))->executeOne();
     if (!$engine) {
         return id(new Aphront404Response());
     }
     $cancel_uri = "/transactions/editengine/{$engine_key}/";
     $reorder_uri = "/transactions/editengine/{$engine_key}/sort/{$type}/";
     $query = id(new PhabricatorEditEngineConfigurationQuery())->setViewer($viewer)->withEngineKeys(array($engine->getEngineKey()));
     if ($is_create) {
         $query->withIsDefault(true);
     } else {
         $query->withIsEdit(true);
     }
     $configs = $query->execute();
     if ($is_create) {
         $configs = msort($configs, 'getCreateSortKey');
     } else {
         $configs = msort($configs, 'getEditSortKey');
     }
     if ($request->isFormPost()) {
         $form_order = $request->getStrList('formOrder');
         // NOTE: This has a side-effect of saving any factory-default forms
         // to the database. We might want to warn the user better, but this
         // shouldn't generally be very important or confusing.
         $configs = mpull($configs, null, 'getIdentifier');
         $configs = array_select_keys($configs, $form_order) + $configs;
         $order = 1;
         foreach ($configs as $config) {
             $xactions = array();
             if ($is_create) {
                 $xaction_type = PhabricatorEditEngineConfigurationTransaction::TYPE_CREATEORDER;
             } else {
                 $xaction_type = PhabricatorEditEngineConfigurationTransaction::TYPE_EDITORDER;
             }
             $xactions[] = id(new PhabricatorEditEngineConfigurationTransaction())->setTransactionType($xaction_type)->setNewValue($order);
             $editor = id(new PhabricatorEditEngineConfigurationEditor())->setActor($viewer)->setContentSourceFromRequest($request)->setContinueOnNoEffect(true);
             $editor->applyTransactions($config, $xactions);
             $order++;
         }
         return id(new AphrontRedirectResponse())->setURI($cancel_uri);
     }
     $list_id = celerity_generate_unique_node_id();
     $input_id = celerity_generate_unique_node_id();
     $list = id(new PHUIObjectItemListView())->setUser($viewer)->setID($list_id)->setFlush(true);
     $form_order = array();
     foreach ($configs as $config) {
         $name = $config->getName();
         $identifier = $config->getIdentifier();
         $item = id(new PHUIObjectItemView())->setHeader($name)->setGrippable(true)->addSigil('editengine-form-config')->setMetadata(array('formIdentifier' => $identifier));
         $list->addItem($item);
         $form_order[] = $identifier;
     }
     Javelin::initBehavior('editengine-reorder-configs', array('listID' => $list_id, 'inputID' => $input_id, 'reorderURI' => $reorder_uri));
     if ($is_create) {
         $title = pht('Reorder Create Forms');
         $button = pht('Save Create Order');
         $note_text = pht('Drag and drop fields to change the order in which they appear in ' . 'the application "Create" menu.');
     } else {
         $title = pht('Reorder Edit Forms');
         $button = pht('Save Edit Order');
         $note_text = pht('Drag and drop fields to change their priority for edits. When a ' . 'user edits an object, they will be shown the first form in this ' . 'list that they have permission to see.');
     }
     $note = id(new PHUIInfoView())->appendChild($note_text)->setSeverity(PHUIInfoView::SEVERITY_NOTICE);
     $input = phutil_tag('input', array('type' => 'hidden', 'name' => 'formOrder', 'value' => implode(', ', $form_order), 'id' => $input_id));
     return $this->newDialog()->setTitle($title)->setWidth(AphrontDialogView::WIDTH_FORM)->appendChild($note)->appendChild($list)->appendChild($input)->addSubmitButton(pht('Save Changes'))->addCancelButton($cancel_uri);
 }
 public function handleRequest(AphrontRequest $request)
 {
     $viewer = $this->getViewer();
     $id = $request->getURIData('id');
     $revision = id(new DifferentialRevisionQuery())->setViewer($viewer)->withIDs(array($id))->executeOne();
     if (!$revision) {
         return new Aphront404Response();
     }
     $type_comment = PhabricatorTransactions::TYPE_COMMENT;
     $type_action = DifferentialTransaction::TYPE_ACTION;
     $type_edge = PhabricatorTransactions::TYPE_EDGE;
     $type_subscribers = PhabricatorTransactions::TYPE_SUBSCRIBERS;
     $xactions = array();
     $action = $request->getStr('action');
     switch ($action) {
         case DifferentialAction::ACTION_COMMENT:
         case DifferentialAction::ACTION_ADDREVIEWERS:
         case DifferentialAction::ACTION_ADDCCS:
             break;
         default:
             $xactions[] = id(new DifferentialTransaction())->setTransactionType($type_action)->setNewValue($action);
             break;
     }
     $edge_reviewer = DifferentialRevisionHasReviewerEdgeType::EDGECONST;
     $reviewers = $request->getStrList('reviewers');
     if (DifferentialAction::allowReviewers($action) && $reviewers) {
         $faux_edges = array();
         foreach ($reviewers as $phid) {
             $faux_edges[$phid] = array('src' => $revision->getPHID(), 'type' => $edge_reviewer, 'dst' => $phid);
         }
         $xactions[] = id(new DifferentialTransaction())->setTransactionType($type_edge)->setMetadataValue('edge:type', $edge_reviewer)->setOldValue(array())->setNewValue($faux_edges);
     }
     $ccs = $request->getStrList('ccs');
     if ($ccs) {
         $xactions[] = id(new DifferentialTransaction())->setTransactionType($type_subscribers)->setOldValue(array())->setNewValue(array_fuse($ccs));
     }
     // Add a comment transaction if there's nothing, so we'll generate a
     // nonempty result.
     if (strlen($request->getStr('content')) || !$xactions) {
         $xactions[] = id(new DifferentialTransaction())->setTransactionType($type_comment)->attachComment(id(new ManiphestTransactionComment())->setContent($request->getStr('content')));
     }
     foreach ($xactions as $xaction) {
         $xaction->setAuthorPHID($viewer->getPHID());
     }
     $engine = new PhabricatorMarkupEngine();
     $engine->setViewer($request->getUser());
     foreach ($xactions as $xaction) {
         if ($xaction->hasComment()) {
             $engine->addObject($xaction->getComment(), PhabricatorApplicationTransactionComment::MARKUP_FIELD_COMMENT);
         }
     }
     $engine->process();
     $phids = mpull($xactions, 'getRequiredHandlePHIDs');
     $phids = array_mergev($phids);
     $handles = id(new PhabricatorHandleQuery())->setViewer($viewer)->withPHIDs($phids)->execute();
     foreach ($xactions as $xaction) {
         $xaction->setHandles($handles);
     }
     $view = id(new DifferentialTransactionView())->setUser($viewer)->setTransactions($xactions)->setIsPreview(true);
     $metadata = array('reviewers' => $reviewers, 'ccs' => $ccs);
     if ($action != DifferentialAction::ACTION_COMMENT) {
         $metadata['action'] = $action;
     }
     $draft_key = 'differential-comment-' . $id;
     $draft = id(new PhabricatorDraft())->setAuthorPHID($viewer->getPHID())->setDraftKey($draft_key)->setDraft($request->getStr('content'))->setMetadata($metadata)->replaceOrDelete();
     if ($draft->isDeleted()) {
         DifferentialDraft::deleteHasDraft($viewer->getPHID(), $revision->getPHID(), $draft_key);
     } else {
         DifferentialDraft::markHasDraft($viewer->getPHID(), $revision->getPHID(), $draft_key);
     }
     return id(new AphrontAjaxResponse())->setContent((string) phutil_implode_html('', $view->buildEvents()));
 }