2020-10-26 11:39:04 +01:00
< ? 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 ;
2021-02-05 15:33:38 +01:00
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 ;
2020-10-26 11:39:04 +01:00
/**
* 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 );
2021-02-24 10:30:00 +01:00
$data = $repository -> findAll ();
2020-10-26 11:39:04 +01:00
return $this -> json ( [
'message' => 'here are your polls' ,
2021-02-24 10:30:00 +01:00
'poll' => count ( $data ),
] );
2020-10-26 11:39:04 +01:00
}
/**
2021-02-24 10:30:00 +01:00
* get a poll config by its custom URL , we do not want polls to be reachable by their numeric id
2020-10-26 11:39:04 +01:00
* @ Get (
* path = " / { id} " ,
* name = " get_poll " ,
2021-02-24 10:30:00 +01:00
* requirements = { " id " = " \ w+ " }
2020-10-26 11:39:04 +01:00
* )
2021-02-24 10:30:00 +01:00
*
2020-10-26 11:39:04 +01:00
* @ param SerializerInterface $serializer
* @ param Request $request
*
* @ return JsonResponse | Response
*/
public function getPollConfig (
SerializerInterface $serializer ,
2021-02-24 10:30:00 +01:00
$id ,
2020-10-26 11:39:04 +01:00
Request $request
) {
2021-02-24 10:30:00 +01:00
$repository = $this -> getDoctrine () -> getRepository ( Poll :: class );
$poll = $repository -> findOneByCustomUrl ( $id );
if ( ! $poll ) {
return $this -> json ( [
'message' => $id . ' : poll not found' ,
],
404 );
}
2020-10-26 11:39:04 +01:00
$comments = $poll -> getComments ();
2021-02-24 10:30:00 +01:00
$pass = $poll -> getPassword ();
2020-10-26 11:39:04 +01:00
$returnedPoll = [
2021-02-24 10:30:00 +01:00
'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 ),
2020-10-26 11:39:04 +01:00
];
2021-02-24 10:30:00 +01:00
$data = $request -> getContent ();
$passwordProvided = false ;
if ( is_array ( $data ) && $data [ 'password_input' ] !== null ){
$passwordProvided = $data [ 'password_input' ];
}
2020-10-26 11:39:04 +01:00
/**
* password protected content
*/
2021-02-24 10:30:00 +01:00
if ( $pass ) {
if ( ! $passwordProvided ){
var_dump ( $data );
// no password given
return $this -> json ( [
'message' => 'this is protected by a password,but you did not provide the password_input parameter, and you should feel bad ' ,
'data' => $data
],
403 );
}
elseif ( $pass === md5 ( $passwordProvided ) ) {
// good matching pass
return $this -> returnPollData ( $poll , $serializer );
} else {
// wrong pass
$data = json_decode ( $data , true );
return $this -> json ( [
'message' => 'this is protected by a password, your password "' . $serializer -> serialize ( $data [ 'password_input' ], 'json' ) . '" is wrong, and you should feel bad' ,
'data' => null ,
],
403 );
}
2020-10-26 11:39:04 +01:00
} else {
2021-02-24 10:30:00 +01:00
// free access to poll
return $this -> returnPollData ( $poll , $serializer );
}
2020-10-26 11:39:04 +01:00
2021-02-24 10:30:00 +01:00
}
2020-10-26 11:39:04 +01:00
2021-02-24 10:30:00 +01:00
function returnPollData ( $poll , $serializer ) {
$jsonResponse = $serializer -> serialize ( $poll , 'json' );
$response = new Response ( $jsonResponse );
$response -> headers -> set ( 'Content-Type' , 'application/json' );
$response -> setStatusCode ( 200 );
2020-10-26 11:39:04 +01:00
2021-02-24 10:30:00 +01:00
return $response ;
2020-10-26 11:39:04 +01:00
}
/**
* @ 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' ,
] );
}
}
/**
2021-02-05 15:33:38 +01:00
* Checks if a slug is already taken by a poll
2020-10-26 11:39:04 +01:00
* @ 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' => [
2021-02-05 15:33:38 +01:00
'slug' => $customUrl ,
2020-10-26 11:39:04 +01:00
],
],
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 );
}
}