findAll(); $polls = $data; $titles = []; $pollData = [ 'message' => 'here are your polls', 'count' => count( $polls ), ]; $debug = 1; if ( $debug ) { foreach ( $polls as $poll ) { $titles[] = [ 'title' => $poll->getTitle(), 'slug' => $poll->getCustomUrl(), ]; } $pollData[ 'polls' ] = $titles; } return $this->json( $pollData ); } /** * get a poll config by its custom URL, we do not want polls to be reachable by their numeric id * @Get( * path = "/{customUrl}", * name = "get_poll" * ) * * @param SerializerInterface $serializer * @param Request $request * * @return JsonResponse|Response */ public function getPollConfig( SerializerInterface $serializer, $customUrl, Request $request ) { $repository = $this->getDoctrine()->getRepository( Poll::class ); $poll = $repository->findOneByCustomUrl( $customUrl ); if ( ! $poll ) { return $this->notFoundPoll( $customUrl ); } $comments = $poll->getComments(); $stacks = $poll->getStacksOfVotes(); $pass = $poll->getPassword(); /** * 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->json( $poll->display() ); } } /** * @param $id * message when the poll is not found * * @return JsonResponse */ public function notFoundPoll( $id ): Response { 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 = "/owner/{owner_email}/", * name = "get_owner_poll", * ) * * @return JsonResponse|Response */ function getOwnerPolls( $owner_email , LoggerInterface $logger ) { $repository = $this->getDoctrine()->getRepository( Owner::class ); $owner = $repository->findOneByEmail( $owner_email ); if ( ! $owner ) { return $this->json( [ 'message' => "Owner $owner_email non trouvé" ], 404 ); } else { $polls = $owner->getPolls(); $pollsDisplay = []; foreach ( $polls as $p ) { $pollsDisplay[] = $p->displayForAdmin(); } $mail_sent = $this->sendOwnerPollsAction( $owner ); $logger->info('getOwnerPolls : Email sent : '.$mail_sent); return $this->json( [ 'mail_sent' => $mail_sent ], $mail_sent ? 200 : 404 ); // return $this->json(['owner' => $owner->displayForAdmin(), 'polls' => $pollsDisplay], 200); } } /** * get a poll config by its custom URL, we do not want polls to be reachable by their numeric id * @Get( * path = "/{customUrl}/pass/{md5}", * name = "get_protected_poll", * ) * * @param SerializerInterface $serializer * @param Request $request * * @return JsonResponse|Response */ function getProtectedPoll( $customUrl, $md5, SerializerInterface $serializer ) { $repository = $this->getDoctrine()->getRepository( Poll::class ); $poll = $repository->findOneByCustomUrl( $customUrl ); if ( ! $poll ) { return $this->notFoundPoll( $customUrl ); } if ( md5( $poll->getPassword() ) === $md5 ) { // good matching pass return $this->json( $poll->display() ); } else { // wrong pass return $this->json( [ 'message' => 'this is protected by a password, your password hash "' . $md5 . '" is wrong, and you should feel bad', // 'md5' => md5( $md5 ), 'data' => null, ], 403 ); } } /** * as an administrator of a poll, get a poll config by its custom URL, we do not want polls to be reachable by their numeric id * @Get( * path = "admin/{admin_key}", * name = "get_admin_poll", * ) * * @param SerializerInterface $serializer * @param Request $request * * @return JsonResponse|Response */ function getAdminPoll( $admin_key, $md5, SerializerInterface $serializer ) { $repository = $this->getDoctrine()->getRepository( Poll::class ); $poll = $repository->findOneByAdminKey( $admin_key ); if ( ! $poll ) { return $this->notFoundPoll( $admin_key ); } // good matching pass return $this->json( $poll->displayForAdmin() ); } 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 = "/{customUrl}/update/{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( $poll->displayForAdmin() , 200 ); } /** * @Post( * path = "/", * name = "new_poll", * requirements = {"creator"="\w+"} * ) * @param Request $request * * @return JsonResponse */ public function newPollAction( Request $request ) { $data = $request->getContent(); $data = json_decode( $data, true ); // search for existing custom url, which must be unique $custom_url = $data[ 'custom_url' ]; $repository = $this->getDoctrine()->getRepository( Poll::class ); $poll = $repository->findOneByCustomUrl( $custom_url ); if ( $poll ) { throw new \JsonException( 'NOPE, ce sondage existe déjà: ' . $custom_url ); } $newpoll = new Poll(); $newpoll ->setModificationPolicy( isset( $data[ 'modification_policy' ] ) ? $data[ 'modification_policy' ] : 'everybody' ) ->setTitle( $data[ 'title' ] ) ->setKind( $data[ 'kind' ] ) ->setCustomUrl( $data[ 'custom_url' ] ); if ( count( $data[ 'allowed_answers' ] ) ) { // TODO check this one $newpoll->setAllowedAnswers( $data[ 'allowed_answers' ] ); } $expiracyCalculated = $newpoll->addDaysToDate( new DateTime(), $data[ 'default_expiracy_days_from_now' ] ); $newpoll->setExpiracyDate( $expiracyCalculated ); $emOwner = $this->getDoctrine()->getRepository( Owner::class ); $foundOwner = $emOwner->findOneByEmail( $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( $data[ 'isOwnerNotifiedByEmailOnNewVote' ] ); $newpoll->setMailOnComment( $data[ 'isOwnerNotifiedByEmailOnNewComment' ] ); $newpoll->setIsZeroKnowledge( $data[ 'is_zero_knowledge' ] ); $newpoll->setDescription( $data[ 'description' ] ); $newpoll->setHideResults( false ); // possible answers $newpoll->setAllowedAnswers( $data[ 'allowed_answers' ] ); $newpoll->setVotesMax( $data[ 'maxCountOfAnswers' ] ); $newpoll->setCommentsAllowed( $data[ 'allowComments' ] ); // setup the password, converting the raw with md5 hash if ( $data[ 'password' ] ) { $newpoll->setPassword( $data[ 'password' ] ); } // text kind of answers, dates are below if ( $data[ 'kind' ] == 'text' ) { // manage choices $choices = $data[ 'choices' ]; foreach ( $choices as $c ) { $newChoice = new Choice(); $newChoice ->setPoll( $newpoll ) ->setName( $c[ 'literal' ] ); $em->persist( $newChoice ); $newpoll->addChoice( $newChoice ); } } // date kind of poll elseif ( $data[ 'kind' ] == 'date' ) { $choices = $data[ 'dateChoices' ]; if ( isset( $data[ 'hasSeveralHours' ] ) && $data[ 'hasSeveralHours' ] == true ) { // different hours spans make more choices foreach ( $choices as $c ) { $currentDate = $c[ 'literal' ]; $timeSlicesOfThisChoice = $c[ 'timeSlices' ]; foreach ( $timeSlicesOfThisChoice as $t ) { $newChoice = new Choice(); $newChoice ->setPoll( $newpoll ) ->setName( $currentDate . ' >>> ' . $t[ 'literal' ] ); $em->persist( $newChoice ); $newpoll->addChoice( $newChoice ); } } } else { // all choices will be having the same time slices from timeSlices $timeSlicesForAllChoices = $data[ 'timeSlices' ]; foreach ( $choices as $c ) { $currentDate = $c[ 'date_object' ]; foreach ( $timeSlicesForAllChoices as $t ) { $newChoice = new Choice(); $newChoice ->setPoll( $newpoll ) ->setName( $currentDate . ' >>> ' . $t[ 'literal' ] ); $em->persist( $newChoice ); $newpoll->addChoice( $newChoice ); } } } } $em->persist( $newpoll ); $em->flush(); $precision = ''; if ( $userWasFound ) { $precision = 'from an existing user : ' . $foundOwner->getEmail(); } $this->sendCreationMailAction( $foundOwner, $newpoll ); $newChoices = $newpoll->display()[ 'choices' ]; return $this->json( [ 'message' => 'you created the poll ' . $newpoll->getCustomUrl() . $precision, 'id' => $newpoll->getId(), 'poll' => $newpoll->displayForAdmin(), 'password_protected' => is_string( $newpoll->getPassword() ), ], 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( Poll::class ); $foundPoll = $em->findOneByCustomUrl( 'dessin-anime' ); $em = $this->getDoctrine()->getRepository( Owner::class ); $foundOwner = $em->findOneByEmail( $emailChoice ); return $this->render( 'emails/creation-mail.html.twig', [ 'poll' => $foundPoll, 'owner' => $foundPoll->getOwner() ] ); } /** * @Delete( * path = "/{admin_key}", * name = "poll_delete", * requirements = {"accessToken"="\w+", "poll_id"="\d+"} * ) * @param Poll $poll * @param $accessToken * * @return JsonResponse */ public function deletePollAction( $admin_key ) { $emPoll = $this->getDoctrine()->getRepository( Poll::class ); $found = $emPoll->findOneByAdminKey( $admin_key ); if ( $found ) { $em = $this->getDoctrine()->getManager(); $em->remove( $found ); $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/{customUrl}", * name = "check_slug_is_unique", * ) */ public function checkSlugIsUniqueAction( string $customUrl ) { $emPoll = $this->getDoctrine()->getRepository( Poll::class ); $found = $emPoll->findOneByCustomUrl( $customUrl ); $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 custom_url is already taken on this Framadate instance ', 'data' => [ 'slug' => $customUrl, ], ], 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' => $customUrl, ], ], 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; $returnedPoll = [ 'message' => 'your poll config', 'poll' => $poll->displayForAdmin(), ]; return $this->json( $returnedPoll, 200 );; } return $this->json( [ 'message' => 'You are not allowed to do anything with this token', 'data' => [ 'token' => $token, ], ], 403 ); } /** * Find expired polls and set them as such * @Get( * path = "/admin/clean_expired_polls/{token}", * name = "clean_expired_polls", * ) * * @param $token * * @return JsonResponse|Response */ public function getExpiredPollsCleanup( $token ) { if ( $token !== 'superCaligistriixpirlidouciousse' ) { return $this->json( [ 'message' => 'not allowed', 'data' => [ 'token' => $token, ], ], 403 ); } $em = $this->getDoctrine()->getManager(); $emPoll = $this->getDoctrine()->getRepository( Poll::class ); $deletablePollsFound = $emPoll->findDeletableExpiredPolls(); // dead by more than 30 days $expiredPollsFound = $emPoll->findExpiredPolls(); // just dead $soon_expired_polls = $emPoll->findSoonExpiredPolls(); // will die in 30 days $deletedTitle = []; $expiredTitle = []; $soon_expired_title = []; $really_delete = false; foreach ( $soon_expired_polls as $item ) { $soon_expired_title[] = $item->getTitle(); } foreach ( $expiredPollsFound as $item ) { $expiredTitle[] = $item->getTitle(); $item->setVotesAllowed( false ); $em->persist( $item ); } foreach ( $deletablePollsFound as $item ) { $deletedTitle[] = $item->getTitle(); if ( $really_delete ) { $item->setVotesAllowed( false ); $em->remove( $item ); } } $em->flush(); return $this->json( [ 'message' => 'cleanup report', 'really_delete' => $really_delete, 'deleted' => count( $deletablePollsFound ), 'deleted_titles' => $deletedTitle, 'expired' => count( $expiredPollsFound ), 'expired_titles' => $expiredTitle, 'soon_to_be_expired' => count( $soon_expired_polls ), 'soon_to_be_expired_titles' => $soon_expired_title, 'data' => [ 'token' => $token, ], ], 200 ); } }