Wordpress add_filter use variable - wordpress

I'm using Awesome Support and I want to add a filter to manually assign the agent to answer the tickets.
This is the funcition:
function wpas_find_agent( $ticket_id = false ) {
if ( defined( 'WPAS_DISABLE_AUTO_ASSIGN' ) && true === WPAS_DISABLE_AUTO_ASSIGN ) {
return apply_filters( 'wpas_find_available_agent', wpas_get_option( 'assignee_default' ), $ticket_id );
}
$users = shuffle_assoc( wpas_get_users( apply_filters( 'wpas_find_agent_get_users_args', array( 'cap' => 'edit_ticket' ) ) ) );
$agent = array();
foreach ( $users->members as $user ) {
$wpas_agent = new WPAS_Member_Agent( $user );
/**
* Make sure the user really is an agent and that he can currently be assigned
*/
if ( true !== $wpas_agent->is_agent() || false === $wpas_agent->can_be_assigned() ) {
continue;
}
$count = $wpas_agent->open_tickets(); // Total number of open tickets for this agent
if ( empty( $agent ) ) {
$agent = array(
'tickets' => $count,
'user_id' => $user->ID,
);
} else {
if ( $count < $agent['tickets'] ) {
$agent = array(
'tickets' => $count,
'user_id' => $user->ID,
);
}
}
}
if ( is_array( $agent ) && isset( $agent['user_id'] ) ) {
$agent_id = $agent['user_id'];
} else {
$default_id = wpas_get_option( 'assignee_default', 1 );
if ( empty( $default_id ) ) {
$default_id = 1;
}
$agent_id = $default_id;
}
return apply_filters( 'wpas_find_available_agent', (int) $agent_id, $ticket_id );
}
And this is the filter I want to add:
add_filter('wpas_find_available_agent', 'asignar_agente', 10, 2);
function asignar_agente($agent_id){
$term_list = wp_get_post_terms( $ticket_id, 'department', array( 'fields' => 'ids' ) );
if($term_list[0] == 34){
$agent_id = 2;
}else{
$agent_id = 3;
}
return $agent_id;
}
How can I pass the $ticket_id variable to the filter to use it?
I need this variable because I need to know the term (department taxonomy) of the ticket is being submitted.
Thank you.

Since you pass $ticket_id when you call apply_filters('wpas_find_available_agent'....); you will be able to get the $ticket_id if you change your filter function to.
function asignar_agente($agent_id, $ticket_id){ <--- just add this parameter here
...
}
this is possible since you pass the parameter in apply_filters and you say add_filter('wpas_find_available_agent', 'asignar_agente', 10, 2); with emphasis on the last parameter with the value 2, that means your filter function will be able to receive 2 parameters.

Related

Unable to select shipping method after filtering 'woocommerce_package_rates'

I just wrote this filter to disable non-free shipping methods when free shipping is available:
add_filter( 'woocommerce_package_rates', 'disable_paid_shipping', 9999, 2 );
function disable_paid_shipping( $rates, $package ) {
$free_rates = array();
foreach ( $rates as $i => $rate ) {
if ( str_contains( $rate->label, "gratuita" ) OR str_contains( $rate->label, "gratuito" ) ) {
$free_rates[] = $rate;
}
if ( str_contains( $rate->id, "local") ) {
$local = $rate;
}
if ( str_contains( $rate->id, "fermopoint") ) {
$fermopoint = $rate;
}
}
if ( !empty( $free_rates ) ) {
if ( isset($fermopoint) ) {
$fermopoint->cost = 0;
$fermopoint->label .= ' gratuito';
array_unshift( $free_rates, $fermopoint );
}
if ( isset($local) ) {
$free_rates[] = $local;
}
$rates = $free_rates;
}
return $rates;
}
The code works as expected, unless for two unexpected events occurring:
no shipping method is selected by default anymore (both in cart and checkout page)
when I choose one in the cart page, it gets unselected right after (only in cart page)
To solve the 1st problem at checkout, I can work around by forcing the selection through a hook on woocommerce_before_cart (although this looks like a forced trick).
For the 2nd problem I have no idea.
Suggestions?
The problem lies in that the WC $rates array is an associative array:
$rates = Array (
[rate_id_0] => [rate_obj_0]
[rate_id_1] => [rate_obj_1]
...
);
While the newly created $free_rates is an indexed array:
$free_rates = Array (
[0] => [rate_obj_0]
[1] => [rate_obj_1]
...
);
As result, WC is unable to match the new $free_rates array with the user's default rate_id, which is supposed to be used as the array key.
Here's the working code:
add_filter( 'woocommerce_package_rates', 'disable_paid_shipping', 9999, 2 );
function disable_paid_shipping( $rates, $package ) {
$free_rates = array();
foreach ( $rates as $i => $rate ) {
if ( str_contains( $rate->label, "gratuita" ) OR str_contains( $rate->label, "gratuito" ) ) {
$free_rates[$rate->id] = $rate;
}
if ( str_contains( $rate->id, "local") ) {
$local = $rate;
}
if ( str_contains( $rate->id, "fermopoint") ) {
$fermopoint = $rate;
}
}
if ( !empty( $free_rates ) ) {
if ( isset($fermopoint) ) {
$fermopoint->cost = 0;
$fermopoint->label .= ' gratuito';
$free_rates = array($fermopoint->id => $fermopoint) + $free_rates; // to set it as 1st
}
if ( isset($local) ) {
$free_rates[$local->id] = $local;
}
$rates = $free_rates;
}
return $rates;
}

How can I add a check and not send an auto-reply to certain comments if the user fills in a custom field?

I'm using custom fields in the comment form "Did you like this book?" and "yes" and "no" values. I want to send 2 different auto-replies to a comment, if the user selects "yes" then the response is "Thank you for your kind recognition, customer's satisfaction is always our goal." and if "no" then the auto answer is "We'll strive to do better." I would appreciate any of your help...
//And this is how I send an auto reply to a comment
add_action( 'comment_post', 'author_new_comment', 10, 3 );
function author_new_comment( $comment_ID, $comment_approved, $commentdata ){
$comment_parent = (int) $commentdata['comment_parent'];
// If a new comment is a reply to another comment, don't do anything
if ( $comment_parent !== 0 ) {
return;
}
//How do I add a response if the comment contains the value of the [likebook ] meta field???
if( !empty( $_POST['likebook'] ) {
return;
}
$commentdata = [
'comment_post_ID' => $commentdata['comment_post_ID'],
'comment_author' => 'admin',
'comment_author_email' => 'admin#example.com',
'comment_author_url' => 'http://example.com',
'comment_content' => 'Thank you for your kind recognition, customer satisfaction is always our goal.',
'comment_type' => 'comment',
'comment_parent' => $comment_ID,
'user_ID' => 1,
];
wp_new_comment( $commentdata );
}
try these,
add_action( 'comment_post', 'author_new_comment', 10, 3 );
function author_new_comment( $comment_ID, $comment_approved, $comment ) {
if ( $comment['comment_parent'] !== 0 ) {
return;
}
if ( ! empty( $_POST['like'] ) ) {
if ( $_POST['like'] == 'dog' ) {
$msg = 'We are glad that you liked it!';
} else {
$msg = 'We will try to make this product better!';
}
$admins = get_super_admins();
$current_user = get_user_by( 'login', $admins[0] );
$data = array(
'comment_post_ID' => $comment['comment_post_ID'],
'comment_content' => $msg,
'comment_parent' => $comment_ID,
'user_id' => $current_user->ID,
'comment_author' => $current_user->user_login,
'comment_author_email' => $current_user->user_email,
'comment_author_url' => $current_user->user_url
);
$comment_id = wp_insert_comment( $data );
if ( is_wp_error( $comment_id ) ) {
throw new Exception( $comment_id );
}
}
}

How to find out the cheapest shipping method and change the shipping label in woocommerce?

So here's what I need to do: find out the cheapest shipping method and change the "Free Shipping" method label to "Free Shipping" + "Cheapest method label". This way the customer will be able to know what is the shipping method used for the free shipping.
First I thought about global variables.. then used the wp_options, but I am not certain if the wp_options are user shared or user-specific data.
Would you have any good ideas or corrections on the following code, which by the way isn't working? Thanks!
add_filter( 'woocommerce_shipping_chosen_method', 'wf_default_shipping_method', 10 );
function wf_default_shipping_method( $method ) {
$the_cheapest_cost = 1000000;
$packages = WC()->shipping()->get_packages()[0]['rates'];
foreach ( array_keys( $packages ) as $key ) {
if ( ( $packages[$key]->cost > 0 ) && ( $packages[$key]->cost < $the_cheapest_cost ) ) {
$the_cheapest_cost = $packages[$key]->cost;
$transport_label = $packages[$key]->label;
$method_id = $packages[$key]->id;
}
}
if(get_option('atransport')){
update_option('atransport', $transport_label);
}else{
add_option('atransport', $transport_label);
}
return $method_id;
}
add_filter( 'woocommerce_package_rates', 'change_shipping_methods_label_names', 20, 2 );
function change_shipping_methods_label_names( $rates, $package ) {
$transport = get_option('atransport');
foreach( $rates as $rate_key => $rate ) {
if ( __( 'Free Shipping', 'woocommerce' ) == $rate->label ){
$rates[$rate_key]->label = __( 'FreeShipping -' . $transport, 'woocommerce' ); // New label name
}
}
delete_option('atransport');
return $rates;
}
You can iterate a loop of $rates and get the cheapest method. then based on the found cheapest method you can change the label. code will go in your active theme functions.php file.
add_filter( 'woocommerce_package_rates', 'hide_other_shipping_when_free_is_available', 100, 1 );
function hide_other_shipping_when_free_is_available( $rates ) {
$cheapest_method = '';
// Loop through shipping rates
if ( is_array( $rates ) ) {
foreach ( $rates as $key => $rate ) {
// Set variables when the rate is cheaper than the one saved
if ( empty( $cheapest_method ) || $rate->cost < $cheapest_method->cost ) {
$cheapest_method = $rate;
}
}
}
// Return the cheapest rate when possible
if ( ! empty( $cheapest_method ) ) {
$free = array();
foreach ( $rates as $rate_id => $rate ) {
if ( $rate->id === $cheapest_method->id ) {
if ( __( 'Free Shipping', 'woocommerce' ) == $rate->label ){
$rates[ $rate_id ] = $rate;
// Here we append the labbelled saved price formated display
$rates[ $rate_id ]->label = 'Free Shipping '.$rates[ $rate_id ]->label;
break; // stop the loop
}
}
}
return $rates;
}
return $rates;
}
Tested and works

How to do email validation by blocking some email domain names in wordpress?

I need to validate an email field in gravity form. We have some known list of email domains and need to validate whether that domains present or not and If that domains present means we need to show the error message.
What is the best way to implement that? Any plugin suggestions?
This is possible with the GW_Email_Domain_Validator snippet here:
https://gravitywiz.com/banlimit-email-domains-for-gravity-form-email-fields/
Full snippet as of July 18, 2020 included here. Use the link above to get the latest version.
<?php
/**
* Gravity Wiz // Gravity Forms // Email Domain Validator
*
* This snippets allows you to exclude a list of invalid domains or include a list of valid domains for your Gravity Form Email fields.
*
* #version 1.4
* #author David Smith <david#gravitywiz.com>
* #license GPL-2.0+
* #link http://gravitywiz.com/banlimit-email-domains-for-gravity-form-email-fields/
*/
class GW_Email_Domain_Validator {
private $_args;
function __construct($args) {
$this->_args = wp_parse_args( $args, array(
'form_id' => false,
'field_id' => false,
'domains' => false,
'validation_message' => __( 'Sorry, <strong>%s</strong> email accounts are not eligible for this form.' ),
'mode' => 'ban' // also accepts "limit"
) );
// convert field ID to an array for consistency, it can be passed as an array or a single ID
if($this->_args['field_id'] && !is_array($this->_args['field_id']))
$this->_args['field_id'] = array($this->_args['field_id']);
$form_filter = $this->_args['form_id'] ? "_{$this->_args['form_id']}" : '';
add_filter("gform_validation{$form_filter}", array($this, 'validate'));
}
function validate($validation_result) {
$form = $validation_result['form'];
foreach($form['fields'] as &$field) {
// if this is not an email field, skip
if(RGFormsModel::get_input_type($field) != 'email')
continue;
// if field ID was passed and current field is not in that array, skip
if($this->_args['field_id'] && !in_array($field['id'], $this->_args['field_id']))
continue;
$page_number = GFFormDisplay::get_source_page( $form['id'] );
if( $page_number > 0 && $field->pageNumber != $page_number ) {
continue;
}
if( GFFormsModel::is_field_hidden( $form, $field, array() ) ) {
continue;
}
$domain = $this->get_email_domain($field);
// if domain is valid OR if the email field is empty, skip
if($this->is_domain_valid($domain) || empty($domain))
continue;
$validation_result['is_valid'] = false;
$field['failed_validation'] = true;
$field['validation_message'] = sprintf($this->_args['validation_message'], $domain);
}
$validation_result['form'] = $form;
return $validation_result;
}
function get_email_domain( $field ) {
$email = explode( '#', rgpost( "input_{$field['id']}" ) );
return trim( rgar( $email, 1 ) );
}
function is_domain_valid( $domain ) {
$mode = $this->_args['mode'];
$domain = strtolower( $domain );
foreach( $this->_args['domains'] as $_domain ) {
$_domain = strtolower( $_domain );
$full_match = $domain == $_domain;
$suffix_match = strpos( $_domain, '.' ) === 0 && $this->str_ends_with( $domain, $_domain );
$has_match = $full_match || $suffix_match;
if( $mode == 'ban' && $has_match ) {
return false;
} else if( $mode == 'limit' && $has_match ) {
return true;
}
}
return $mode == 'limit' ? false : true;
}
function str_ends_with( $string, $text ) {
$length = strlen( $string );
$text_length = strlen( $text );
if( $text_length > $length ) {
return false;
}
return substr_compare( $string, $text, $length - $text_length, $text_length ) === 0;
}
}
To only accept submissions from a given email domain you can do something like this:
new GW_Email_Domain_Validator( array(
'form_id' => 326,
'field_id' => 1,
'domains' => array( 'gmail.com', 'hotmail.com', '.co.uk' ),
'validation_message' => __( 'Oh no! <strong>%s</strong> email accounts are not eligible for this form.' ),
'mode' => 'limit'
) );

Conditionally updating roles in WordPress

I actually want to create an easy function but it doesn't seem to work.
I want that when a user logs to his account on Wordpress to change his role (subscriber -> directory_1) on some condition (easy in this case to test, it should change everytime, but still not working).
Here is my code :
add_action('wp_login', 'update_roles');
function update_roles()
{
global $wpdb;
$author = wp_get_current_user();
if(current_user_can('subscriber'))
{
$author->remove_role( 'subscriber' );
$author->add_role( 'directory_1' );
}
}
Thanks for the help!
You should be using wp_update_user() to update a user's role. After you have added a role using add_role(), you can do something like this:
function custom_update_roles( $user_login, $user ) {
if ( ! empty( $user->roles ) && is_array( $user->roles ) ) {
if ( in_array( "subscriber", $user->roles ) ) {
$user_id = wp_update_user( array( 'ID' => $user->ID, 'role' => 'directory_1' ) );
if ( is_wp_error( $user_id ) ) {
// Error.
} else {
// Success.
}
} else {
// This user is not a subscriber.
}
}
}
add_action( 'wp_login', 'custom_update_roles', 10, 2 );
Refs:
http://codex.wordpress.org/Function_Reference/wp_update_user
http://codex.wordpress.org/Function_Reference/add_role

Resources