auto-responder with login details in Symfony - symfony

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');
}

Related

Login WP - Connect single field to an external api

I made a plugin to allow wordpress login with external api.
Everything works, now what I have to do is that when a user logs in for the first time, the plugin checks to see if it is already present on wp, and where it was not already present, it creates a new user by taking behind username, email and password.
The new user is created but I would like it to bring with it also the id field from the external api saving it in an ACF field.
This is the code created so far:
function au_auth($user, $username, $password)
{
$options = get_option('au_options');
$endpoint = $options['au_apiurl'];
$user_email_key = 'email';
$password_key = 'password';
// Makes sure there is an endpoint set as well as username and password
if (!$endpoint || $user !== null || (empty($username) && empty($password))) {
return false;
}
// Check user exists locally
$user_exists = wp_authenticate_username_password(null, $username, $password);
if ($user_exists && $user_exists instanceof WP_User) {
$user = new WP_User($user_exists);
return $user;
}
// Build the POST request
$login_data = array(
$user_email_key => $username,
$password_key => $password
);
$auth_args = array(
'method' => 'POST',
'headers' => array(
'Content-type: application/x-www-form-urlencoded'
),
'sslverify' => false,
'body' => $login_data
);
$response = wp_remote_post($endpoint, $auth_args);
// Token if success; Not used right now
$response_token = json_decode($response['response']['token'], true);
$response_code = $response['response']['code'];
if ($response_code == 400) {
// User does not exist, send back an error message
$user = new WP_Error('denied', __("<strong>Error</strong>: Your username or password are incorrect."));
} else if ($response_code == 200) {
// External user exists, try to load the user info from the WordPress user table
$userobj = new WP_User();
// Does not return a WP_User object but a raw user object
$user = $userobj->get_data_by('email', $username);
if ($user && $user->ID) {
// Attempt to load the user with that ID
$user = new WP_User($user->ID);
}
} else {
// The user does not currently exist in the WordPress user table.
// Setup the minimum required user information
$userdata = array(
'user_email' => $username,
'user_login' => $username,
'user_pass' => $password
);
// A new user has been created
$new_user_id = wp_insert_user($userdata);
// Assign editor role to the new user (so he can access protected articles)
wp_update_user(
array(
'ID' => $new_user_id,
'role' => 'editor'
)
);
// Load the new user info
$user = new WP_User ($new_user_id);
}
}
// Useful for times when the external service is offline
remove_action('authenticate', 'wp_authenticate_username_password', 20);
return $user;
}
Anyone have any way how to help me?
Resolved! I hope this will help those who have found themselves in the same situation as me:
add_filter('authenticate', 'au_auth', 10, 3);
add_filter('register_new_user', 'au_registration', 10, 3);
// add_filter('profile_update', 'au_profile_update', 10, 3);
// add_filter('edit_user_profile_update', 'au_profile_edit', 10, 3);
function au_auth($user, $username, $password)
{
$options = get_option('au_options');
$endpoint = $options['au_apiurl'];
// Makes sure there is an endpoint set as well as username and password
if (!$endpoint || $user !== null || (empty($username) && empty($password))) {
return false;
}
$auth_args = [
'method' => 'POST',
'headers' => [
'Content-type: application/x-www-form-urlencoded',
],
'sslverify' => false,
'body' => [
'email' => $username,
'password' => $password,
],
];
$response = wp_remote_post($endpoint, $auth_args);
// Token if success; Not used right now
$response_token = json_decode($response['response']['token'], true);
$body = json_decode($response['body'], true);
$response_status_code = $response['response']['code'];
$success = $body !== 'KO';
if (!$success) {
// User does not exist, send back an error message
$user = new WP_Error('denied', __('<strong>Error</strong>: Your username
or password are incorrect.'));
} elseif ($success) {
$idExternal = $body['Id'];
$nome = $body['Name'];
$cognome = $body['Surname'];
$email = $body['Email'];
$userobj = new WP_User();
$user = $userobj->get_data_by('email', $email);
if ($user && $user->ID) {
$user = new WP_User($user->ID);
} else {
$userdata = [
'user_email' => $email,
'user_login' => join(' ', [$name, $surname]),
'user_pass' => '----',
];
$new_user_id = wp_insert_user($userdata);
$new_user_composite_id = 'user_' . $new_user_id;
update_field('field_60084ad3970a8', $idExternal, $new_user_composite_id);
update_field('field_5f22ca201c7b0', $name, $new_user_composite_id);
update_field('field_5f22ccd498f40', $surname, $new_user_composite_id);
update_field('field_5f22ce7b7c1db', $email, $new_user_composite_id);
$user = new WP_User($new_user_id);
}
}
remove_action('authenticate', 'wp_authenticate_username_password', 20);
return $user;
}

How to use a request post data in findOneBy method

I am writing a method to request a password reset in symfony
I get the email of the user from the posted value
$data = $form->getData();
$email = $data['email'];
It seems that I get the good email value and I can verify it by a
dump($email);
that returns
"firstname.name#domain.ext"
Then I try to fetch a user in the database with
$user = $this->getDoctrine()->getRepository(User::class)->findOneBy(["email" => $email]);
but the result is null.
After that I try 2 different ways and both of them work perfectly i.e. give a valid user.
1- I replace
$email = $data['email'];
with
$email = "firstname.name#domain.ext";
2-
I change the line that fetches the user with:
$user = $this->getDoctrine()->getRepository(User::class)->findOneBy(["email" => "firstname.name#domain.ext"]);
Obviously the trouble comes from the way the value is passed to the findOneBy method, not because the user is not in the database.
I would like to know what I should do to use the value I got from the Post ?
Here is my controller
/**
* #Route("/passforgotten", name="app_forgotten_password", methods="GET|POST")
*/
public function askResetPass(
Request $request,
UserPasswordEncoderInterface $encoder,
ManagerRegistry $managerRegistry,
\Swift_Mailer $mailer,
TokenGeneratorInterface $tokenGenerator
): Response {
$defaultData = ['message' => 'Type your message here'];
$form = $this->createFormBuilder($defaultData)
->add('email', EmailType::class)
->add('send', SubmitType::class)
->getForm();
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$data = $form->getData();
$email = $data['email'];
//alternative that works of course with a real email
//$email="firstname.name#domain.ext";
dump($email);
$user = $this->getDoctrine()->getRepository(User::class)->findOneBy(["email" => $email]);
dump($email);
dump($user);
if ($user === null) {
$this->addFlash('danger', 'Email Inconnu, recommence !');
return $this->redirectToRoute('app_register');
}
$token = $tokenGenerator->generateToken();
$manager = $managerRegistry->getManager();
try {
$user->setResetPasswordToken($token);
$manager->flush();
} catch (\Exception $e) {
$this->addFlash('warning', $e->getMessage());
return $this->redirectToRoute('home');
}
//this has not been tested yet
$url = $this->generateUrl('security/ask_reset_password', array('token' => $token), UrlGeneratorInterface::ABSOLUTE_URL);
$message = (new \Swift_Message('Rénitialisation du mot de pass'))
->setFrom(array('symfony#domain.ext'))
->setTo($user->getEmail())
->setBody('hello ask for reset pass!'
);
$mailer->send($message);
$this->addFlash('notice', 'Mail correctement envoyé !');
//this is not finished
return $this->redirectToRoute('a_route');
}
return $this->render('security/ask_reset_password.html.twig', [
'form' => $form->createView()
]);
}
Sorry but I was passing a misspelled email a letter l just before a b was missing and I used the form memorization of it each time. In fact it works in every case.

Drupal 7: How to send HTML Email

Could someone tell me what i am missing to send an HTML email using Drupal's function? Here is my call:
try{
drupal_mail('my_module', 'forgot', $node->field_email_address['und'][0]['value'], language_default(), array('reset_key' => $key),'do-not-reply#myemailaddress.com');
}catch(Exception $e){
print_r($e->getMessage());die();
}
And here is the function:
function my_module_mail($key, &$message, $params) {
$body = '<p>Click the link below to reset your password.</p>
<p>Click this link to reset your password</p>
';
// $headers = array(
// 'MIME-Version' => '1.0',
// 'Content-Type' => 'text/html; charset=UTF-8; format=flowed',
// 'Content-Transfer-Encoding' => '8Bit',
// 'X-Mailer' => 'Drupal'
// );
// $message['headers'] = $headers;
$message['subject'] = 'Why wont this send html??';
$message['headers']['Content-Type'] = 'text/html; charset=UTF-8;';
$message['body'][] = $body;
$message['from'] = 'do-not-reply#myemailaddress.com';
}
I tired just the html header and the full set that is commented out. What am I missing? The email sends fine but it's plain text. Thanks and let me know!
You can use this function
function my_module_custom_drupal_mail($target = NULL, $from = null, $subject, $message, $attachment = NULL){
$my_module = 'my_module';
$my_mail_token = microtime();
$message = array(
'id' => $my_module . '_' . $my_mail_token,
'to' => $target,
'subject' => $subject,
'body' => array($message),
'module' => $my_module,
'key' => $my_mail_token,
'from' => "$from <email#email.com>",
'headers' => array(
'From' => "$from <email#email.com>",
'Sender' => "$from <email#email.com>",
'Return-Path' => "$from <email#email.com>",
'Content-Type' => 'text/html; charset=utf-8'
),
);
if ($attachment) {
$file_content = file_get_contents($attachment[0]);
$message['params']['attachments'][] = array(
'filecontent' => $file_content,
'filename' => $attachment[1],
'filemime' => $attachment[2],
);
}
$system = drupal_mail_system($my_module, $my_mail_token);
$message = $system->format($message);
if ($system->mail($message)) {
return TRUE;
}
else {
return FALSE;
}
}
AND call it like :
$body = '<p>Click the link below to reset your password.</p>
<p>Click this link to reset your password</p>
';
$subject ='Why wont this send html??';
$from = 'myemail#email.com';
$sent = my_module_custom_drupal_mail($node->field_email_address['und'][0]['value'], $from, $subject, $body);
Customize it like you want ! :)
A few things need to be done:
/**
* Class SomeCustomModuleMailSystem Implements MailSystemInterface.
*
* Used to enable HTML email to be sent.
*/
class SomeCustomModuleMailSystem extends DefaultMailSystem {
public function format(array $message) {
$message['body'] = implode("\n\n", $message['body']);
$message['body'] = drupal_wrap_mail($message['body']);
return $message;
}
}
This to be done one time, so probably in a hook_enable or hook_update:
$current = variable_get('mail_system', ['default-system' => 'DefaultMailSystem']);
$addition = ['some_custom_module' => 'SomeCustomModuleMailSystem'];
variable_set('mail_system', array_merge($current, $addition));
Invoke hook_mail as normal, e.g.
/**
* Implements hook_mail().
*/
function some_custom_module_mail($key, &$message, $params) {
switch ($key) {
case 'some_mail_key':
$message['headers']['Content-Type'] = 'text/html; charset=UTF-8;';
$message['subject'] = $params['subject'];
$message['body'][] = $params['body'];
break;
}
}
Finally call it with something like this:
// Set variables required for the email.
$module = 'some_custom_module';
$key = 'some_mail_key';
$to = $email = 'thetoaddress#something.com';
$language = language_default();
$params['subject'] = 'Email subject';
$params['body'] = '<html><body>The HTML!</body></html>';
$from = 'thefromaddress#something.com';
$send = TRUE;
// Send the mail and log the result.
$result = drupal_mail($module, $key, $to, $language, $params, $from, $send);
if ($result['result'] === TRUE) {
watchdog('some_custom_module', 'HTML email successfully sent.', [], WATCHDOG_INFO);
}
else {
watchdog('some_custom_module', 'HTML email failed to send', [], WATCHDOG_ERROR);
}

Prevent EntityManager for one entity but not the other

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.

Functional Testing in Symfony

I am new in testing.I want to test my function.I have successfully installed phpUnit. I check many tutorials on internet.But I could not get the proper information regarding testing. Here is the my function code:
public function loginAction(Request $request)
{
$session = $this->getRequest()->getSession();
if( $session->get('userId') && $session->get('userId') != '' && $session->get('type') == '2')
{
//if user is login then it will be redirect to login page
return $this->redirect($this->generateUrl('registrarGeneral_dashboard'));
}
$em = $this->getDoctrine()->getEntityManager();
$repository = $em->getRepository('DRPAdminBundle:User');
if ($request->getMethod() == 'POST')
{
$session->clear();
$userName = $request->get('username');
$password = md5($request->get('password'));
//find email, password type and status of User
$user = $repository->findOneBy(array('username' => $userName, 'password' => $password,'type'=>2,'status'=>1 ));
$userEmail = $repository->findOneBy(array('email' => $userName, 'password' => $password,'type'=>2,'status'=>1 ));
if ($user)
{
//set session of User login
$session->set('userId', $user->getId());
$session->set('type', 2);
$session->set('nameRegistrar', $user->getFirstName());
$session->set('pictureRegistrar', $user->getPicture());
//echo "<pre>";print_r($session->get('picture'));die;
return $this->redirect($this->generateUrl('registrarGeneral_dashboard'));
}
if ($userEmail)
{
$session->set('type', 2);
$session->set('userId', $userEmail->getId());
$session->set('nameRegistrar', $userEmail->getFirstName());
$session->set('pictureRegistrar', $userEmail->getPicture());
//echo "<pre>";print_r($session->get('picture'));die;
return $this->redirect($this->generateUrl('registrarGeneral_dashboard'));
}
else
{
return $this->render('DRPRegistrarGeneralBundle:Pages:login.html.twig', array('name' => 'Invalid Email/Password'));
}
}
return $this->render('DRPRegistrarGeneralBundle:Pages:login.html.twig');
}
how to test this function? Please help
I don't know what you want to test but here is an exemple of what you can do to test user fonctionnalities :
public function testUserPageDown()
{
$client = static::createClient();
$client->request('GET', '/user/login');
$this->assertTrue($client->getResponse()->isSuccessful());
$client->request('GET', '/user/register');
$this->assertTrue($client->getResponse()->isSuccessful());
}
public function testUserFirewall()
{
$client = static::createClient();
//Trying go to user routes without being logged
$client->request('GET', '/user/profile');
$this->assertTrue($client->getResponse()->isRedirect());
$client->request('GET', '/user/profile/edit');
$this->assertTrue($client->getResponse()->isRedirect());
$client->request('GET', '/user/profile/editpassword');
$this->assertTrue($client->getResponse()->isRedirect());
}
public function testUserFormRegister()
{
$client = static::createClient();
$crawler = $client->request('GET', '/user/register');
$buttonCrawlerNode = $crawler->selectButton('submit_user_register');
$form = $buttonCrawlerNode->form();
$testForm = array(
'wineot_databundle_user[username]' => 'test',
'wineot_databundle_user[firstname]' => 'test',
'wineot_databundle_user[lastname]' => 'test',
'wineot_databundle_user[mail]' => 'test#mail.fr',
'wineot_databundle_user[plain_password][first]' => 'blabla321',
'wineot_databundle_user[plain_password][second]' => 'blabla321'
);
$response = $client->getResponse();
$client->submit($form, $testForm);
//If the submit is true that mean that the register is ok
$this->assertTrue($response->isSuccessful());
}
I hope that will help you do undestand how to test.

Resources