public function actionSubmit()
 {
     $token = Yii::$app->request->get('token');
     // Better way to get this?
     $code = Code::findCodeByToken($token);
     if (!$code || !$code->isValid()) {
         throw new UserException(Yii::t('app', 'Invalid voting code'));
     } elseif ($code->isUsed()) {
         throw new UserException(Yii::t('app', 'This voting code has already been used'));
     }
     $poll = $code->getPoll()->with('options')->one();
     $data = Yii::$app->request->getBodyParams();
     $optionIDs = $data['options'];
     if ($optionIDs === null || !is_array($optionIDs)) {
         throw new UserException(Yii::t('app', 'Bad Request'));
     }
     if (count($optionIDs) < $poll->select_min) {
         throw new UserException(Yii::t('app', 'Too few options selected'));
     }
     if (count($optionIDs) > $poll->select_max) {
         throw new UserException(Yii::t('app', 'Too many options selected'));
     }
     $transaction = Yii::$app->db->beginTransaction();
     $vote = new Vote();
     $vote->code_id = $code->id;
     if (!$vote->save()) {
         throw new UserException(Yii::t('app', 'Something went wrong'));
     }
     foreach ($optionIDs as $optionId) {
         $option = $poll->getOptions()->where(['id' => $optionId])->one();
         if (!$option) {
             $transaction->rollBack();
             throw new UserException(Yii::t('app', 'Invalid option'));
         }
         try {
             $vote->link('options', $option);
         } catch (Exception $e) {
             $transaction->rollBack();
             throw new UserException(Yii::t('app', 'Something went wrong'));
         }
     }
     $code->code_status = Code::CODE_STATUS_USED;
     if (!$code->save()) {
         $transaction->rollBack();
         throw new UserException(Yii::t('app', 'Something went wrong'));
     }
     $transaction->commit();
     // Log the vote in the vote log file.
     $arrayString = implode(", ", $optionIDs);
     $arrayString = "[{$arrayString}]";
     Yii::info("{$code->token} {$arrayString}", 'vote');
     return $data;
 }
 public function actionVoting()
 {
     $token = Yii::$app->session->get('token', null);
     if (!$token) {
         return $this->redirect(['index']);
     } else {
         // display the form from the poll options
         // get code through the token
         $code = Code::findCodeByToken($token);
         // check again if its not used etc.
         if ($code->checkCode()) {
             // display the form when code is not used and valid
             $model = new VotingForm($code);
             $success = false;
             if (Yii::$app->request->post($model->formName())) {
                 $model->load(Yii::$app->request->post());
                 if ($model->validate()) {
                     // save the vote and selected options
                     $transaction = \Yii::$app->db->beginTransaction();
                     try {
                         $vote = new Vote();
                         $vote->code_id = $code->id;
                         if ($vote->save()) {
                             // save selected options if there are any submitted, votes without options selected could also be done.
                             if (is_array($model->options)) {
                                 foreach ($model->options as $optionId) {
                                     $option = $model->getOptionById($optionId);
                                     $vote->link('options', $option);
                                     /*if (!$vote->link('options', $option)) {
                                           throw new \Exception("Option couldn't be linked to vote", 1);
                                       }*/
                                 }
                             }
                             $code->code_status = Code::CODE_STATUS_USED;
                             if (!$code->save()) {
                                 if ($code->getErrors()) {
                                     Yii::$app->getSession()->addFlash('error', Html::errorSummary($code, $options = ['header' => Yii::t('app/error', 'Failed to save due to error:')]));
                                 }
                                 throw new \Exception(Yii::t('app/error', "Code Couldn't be saved "), 1);
                             }
                         } else {
                             if ($vote->getErrors()) {
                                 Yii::$app->getSession()->addFlash('error', Html::errorSummary($vote, $options = ['header' => Yii::t('app/error', 'Failed to save due to error:')]));
                             }
                             throw new \Exception(Yii::t('app/error', "Vote Couldn't be saved "), 1);
                         }
                         $transaction->commit();
                         $success = true;
                     } catch (\Exception $e) {
                         $transaction->rollBack();
                         Yii::warning('There was an error on saving a vote: ' . $e->getMessage());
                         if (!Yii::$app->getSession()->hasFlash('error')) {
                             Yii::$app->getSession()->addFlash('error', $e->getMessage());
                         }
                         //throw new HttpException(400, 'There was an error on saving a vote: '.$e->getMessage());
                     }
                 }
             }
             if ($success) {
                 // remove the token
                 Yii::$app->session->remove('token');
                 return $this->render('voting_success');
             } else {
                 return $this->render('voting', ['show_form' => true, 'model' => $model]);
             }
         } else {
             Yii::$app->session->remove('token');
             Yii::$app->getSession()->setFlash('token-error', $code->getErrors('token')[0]);
         }
     }
     return $this->render('voting', ['show_form' => false, 'model' => null]);
 }