public function handleRequest(AphrontRequest $request)
 {
     $viewer = $request->getViewer();
     $id = $request->getURIData('id');
     if ($id) {
         $poll = id(new PhabricatorSlowvoteQuery())->setViewer($viewer)->withIDs(array($id))->requireCapabilities(array(PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT))->executeOne();
         if (!$poll) {
             return new Aphront404Response();
         }
         $is_new = false;
     } else {
         $poll = PhabricatorSlowvotePoll::initializeNewPoll($viewer);
         $is_new = true;
     }
     if ($is_new) {
         $v_projects = array();
     } else {
         $v_projects = PhabricatorEdgeQuery::loadDestinationPHIDs($poll->getPHID(), PhabricatorProjectObjectHasProjectEdgeType::EDGECONST);
         $v_projects = array_reverse($v_projects);
     }
     $e_question = true;
     $e_response = true;
     $errors = array();
     $v_question = $poll->getQuestion();
     $v_description = $poll->getDescription();
     $v_responses = $poll->getResponseVisibility();
     $v_shuffle = $poll->getShuffle();
     $v_space = $poll->getSpacePHID();
     $responses = $request->getArr('response');
     if ($request->isFormPost()) {
         $v_question = $request->getStr('question');
         $v_description = $request->getStr('description');
         $v_responses = (int) $request->getInt('responses');
         $v_shuffle = (int) $request->getBool('shuffle');
         $v_view_policy = $request->getStr('viewPolicy');
         $v_projects = $request->getArr('projects');
         $v_space = $request->getStr('spacePHID');
         if ($is_new) {
             $poll->setMethod($request->getInt('method'));
         }
         if (!strlen($v_question)) {
             $e_question = pht('Required');
             $errors[] = pht('You must ask a poll question.');
         } else {
             $e_question = null;
         }
         if ($is_new) {
             $responses = array_filter($responses);
             if (empty($responses)) {
                 $errors[] = pht('You must offer at least one response.');
                 $e_response = pht('Required');
             } else {
                 $e_response = null;
             }
         }
         $xactions = array();
         $template = id(new PhabricatorSlowvoteTransaction());
         $xactions[] = id(clone $template)->setTransactionType(PhabricatorSlowvoteTransaction::TYPE_QUESTION)->setNewValue($v_question);
         $xactions[] = id(clone $template)->setTransactionType(PhabricatorSlowvoteTransaction::TYPE_DESCRIPTION)->setNewValue($v_description);
         $xactions[] = id(clone $template)->setTransactionType(PhabricatorSlowvoteTransaction::TYPE_RESPONSES)->setNewValue($v_responses);
         $xactions[] = id(clone $template)->setTransactionType(PhabricatorSlowvoteTransaction::TYPE_SHUFFLE)->setNewValue($v_shuffle);
         $xactions[] = id(clone $template)->setTransactionType(PhabricatorTransactions::TYPE_VIEW_POLICY)->setNewValue($v_view_policy);
         $xactions[] = id(clone $template)->setTransactionType(PhabricatorTransactions::TYPE_SPACE)->setNewValue($v_space);
         if (empty($errors)) {
             $proj_edge_type = PhabricatorProjectObjectHasProjectEdgeType::EDGECONST;
             $xactions[] = id(new PhabricatorSlowvoteTransaction())->setTransactionType(PhabricatorTransactions::TYPE_EDGE)->setMetadataValue('edge:type', $proj_edge_type)->setNewValue(array('=' => array_fuse($v_projects)));
             $editor = id(new PhabricatorSlowvoteEditor())->setActor($viewer)->setContinueOnNoEffect(true)->setContentSourceFromRequest($request);
             $xactions = $editor->applyTransactions($poll, $xactions);
             if ($is_new) {
                 $poll->save();
                 foreach ($responses as $response) {
                     $option = new PhabricatorSlowvoteOption();
                     $option->setName($response);
                     $option->setPollID($poll->getID());
                     $option->save();
                 }
             }
             return id(new AphrontRedirectResponse())->setURI('/V' . $poll->getID());
         } else {
             $poll->setViewPolicy($v_view_policy);
         }
     }
     $instructions = phutil_tag('p', array('class' => 'aphront-form-instructions'), pht('Resolve issues and build consensus through ' . 'protracted deliberation.'));
     $form = id(new AphrontFormView())->setUser($viewer)->appendChild($instructions)->appendChild(id(new AphrontFormTextAreaControl())->setHeight(AphrontFormTextAreaControl::HEIGHT_VERY_SHORT)->setLabel(pht('Question'))->setName('question')->setValue($v_question)->setError($e_question))->appendChild(id(new PhabricatorRemarkupControl())->setUser($viewer)->setLabel(pht('Description'))->setName('description')->setValue($v_description))->appendControl(id(new AphrontFormTokenizerControl())->setLabel(pht('Projects'))->setName('projects')->setValue($v_projects)->setDatasource(new PhabricatorProjectDatasource()));
     if ($is_new) {
         for ($ii = 0; $ii < 10; $ii++) {
             $n = $ii + 1;
             $response = id(new AphrontFormTextControl())->setLabel(pht('Response %d', $n))->setName('response[]')->setValue(idx($responses, $ii, ''));
             if ($ii == 0) {
                 $response->setError($e_response);
             }
             $form->appendChild($response);
         }
     }
     $poll_type_options = array(PhabricatorSlowvotePoll::METHOD_PLURALITY => pht('Plurality (Single Choice)'), PhabricatorSlowvotePoll::METHOD_APPROVAL => pht('Approval (Multiple Choice)'));
     $response_type_options = array(PhabricatorSlowvotePoll::RESPONSES_VISIBLE => pht('Allow anyone to see the responses'), PhabricatorSlowvotePoll::RESPONSES_VOTERS => pht('Require a vote to see the responses'), PhabricatorSlowvotePoll::RESPONSES_OWNER => pht('Only I can see the responses'));
     if ($is_new) {
         $form->appendChild(id(new AphrontFormSelectControl())->setLabel(pht('Vote Type'))->setName('method')->setValue($poll->getMethod())->setOptions($poll_type_options));
     } else {
         $form->appendChild(id(new AphrontFormStaticControl())->setLabel(pht('Vote Type'))->setValue(idx($poll_type_options, $poll->getMethod())));
     }
     if ($is_new) {
         $title = pht('Create Slowvote');
         $button = pht('Create');
         $cancel_uri = $this->getApplicationURI();
     } else {
         $title = pht('Edit %s', 'V' . $poll->getID());
         $button = pht('Save Changes');
         $cancel_uri = '/V' . $poll->getID();
     }
     $policies = id(new PhabricatorPolicyQuery())->setViewer($viewer)->setObject($poll)->execute();
     $form->appendChild(id(new AphrontFormSelectControl())->setLabel(pht('Responses'))->setName('responses')->setValue($v_responses)->setOptions($response_type_options))->appendChild(id(new AphrontFormCheckboxControl())->setLabel(pht('Shuffle'))->addCheckbox('shuffle', 1, pht('Show choices in random order.'), $v_shuffle))->appendChild(id(new AphrontFormPolicyControl())->setUser($viewer)->setName('viewPolicy')->setPolicyObject($poll)->setPolicies($policies)->setCapability(PhabricatorPolicyCapability::CAN_VIEW)->setSpacePHID($v_space))->appendChild(id(new AphrontFormSubmitControl())->setValue($button)->addCancelButton($cancel_uri));
     $crumbs = $this->buildApplicationCrumbs($this->buildSideNavView());
     $crumbs->addTextCrumb($title);
     $form_box = id(new PHUIObjectBoxView())->setHeaderText($title)->setFormErrors($errors)->setForm($form);
     return $this->buildApplicationPage(array($crumbs, $form_box), array('title' => $title));
 }
 private function renderStatus(PhabricatorSlowvoteOption $option)
 {
     if (!$this->areResultsVisible()) {
         return null;
     }
     $poll = $this->getPoll();
     $choices = mgroup($poll->getChoices(), 'getOptionID');
     $choices = count(idx($choices, $option->getID(), array()));
     $count = count(mgroup($poll->getChoices(), 'getAuthorPHID'));
     $percent = sprintf('%d%%', $count ? 100 * $choices / $count : 0);
     switch ($poll->getMethod()) {
         case PhabricatorSlowvotePoll::METHOD_PLURALITY:
             $status = pht('%s (%d / %d)', $percent, $choices, $count);
             break;
         case PhabricatorSlowvotePoll::METHOD_APPROVAL:
             $status = pht('%s Approval (%d / %d)', $percent, $choices, $count);
             break;
     }
     return phutil_tag('div', array('class' => 'slowvote-status'), $status);
 }
 public function processRequest()
 {
     $request = $this->getRequest();
     $user = $request->getUser();
     $poll = new PhabricatorSlowvotePoll();
     $poll->setAuthorPHID($user->getPHID());
     $e_question = true;
     $e_response = true;
     $errors = array();
     $responses = $request->getArr('response');
     if ($request->isFormPost()) {
         $poll->setQuestion($request->getStr('question'));
         $poll->setResponseVisibility($request->getInt('response_visibility'));
         $poll->setShuffle($request->getBool('shuffle', false));
         $poll->setMethod($request->getInt('method'));
         if (!strlen($poll->getQuestion())) {
             $e_question = 'Required';
             $errors[] = 'You must ask a poll question.';
         } else {
             $e_question = null;
         }
         $responses = array_filter($responses);
         if (empty($responses)) {
             $errors[] = 'You must offer at least one response.';
             $e_response = 'Required';
         } else {
             $e_response = null;
         }
         if (empty($errors)) {
             $poll->save();
             foreach ($responses as $response) {
                 $option = new PhabricatorSlowvoteOption();
                 $option->setName($response);
                 $option->setPollID($poll->getID());
                 $option->save();
             }
             return id(new AphrontRedirectResponse())->setURI('/V' . $poll->getID());
         }
     }
     $error_view = null;
     if ($errors) {
         $error_view = new AphrontErrorView();
         $error_view->setTitle('Form Errors');
         $error_view->setErrors($errors);
     }
     $form = id(new AphrontFormView())->setUser($user)->appendChild('<p class="aphront-form-instructions">Resolve issues and build ' . 'consensus through protracted deliberation.</p>')->appendChild(id(new AphrontFormTextControl())->setLabel('Question')->setName('question')->setValue($poll->getQuestion())->setError($e_question));
     for ($ii = 0; $ii < 10; $ii++) {
         $n = $ii + 1;
         $response = id(new AphrontFormTextControl())->setLabel("Response {$n}")->setName('response[]')->setValue(idx($responses, $ii, ''));
         if ($ii == 0) {
             $response->setError($e_response);
         }
         $form->appendChild($response);
     }
     $poll_type_options = array(PhabricatorSlowvotePoll::METHOD_PLURALITY => 'Plurality (Single Choice)', PhabricatorSlowvotePoll::METHOD_APPROVAL => 'Approval (Multiple Choice)');
     $response_type_options = array(PhabricatorSlowvotePoll::RESPONSES_VISIBLE => 'Allow anyone to see the responses', PhabricatorSlowvotePoll::RESPONSES_VOTERS => 'Require a vote to see the responses', PhabricatorSlowvotePoll::RESPONSES_OWNER => 'Only I can see the responses');
     $form->appendChild(id(new AphrontFormSelectControl())->setLabel('Vote Type')->setName('method')->setValue($poll->getMethod())->setOptions($poll_type_options))->appendChild(id(new AphrontFormSelectControl())->setLabel('Responses')->setName('response_visibility')->setValue($poll->getResponseVisibility())->setOptions($response_type_options))->appendChild(id(new AphrontFormCheckboxControl())->setLabel('Shuffle')->addCheckbox('shuffle', 1, 'Show choices in random order', $poll->getShuffle()))->appendChild(id(new AphrontFormSubmitControl())->setValue('Create Slowvote')->addCancelButton('/vote/'));
     $panel = new AphrontPanelView();
     $panel->setWidth(AphrontPanelView::WIDTH_FORM);
     $panel->setHeader('Create Slowvote');
     $panel->appendChild($form);
     return $this->buildStandardPageResponse(array($error_view, $panel), array('title' => 'Create Slowvote'));
 }
 private function renderPollOption(PhabricatorSlowvotePoll $poll, array $viewer_choices, PhabricatorSlowvoteOption $option)
 {
     $id = $option->getID();
     switch ($poll->getMethod()) {
         case PhabricatorSlowvotePoll::METHOD_PLURALITY:
             // Render a radio button.
             $selected_option = head($viewer_choices);
             if ($selected_option) {
                 $selected = $selected_option->getOptionID();
             } else {
                 $selected = null;
             }
             if ($selected == $id) {
                 $checked = "checked";
             } else {
                 $checked = null;
             }
             $input = phutil_render_tag('input', array('type' => 'radio', 'name' => 'vote[]', 'value' => $id, 'checked' => $checked));
             break;
         case PhabricatorSlowvotePoll::METHOD_APPROVAL:
             // Render a check box.
             $checked = null;
             foreach ($viewer_choices as $choice) {
                 if ($choice->getOptionID() == $id) {
                     $checked = 'checked';
                     break;
                 }
             }
             $input = phutil_render_tag('input', array('type' => 'checkbox', 'name' => 'vote[]', 'checked' => $checked, 'value' => $id));
             break;
         default:
             throw new Exception("Unknown poll method!");
     }
     if ($checked) {
         $checked_class = 'phabricator-slowvote-checked';
     } else {
         $checked_class = null;
     }
     return phutil_render_tag('label', array('class' => 'phabricator-slowvote-label ' . $checked_class), $input . phutil_escape_html($option->getName()));
 }