Wordpress - create route to action in plugin - php

I want to create a route in my wordpress plugin that isn't linked to a page but to an action that sends an email. So i would send a get request like this
example.com/send/email?email=test#test.co.uk
and this would link to an action with the email as a parameter. I'm very new to Wordpress so forgive me if this is a stupid question but I'm really struggling to achieve this or evebn find a good starting point, can anyone help?

A good option in your case would be to use a rewrite endpoint. A rewrite endpoint allows you to add extra query parameters to certain URLs. For instance you can add a gallery endpoint to all posts, that could render a different template showing all images for the given post. More information about add_rewrite_endpoint() can be seen in the Codex.
Below is some code that adds a send endpoint to EP_ROOT(the home page of the site). Note that you'll have to go to Settings > Permalinks after adding this code in order for the rewrite endpoint to start working.
Once we have the rewrite endpoint in place, we hook to the template_redirect action in order to check for the presence of the send query var. If send is not present, then we do nothing.
If send is present, but empty(like for instance if you load the page http://example.com/send/), then we redirect to the home page.
Otherwise we split send into multiple parts at every / and assign that to the $send_parts variable. We then use a switch statement to see what the $send_action(the first part after /send/) and act accordingly.
Right now we're only checking for the email action(if it's not email, we redirect to the home page again). We check if there's an actual email($send_parts[1]) and whether it's a valid email(I have to note that is_email() is not RFC compliant and it might reject valid email addresses, so use with caution). If it's a valid email, we use wp_mail() to send the email, otherwise we redirect to the home page.
Now, since I don't know how you're planning to implement this my code doesn't cover things like authentication(who can send emails - if it's everyone, I can abuse your site and spam users and get your mail server blacklisted - bad :( ), generation of the email Subject and Message(is it going to be dynamic via $_POST variables, is it going to be pre-defined, etc.). Those are specifics that you will have to implement on your own.
Once the code below is placed in an appropriate file(a .php file that gets loaded in the current theme, or an active plugin's file) and you regenerate your Rewrite Rules(by going to Settings > Permalinks), you can go to http://example.com/send/email/your.email#example.com/ and you should receive an email with a subject "Hello" and a message "This is a message".
function so_34002145_add_email_endpoint() {
add_rewrite_endpoint( 'send', EP_ROOT );
}
add_action( 'init', 'so_34002145_add_email_endpoint', 10 );
function so_34002145_handle_send_email() {
$send = get_query_var( 'send', null );
// This is not a /send/ URL
if ( is_null( $send ) ) {
return;
}
// We're missing an action, the URL is /send/
// Take the user to the home page, since this is an incomplete request.
if ( empty( $send ) ) {
wp_redirect( home_url( '/' ) );
exit;
}
$send_parts = explode( '/', $send );
$send_action = $send_parts[0];
switch ( $send_action ) {
case 'email':
$email = ! empty( $send_parts[1] ) ? $send_parts[1] : false;
if ( ! $email || ! is_email( $email ) ) {
// A missing or invalid email address, abort
wp_redirect( home_url( '/' ) );
exit;
}
wp_mail( $email, 'Hello', 'This is a message' );
break;
default:
// This is an unknown action, send to the home page
wp_redirect( home_url( '/' ) );
exit;
break;
}
}
add_action( 'template_redirect', 'so_34002145_handle_send_email', 10 );

Related

Wordpress how to send email confirmations on post status change

I have a custom post type called "Booking" in WP travel plugin. I want it to fire an event when i change the status of that custom post type from 'pending' to 'booked'.
The event should send a confirmation email to the user in question.
I tried the following :
function show_alert_msg( $new_status, $old_status, $post ) {
if ( 'Booked' === $new_status && 'pending' !== $old_status && $post->post_type=='Booking' )
{
echo '<script>alert(Show message after transition to booked)</script>' ;
}else{
echo '<script>alert(failed)</script>' ;
}
}
add_action( 'transition_post_status', 'show_alert_msg', 10, 3 );
but whenever i change the status nothing happens.
what i am doing wrong? and how can I approach this correctly so that when the booking status changes from pending to Booked, the confirmation email is sent to the user ?
It's because there are several bugs in your code!
You're using WP travel plugin. This plugin register its custom post type as "itinerary-booking", but in your code, you're checking for a custom post type called "Booking" which doesn't exist, so that condition never returns true!
You could navigate to this path:
"your website folder > wp-content > plugins > wp-travel > inc"
and open up class-post-types.php file on line 126 you see this register_post_type( 'itinerary-booking', $args );
Also, you're using transition_post_status action hook which is used for the checking a post status. The status of pending and booked are custom post meta data and saved into the database under the wp_travel_booking_status name and have nothing to do with the post status itself! Which means it's totally different than what you're trying to do.
So, this filter hook transition_post_status is not responsible to pick up those statuses.
Also, when trying to debug/test your code, specially on transition_post_status and save_post hooks, do NOT use javascript alert, console.log and/or php echo, print_r, var_dump etc. because when you hit those hooks, printing, echoing, alerting won't work. Just use php die function which will stop the app and lets you know that you hit the hook.
Also capitalization matters! Make sure you're using the right capitalization for your values, for example, in this case, everything is lowercase. So keep an eye on that!
Now what can you do about it?
Well, you could change your hook to save_post action hook which means every time that you update your post, it'll fire!
You could change your conditional check to look for itinerary-booking custom post type.
Also you could use get_post_meta function, to check for your status change!
Now putting it all together, you could use the following code:
add_action( 'save_post', 'sending_email_confirmation_to_user');
function sending_email_confirmation_to_user( $post_id )
{
if ( 'itinerary-booking' == get_post_type( $post_id ) ){
$post_status_after_update = get_post_meta( $post_id, 'wp_travel_booking_status', true );
if( 'booked' === $post_status_after_update ){
die("Send your email here!");
} else {
die("your post status is not booked!");
}
}
}
Note:
I used die statement just to give you an example, so make sure to replace die("Send your email here!"); with your custom function that sends out emails!
Status of booked is lowercase, so don't change it to uppercase like the one you tried in your code! Otherwise it won't work!
When your post status is not "booked", you don't have to do anything, i used die("your post status is not booked!"); just to give you an example!
Update
When you use save_post hook, it runs every time you update your custom post data, BUT you do NOT want to send an email every single time. Right?
When you change the status from 'pending' to 'booked' you could save a meta data in the database so that you know you've already sent an email confirmation and you don't want to send another email. You could do that using update_post_meta function.
add_action( 'save_post', 'sending_email_confirmation_to_user');
function sending_email_confirmation_to_user( $post_id )
{
if ( 'itinerary-booking' == get_post_type( $post_id ) ){
$post_email_status = get_post_meta( $post_id, 'custom_confirmation_email', true );
$post_status_after_update = get_post_meta( $post_id, 'wp_travel_booking_status', true );
if( 'booked' === $post_status_after_update && empty( $post_email_status )){
$email_sent = update_post_meta( $post_id, 'custom_confirmation_email', 'sent-at-'. date( 'M_d_Y-H_i_s' ) );
die("Send your email here!");
}
}
}
Note:
This will make sure that you only send your email confirmation once!
If the email confirmation data is empty in the database, it'll send the email and update the value in the database and won't send extra emails.
Also, I've stored a meta data in your database called custom_confirmation_email and used 'sent-at-'. date('M_d_Y-H_i_s') as its value which looks like this: sent-at-Oct_01_2021-17_42_42 which is the date and time when the status changed from 'pending' to 'booked' for the first time.
All of the snippets and explanations have been fully tested and work!

How to whitelist the order-received page in wordpress using the force-login plugin

I am using the plugin force login: https://en-gb.wordpress.org/plugins/wp-force-login/ and need to allow guests to get to the order received page after purchasing.
After checking out, a user which is logged in would be forwarded to this page: [mydomain]/checkout/order-received/[order_id]/?key=[order_key]. I have tried this: Show customer details on WooCommerce Thankyou page even if not registered but could not figure out what to do after I added it.
I currently have this code which allows certain pages to be whitelisted so users that are not logged in can bypass the "force-login" plugin and pay for the relevant product:
add_filter('v_forcelogin_whitelist', 'my_forcelogin_whitelist', 10, 1);
function my_forcelogin_whitelist() {
return array(
home_url( '/cart/' ),
home_url( '/checkout/' ),
home_url( '/cart/?add-to-cart=1465' ),
);
}
I want none logged in users to be forwarded to a page which looks like this after checkout:
[mydomain]/checkout/order-received/5304/?key=wc_order_5cffcfbc96028
For anyone that has this problem this is how I got it working. Since some of the URL's generated are dynamic I needed a work around for those. Using the following code in function.php works for ALL URL's assiciated with woocommerce:
function my_forcelogin_bypass( $bypass ) {
if ( class_exists( 'WooCommerce' ) ) {
if ( is_woocommerce() || is_wc_endpoint_url() ) {
$bypass = true;
}
}
return $bypass;
}
add_filter( 'v_forcelogin_bypass', 'my_forcelogin_bypass' );
WooCommerce Checkout/order-received issue
For the problem of [mydomain]/checkout/order-received/[order_id]/?key=[order_key] it is not loading right or is not showing something or 500 Internal Server Error ?
For Temporary purpose because whenever the plugin will be updated the file will be updated in a woo-commerce plugin?
Open File Zilla
The Visit : /var/www/html/wp-content/plugins/woocommerce/includes directory
Then in the directory open : class-wc-order.php
Find this with ctrl+F : get_checkout_order_received_url()
There Will be two lines of code(Earlier) :
$order_received_url = wc_get_endpoint_url( 'order-received', $this->get_id(), wc_get_checkout_url() );
$order_received_url = add_query_arg( 'key', $this->get_order_key(), $order_received_url );
Change to(Updated) Add a comment in the second line :
$order_received_url = wc_get_endpoint_url( 'order-received', $this->get_id(), wc_get_checkout_url() );
//$order_received_url = add_query_arg( 'key', $this->get_order_key(), $order_received_url );
Save it and update it to the server.
You issue will be resolved, but it's for temporary it will be changes whenever the woocommerce plugin will be updated, so you have to update it again.
Thanks!

Woocommerce: Redirect after lost password submitted

I try to redirect my users to a custom page after successfully submitting the lost password form. By default, users are redirected to the "my-account" page.
The method responsible for doing this redirect is called process_lost_password() and is located in plugins/woocommerce/includes/class-wc-form-handler.php and looks like follows:
/**
* Handle lost password form.
*/
public static function process_lost_password() {
if ( isset( $_POST['wc_reset_password'] ) && isset( $_POST['user_login'] ) && isset( $_POST['_wpnonce'] ) && wp_verify_nonce( $_POST['_wpnonce'], 'lost_password' ) ) {
$success = WC_Shortcode_My_Account::retrieve_password();
// If successful, redirect to my account with query arg set.
if ( $success ) {
wp_redirect( add_query_arg( 'reset-link-sent', 'true', wc_get_account_endpoint_url( 'lost-password' ) ) );
exit;
}
}
}
Unfortunately, this method does not offer any action to hook into.
Is there a way to override this method or change the redirect link in any other way?
Since process_lost_password() is run as an 'wp_load' action
add_action( 'wp_loaded', array( __CLASS__, 'process_lost_password' ), 20 );
You simply need to add your own action with a higher priority
add_action( 'wp_loaded', 'your_handler', 19 );
I RESOLVED the issue by going under
WooCommerce
Emails****
Place your email in the box all the way to the bottom where it states From address because I am the administrator and Remove the admin email address.
I did a couple of dummy accounts and it work fine now all passwords work very well.
I created a page added the end points to /lost-password/ for my permalinks. Checked the custom header and checked the title boxes towards the middle of page and Published the page. That fixed the issue for me.

Email validation with Ultimate Member Plugin

I need help modifying the code below. I'm using the Ultimate Member plugin on my Wordpress site for membership. I only want those people within my organization to be able to register for the site (my departments use different domains for their email addresses, it's a headache and I don't want to get into that). Right now, it will automatically validate emails from #company1.com, but I need to add up to 10 more email addresses to that code to perform automatic validation. Basically, anyone that doesn't have an email address listed, is automatically denied membership to the site.
add_action('um_before_new_user_register', 'require_google_email_for_signup');
function require_google_email_for_signup( $args ) {
extract($args);
if ( !strstr( $user_email, '#company1.com' ) )
exit( wp_redirect( add_query_arg('err', 'you_must_have_googlemail') ) );
}
"um_before_new_user_register" has been removed from the 2.x version. You can use the below working code for complete form validation not just a single field.
add_action('um_submit_form_errors_hook_','um_custom_validate_form', 999, 1);
function um_custom_validate_form( $args ) {
global $ultimatemember;
$user_email = $args['user_email'];
if ( !strstr( $user_email, '#domain1.com' )){
$ultimatemember->classes['form']->add_error( 'user_email', 'You must register with a valid email address.' );
}
}
strstr() is more memory intensive compared to strpos(), so I will recommend using the latter. When dealing with an array, you can use the following iterative logic:
Set a variable, say $check, to false
Iterate through each allowed domain in a for loop
Whenever a match is found (by using strpos()), we set $check to true and break out of the loop. This ensures that we do not traverse the entire array when a match is already found
Evaluate $check, and decide whether to throw an error / exit
Hint: I would recommend converting your user-email to lowercase when using strpos (or you can use stripos()), because some users may enter emails that are of mixed cases.
With that in mind, here is an example:
<?php
add_action('um_before_new_user_register', 'require_google_email_for_signup');
function require_google_email_for_signup( $args ) {
extract($args);
// Store allowed domains in an array
$allowed_domains = ['#company1.com', '#company2.com', '#company3.com'];
// Set flag to false (fail-safe)
$check = false;
// Iterate through all allowed domains
foreach( $allowed_domains as $domain ) {
// If a match is found (remember to use lowercase emails!)
// Update flag and break out of for loop
if ( strpos( strtolower( $user_email ), $domain ) !== false ) {
$check = true;
break;
}
}
if ( !$check )
exit( wp_redirect( add_query_arg('err', 'you_must_have_googlemail') ) );
}
Use this code:
<?php
add_action('um_before_new_user_register', 'require_google_email_for_signup');
function require_google_email_for_signup( $args ) {
extract($args);
/* add multiple domains name here */
$allow_domains = ['company1.com', 'company2.com', 'company3.com'];
/* get domain name from user email */
$domain_name = substr(strrchr($user_email, "#"), 1);
if (!in_array($domain_name, $allow_domains)){
exit( wp_redirect( add_query_arg('err', 'you_must_have_googlemail') ) );
}
}
?>
This custom code no longer works in the latest version 2 update to ultimate member. The hook was removed, so it’s no longer possible to do email address blocking with this code. Does anyone have any suggestions on how to get this to work again? Here is the code I'm using:
/* ULTIMATE MEMBER PLUGIN DOMAIN WHITELISTING CODE SNIPPET
enter code here`The following code will require a domain name to be
whitelisted for user `enter code here`registrations.
It forces a user email to match one included in this code at registration.
You can add any provider you want by copying and pasting a new line as per
instructions.*/
add_action('um_before_new_user_register', 'force_google_email_for_avnw_signup');
function force_google_email_for_avnw_signup( $args ) {
extract($args);
if ( !strstr( $user_email, '#anydomain.com' ) )
exit( wp_redirect( add_query_arg('err', 'whitelisted_email_required') ) );
}

Redirect after profile update, language specific

The profile-update URLs for User Profiles are language specific: .../nl/profile.php and .../en/profile.php. When users click "Update Profile" I can redirect them to any URL. But now I want to test the current URL to see if there's /nl/ in there, so I can give them a redirect to their own language. I use the code below but the result of the 'if statement' is always false. I can see that: when I enter another url there, it picks up that one. So the code seems to work, just the test fails. Any ideas what I'm doing wrong?
add_action( 'profile_update', 'custom_profile_redirect', 12 );
function custom_profile_redirect() {
if(strpos("//{$_SERVER['HTTP_HOST']}{$_SERVER['REQUEST_URI']}", '/nl/') === false ) {
wp_redirect( trailingslashit( home_url() . '/en' ) );
} else {
wp_redirect( trailingslashit( home_url() . '/nl' ) );
}
exit;
}
[edit:] Variables I managed to retrieve are all set to 'en' after the profile update, even the plugin's global variable. I now worked around it by adding a LanguagePreference dropdown in the sign up form. In the After-Update-Redirect, I read the usermeta and redirect to their own preference.
There must be better ways to achieve this...

Categories