475 lines
12 KiB
PHP
475 lines
12 KiB
PHP
|
<?php
|
||
|
|
||
|
namespace App\Controller\api;
|
||
|
|
||
|
use App\Controller\FramadateController;
|
||
|
use App\Entity\Choice;
|
||
|
use App\Entity\Owner;
|
||
|
use App\Entity\Poll;
|
||
|
use JMS\Serializer\Exception\RuntimeException;
|
||
|
use JMS\Serializer\SerializerBuilder;
|
||
|
use JMS\Serializer\SerializerInterface;
|
||
|
use Swift_Mailer;
|
||
|
use Symfony\Component\HttpFoundation\JsonResponse;
|
||
|
use Symfony\Component\HttpFoundation\Request;
|
||
|
use Symfony\Component\HttpFoundation\Response;
|
||
|
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
|
||
|
|
||
|
use FOS\RestBundle\Controller\Annotations\Get;
|
||
|
use FOS\RestBundle\Controller\Annotations\Put;
|
||
|
use FOS\RestBundle\Controller\Annotations\Delete;
|
||
|
use FOS\RestBundle\Controller\Annotations\Post;
|
||
|
use FOS\RestBundle\Controller\Annotations\Route;
|
||
|
|
||
|
/**
|
||
|
* Class DefaultController
|
||
|
* @package App\Controller
|
||
|
* @Route("/api/v1/poll",name="api_")
|
||
|
*/
|
||
|
class PollController extends FramadateController {
|
||
|
/**
|
||
|
* @Get(
|
||
|
* path = "/",
|
||
|
* name = "get_all_polls"
|
||
|
* )
|
||
|
*/
|
||
|
public function getAllPollsAction() {
|
||
|
$repository = $this->getDoctrine()->getRepository( Poll::class );
|
||
|
$data = $repository->findAll();
|
||
|
|
||
|
|
||
|
return $this->json( [
|
||
|
'message' => 'here are your polls',
|
||
|
'poll' => count( $data ),
|
||
|
] );
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @param $id
|
||
|
* message when the poll is not found
|
||
|
* @return JsonResponse
|
||
|
*/
|
||
|
public function notFoundPoll($id){
|
||
|
return $this->json( [
|
||
|
'message' => $id . ' : poll not found',
|
||
|
],
|
||
|
404 );
|
||
|
}
|
||
|
/**
|
||
|
* get a poll config by its custom URL, we do not want polls to be reachable by their numeric id
|
||
|
* @Get(
|
||
|
* path = "/{id}",
|
||
|
* name = "get_poll",
|
||
|
* requirements = {"id"="\w+"}
|
||
|
* )
|
||
|
*
|
||
|
* @param SerializerInterface $serializer
|
||
|
* @param Request $request
|
||
|
*
|
||
|
* @return JsonResponse|Response
|
||
|
*/
|
||
|
public function getPollConfig(
|
||
|
SerializerInterface $serializer,
|
||
|
$id,
|
||
|
Request $request
|
||
|
) {
|
||
|
$repository = $this->getDoctrine()->getRepository( Poll::class );
|
||
|
$poll = $repository->findOneByCustomUrl( $id );
|
||
|
|
||
|
if ( ! $poll ) {
|
||
|
return $this->notFoundPoll($id);
|
||
|
}
|
||
|
|
||
|
$comments = $poll->getComments();
|
||
|
$pass = $poll->getPassword();
|
||
|
|
||
|
$returnedPoll = [
|
||
|
'message' => 'your poll config for ' . $poll->getTitle(),
|
||
|
'password_protected' => $pass ? 'yes' : 'no',
|
||
|
// TODO do not render sub objects of owner, it returns too many things
|
||
|
'poll' => $poll,
|
||
|
'stacks_count' => count( $poll->getStacksOfVotes() ),
|
||
|
'stacks' => $poll->getStacksOfVotes(),
|
||
|
'choices_count' => $poll->computeAnswers(),
|
||
|
'choices' => $poll->getChoices(),
|
||
|
'comments' => $comments,
|
||
|
'comments_count' => count( $comments ),
|
||
|
];
|
||
|
|
||
|
/**
|
||
|
* password protected content
|
||
|
*/
|
||
|
if ( $pass ) {
|
||
|
// no password possibly given by this route
|
||
|
return $this->json( [
|
||
|
'message' => 'this is protected by a password,but you did not provide the encoded password parameter, and you should feel bad. ' ,
|
||
|
],
|
||
|
403 );
|
||
|
|
||
|
} else {
|
||
|
// free access to poll
|
||
|
return $this->returnPollData( $poll, $serializer );
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* get a poll config by its custom URL, we do not want polls to be reachable by their numeric id
|
||
|
* @Get(
|
||
|
* path = "/{id}/pass/{md5}",
|
||
|
* name = "get_protected_poll",
|
||
|
* requirements = {"id"="\w+"}
|
||
|
* )
|
||
|
*
|
||
|
* @param SerializerInterface $serializer
|
||
|
* @param Request $request
|
||
|
*
|
||
|
* @return JsonResponse|Response
|
||
|
*/
|
||
|
function getProtectedPoll($id,$md5, SerializerInterface $serializer){
|
||
|
$repository = $this->getDoctrine()->getRepository( Poll::class );
|
||
|
$poll = $repository->findOneByCustomUrl( $id );
|
||
|
|
||
|
if ( ! $poll ) {
|
||
|
return $this->notFoundPoll($id);
|
||
|
}
|
||
|
|
||
|
if ( $poll->getPassword() === $md5 ) {
|
||
|
// good matching pass
|
||
|
return $this->returnPollData( $poll, $serializer );
|
||
|
} else {
|
||
|
// wrong pass
|
||
|
return $this->json( [
|
||
|
'message' => 'this is protected by a password, your password "' . $md5 . '" is wrong, and you should feel bad',
|
||
|
'md5' => md5($md5),
|
||
|
'data' => null,
|
||
|
],
|
||
|
403 );
|
||
|
}
|
||
|
|
||
|
|
||
|
}
|
||
|
|
||
|
function returnPollData( $poll, $serializer ) {
|
||
|
$jsonResponse = $serializer->serialize( $poll, 'json' );
|
||
|
|
||
|
$response = new Response( $jsonResponse );
|
||
|
$response->headers->set( 'Content-Type', 'application/json' );
|
||
|
$response->setStatusCode( 200 );
|
||
|
|
||
|
return $response;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @Put(
|
||
|
* path = "/{id}/{token}",
|
||
|
* name = "update_poll",
|
||
|
* requirements = {"content"="\w+", "poll_id"="\d+"}
|
||
|
* )
|
||
|
*/
|
||
|
public function updatePollConfig(
|
||
|
Poll $poll,
|
||
|
string $token,
|
||
|
Request $request
|
||
|
) {
|
||
|
if ( $poll->getAdminKey() !== $token ) {
|
||
|
return $this->json( [
|
||
|
'message' => 'you are NOT allowed to update the poll ' . $poll->getTitle(),
|
||
|
],
|
||
|
403 );
|
||
|
}
|
||
|
|
||
|
// TODO check validity of request
|
||
|
// update only if we have the admin key
|
||
|
$em = $this->getDoctrine()->getManager();
|
||
|
$em->persist( $poll );
|
||
|
$em->flush();
|
||
|
|
||
|
return $this->json( [
|
||
|
'message' => 'you updated the poll ' . $poll->getTitle(),
|
||
|
],
|
||
|
200 );
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @Post(
|
||
|
* path = "/",
|
||
|
* name = "new_poll",
|
||
|
* requirements = {"creator"="\w+"}
|
||
|
* )
|
||
|
* @param Request $request
|
||
|
*
|
||
|
* @return JsonResponse
|
||
|
*/
|
||
|
public function newPollAction( Request $request ) {
|
||
|
|
||
|
$data = $request->getContent();
|
||
|
|
||
|
$serializer = SerializerBuilder::create()->build();
|
||
|
try {
|
||
|
$newpoll = $serializer->deserialize( $data, 'App\Entity\Poll', 'json' );
|
||
|
} catch ( RuntimeException $e ) {
|
||
|
return $this->json( [ "message" => "Incorrect JSON in request" ], 400 );
|
||
|
}
|
||
|
$newpoll
|
||
|
->setAdminKey( $newpoll->generateAdminKey() )
|
||
|
->setCreationDate( new DateTime() )
|
||
|
->setModificationPolicy( 'nobody' );
|
||
|
$timeStamp = time() + ( 3600 * 24 * 90 ); // 90 days by default
|
||
|
$newpoll->setExpiracyDate( ( new DateTime() )->setTimestamp( $timeStamp ),
|
||
|
new DateTimeZone( 'Europe/Paris' ) );
|
||
|
$data = json_decode( $data, true );
|
||
|
$em = $this->getDoctrine()->getRepository( Owner::class );
|
||
|
$foundOwner = $em->findOneBy( [ 'email' => $data[ 'owner' ][ 'email' ] ] );
|
||
|
|
||
|
|
||
|
$userWasFound = false;
|
||
|
if ( ! $foundOwner ) {
|
||
|
//create a new owner
|
||
|
$owner = new Owner();
|
||
|
|
||
|
$owner->setPseudo( $data[ 'owner' ][ 'pseudo' ] );
|
||
|
$owner->setEmail( $data[ 'owner' ][ 'email' ] );
|
||
|
$foundOwner = $owner;
|
||
|
} else {
|
||
|
$userWasFound = true;
|
||
|
}
|
||
|
// link the owner and the poll
|
||
|
$newpoll->setOwner( $foundOwner );
|
||
|
$foundOwner->addPoll( $newpoll );
|
||
|
|
||
|
|
||
|
$em = $this->getDoctrine()->getManager();
|
||
|
$em->persist( $newpoll );
|
||
|
$em->persist( $foundOwner );
|
||
|
|
||
|
// emails
|
||
|
$newpoll->setMailOnComment( true );
|
||
|
$newpoll->setMailOnVote( true );
|
||
|
$newpoll->setHideResults( false );
|
||
|
// possible answers
|
||
|
$newpoll->setAllowedAnswers( [ 'yes' ] );
|
||
|
if ( $data[ 'voteChoices' ] ) {
|
||
|
switch ( $data[ 'voteChoices' ] ) {
|
||
|
case "only_yes":
|
||
|
default:
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
// setup the password, converting the raw with md5 hash
|
||
|
if ( $data[ 'password' ] ) {
|
||
|
$newpoll->setPassword( $data[ 'password' ] );
|
||
|
}
|
||
|
// manage choices
|
||
|
// text kind of answers, dates are below
|
||
|
if ( $data[ 'pollType' ] == 'classic' ) {
|
||
|
$choices = $data[ 'dateList' ];
|
||
|
foreach ( $choices as $c ) {
|
||
|
$newChoice = new Choice();
|
||
|
$newChoice
|
||
|
->setPoll( $newpoll )
|
||
|
// ->setUrl( $c[ 'url' ] )
|
||
|
->setName( $c[ 'literal' ] );
|
||
|
$em->persist( $newChoice );
|
||
|
// TODO add also choices for each time range in a day
|
||
|
}
|
||
|
} elseif ( $data[ 'pollType' ] == 'dates' ) {
|
||
|
if ( $data[ 'allowSeveralHours' ] == true ) {
|
||
|
// different hours spans
|
||
|
$choices = $data[ 'dateList' ];
|
||
|
} else {
|
||
|
//TODO (Sébastien) I assume this shouldn't be empty ?
|
||
|
// all days have the same hour spans
|
||
|
}
|
||
|
|
||
|
|
||
|
}
|
||
|
|
||
|
$em->persist( $newpoll );
|
||
|
$em->flush();
|
||
|
$precision = '';
|
||
|
if ( $userWasFound ) {
|
||
|
$precision = 'from an existing user : ' . $foundOwner->getEmail();
|
||
|
}
|
||
|
|
||
|
$this->sendCreationMailAction( $foundOwner, $newpoll );
|
||
|
|
||
|
return $this->json( [
|
||
|
'message' => 'you created a poll ' . $precision,
|
||
|
'poll' => $newpoll,
|
||
|
'password_protected' => is_string( $newpoll->getPassword() ),
|
||
|
'admin_key' => $newpoll->getAdminKey(),
|
||
|
'owner_modifier_token' => $foundOwner->getModifierToken(),
|
||
|
|
||
|
],
|
||
|
201 );
|
||
|
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @Get(
|
||
|
* path = "/mail/test-mail-poll/{emailChoice}",
|
||
|
* name = "test-mail-poll",
|
||
|
* )
|
||
|
*
|
||
|
* send the creation mail to owner
|
||
|
*
|
||
|
* @param Owner $admin_user
|
||
|
* @param Poll $poll
|
||
|
* @param Swift_Mailer $mailer
|
||
|
*
|
||
|
* @return int
|
||
|
* not that the email tktest_commentateur@tktest.com does not really exist
|
||
|
*/
|
||
|
// public function sendCreationMailAction( Owner $admin_user, Poll $poll, \Swift_Mailer $mailer) {
|
||
|
public function testSendCreationMailAction(
|
||
|
$emailChoice = 'tktest_commentateur@tktest.com'
|
||
|
) {
|
||
|
$em = $this->getDoctrine()->getRepository( Owner::class );
|
||
|
$foundOwner = $em->findOneByEmail( $emailChoice );
|
||
|
if ( $foundOwner ) {
|
||
|
$poll = $foundOwner->getPolls()[ 0 ];
|
||
|
$comment = $foundOwner->getComments()[ 0 ];
|
||
|
|
||
|
$sent = $this->sendOwnerPollsAction( $foundOwner, $poll );
|
||
|
if ( $sent ) {
|
||
|
return $this->json( [ "message" => "test email sent to " . $foundOwner->getEmail() . "!" ], 200 );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return $this->json( [ "message" => "user with this email was not found" ], 400 );
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* @Delete(
|
||
|
* path = "/{id}",
|
||
|
* name = "poll_delete",
|
||
|
* requirements = {"accessToken"="\w+", "poll_id"="\d+"}
|
||
|
* )
|
||
|
* @param Poll $poll
|
||
|
* @param $accessToken
|
||
|
*
|
||
|
* @return JsonResponse
|
||
|
*/
|
||
|
public
|
||
|
function deletePollAction(
|
||
|
Poll $poll,
|
||
|
$accessToken
|
||
|
) {
|
||
|
|
||
|
if ( $accessToken == $poll->getAdminKey() ) {
|
||
|
$em = $this->getDoctrine()->getManager();
|
||
|
$em->remove( $poll );
|
||
|
$em->flush();
|
||
|
|
||
|
return $this->json( [
|
||
|
'message' => 'boom! le sondage et ses objets assocités a été supprimé',
|
||
|
] );
|
||
|
} else {
|
||
|
return $this->json( [
|
||
|
'message' => 'le token d\'autorisation est invalide, vous ne pouvez pas modifier ce sondage',
|
||
|
] );
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Checks if a slug is already taken by a poll
|
||
|
* @Get(
|
||
|
* path = "/slug/{slug}",
|
||
|
* name = "check_slug_is_unique",
|
||
|
* )
|
||
|
*/
|
||
|
public function checkSlugIsUniqueAction( string $slug ) {
|
||
|
$emPoll = $this->getDoctrine()->getRepository( Poll::class );
|
||
|
$found = $emPoll->findOneByCustomUrl( $slug );
|
||
|
$elaborated_message_version = false;
|
||
|
|
||
|
if ( $found ) {
|
||
|
if ( ! $elaborated_message_version ) {
|
||
|
return $this->json( null,
|
||
|
204 );
|
||
|
}
|
||
|
|
||
|
// we should use an other slug
|
||
|
return $this->json( [
|
||
|
'message' => ' NO, this slug is already taken on this Framadate instance ',
|
||
|
'data' => [
|
||
|
'slug' => $slug,
|
||
|
],
|
||
|
],
|
||
|
204 );
|
||
|
}
|
||
|
if ( ! $elaborated_message_version ) {
|
||
|
return $this->json( null,
|
||
|
404 );
|
||
|
}
|
||
|
|
||
|
return $this->json( [
|
||
|
'message' => ' yes this slug is available on this Framadate instance ',
|
||
|
'data' => [
|
||
|
'slug' => $slug,
|
||
|
],
|
||
|
],
|
||
|
404 );
|
||
|
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get Admin poll config
|
||
|
* @Get(
|
||
|
* path = "/admin/{token}",
|
||
|
* name = "get_admin_config",
|
||
|
* )
|
||
|
*
|
||
|
* @param SerializerInterface $serializer
|
||
|
* @param $token
|
||
|
*
|
||
|
* @return JsonResponse|Response
|
||
|
*/
|
||
|
public function getAdministrationConfig( SerializerInterface $serializer, $token ) {
|
||
|
$emPoll = $this->getDoctrine()->getRepository( Poll::class );
|
||
|
$pollFound = $emPoll->findOneByAdminKey( $token );
|
||
|
|
||
|
if ( $pollFound ) {
|
||
|
|
||
|
$poll = $pollFound;
|
||
|
$comments = $poll->getComments();
|
||
|
$stacks = $poll->getStacksOfVotes();
|
||
|
|
||
|
$returnedPoll = [
|
||
|
'message' => 'your poll config',
|
||
|
'poll' => $poll,
|
||
|
'stacks_count' => count( $stacks ),
|
||
|
'stacks' => $stacks,
|
||
|
'choices_count' => $poll->computeAnswers(),
|
||
|
'choices' => $poll->getChoices(),
|
||
|
'comments' => $comments,
|
||
|
'comments_count' => count( $comments ),
|
||
|
'token' => $token,
|
||
|
];
|
||
|
|
||
|
$jsonResponse = $serializer->serialize( $returnedPoll, 'json' );
|
||
|
|
||
|
$response = new Response( $jsonResponse );
|
||
|
$response->headers->set( 'Content-Type', 'application/json' );
|
||
|
$response->setStatusCode( 200 );
|
||
|
|
||
|
return $response;
|
||
|
}
|
||
|
|
||
|
return $this->json( [
|
||
|
'message' => 'You are not allowed to do anything with this token',
|
||
|
'data' => [
|
||
|
'token' => $token,
|
||
|
],
|
||
|
],
|
||
|
403 );
|
||
|
|
||
|
}
|
||
|
|
||
|
}
|