date-poll-api/src/Controller/api/v1/VoteController.php

312 lines
8.4 KiB
PHP
Executable File

<?php
namespace App\Controller\api\v1;
use App\Controller\EmailsController;
use App\Entity\Choice;
use App\Entity\Comment;
use App\Entity\Owner;
use App\Entity\Poll;
use App\Entity\StackOfVotes;
use App\Entity\Vote;
use App\Repository\ChoiceRepository;
use FOS\RestBundle\Controller\Annotations\Delete;
use FOS\RestBundle\Controller\Annotations\Patch;
use FOS\RestBundle\Controller\Annotations\Route;
use JMS\Serializer\SerializerInterface;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
/**
* Class DefaultController
* @package App\Controller
* @Route("/api/v1/vote-stack",name="api_")
*/
class VoteController extends EmailsController {
/**
* add a vote stack on a poll
* @Route(
* path = "/",
* name = "new_vote_stack",
* methods={"POST","OPTIONS"}
* )
*
* @param SerializerInterface $serializer
* @param Request $request
*
* @return JsonResponse|Response
*/
public function newVoteStackAction(
SerializerInterface $serializer,
Request $request,
ChoiceRepository $choice_repository
) {
$data = $request->getContent();
$data = json_decode( $data, true );
$poll_custom_url = $data[ 'custom_url' ];
/***
* checks before persisting
*/
$em = $this->getDoctrine()->getManager();
$emPol = $em->getRepository( Poll::class );
$poll = $emPol->findOneByCustomUrl( $poll_custom_url );
// check : existence of poll
if ( ! $poll ) {
return $this->json( [ 'message' => 'poll "' . $poll_custom_url . '" not found' ], 404 );
}
// check : limit of number of participation max
if ( count( $poll->getStacksOfVotes() ) == $poll->getVotesMax() ) {
return $this->json( [ 'message' => 'poll "' . $poll_custom_url . '" not allowed to have more stack of votes than ' . $poll->getVotesMax() ],
403 );
}
// var_dump($data);
// die();
$owner = new Owner();
$owner
->addPoll( $poll );
$newStack = new StackOfVotes();
$newStack
->setPoll( $poll )
->setIp( $_SERVER[ 'REMOTE_ADDR' ] )
->setPseudo( $data[ "pseudo" ] )
->setOwner( $owner );
$owner
->setPseudo( $data[ 'owner' ][ "pseudo" ] )
->setPseudo( $data[ 'owner' ][ "email" ] )
->addStackOfVote( $newStack );
$emChoice = $choice_repository;
$newComment = new Comment();
$newComment->setPseudo( $data [ 'pseudo' ] )
->setPoll( $poll )
->setText( $data[ 'comment' ] );
$owner->addComment( $newComment );
$em->persist( $newComment );
foreach ( $data[ 'votes' ] as $vote ) {
if ( ! $vote[ 'value' ] ) {
continue;
}
$newVote = new Vote();
$newVote->setPoll( $poll );
$newStack->addVote( $newVote );
$choiceFound = $emChoice->find( $vote[ 'choice_id' ] );
if ( $choiceFound ) {
$choiceFound->addVote( $newVote );
$newVote->setStacksOfVotes( $newStack )
->setChoice( $choiceFound )
->setValue( $vote[ 'value' ] );
$em->persist( $choiceFound );
} else {
throw new NotFoundHttpException( 'no choice of id' . $vote[ 'choice_id' ] );
}
$poll->addVote( $newVote );
$em->persist( $newVote );
}
$newStack
->setPoll( $poll );
$em->persist( $newStack );
$em->persist( $poll );
$em->flush();
if ( $poll->getMailOnVote() ) {
$this->sendVoteNotificationAction( $newStack->getOwner(), $newStack );
}
return $this->json( $newStack->displayForAdmin() );
}
/**
* update vote stack
* @Route(
* path = "/{id}/token/{modifierToken}",
* name = "update_vote_stack",
* methods={"PATCH","OPTIONS"}
* )
*
* @param SerializerInterface $serializer
* @param StackOfVotes $id
* @param $modifierToken
* @param Request $request
*
* @return JsonResponse|Response
*/
public
function updateVoteStackAction(
SerializerInterface $serializer,
StackOfVotes $id,
$modifierToken,
Request $request
) {
$voteStack = $id;
if ( ! $voteStack ) {
return $this->json( [ 'message' => 'vote stack not found' ], 404 );
}
$poll = $voteStack->getPoll();
$whocanchangeanswers = $poll->getModificationPolicy();
$data = $request->getContent();
$data = json_decode( $data, true );
$table_votes_by_choice_id = [];
if ( $whocanchangeanswers == 'everybody' ) {
$table_votes_by_choice_id = $this->patchVotes( $voteStack, $data[ 'votes' ] );
} else if ( $whocanchangeanswers == 'self' ) {
// someone with the right token of this vote stack only can change this
if ( ! $modifierToken || $voteStack->getOwner()->getModifierToken() !== $modifierToken ) {
return $this->json( [ 'message' => 'your token does not allow you to modify this vote ' ],
403 );
}
$this->patchVotes( $voteStack, $data[ 'votes' ] );
// everything is ok, we can update all the votes of the vote stack
} else if ( $whocanchangeanswers == 'nobody' ) {
// only the poll admin with the poll modifier token can change this
if ( ! $modifierToken || $poll->getOwner()->getModifierToken() !== $modifierToken ) {
return $this->json( [ 'message' => 'your token does not allow you to modify this vote ' ],
403 );
}
$this->patchVotes( $voteStack, $data[ 'votes' ] );
}
// if only self users are allowed to modify a vote, check it
//TODO
// match votes and choices
// update answers
// save everything
$jsonResponse = $voteStack->displayForAdmin();
return $this->json( $jsonResponse, 200 );
}
public function patchVotes( $stackOfVotes, $data ) {
$table_votes_by_choice_id = [];
$votes = $stackOfVotes->getVotes();
$choices = $stackOfVotes->getPoll()->getChoices();
$table_choices_by_id = [];
$em = $this->getDoctrine()->getManager();
foreach ( $choices as $c ) {
$table_choices_by_id[ $c->getId() ] = $c;
}
foreach ( $votes as $stack_vote ) {
$table_votes_by_choice_id[ $stack_vote->getChoice()->getId() ] = $stack_vote;
}
foreach ( $data as $vote ) {
$newValue = $vote[ 'value' ];
$choice_id = $vote[ 'choice_id' ];
// if the new value is null, remove the vote
if ( isset( $table_choices_by_id[ $choice_id ] ) ) {
if ( isset( $table_votes_by_choice_id[ $choice_id ] ) ) {
$voteFound = $table_votes_by_choice_id[ $choice_id ];
if ( $newValue ) {
$voteFound->setValue( $newValue );
$em->persist( $voteFound );
} else {
$stackOfVotes->removeVote( $voteFound );
$em->remove( $voteFound );
}
} else if ( $newValue ) {
// create vote for this stack
$newVote = new Vote();
$newVote->setChoice( $em->find( Choice::class, $choice_id ) )
->setValue( $newValue );
$em->persist( $newVote );
$stackOfVotes->addVote( $newVote );
}
}
}
$em->persist( $stackOfVotes );
$em->flush();
return $table_votes_by_choice_id;
}
/**
* @Route(
* path = "/{id}/token/{modifierToken}",
* name = "delete_vote_stack",
* requirements = { "id"="\d+","modifierToken"="\w+"},
* methods={"DELETE"}
* )
* @param StackOfVotes $stack_of_votes
*/
public function deleteVoteStackAction( StackOfVotes $stack_of_votes, $modifierToken ) {
if ( $modifierToken == $stack_of_votes->getOwner()->getModifierToken() ) {
$em = $this->getDoctrine()->getManager();
$id = $stack_of_votes->getId();
$em->remove( $stack_of_votes );
$em->flush();
return $this->json( [
'message' => 'boom! la stack de vote ' . $id . ' a été supprimée',
],
200 );
} else {
return $this->json( [
'message' => 'le token d\'autorisation est invalide, vous ne pouvez pas modifier cet ensemble de réponses',
],
403 );
}
}
/**
* @Delete(
* path = "/poll/{id}/votes/{accessToken}",
* name = "poll_votes_delete",
* requirements = {"accessToken"="\w+", "poll_id"="\d+"}
* )
* @return JsonResponse
*/
public
function deletePollVotesAction(
Poll $poll,
$accessToken
) {
if ( $accessToken == $poll->getAdminKey() ) {
$em = $this->getDoctrine()->getManager();
$length = count( $poll->getVotes() );
$em->remove( $poll->getVotes() );
$em->flush();
return $this->json( [
'message' => 'boom! les ' . $length . ' votes du sondage ont été supprimés',
],
200 );
} else {
return $this->json( [
'message' => 'le token d\'autorisation est invalide, vous ne pouvez pas modifier ce sondage',
],
403 );
}
}
}