When registering user, I am hooking into user_register hook to send some call to the external API.
add_action( 'user_register', 'create_user_on_api' );
inside the create_user_on_api function I am making the call (nonces are there, and tons of security checks, but I'm omitting those for brevity) using wp_remote_post()
function create_user_on_api( $user_id ) {
$user_create_response = wp_remote_post( "someurlgoeshere.api", $curl_args );
if ( is_wp_error( $user_create_response ) ) {
throw new Exception( 'wp error' );
} else {
$code = wp_remote_retrieve_response_code( $user_create_response );
$msg = wp_remote_retrieve_response_message( $user_create_response );
$body = wp_remote_retrieve_body( $user_create_response );
if ( $code !== 200 ) {
throw new Exceprion( 'error' );
}
}
}
This is the gist of it.
The problem is following: using any error handles causes white screen of death, error is logged in my debug.log, and I would like to throw a notice on my admin dashboard that, even though api call failed, the user is created in WP, and you'll have to create it manually on the API or try again.
I tried echoing stuff, custom exception handling mentioned here, but so far no luck.
Any idea how to do that? Can I hook into admin notices in any way?
Ok, found a solution. A hacky one but it works.
On api error I am storing a error message in a transient, which has an expiry of 60 seconds and I created a user_notices function that I hook on admin_notices hook. In it I check two things: if I'm on users screen
$current_screen = get_current_screen();
if ( $current_screen->id === 'users' ) {
}
And then inside this I check if the transients are empty, and then assign them to the $error_message array, which I output in a foreach (in case I have multiple error messages)
if ( ! empty( $error_msg_array ) ) {
foreach ( $error_msg_array as $error_msg_key => $error_msg ) {
?>
<div class="error notice">
<p><?php printf( '<strong>Apigee error:</strong> %s', esc_html( $error_msg ) ); ?></p>
</div>
<?php
}
}
And this seems to be working.
Related
I run an e-commerce site and need to change my checkout error messages.
Recently I have had a customer say that they made a mistake entering their credit card's expiration date, but they were confused because the error message displayed by woocommerce says "Your card's security code is incorrect." This led them to double and triple check the security code instead of the expiration date which was the real problem.
I would like to find a solution that allows me to change that error message to say, "Your card's security code or expiration date is incorrect."
I would also be okay with a solution that allows me to input a single generic error message such as, "Some information is incorrect or missing." that would be used for all payment info errors.
Somebody please help me.
I have tried implementing the following solutions from other forums into my functions.php file with no luck:
Attempt 1:
function ShowOneError( $fields, $errors ){
// if their is any validation errors
if( !empty( $errors->get_error_codes() ) ) {
// remove all of Error msg
foreach( $errors->get_error_codes() as $code ) {
$errors->remove( $code );
}
// our custom Error msg
$errors->add('validation','There is an error in filed data.');
}
}
add_action('woocommerce_after_checkout_validation','ShowOneError',999,2);
Attempt 2:
// alter the subscriptions error
function my_woocommerce_add_error( $error ) {
if( 'The generic error message' == $error ) {
$error = 'The shiny brand new error message';
}
return $error;
}
add_filter( 'woocommerce_add_error', 'my_woocommerce_add_error' );
Attempt 3:
add_action( 'woocommerce_after_checkout_validation', 'quadlayers', 9999, 2);
function quadlayers( $fields, $errors ){
// in case any validation errors
if( !empty( $errors->get_error_codes() ) ) {
// omit all existing error messages
foreach( $errors->get_error_codes() as $code ) {
$errors->remove( $code );
}
// display custom single error message
$errors->add( 'validation', 'Your Custom Message Goes Here!!!' );
}
}
When publishing a new post in WordPress I want to show an extra admin_notice to show a custom message. I'm using the admin_notices hooks for this. I tested this and it works. What doesn't work is to show it when the post is published.
I tried a couple of methods including the ' publish_post' hook. The hook is firing, when I put a var_dump('bla');exit(); I can see this working. I think the reason the admin_notices doesn't show is because the page is refreshing. So if there would be something like 'after_publish_post' that'd be great but I cannot find it.
I also tried something I've found in a similar question:
if( ( $_POST['post_status'] == 'publish' ) && ( $_POST['original_post_status'] != 'publish' ) ) { echo "New post!"; exit();}
This also has no effect
--
What I have at this moment is:
add_action('publish_post', array($this,'onInsertPost')); //does work, function gets triggered
public function onInsertPost($post_id, $post, $update) {
add_action( 'admin_notices', array($this, 'info_text_news') );
}
public function info_text_news() {
$class = 'notice notice-info';
$message = __( 'My message', 'admin_notice' );
printf( '<div class="%1$s"><p>%2$s</p></div>', esc_attr( $class ), $message);
}
Like I earlier said, all this code is working but togheter the notice is not showing up. I think because of the refreshing page after pressing the publish button.
I've found a solution to do this. I'm checking the post date and comparing it to the date of today. If the post is posted today it triggers the hook. In my case, one day is fine. If you need to only show it after post you can adjust it to checking the time also.
global $pagenow;
if ( $pagenow == 'post.php' ) {
$currentPost = get_post( $_GET['post'] );
$postdate = substr($currentPost->post_date, 0 , 10);
//if post type is post and post is published today show info message
if($currentPost->post_type == 'post' && $postdate == date('Y-m-d')) {
add_action( 'admin_notices', array($this, 'info_text_news') );
}
}
I am trying to create a "Product Redeem Page as shown in this tutorial on SitePoint.
Problem is that the product does indeed gets added to the cart and you can proceed to the checkout, but the discount that is associated with the coupon code is not automagically applied. In the coupon code I created the value is set to 100% discount.
You could apply te coupon code again via the "Do you have a coupon code" fly out on the checkout page, but this defeats the whole purpose.
I also did not get this code working to begin with, but I was able to figure out that:
// Check coupon to make determine if its valid or not
if( ! $coupon->id && ! isset( $coupon->id ) ) {
...Rest of code here...
should be:
// Check coupon to make determine if its valid or not
if( ! $coupon->id && ! isset( $coupon_id ) ) {
Please note the second Not isset variable name. Maybe this does work, but is not the proper way of handling things, everybody knows, but me.
Sadly I am out of my comfort zone a.t.m., but I am willing to learn by making mistakes and figuring out how to fix them and learn from people who are way smarter then me and/or way more advanced. In my direct cirlce of friends I have no one that I could aks and get any other answer then: "Huh?!?", so I am giving it a shot here on Stackoverflow.
A link to the tutorial on SitePoint only is probably not appreciated, so here is the complete code I am using:
The Ajax handlers added in functions.php
add_action( 'wp_ajax_spyr_coupon_redeem_handler', 'spyr_coupon_redeem_handler' );
add_action( 'wp_ajax_nopriv_spyr_coupon_redeem_handler', 'spyr_coupon_redeem_handler' );
The coupon login also added to functions.php
function spyr_coupon_redeem_handler() {
// Get the value of the coupon code
$code = $_REQUEST['coupon_code'];
// Check coupon code to make sure is not empty
if( empty( $code ) || !isset( $code ) ) {
// Build our response
$response = array(
'result' => 'error',
'message' => 'Code text field can not be empty.'
);
header( 'Content-Type: application/json' );
echo json_encode( $response );
// Always exit when doing ajax
exit();
}
// Create an instance of WC_Coupon with our code
$coupon = new WC_Coupon( $code );
// Check coupon to make determine if its valid or not
if( ! $coupon->id && ! isset( $coupon_id ) ) {
// Build our response
$response = array(
'result' => 'error',
'message' => 'Invalid code entered. Please try again.'
);
header( 'Content-Type: application/json' );
echo json_encode( $response );
// Always exit when doing ajax
exit();
} else {
// Attempting to add the coupon code as a discount.
WC()->cart->add_discount( $code );
// Coupon must be valid so we must
// populate the cart with the attached products
foreach( $coupon->product_ids as $prod_id ) {
WC()->cart->add_to_cart( $prod_id );
}
// Build our response
$response = array(
'result' => 'success',
'href' => WC()->cart->get_cart_url()
);
header( 'Content-Type: application/json' );
echo json_encode( $response );
// Always exit when doing ajax
exit();
}
}
The jQuery form submission code, enqueued via the registered Ajax handlers in functions.php
jQuery( document ).ready( function() {
jQuery( '#ajax-coupon-redeem input[type="submit"]').click( function( ev ) {
// Get the coupon code
var code = jQuery( 'input#coupon').val();
// We are going to send this for processing
data = {
action: 'spyr_coupon_redeem_handler',
coupon_code: code
}
// Send it over to WordPress.
jQuery.post( woocommerce_params.ajax_url, data, function( returned_data ) {
if( returned_data.result == 'error' ) {
jQuery( 'p.result' ).html( returned_data.message );
} else {
// Hijack the browser and redirect user to cart page
window.location.href = returned_data.href;
}
})
// Prevent the form from submitting
ev.preventDefault();
});
});
Thanks in advance of pointing me in the right direction.
Update: At this moment I got the wanted functionality working.
What needed to be done is to add:
// Let's add the discount to the cart.
global $woocommerce;
WC()->cart->add_discount( $code );
inside the foreach statement. The complete else statement now looks like this:
} else {
// Coupon must be valid so we must
// populate the cart with the attached products
foreach( $coupon->product_ids as $prod_id ) {
WC()->cart->add_to_cart( $prod_id );
// Let's add the discount to the cart.
global $woocommerce;
WC()->cart->add_discount( $code );
}
// Build our response
$response = array(
'result' => 'success',
'href' => WC()->cart->get_cart_url()
);
header( 'Content-Type: application/json' );
echo json_encode( $response );
// Always exit when doing ajax
exit();
I'm still not sure if this is the correct way of handeling this, but it seems to work.
For instance I am calling(?!) the global $woocommerce variable, but below I am using the global(?!) class WC() to add the coupon. Not sure if this is as clean and logical as it gets.
If anybody knows of a better/cleaner way, please let me know! I am happy to learn from you guys and maybe one day I may be able to return the favour, who knows.
I am working on a WordPress plugin which adds an auth code to the login form.
This is the process of checking if the auth code is valid:
add_action( 'wp_authenticate', 'authcode_check', 5 );
function authcode_check($username) {
$options = get_option( 'authcode_settings' );
if(!empty($options['code'])) {
global $wpdb;
if ( !username_exists( $username ) ) {
return;
}
$set_code = $options['code'];
$submit_code = $_POST['auth_key'];
if(empty($submit_code)) {
add_filter( 'login_errors', function( $error ) {$error = '<strong>ERROR</strong>: Authentication code cannot be empty.';return $error;} );
return;
} elseif ( ! ( $set_code == $submit_code ) ) {
add_filter( 'login_errors', function( $error ) {$error = '<strong>ERROR</strong>: Authentication code is invalid.';return $error;} );
return;
}
}
}
The problem is; when the user enters their WordPress name and password correctly, but not the auth code, the form still submits and log the user in.
I tried return false but that didn't work.
Is there any way to prevent the form from logging the user in when they have entered a wrong auth code?
Working Example
Updated after chat with #J.Doe
We can hook into the login_form hook, to display the input for the authentication code:
/**
* 'Authentication Code' Input
*/
add_action( 'login_form', function()
{
// Fetch the stored code
$options = get_option( 'authcode_settings' );
// Display code input
if( isset( $options['code'] ) )
printf(
'<p class="login-authenticate">
<label for="auth_key">%s</label>
<input type="text" name="so38551606_auth_key" id="so38551606_auth_key"
class="input" value="" size="20" autocomplete="off" />
</p>',
esc_html__( 'Authentication Code', 'mydomain' )
);
} );
You can hook into the authenticate filter, within the wp_authenticate() function, for the validating part:
/**
* Validate 'Authentication Code' Input
*/
add_filter( 'authenticate', function( $user )
{
// Fetch stored code value
$options = get_option( 'authcode_settings' );
// Nothing to do if there's no stored code value
if( ! isset( $options['code'] ) )
return $user;
// Fetch the user's code input
$submit_code = isset( $_POST['so38551606_auth_key'] )
? $_POST['so38551606_auth_key']
: null;
// Validation's logic
$is_valid_auth_code = ! is_null( $submit_code )
&& ( $options['code'] === $submit_code );
// Valid auth code
if( $is_valid_auth_code )
return $user;
// Add an unvalid auth code error
if( is_wp_error( $user ) )
$user->add(
'invalid_auth_code',
sprintf(
'<strong>%s</strong>: %s',
esc_html__( 'ERROR', 'mydomain' ),
esc_html__( 'Authentication code is invalid.', 'mydomain' )
)
);
// Create a new auth code error
else
$user = new WP_Error(
'invalid_auth_code',
sprintf(
'<strong>%s</strong>: %s',
esc_html__( 'ERROR', 'mydomain' ),
esc_html__( 'Authentication code is invalid.', 'mydomain' )
)
);
return $user;
}, 100 );
Here we use a priority of 100 because we want to run it after the default callbacks of:
add_filter( 'authenticate', 'wp_authenticate_username_password', 20, 3 );
add_filter( 'authenticate', 'wp_authenticate_email_password', 20, 3 );
add_filter( 'authenticate', 'wp_authenticate_spam_check', 99 );
We prefixed the POST variable with so38551606_ to avoid possible name collision.
Output example:
Instead of return false use return as apparently WordPress prefers it that way, look at the existing username code it just returns, not false, not true, just return
Also place the add filter functions before the return statements as a return signifies that the code stops running at that point, nothing below it is executed anymore, so your filters won't appear unless you move them
Can you prove the user isn't being logged in? Or are you just assuming they are being logged in because the error messages aren't being shown?
Anything after the return keyword won't be run. So in your if statements, you have two return false;s if the auth key doesn't match and then you are calling a function afterwards. This function won't be run so the error code won't be displayed.
What you can do however, is move the function above the return keyword. It will then display the error and return false.
We have a complicated weird system where we need to check if the wordpress administrator has logged in and by logged in i dont just mean the session but initial second when the query is sent to validate the credentials entered. I was thinking doing traditional php where I do something like the following:
if(isset($_POST['submit']) { // do something }
But that would be the incorrect way. Where exactly would i look to see this peice , i believe its wp-login.php but wasnt able to find what i was looking for.
thanks
try
global $current_user;
$user = get_userdata($current_user->ID);
$userRole = (!empty($user->roles) ? $user->roles : '');
if(in_array('administrator', $userRole)) {
// do your stuff
}
or you can try :- http://codex.wordpress.org/Function_Reference/current_user_can
You can use very neat Wordpress function to determine the user capabilities, it is called current_user_can():
<?php
if ( current_user_can('update_core') ) {
echo 'The current user is Administrator or Super administrator (in Multisite)';
}
Only Administrators of single site installations have the below list of capabilities. In Multi-site, only the Super Admin has these abilities:
update_core
update_plugins
update_themes
install_plugins
install_themes
delete_themes
edit_plugins
edit_themes
edit_users
create_users
delete_users
unfiltered_html
See here for more information.
We can add some custom action inside the filter hook login_redirect. If the form was not submitted, the $user param is a WP_Error Object.
add_filter( 'login_redirect', function( $redirect_to, $requested_redirect_to, $user )
{
if( !is_wp_error( $user ) && in_array( 'administrator', $user->roles ) )
{
# Do your thing; here just inspecting the WP_User Object
wp_die(
sprintf( '<pre>%s</pre>', print_r( $user, true ) ),
'Var dump',
array(
'response' => 500,
'back_link' => true
)
);
}
return $redirect_to;
}, 10, 3 );