so I have a controller that essentially submits an edit of a category for approval by sending an email to the admin. This was fine before I decided to add in an actions table to store action history (e.g. category: edit).
The problem that's arose is that, by using entityManager to add data to the actions table, it's automatically updating the category entity due to the Event Watcher.
I tried a google and couldn't find anything on setting entityManager to one entity only.
This is my current controller:
<?php
namespace App\Controller\Category\Edit;
use App\Entity\Action;
use App\Entity\Category;
use App\Entity\User;
use App\Form\Category\EditCategoryType;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
class EditController extends Controller
{
public function edit($id, Request $request, \Swift_Mailer $mailer)
{
$this->denyAccessUnlessGranted('IS_AUTHENTICATED_FULLY');
$category = $this->getDoctrine()->getRepository(Category::class)->find($id);
$categoryGuru = $category->getGuru();
$guruName = $categoryGuru->getUsername();
$category->setGuru($categoryGuru);
$form = $this->createForm(EditCategoryType::class, $category);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$formData = $form->getData();
$name = $formData->getName();
$description = $formData->getDescription();
$newGuruId = $form['guru']->getData();
$newGuru = $this->getDoctrine()->getRepository(User::class)->find($newGuruId);
$actionId = $this->setAction();
$approveUrl = $category->getId();
$approveUrl .= '/'. $actionId;
$approveUrl .= '/'. $name;
$approveUrl .= '/'. $description;
$approveUrl .= '/'. $newGuru->getId();
$message = (new \Swift_Message('Category Edit Request - '. $category->getName()))
->setFrom('some#email.com')
->setTo('another#email.co.uk')
->setBody(
$this->renderView(
'emails/category/edit-request.html.twig',
array(
'category' => $category->getName(),
'category_new_name' => $name,
'description' => $category->getDescription(),
'category_new_description' => $description,
'guru' => $guruName,
'category_new_guru' => $newGuru->getUsername(),
'category_new_guru_id' => $newGuru->getId(),
'category_id' => $category->getId(),
'category_author' => $this->getUser()->getUsername(),
'approve_url' => $approveUrl,
'action_id' => $actionId
)
),
'text/html'
);
$mailer->send($message);
$this->addFlash('success', 'Category Edit Submitted for Review.');
return $this->redirectToRoute('category_list');
}
return $this->render(
'category/edit.html.twig',
array('form' => $form->createView(), 'category' => $category, 'guru' => $categoryGuru)
);
}
# this was originally a part of the above controller
# tried separating to see if it would work - didn't
public function setAction()
{
$action = new Action();
$entityManager = $this->getDoctrine()->getManager();
# set action data
$action->setDate(new \DateTime());
$action->setUserId($this->getUser()->getId());
$action->setDescription($this->getUser()->getUsername(). ' has edited a category');
$action->setStatus('pending');
$action->setType('Category: edit');
$entityManager->persist($action);
$entityManager->flush();
return $action->getId();
}
}
The answer I came to was, don't. Use the Repository class:
CategoryRepository.php
public function addAction($userId, $description, $status, $type)
{
$entityManager = $this->getEntityManager();
$connection = $entityManager->getConnection();
$date = date('Y-m-d H:i:s', strtotime('now'));
$connection->insert(
'action',
array(
'type' => $type,
'user_id' => $userId,
'date' => $date,
'description' => $description,
'status' => $status
)
);
return $entityManager->getConnection()->lastInsertId();
}
then call it in the controller - no longer classing entityManager issues.
Related
I try to make answers for question.
Here is my AnswerController:
#[Route('/{slug}/{name}/answer/{question}', name: 'answer_question')]
public function answer(Question $q, QuestionRepository $questionRepository, string $question, Request $request, EntityManagerInterface $entityManager, string $slug, string $name, AnswerRepository $answerRepository): Response
{
$questions = $questionRepository->findOneBySlug($question);
$answers = $answerRepository->findAnswers($question);
$form = $this->createForm(AnswerType::class);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$data = $form->getData();
$answer = new Answer();
$answer->setContent($data->getContent());
$answer->setAnsweredAt(new \DateTime);
$answer->setQuestion($q);
$entityManager->persist($answer);
$entityManager->flush();
return $this->redirectToRoute('show_question', [
'slug' => $slug,
'name' => $name,
'question' => $question,
]);
}
return $this->render('answer/index.html.twig', [
'questions' => $questions,
'answers' => $answers,
'answer' => $form->createView(),
]);
}
I have problem with
App\Entity\Question object not found by the #ParamConverter annotation
EDIT:
Still I have a little problem with wildcards,
for example when i put address "/audi-a3/8v/answer/question" it's ok, but when i put "/audi-a4/8v/answer/question" ( there isn't audi-a4 with model 8v but this address gives me correct page for "8V" model. It doesn't match ).
Can someone explain me how to do it right?
I did some changes in AnswerController and now it's working.
Set ParamConverter manually.
#[Route('/{car}/{name}/answer/{slug}', name: 'answer_question')]
#[ParamConverter('question', class: Question::class, options: ['mapping' => ['slug' => 'slug']])]
public function answer(Question $question, QuestionRepository $questionRepository, Request $request, EntityManagerInterface $entityManager, string $slug, string $name, string $car, AnswerRepository $answerRepository): Response
{
$questions = $questionRepository->findOneBySlug($slug);
$answers = $answerRepository->findAnswers($slug);
$form = $this->createForm(AnswerType::class);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$data = $form->getData();
$answer = new Answer();
$answer->setContent($data->getContent());
$answer->setAnsweredAt(new \DateTime);
$answer->setQuestion($question);
$entityManager->persist($answer);
$entityManager->flush();
return $this->redirectToRoute('show_question', [
'slug' => $slug,
'name' => $name,
'car' => $car,
]);
}
return $this->render('answer/index.html.twig', [
'questions' => $questions,
'answers' => $answers,
'answer' => $form->createView(),
]);
}
Here is the funcion im using
public function sendCredentialsEmailMessage(UserInterface $user)
{
$template = 'Emails/afterRegister.html.twig';
$rendered = $this->templating->render($template, array(
'user' => $user,
));
$this->sendEmailMessage($rendered,
$this->parameters['from_email']['confirmation'], $user->getEmail());
}
Basically I want the auto-mailer to send my template along with the login name. When i create a new user nothing is being sent. My email template is located in app>resources>views>emails>
and this controller file is located in src>myname>userbundle>mailer>
protected function sendEmailMessage($renderedTemplate, $fromEmail, $toEmail)
{
// Render the email, use the first line as the subject, and the rest as the body
$renderedLines = explode("\n", trim($renderedTemplate));
$subject = array_shift($renderedLines);
$body = implode("\n", $renderedLines);
$message = (new \Swift_Message())
->setSubject($subject)
->setFrom($fromEmail)
->setTo($toEmail)
->setBody($body);
$this->mailer->send($message);
}
Also this works for sure:
public function sendResettingEmailMessage(UserInterface $user)
{
$template = $this->parameters['resetting.template'];
$url = $this->router->generate('fos_user_resetting_reset', array('token' => $user->getConfirmationToken()),
UrlGeneratorInterface::ABSOLUTE_URL);
$rendered = $this->templating->render($template, array(
'user' => $user,
'confirmationUrl' => $url,
));
$this->sendEmailMessageCustom($rendered, $this->from, (string)$user->getEmail(),'Password resseting');
}
I'm trying to render twig template as variable, using symfony. I have a 'sendAction' Controller, which uses the mailgun API to send emails to one or more mailing lists. Here is my code for the Controller:
public function sendAction(Request $request, Newsletter $newsletter, MailgunManager $mailgunManager) {
$form = $this->createForm(SendForm::class);
$form->handleRequest($request);
$formData = array();
if ($form->isSubmitted() && $form->isValid()) {
$formData = $form->getData();
$mailingLists = $formData['mailingLists'];
foreach ($mailingLists as $list) {
$mailgunManager->sendMail($list->getAddress(), $newsletter->getSubject(), 'test', $newsletter->getHtmlContent());
return $this->render('webapp/newsletter/sent.html.twig');
}
}
return $this->render('webapp/newsletter/send.html.twig', array(
'newsletter' => $newsletter,
'form' => $form->createView()
));
}
}
And here's my sendMail (mailgun) function:
public function sendMail($mailingList, $subject, $textBody, $htmlBody) {
$mgClient = new Mailgun($this::APIKEY);
# Make the call to the client.
$mgClient->sendMessage($this::DOMAIN, array(
'from' => $this::SENDER,
'to' => $mailingList,
'subject' => $subject,
'text' => $textBody,
'html' => $htmlBody
));
}
I want my ' $newsletter->getHtmlContent()' to render template called 'newsletter.twig.html'. can anyone help me or point me in the right direction as to what I can do or Where I can find Tutorials or notes on what I am trying to do. the symfony documentation is quite vague.
You can use getContent() chained to your render function.
return $this->render('webapp/newsletter/send.html.twig', array(
'newsletter' => $newsletter,
'form' => $form->createView()
))->getContent();
Simply inject an instance of Symfony\Bundle\FrameworkBundle\Templating\EngineInterface into your action, and you’ll be able to use Twig directly:
public function sendAction(Request $request, EngineInterface $tplEngine, Newsletter $newsletter, MailgunManager $mailgunManager)
{
// ... other code
$html = $tplEngine->render('webapp/newsletter/send.html.twig', [
'newsletter' => $newsletter,
'form' => $form->createView()
]);
}
Note that $this->render() (in the controller action) will return an instance of Symfony\Component\HttpFoundation\Response, while $tplEngine->render() returns a HTML string.
Please consider the following php class extends the WP_REST_Controller class of Wordpress related to Rest API:
<?php
class MCQAcademy_Endpoint extends WP_REST_Controller {
/**
* Register the routes for the objects of the controller.
*/
public function register_routes() {
$version = '1';
$namespace = 'custompath/v' . $version;
$base = 'endpointbase';
register_rest_route(
$namespace,
'/' . $base,
array(
array(
'methods' => WP_REST_Server::READABLE,
'callback' => array( $this, 'get_items' ),
'permission_callback' => array( $this, 'get_items_permissions_check' ),
'args' => array(),
)
)
);
}
/**
*
*/
public function get_items( $request ) {
$rs = array(
'data' => array(),
'request' => array(
'lang' => 'en',
),
);
$args = array();
$items = get_posts( $args );
foreach( $items as $item ) {
$itemdata = $this->prepare_item_for_response( $item, $request );
$rs['data'][] = $this->prepare_response_for_collection( $itemdata );
}
$rs['wp_get_current_user'] = wp_get_current_user(); // Does not output as expected
return new WP_REST_Response( $rs, 200 );
}
/**
* Check if a given request has access to get items
*/
public function get_items_permissions_check( $request ) {
return true; // to make readable by all
}
/**
* Prepare the item for create or update operation
*/
protected function prepare_item_for_database( $request ) {
return $request;
}
/**
* Prepare the item for the REST response
*/
public function prepare_item_for_response( $item, $request ) {
$data = array(
'ID' => $item->ID,
'post_content' => wpautop($item->post_content),
'post_title' => $item->post_title,
);
return $data;
}
/**
* Get the query params for collections
*/
public function get_collection_params() {
return array(
'page' => array(
'description' => 'Current page of the collection.',
'type' => 'integer',
'default' => 1,
'sanitize_callback' => 'absint',
),
'per_page' => array(
'description' => 'Maximum number of items to be returned in result set.',
'type' => 'integer',
'default' => 10,
'sanitize_callback' => 'absint',
),
'search' => array(
'description' => 'Limit results to those matching a string.',
'type' => 'string',
'sanitize_callback' => 'sanitize_text_field',
),
);
}
// Register our REST Server
public function hook_rest_server(){
add_action( 'rest_api_init', array( $this, 'register_routes' ) );
}
}
$myEndpoint = new MCQAcademy_Endpoint();
$myEndpoint->hook_rest_server();
Everything is going well except calling the wp_get_current_user() function in the get_items() function return empty user even though the user is loggedin in the website.
What is the solution to get the loggedin user info in Rest API endpoint function?
public function contactAction(Request $request)
{
$contact = new Contact();
$form = $this->createForm(ContactType::class, $contact);
$em = $this->getDoctrine()->getManager();
$form->handleRequest($request);
if($form->isSubmitted() && $form->isValid()) {
$name = $form['name']->getData();
$email = $form['email']->getData();
$subject = $form['subject']->getData();
$message = $form['message']->getData();
$contact->setName($name);
$contact->setEmail($email);
$contact->setSubject($subject);
$contact->setMessage($message);
}
$message = \Swift_Message::newInstance()
->setSubject($subject) // here the error
->setFrom('jardisindustrie#gmail.com')
->setTo($email)
->setBody($this->renderView('sendmail.html.twig', array(
'name' => $name,
'message' => $message,
'email' => $email,
'subject' => $subject)), 'text/html');
$this->get('mailer')->send($message);
return $this->render('SDCoreBundle::contact.html.twig', [
'form' => $form->createView()
]);
}
I don't know why but it did work good and this afternoon I try again and I have the error message...
I want to make a contact form with swiftmailer, normally I do like that but here i don't know why there is a trouble.
Thanks for your help
You are missing the complete error message. But from the first look, the code that creates and sends a message should be inside the if($form->isSubmitted() && $form->isValid()) block, otherwise it will try to send a message when the form is not submited but only being displayed.