I have a forum developed with CodeIgniter. And I have my website, powered by Wordpress.
Basically what I'm looking to do is when a user registers on the forums, it adds those details to the Wordpress user table, so they're registered on both.
My code for the forum...
/**
* Create new user record
*
* #param array
* #param bool
* #return array
*/
// username email password last_ip key
function create_user($data)
{
$sql = "INSERT INTO users (username,
email,
password,
last_ip,
created,
activated
) VALUES (
?, ?, ?, ?, ?, ?
)";
$this->db->query($sql, array(
$data['username'],
$data['email'],
$data['password'],
$data['last_ip'],
date("Y-m-d H:i:s", utc_time()),
$data['activated']
));
if ($user_id = $this->db->insert_id()) {
$this->create_profile($user_id);
return TRUE;
}
return FALSE;
}
function activate_user($username)
{
$this->db->query("UPDATE users SET activated = 1 WHERE username = ?", $username);
return $this->db->affected_rows();
}
and the Wordpress register class...
/**
* Handles registering a new user.
*
* #param string $user_login User's username for logging in
* #param string $user_email User's email address to send password and add
* #return int|WP_Error Either user's ID or error on failure.
*/
function register_new_user( $user_login, $user_email ) {
$errors = new WP_Error();
$sanitized_user_login = sanitize_user( $user_login );
$user_email = apply_filters( 'user_registration_email', $user_email );
// Check the username
if ( $sanitized_user_login == '' ) {
$errors->add( 'empty_username', __( '<strong>ERROR</strong>: Please enter a username.' ) );
} elseif ( ! validate_username( $user_login ) ) {
$errors->add( 'invalid_username', __( '<strong>ERROR</strong>: This username is invalid because it uses illegal characters. Please enter a valid username.' ) );
$sanitized_user_login = '';
} elseif ( username_exists( $sanitized_user_login ) ) {
$errors->add( 'username_exists', __( '<strong>ERROR</strong>: This username is already registered, please choose another one.' ) );
}
// Check the e-mail address
if ( $user_email == '' ) {
$errors->add( 'empty_email', __( '<strong>ERROR</strong>: Please type your e-mail address.' ) );
} elseif ( ! is_email( $user_email ) ) {
$errors->add( 'invalid_email', __( '<strong>ERROR</strong>: The email address isn’t correct.' ) );
$user_email = '';
} elseif ( email_exists( $user_email ) ) {
$errors->add( 'email_exists', __( '<strong>ERROR</strong>: This email is already registered, please choose another one.' ) );
}
do_action( 'register_post', $sanitized_user_login, $user_email, $errors );
$errors = apply_filters( 'registration_errors', $errors, $sanitized_user_login, $user_email );
if ( $errors->get_error_code() )
return $errors;
$user_pass = wp_generate_password( 12, false);
$user_id = wp_create_user( $sanitized_user_login, $user_pass, $user_email );
if ( ! $user_id ) {
$errors->add( 'registerfail', sprintf( __( '<strong>ERROR</strong>: Couldn’t register you... please contact the webmaster !' ), get_option( 'admin_email' ) ) );
return $errors;
}
update_user_option( $user_id, 'default_password_nag', true, true ); //Set up the Password change nag.
wp_new_user_notification( $user_id, $user_pass );
return $user_id;
}
I don't need all the extra bumph of the Wordpress class, I'm just looking for a barebones forum values addition to the Wordpress user table.
Any help?
Two database configs will be required in your codeigniter config file:
$db['wordpress']
$db['default'] //priority
To use the wordpress DB assign it a var in your main controller.
$this->wordpress_db = $this->load->database('wordpress', TRUE);
//Normal query
$this->db->query();
//wordpress Query
$this->wordpress_db->query();
The rest should become obvious
Related
How can I automatically assign a new email to a user in WordPress AND restrict any further update after the first login ?
For example setting the email to the following structure:
{user_id}#example.com
I've tried a few things but couldn't figure it out, any help is appreciated.
I wrote this code, but only users whose email has been registered, their email has been edited, other people who have not registered email, no email has been registered for them. How do I solve this?
my code:
add_action ('admin_head','set_auto_mail');
function set_auto_mail() {
$users = get_users(array('fields'=>'all'));
foreach($users as $user){
$user = get_userdata($user->ID);
if ( in_array( 'subscriber', (array) $user->roles ) ) {
$mail = ($user->ID)."#example.com";
if($mail!=' ') wp_update_user( array ('ID' => $user->ID, 'user_email' => $mail) );
else wp_update_user( array ('ID' => $user->ID, 'user_email' => $user->user_email) );
if($user->user_email == '')
wp_update_user( array ('ID' => $user->ID, 'user_email' => $user->user_email) );
}
}
}
This should do exactly what you wanted.
We set a new user meta data called is_new_user which we will use later on to detect if this is the first ever login for a specific user.
We set a hook to update the user_email on first time login and we update is_new_user to specify that this isn't a new user anymore. Like that we prevent permanent update on login.
Then we fire up the necessary functions to disable email updates. Visually and from the backend for all non-new users.
I'm using first_name, las_name and ID for the email structure. Output:
$first_name.$last_name$ID#bogus.com
<?php
/**
* Adds meta data is_new_user to a user, which let us detect new users on first login.
*
* Fires immediately after a new user is registered.
*
* #link https://developer.wordpress.org/reference/hooks/wp_login/
*/
add_action( 'user_register', 'wpso66983605_add_user_meta_is_new_user' );
function wpso66983605_add_user_meta_is_new_user( $user_id ) {
add_user_meta( $user_id, 'is_new_user', 1, true );
};
/**
* Update user email on first login.
*
* Fires after the user has successfully logged in.
*
* #link https://developer.wordpress.org/reference/hooks/wp_login/
*/
add_action( 'wp_login', 'wpso66983605_set_user_email_on_first_login', 10, 2 );
function wpso66983605_set_user_email_on_first_login( $user_login, $user ) {
if ( ! get_user_meta( $user->ID, 'is_new_user', true ) ) {
return;
};
if ( get_user_meta( $user->ID, 'is_new_user', true ) ) {
update_user_meta( $user->ID, 'is_new_user', 0, 1 );
$userdata = array (
'ID' => $user->ID,
'user_email' => sanitize_email( sanitize_title_with_dashes( $user->first_name . '.' . $user->last_name . $user->ID) . '#bogus.com' ),
);
wp_update_user( $userdata );
};
};
/**
* Prevent users from changing their email address
*
* Modified to ONLY fire when a user is considered as non-new user (user has already made at least 1 login).
*
* #link https://wordpress.stackexchange.com/a/363376/190376
*/
if ( ! class_exists( 'DisableMailChange' ) ) {
class DisableMailChange {
public function __construct() {
add_action( 'personal_options_update', array( $this, 'disable_mail_change_BACKEND' ), 5 );
add_action( 'show_user_profile', array( $this, 'disable_mail_change_HTML' ) );
}
public function disable_mail_change_BACKEND( $user_id ) {
if ( ! get_user_meta( get_current_user_id(), 'is_new_user', true ) ) {
if ( ! current_user_can( 'manage_options' ) ) {
$user = get_user_by( 'id', $user_id );
$_POST['email'] = $user->user_email;
};
};
}
public function disable_mail_change_HTML( $user ) {
if ( ! get_user_meta( get_current_user_id(), 'is_new_user', true ) ) {
if ( ! current_user_can( 'manage_options' ) ) {
echo '<script>document.getElementById("email").setAttribute("disabled","disabled");</script>';
};
};
}
};
new DisableMailChange();
};
I'm trying to override the authenticate to edit the default error message.
/**
Purposed: Custom Login Error Message
Description: This function override the default error message on login form.
**/
remove_filter( 'authenticate', 'wp_authenticate_username_password' );
add_filter( 'authenticate', 'custom_authenticate_username_password', 30, 3 );
/**
* Remove Wordpress filer and write our own with changed error text.
*/
function custom_authenticate_username_password( $user, $username, $password ) {
if ( is_a($user, 'WP_User') )
return $user;
if ( empty( $username ) || empty( $password ) ) {
if ( is_wp_error( $user ) )
return $user;
$error = new WP_Error();
if ( empty( $username ) )
$error->add('empty_email', __('The username or email field is empty.'));
if ( empty( $password ) )
$error->add('empty_password', __( 'The password field is empty' ));
return $error;
}
$user = get_user_by( 'login', $username );
if ( !$user )
return new WP_Error( 'invalid_username', sprintf( __( 'Invalid username or email address.' ), wp_lostpassword_url() ) );
$user = apply_filters( 'wp_authenticate_user', $user, $password );
if ( is_wp_error( $user ) )
return $user;
if ( ! wp_check_password( $password, $user->user_pass, $user->ID ) )
return new WP_Error( 'incorrect_password', sprintf( __( 'The password you\'ve entered is incorrect.' ),
$username, wp_lostpassword_url() ) );
return $user;
}
Unfortunately, the empty username or password error is not overriding.
The default error message for username and password are;
<strong>Error</strong> : The username field is empty.
<strong>Error</strong> : The password field is empty.
I would like to change it to;
The username or email field is empty.
The password field is empty.
However, the invalid_username and incorrect_password are working and I successfully override it.
You have an or statement and an individual statement, it's only going to return one. Try changing it around a little:
Updated
Regardless of how you would like to structure your code, I added the $error->get_error_messages(); at the end of the error. For more more information, you can have a look at this information: https://code.tutsplus.com/tutorials/wordpress-error-handling-with-wp_error-class-i--cms-21120
if ( empty( $username ) || empty( $password ) ) {
$error = new WP_Error();
if ( empty( $username ) || empty( $password ) ) {
if ( empty( $username ) ) {
$error->add( 'empty_email', __( 'The username or email field is empty.' ) );
}
if (empty( $password ) ) {
$error->add( 'empty_password', __( 'The password field is empty' ) );
}
}
return $error->get_error_messages();
} elseif ( is_wp_error( $user ) ) {
return $user->get_error_message();
}
The following code is the reason why it doesn't overriding.
if ( empty( $username ) || empty( $password ) ) {
if ( is_wp_error( $user ) )
return $user;
...
Try to remove this condition.
if (is_wp_error( $user ) )
return $user;
It should be something like this.
/**
Purposed: Custom Login Error Message
Description: This function override the default error message on login form.
**/
remove_filter( 'authenticate', 'wp_authenticate_username_password' );
add_filter( 'authenticate', 'custom_authenticate_username_password', 30, 3 );
/**
* Remove Wordpress filer and write our own with changed error text.
*/
function custom_authenticate_username_password( $user, $username, $password ) {
if (is_a($user, 'WP_User')){
return $user;
}
if (empty($username) || empty($password)) {
$error = new WP_Error();
if (empty($username )){
$error->add('empty_email', __('The username or email field is empty.'));
}
if (empty($password)){
$error->add('empty_password', __( 'The password field is empty' ));
}
return $error;
}
$user = get_user_by( 'login', $username );
if (!$user){
return new WP_Error( 'invalid_username', sprintf( __( 'Invalid username or email address.' ), wp_lostpassword_url()));
}
$user = apply_filters( 'wp_authenticate_user', $user, $password );
if (is_wp_error($user)){
return $user;
}
if (!wp_check_password( $password, $user->user_pass, $user->ID )){
return new WP_Error( 'incorrect_password', sprintf( __( 'The password you\'ve entered is incorrect.' ),
$username, wp_lostpassword_url() ) );
}
return $user;
}
Notice that I added braces to every condition to make it more clear.
You might also want to override the function wp_authenticate_email_password.
remove_filter( 'authenticate', 'wp_authenticate_email_password' );
add_filter( 'authenticate', 'custom_authenticate_email_password', 31, 3 );
function custom_authenticate_email_password( $user, $email, $password ) {
if ($user instanceof WP_User) {
return $user;
}
if (empty($email) || empty($password)) {
$error = new WP_Error();
if ( empty( $email ) ) {
// Uses 'empty_username' for back-compat with wp_signon().
$error->add( 'empty_username', __( 'The username or email field is empty.' ) );
}
if ( empty( $password ) ) {
$error->add( 'empty_password', __( 'The password field is empty.' ) );
}
return $error;
}
if (!is_email($email)) {
return $user;
}
$user = get_user_by('email', $email);
if (!$user) {
return new WP_Error('invalid_email',__( 'Invalid username or email address.' ));
}
/** This filter is documented in wp-includes/user.php */
$user = apply_filters( 'wp_authenticate_user', $user, $password );
if (is_wp_error($user)){
return $user;
}
if (!wp_check_password( $password, $user->user_pass, $user->ID)){
return new WP_Error('incorrect_password',sprintf( __( 'The password you\'ve entered is incorrect.' ),
$email, wp_lostpassword_url() ) );
}
return $user;
}
There are two functions under authenticate, wp_authenticate_username_password and wp_authenticate_email_password. Try to override both of them, maybe one of them has the error message that is not overriding, use the codes above and examine.
A number of questions have been raised on StackOverflow in regards to using email address as username when registering via My Account. I have the working code included below.
$this->loader->add_filter('pre_user_login', $plugin_public, 'audp_wc_register_email_as_username' );
public function audp_wc_register_email_as_username( $user_login ) {
if ( isset ( $_POST['email'] ) ) {
$user_login = $_POST['email'];
}
return $user_login;
}
I've updated my own question with the following code to update the user_login details.
$this->loader->add_action( 'woocommerce_save_account_details', $plugin_public, 'audp_wc_update_email_and_username', 20, 1 );
public function audp_wc_update_email_and_username() {
if ( isset( $_POST['account_email'] ) ) {
global $wpdb;
$user_id = get_current_user_id();
$new_login = $_POST['account_email'];
// Update user user_login
$wpdb -> update( $wpdb -> users,
array( 'user_login' => $new_login, 'user_nicename' => $new_nicename ),
array( 'ID' => $user_id )
);
}
// Update nickname
update_user_meta( $user_id, 'nickname', $new_login );
}
I've updated the question to include the full code. Because we are dealing with user_login we cannot use wp_update_user(), I have used the class description above, but the below code is standard (non-class) functions.
add_action( 'woocommerce_save_account_details', 'audp_wc_update_email_and_username', 20, 1 );
function audp_wc_update_email_and_username() {
if ( isset( $_POST['account_email'] ) ) {
global $wpdb;
$user_id = get_current_user_id();
$new_login = $_POST['account_email'];
// Update user user_login
$wpdb -> update( $wpdb -> users,
array( 'user_login' => $new_login, 'user_nicename' => $new_nicename ),
array( 'ID' => $user_id )
);
// Update nickname
update_user_meta( $user_id, 'nickname', $new_login );
}
I have updated my code, but the problem is get_the_ID not getting any value. Can you please help. This code was adding function.php in child theme.
// Works in single post outside of the Loop
add_filter( 'authenticate', 'myplugin_auth_signon', 30, 3 );
function myplugin_auth_signon( $user, $username, $password ) {
$user = get_user_by( 'login', $username );
$roles = $user->roles['0'];
$id = get_the_ID();
echo $id;
if ( is_page( $id == 400380 ) )
{
echo "Employee Page";
$user = new WP_Error( 'denied', "Customer have no permission to login from this employee login form" );
}
if ( is_page( $id == 399649 ) )
{
echo "Customer";
$user = new WP_Error( 'denied', "Employee have no permission to login from this customer login form" );
}
return $user;
}
You can restrict other role from login use authenticate filter hook.
add_filter( 'authenticate', 'myplugin_auth_signon', 30, 3 );
function myplugin_auth_signon( $user, $username, $password ) {
$user = get_user_by( 'login', $username );
$roles = $user->roles['0'];
if($roles != 'sales' && is_page('YOUR_SALES_PAGE_ID')){
$user = new WP_Error( 'denied', "You have not permission to login from this form" );
return $user;
}
return $user;
}
Replace YOUR_SALES_PAGE_ID with your current sales login page id.
For more help see this link : Click here
User roles comes from database ? check it before, then do your logic.
I have a custom order status called Shipping Details which will be selected after the Order complete trigger is fired.
Code for the Order Status
function register_shipping_details_status() {
register_post_status( 'wc-shipping-details', array(
'label' => 'Send Shipping Details',
'public' => true,
'exclude_from_search' => false,
'show_in_admin_all_list' => true,
'show_in_admin_status_list' => true
//'label_count' => _n_noop( 'Shipping Details <span class="count">(%s)</span>', 'Shipping Details <span class="count">(%s)</span>' )
) );
}
add_action( 'init', 'register_shipping_details_status' );
// Add to list of WC Order statuses
function add_shipping_details_to_order_statuses( $order_statuses ) {
$new_order_statuses = array();
// add new order status after completed
foreach ( $order_statuses as $key => $status ) {
$new_order_statuses[ $key ] = $status;
if ( 'wc-completed' === $key ) {
$new_order_statuses['wc-shipping-details'] = 'Send Shipping Details';
}
}
return $new_order_statuses;
}
add_filter( 'wc_order_statuses', 'add_shipping_details_to_order_statuses' );
and my email trigger code is here.
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
}
if ( ! class_exists( 'WC_Shipping_Details_Email' ) ) :
/**
* Customer Shipping Details Email
*/
class WC_Shipping_Details_Email extends WC_Email {
/**
* Constructor.
*/
public function __construct() {
$this->id = 'wc_shipping_details';
$this->customer_email = true;
$this->title = __( 'Shipping Details', 'woocommerce' );
$this->description = __( 'Shipping details emails are sent after the order has been marked completed .', 'woocommerce' );
$this->heading = __( 'Shipping Details for your order', 'woocommerce' );
$this->subject = __( 'Shipping details for your order from INAI', 'woocommerce' );
$this->template_html = 'emails/customer-shipping-details.php';
$this->template_plain = 'emails/plain/customer-shipping-details.php';
// Triggers for this email
add_action( 'woocommerce_order_status_shipping_details_notification', array( $this, 'trigger' ) );
// Call parent constuctor
parent::__construct();
}
/**
* Trigger.
*
* #param int $order_id
*/
public function trigger( $order_id ) {
if ( $order_id ) {
$this->object = wc_get_order( $order_id );
$this->recipient = $this->object->billing_email;
$this->find['order-date'] = '{order_date}';
$this->find['order-number'] = '{order_number}';
$this->replace['order-date'] = date_i18n( wc_date_format(), strtotime( $this->object->order_date ) );
$this->replace['order-number'] = $this->object->get_order_number();
}
if ( ! $this->is_enabled() || ! $this->get_recipient() ) {
return;
}
$this->send( $this->get_recipient(), $this->get_subject(), $this->get_content(), $this->get_headers(), $this->get_attachments() );
}
The action for registering the email
//custom hooks for custom woocommerce order email
function register_custom_order_status_action( $actions ){
$actions[] = 'woocommerce_order_status_shipping_details';
return $actions;
}
add_filter( 'woocommerce_email_actions', 'register_custom_order_status_action' );
For some reason the mail is not getting triggered. I have looked around a lot and even found a few others for whom the problem has been solved. WooCommerce - send custom email on custom order status change.
My code is almost exactly the same, still don't know what i'm missing. Please help.