public function handleRequest(AphrontRequest $request)
 {
     $viewer = $request->getViewer();
     $event = id(new PhabricatorCalendarEventQuery())->setViewer($viewer)->withIDs(array($request->getURIData('id')))->requireCapabilities(array(PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT))->executeOne();
     if (!$event) {
         return new Aphront404Response();
     }
     if (!$request->validateCSRF()) {
         return new Aphront400Response();
     }
     if ($event->getIsAllDay()) {
         return new Aphront400Response();
     }
     $xactions = array();
     $duration = $event->getDuration();
     $start = $request->getInt('start');
     $start_value = id(AphrontFormDateControlValue::newFromEpoch($viewer, $start));
     $end = $start + $duration;
     $end_value = id(AphrontFormDateControlValue::newFromEpoch($viewer, $end));
     $xactions[] = id(new PhabricatorCalendarEventTransaction())->setTransactionType(PhabricatorCalendarEventStartDateTransaction::TRANSACTIONTYPE)->setNewValue($start_value);
     $xactions[] = id(new PhabricatorCalendarEventTransaction())->setTransactionType(PhabricatorCalendarEventEndDateTransaction::TRANSACTIONTYPE)->setNewValue($end_value);
     $editor = id(new PhabricatorCalendarEventEditor())->setActor($viewer)->setContinueOnMissingFields(true)->setContentSourceFromRequest($request)->setContinueOnNoEffect(true);
     $xactions = $editor->applyTransactions($event, $xactions);
     return id(new AphrontReloadResponse());
 }
 public function handleRequest(AphrontRequest $request)
 {
     $viewer = $this->getViewer();
     $id = $request->getURIData('id');
     $event = id(new PhabricatorCalendarEventQuery())->setViewer($viewer)->withIDs(array($id))->executeOne();
     if (!$event) {
         return new Aphront404Response();
     }
     $response = $this->newImportedEventResponse($event);
     if ($response) {
         return $response;
     }
     $cancel_uri = $event->getURI();
     if (!$event->getIsUserAttending($viewer->getPHID())) {
         return $this->newDialog()->setTitle(pht('Not Attending Event'))->appendParagraph(pht('You can not change your display availability for events you ' . 'are not attending.'))->addCancelButton($cancel_uri);
     }
     // TODO: This endpoint currently only works via AJAX. It would be vaguely
     // nice to provide a plain HTML version of the workflow where we return
     // a dialog with a vanilla <select /> in it for cases where all the JS
     // breaks.
     $request->validateCSRF();
     $invitee = $event->getInviteeForPHID($viewer->getPHID());
     $map = PhabricatorCalendarEventInvitee::getAvailabilityMap();
     $new_availability = $request->getURIData('availability');
     if (isset($map[$new_availability])) {
         $invitee->setAvailability($new_availability)->save();
         // Invalidate the availability cache.
         $viewer->writeAvailabilityCache(array(), null);
     }
     return id(new AphrontRedirectResponse())->setURI($cancel_uri);
 }
 public function handleRequest(AphrontRequest $request)
 {
     $viewer = $this->getViewer();
     if (!$request->validateCSRF()) {
         return new Aphront403Response();
     }
     $task = id(new ManiphestTaskQuery())->setViewer($viewer)->withIDs(array($request->getInt('task')))->needProjectPHIDs(true)->requireCapabilities(array(PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT))->executeOne();
     if (!$task) {
         return new Aphront404Response();
     }
     if ($request->getInt('after')) {
         $after_task = id(new ManiphestTaskQuery())->setViewer($viewer)->withIDs(array($request->getInt('after')))->executeOne();
         if (!$after_task) {
             return new Aphront404Response();
         }
         list($pri, $sub) = ManiphestTransactionEditor::getAdjacentSubpriority($after_task, $is_after = true);
     } else {
         list($pri, $sub) = ManiphestTransactionEditor::getEdgeSubpriority($request->getInt('priority'), $is_end = false);
     }
     $xactions = array();
     $xactions[] = id(new ManiphestTransaction())->setTransactionType(ManiphestTransaction::TYPE_PRIORITY)->setNewValue($pri);
     $xactions[] = id(new ManiphestTransaction())->setTransactionType(ManiphestTransaction::TYPE_SUBPRIORITY)->setNewValue($sub);
     $editor = id(new ManiphestTransactionEditor())->setActor($viewer)->setContinueOnMissingFields(true)->setContinueOnNoEffect(true)->setContentSourceFromRequest($request);
     $editor->applyTransactions($task, $xactions);
     return id(new AphrontAjaxResponse())->setContent(array('tasks' => $this->renderSingleTask($task)));
 }
 public function handleRequest(AphrontRequest $request)
 {
     $action = $request->getURIData('action');
     $id = $request->getURIData('requestID');
     $viewer = $request->getViewer();
     $request->validateCSRF();
     $pull = id(new ReleephRequestQuery())->setViewer($viewer)->withIDs(array($id))->executeOne();
     if (!$pull) {
         return new Aphront404Response();
     }
     $branch = $pull->getBranch();
     $product = $branch->getProduct();
     $origin_uri = '/' . $pull->getMonogram();
     $editor = id(new ReleephRequestTransactionalEditor())->setActor($viewer)->setContinueOnNoEffect(true)->setContentSourceFromRequest($request);
     $xactions = array();
     switch ($action) {
         case 'want':
         case 'pass':
             static $action_map = array('want' => ReleephRequest::INTENT_WANT, 'pass' => ReleephRequest::INTENT_PASS);
             $intent = $action_map[$action];
             $xactions[] = id(new ReleephRequestTransaction())->setTransactionType(ReleephRequestTransaction::TYPE_USER_INTENT)->setMetadataValue('isAuthoritative', $product->isAuthoritative($viewer))->setNewValue($intent);
             break;
         case 'mark-manually-picked':
         case 'mark-manually-reverted':
             if ($pull->getRequestUserPHID() === $viewer->getPHID() || $product->isAuthoritative($viewer)) {
                 // We're all good!
             } else {
                 throw new Exception(pht("Bug! Only pushers or the requestor can manually change a " . "request's in-branch status!"));
             }
             if ($action === 'mark-manually-picked') {
                 $in_branch = 1;
                 $intent = ReleephRequest::INTENT_WANT;
             } else {
                 $in_branch = 0;
                 $intent = ReleephRequest::INTENT_PASS;
             }
             $xactions[] = id(new ReleephRequestTransaction())->setTransactionType(ReleephRequestTransaction::TYPE_USER_INTENT)->setMetadataValue('isManual', true)->setMetadataValue('isAuthoritative', true)->setNewValue($intent);
             $xactions[] = id(new ReleephRequestTransaction())->setTransactionType(ReleephRequestTransaction::TYPE_MANUAL_IN_BRANCH)->setNewValue($in_branch);
             break;
         default:
             throw new Exception(pht('Unknown or unimplemented action %s.', $action));
     }
     $editor->applyTransactions($pull, $xactions);
     if ($request->getBool('render')) {
         $field_list = PhabricatorCustomField::getObjectFields($pull, PhabricatorCustomField::ROLE_VIEW);
         $field_list->setViewer($viewer)->readFieldsFromStorage($pull);
         // TODO: This should be more modern and general.
         $engine = id(new PhabricatorMarkupEngine())->setViewer($viewer);
         foreach ($field_list->getFields() as $field) {
             if ($field->shouldMarkup()) {
                 $field->setMarkupEngine($engine);
             }
         }
         $engine->process();
         $pull_box = id(new ReleephRequestView())->setUser($viewer)->setCustomFields($field_list)->setPullRequest($pull)->setIsListView(true);
         return id(new AphrontAjaxResponse())->setContent(array('markup' => hsprintf('%s', $pull_box)));
     }
     return id(new AphrontRedirectResponse())->setURI($origin_uri);
 }
 public function handleRequest(AphrontRequest $request)
 {
     $viewer = $request->getViewer();
     $id = $request->getURIData('id');
     $request->validateCSRF();
     $column_phid = $request->getStr('columnPHID');
     $object_phid = $request->getStr('objectPHID');
     $after_phid = $request->getStr('afterPHID');
     $before_phid = $request->getStr('beforePHID');
     $order = $request->getStr('order', PhabricatorProjectColumn::DEFAULT_ORDER);
     $project = id(new PhabricatorProjectQuery())->setViewer($viewer)->requireCapabilities(array(PhabricatorPolicyCapability::CAN_VIEW))->withIDs(array($id))->executeOne();
     if (!$project) {
         return new Aphront404Response();
     }
     $board_phid = $project->getPHID();
     $object = id(new ManiphestTaskQuery())->setViewer($viewer)->withPHIDs(array($object_phid))->needProjectPHIDs(true)->requireCapabilities(array(PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT))->executeOne();
     if (!$object) {
         return new Aphront404Response();
     }
     $columns = id(new PhabricatorProjectColumnQuery())->setViewer($viewer)->withProjectPHIDs(array($project->getPHID()))->execute();
     $columns = mpull($columns, null, 'getPHID');
     $column = idx($columns, $column_phid);
     if (!$column) {
         // User is trying to drop this object into a nonexistent column, just kick
         // them out.
         return new Aphront404Response();
     }
     $engine = id(new PhabricatorBoardLayoutEngine())->setViewer($viewer)->setBoardPHIDs(array($board_phid))->setObjectPHIDs(array($object_phid))->executeLayout();
     $columns = $engine->getObjectColumns($board_phid, $object_phid);
     $old_column_phids = mpull($columns, 'getPHID');
     $xactions = array();
     $order_params = array();
     if ($order == PhabricatorProjectColumn::ORDER_NATURAL) {
         if ($after_phid) {
             $order_params['afterPHID'] = $after_phid;
         } else {
             if ($before_phid) {
                 $order_params['beforePHID'] = $before_phid;
             }
         }
     }
     $xactions[] = id(new ManiphestTransaction())->setTransactionType(PhabricatorTransactions::TYPE_COLUMNS)->setNewValue(array(array('columnPHID' => $column->getPHID()) + $order_params));
     if ($order == PhabricatorProjectColumn::ORDER_PRIORITY) {
         $priority_xactions = $this->getPriorityTransactions($object, $after_phid, $before_phid);
         foreach ($priority_xactions as $xaction) {
             $xactions[] = $xaction;
         }
     }
     $editor = id(new ManiphestTransactionEditor())->setActor($viewer)->setContinueOnMissingFields(true)->setContinueOnNoEffect(true)->setContentSourceFromRequest($request);
     $editor->applyTransactions($object, $xactions);
     return $this->newCardResponse($board_phid, $object_phid);
 }
 /**
  * @phutil-external-symbol class PhabricatorStartup
  */
 public function handleRequest(AphrontRequest $request)
 {
     $viewer = $request->getViewer();
     // NOTE: Throws if valid CSRF token is not present in the request.
     $request->validateCSRF();
     $name = $request->getStr('name');
     $file_phid = $request->getStr('phid');
     // If there's no explicit view policy, make it very restrictive by default.
     // This is the correct policy for files dropped onto objects during
     // creation, comment and edit flows.
     $view_policy = $request->getStr('viewPolicy');
     if (!$view_policy) {
         $view_policy = $viewer->getPHID();
     }
     $is_chunks = $request->getBool('querychunks');
     if ($is_chunks) {
         $params = array('filePHID' => $file_phid);
         $result = id(new ConduitCall('file.querychunks', $params))->setUser($viewer)->execute();
         return id(new AphrontAjaxResponse())->setContent($result);
     }
     $is_allocate = $request->getBool('allocate');
     if ($is_allocate) {
         $params = array('name' => $name, 'contentLength' => $request->getInt('length'), 'viewPolicy' => $view_policy);
         $result = id(new ConduitCall('file.allocate', $params))->setUser($viewer)->execute();
         $file_phid = $result['filePHID'];
         if ($file_phid) {
             $file = $this->loadFile($file_phid);
             $result += $file->getDragAndDropDictionary();
         }
         return id(new AphrontAjaxResponse())->setContent($result);
     }
     // Read the raw request data. We're either doing a chunk upload or a
     // vanilla upload, so we need it.
     $data = PhabricatorStartup::getRawInput();
     $is_chunk_upload = $request->getBool('uploadchunk');
     if ($is_chunk_upload) {
         $params = array('filePHID' => $file_phid, 'byteStart' => $request->getInt('byteStart'), 'data' => $data);
         $result = id(new ConduitCall('file.uploadchunk', $params))->setUser($viewer)->execute();
         $file = $this->loadFile($file_phid);
         if ($file->getIsPartial()) {
             $result = array();
         } else {
             $result = array('complete' => true) + $file->getDragAndDropDictionary();
         }
         return id(new AphrontAjaxResponse())->setContent($result);
     }
     $file = PhabricatorFile::newFromXHRUpload($data, array('name' => $request->getStr('name'), 'authorPHID' => $viewer->getPHID(), 'viewPolicy' => $view_policy, 'isExplicitUpload' => true));
     $result = $file->getDragAndDropDictionary();
     return id(new AphrontAjaxResponse())->setContent($result);
 }
 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)
 {
     $viewer = $request->getViewer();
     $story_type = 'PhabricatorNotificationTestFeedStory';
     $story_data = array('title' => pht('This is a test notification, sent at %s.', phabricator_datetime(time(), $viewer)));
     $viewer_phid = $viewer->getPHID();
     // NOTE: Because we don't currently show you your own notifications, make
     // sure this comes from a different PHID.
     $application_phid = id(new PhabricatorNotificationsApplication())->getPHID();
     // TODO: When it's easier to get these buttons to render as forms, this
     // would be slightly nicer as a more standard isFormPost() check.
     if ($request->validateCSRF()) {
         id(new PhabricatorFeedStoryPublisher())->setStoryType($story_type)->setStoryData($story_data)->setStoryTime(time())->setStoryAuthorPHID($application_phid)->setRelatedPHIDs(array($viewer_phid))->setPrimaryObjectPHID($viewer_phid)->setSubscribedPHIDs(array($viewer_phid))->setNotifyAuthor(true)->publish();
     }
     return id(new AphrontAjaxResponse());
 }
 public function handleRequest(AphrontRequest $request)
 {
     $viewer = $request->getViewer();
     $request->validateCSRF();
     $board_phid = $request->getStr('boardPHID');
     $object_phid = $request->getStr('objectPHID');
     $file_phid = $request->getStr('filePHID');
     $object = id(new ManiphestTaskQuery())->setViewer($viewer)->withPHIDs(array($object_phid))->requireCapabilities(array(PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT))->executeOne();
     if (!$object) {
         return new Aphront404Response();
     }
     $file = id(new PhabricatorFileQuery())->setViewer($viewer)->withPHIDs(array($file_phid))->executeOne();
     if (!$file) {
         return new Aphront404Response();
     }
     $xactions = array();
     $xactions[] = id(new ManiphestTransaction())->setTransactionType(ManiphestTransaction::TYPE_COVER_IMAGE)->setNewValue($file->getPHID());
     $editor = id(new ManiphestTransactionEditor())->setActor($viewer)->setContinueOnMissingFields(true)->setContinueOnNoEffect(true)->setContentSourceFromRequest($request);
     $editor->applyTransactions($object, $xactions);
     return $this->newCardResponse($board_phid, $object_phid);
 }
 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());
 }
 /**
  * Require high security, or prompt the user to enter high security.
  *
  * If the user's session is in high security, this method will return a
  * token. Otherwise, it will throw an exception which will eventually
  * be converted into a multi-factor authentication workflow.
  *
  * @param PhabricatorUser User whose session needs to be in high security.
  * @param AphrontReqeust  Current request.
  * @param string          URI to return the user to if they cancel.
  * @param bool            True to jump partial sessions directly into high
  *                        security instead of just upgrading them to full
  *                        sessions.
  * @return PhabricatorAuthHighSecurityToken Security token.
  * @task hisec
  */
 public function requireHighSecuritySession(PhabricatorUser $viewer, AphrontRequest $request, $cancel_uri, $jump_into_hisec = false)
 {
     if (!$viewer->hasSession()) {
         throw new Exception(pht('Requiring a high-security session from a user with no session!'));
     }
     $session = $viewer->getSession();
     // Check if the session is already in high security mode.
     $token = $this->issueHighSecurityToken($session);
     if ($token) {
         return $token;
     }
     // Load the multi-factor auth sources attached to this account.
     $factors = id(new PhabricatorAuthFactorConfig())->loadAllWhere('userPHID = %s', $viewer->getPHID());
     // If the account has no associated multi-factor auth, just issue a token
     // without putting the session into high security mode. This is generally
     // easier for users. A minor but desirable side effect is that when a user
     // adds an auth factor, existing sessions won't get a free pass into hisec,
     // since they never actually got marked as hisec.
     if (!$factors) {
         return $this->issueHighSecurityToken($session, true);
     }
     // Check for a rate limit without awarding points, so the user doesn't
     // get partway through the workflow only to get blocked.
     PhabricatorSystemActionEngine::willTakeAction(array($viewer->getPHID()), new PhabricatorAuthTryFactorAction(), 0);
     $validation_results = array();
     if ($request->isHTTPPost()) {
         $request->validateCSRF();
         if ($request->getExists(AphrontRequest::TYPE_HISEC)) {
             // Limit factor verification rates to prevent brute force attacks.
             PhabricatorSystemActionEngine::willTakeAction(array($viewer->getPHID()), new PhabricatorAuthTryFactorAction(), 1);
             $ok = true;
             foreach ($factors as $factor) {
                 $id = $factor->getID();
                 $impl = $factor->requireImplementation();
                 $validation_results[$id] = $impl->processValidateFactorForm($factor, $viewer, $request);
                 if (!$impl->isFactorValid($factor, $validation_results[$id])) {
                     $ok = false;
                 }
             }
             if ($ok) {
                 // Give the user a credit back for a successful factor verification.
                 PhabricatorSystemActionEngine::willTakeAction(array($viewer->getPHID()), new PhabricatorAuthTryFactorAction(), -1);
                 if ($session->getIsPartial() && !$jump_into_hisec) {
                     // If we have a partial session and are not jumping directly into
                     // hisec, just issue a token without putting it in high security
                     // mode.
                     return $this->issueHighSecurityToken($session, true);
                 }
                 $until = time() + phutil_units('15 minutes in seconds');
                 $session->setHighSecurityUntil($until);
                 queryfx($session->establishConnection('w'), 'UPDATE %T SET highSecurityUntil = %d WHERE id = %d', $session->getTableName(), $until, $session->getID());
                 $log = PhabricatorUserLog::initializeNewLog($viewer, $viewer->getPHID(), PhabricatorUserLog::ACTION_ENTER_HISEC);
                 $log->save();
             } else {
                 $log = PhabricatorUserLog::initializeNewLog($viewer, $viewer->getPHID(), PhabricatorUserLog::ACTION_FAIL_HISEC);
                 $log->save();
             }
         }
     }
     $token = $this->issueHighSecurityToken($session);
     if ($token) {
         return $token;
     }
     throw id(new PhabricatorAuthHighSecurityRequiredException())->setCancelURI($cancel_uri)->setFactors($factors)->setFactorValidationResults($validation_results);
 }
 public function handleRequest(AphrontRequest $request)
 {
     $viewer = $request->getViewer();
     $projectid = $request->getURIData('projectID');
     $project = id(new PhabricatorProjectQuery())->setViewer($viewer)->requireCapabilities(array(PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT))->withIDs(array($projectid))->executeOne();
     if (!$project) {
         return new Aphront404Response();
     }
     $this->setProject($project);
     $project_id = $project->getID();
     $board_uri = $this->getApplicationURI("board/{$project_id}/");
     $reorder_uri = $this->getApplicationURI("board/{$project_id}/reorder/");
     if ($request->isFormPost()) {
         // User clicked "Done", make sure the page reloads to show the new
         // column order.
         return id(new AphrontRedirectResponse())->setURI($board_uri);
     }
     $columns = id(new PhabricatorProjectColumnQuery())->setViewer($viewer)->withProjectPHIDs(array($project->getPHID()))->execute();
     $columns = msort($columns, 'getSequence');
     $column_phid = $request->getStr('columnPHID');
     if ($column_phid && $request->validateCSRF()) {
         $columns = mpull($columns, null, 'getPHID');
         if (empty($columns[$column_phid])) {
             return new Aphront404Response();
         }
         $target_column = $columns[$column_phid];
         $new_sequence = $request->getInt('sequence');
         if ($new_sequence < 0) {
             return new Aphront404Response();
         }
         // TODO: For now, we're not recording any transactions here. We probably
         // should, but this sort of edit is extremely trivial.
         // Resequence the columns so that the moved column has the correct
         // sequence number. Move columns after it up one place in the sequence.
         $new_map = array();
         foreach ($columns as $phid => $column) {
             $value = $column->getSequence();
             if ($column->getPHID() == $column_phid) {
                 $value = $new_sequence;
             } else {
                 if ($column->getSequence() >= $new_sequence) {
                     $value = $value + 1;
                 }
             }
             $new_map[$phid] = $value;
         }
         // Sort the columns into their new ordering.
         asort($new_map);
         // Now, compact the ordering and adjust any columns that need changes.
         $project->openTransaction();
         $sequence = 0;
         foreach ($new_map as $phid => $ignored) {
             $new_value = $sequence++;
             $cur_value = $columns[$phid]->getSequence();
             if ($new_value != $cur_value) {
                 $columns[$phid]->setSequence($new_value)->save();
             }
         }
         $project->saveTransaction();
         return id(new AphrontAjaxResponse())->setContent(array('sequenceMap' => mpull($columns, 'getSequence', 'getPHID')));
     }
     $list_id = celerity_generate_unique_node_id();
     $list = id(new PHUIObjectItemListView())->setUser($viewer)->setID($list_id)->setFlush(true);
     foreach ($columns as $column) {
         $item = id(new PHUIObjectItemView())->setHeader($column->getDisplayName())->addIcon('none', $column->getDisplayType());
         if ($column->isHidden()) {
             $item->setDisabled(true);
         }
         $item->setGrippable(true);
         $item->addSigil('board-column');
         $item->setMetadata(array('columnPHID' => $column->getPHID(), 'columnSequence' => $column->getSequence()));
         $list->addItem($item);
     }
     Javelin::initBehavior('reorder-columns', array('listID' => $list_id, 'reorderURI' => $reorder_uri));
     $note = id(new PHUIInfoView())->appendChild(pht('Drag and drop columns to reorder them.'))->setSeverity(PHUIInfoView::SEVERITY_NOTICE);
     return $this->newDialog()->setTitle(pht('Reorder Columns'))->setWidth(AphrontDialogView::WIDTH_FORM)->appendChild($note)->appendChild($list)->addSubmitButton(pht('Done'));
 }
 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 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;
 }
 public function handleRequest(AphrontRequest $request)
 {
     $viewer = $request->getViewer();
     $id = $request->getURIData('id');
     $request->validateCSRF();
     $column_phid = $request->getStr('columnPHID');
     $object_phid = $request->getStr('objectPHID');
     $after_phid = $request->getStr('afterPHID');
     $before_phid = $request->getStr('beforePHID');
     $order = $request->getStr('order', PhabricatorProjectColumn::DEFAULT_ORDER);
     $project = id(new PhabricatorProjectQuery())->setViewer($viewer)->requireCapabilities(array(PhabricatorPolicyCapability::CAN_VIEW))->withIDs(array($id))->executeOne();
     if (!$project) {
         return new Aphront404Response();
     }
     $board_phid = $project->getPHID();
     $object = id(new ManiphestTaskQuery())->setViewer($viewer)->withPHIDs(array($object_phid))->needProjectPHIDs(true)->requireCapabilities(array(PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT))->executeOne();
     if (!$object) {
         return new Aphront404Response();
     }
     $columns = id(new PhabricatorProjectColumnQuery())->setViewer($viewer)->withProjectPHIDs(array($project->getPHID()))->execute();
     $columns = mpull($columns, null, 'getPHID');
     $column = idx($columns, $column_phid);
     if (!$column) {
         // User is trying to drop this object into a nonexistent column, just kick
         // them out.
         return new Aphront404Response();
     }
     $engine = id(new PhabricatorBoardLayoutEngine())->setViewer($viewer)->setBoardPHIDs(array($board_phid))->setObjectPHIDs(array($object_phid))->executeLayout();
     $columns = $engine->getObjectColumns($board_phid, $object_phid);
     $old_column_phids = mpull($columns, 'getPHID');
     $xactions = array();
     if ($order == PhabricatorProjectColumn::ORDER_NATURAL) {
         $order_params = array('afterPHID' => $after_phid, 'beforePHID' => $before_phid);
     } else {
         $order_params = array();
     }
     $xactions[] = id(new ManiphestTransaction())->setTransactionType(ManiphestTransaction::TYPE_PROJECT_COLUMN)->setNewValue(array('columnPHIDs' => array($column->getPHID()), 'projectPHID' => $column->getProjectPHID()) + $order_params)->setOldValue(array('columnPHIDs' => $old_column_phids, 'projectPHID' => $column->getProjectPHID()));
     if ($order == PhabricatorProjectColumn::ORDER_PRIORITY) {
         $priority_xactions = $this->getPriorityTransactions($object, $after_phid, $before_phid);
         foreach ($priority_xactions as $xaction) {
             $xactions[] = $xaction;
         }
     }
     $proxy = $column->getProxy();
     if ($proxy) {
         // We're moving the task into a subproject or milestone column, so add
         // the subproject or milestone.
         $add_projects = array($proxy->getPHID());
     } else {
         if ($project->getHasSubprojects() || $project->getHasMilestones()) {
             // We're moving the task into the "Backlog" column on the parent project,
             // so add the parent explicitly. This gets rid of any subproject or
             // milestone tags.
             $add_projects = array($project->getPHID());
         } else {
             $add_projects = array();
         }
     }
     if ($add_projects) {
         $project_type = PhabricatorProjectObjectHasProjectEdgeType::EDGECONST;
         $xactions[] = id(new ManiphestTransaction())->setTransactionType(PhabricatorTransactions::TYPE_EDGE)->setMetadataValue('edge:type', $project_type)->setNewValue(array('+' => array_fuse($add_projects)));
     }
     $editor = id(new ManiphestTransactionEditor())->setActor($viewer)->setContinueOnMissingFields(true)->setContinueOnNoEffect(true)->setContentSourceFromRequest($request);
     $editor->applyTransactions($object, $xactions);
     return $this->newCardResponse($board_phid, $object_phid);
 }