do_action passing a variable with T_OBJECT_OPERATOR(->) PHP - php

I have a plugin that uses a custom checkout form. In this checkout form there is a "create account" checkbox identical to the default Wordpress one. I am trying to write some code to add another checkbox that allows the user to choose a role for this new account. The plugin that creates this checkout form has a do_action that I want to hook into. It even has a variable that I need. Sadly, I'm uncertain how to use this.
The do_action:
do_action( 'woocommerce_after_checkout_validation', $woocommerce_checkout->posted );
As you can see this uses $woocommerce_checkout->posted
My code has the following
add_action('woocommerce_after_checkout_validation', 'validate_professional_field' 10,1);
And In my function I try to use this with the following code:
function validate_professional_field( $woocommerce_checkout->posted ) {}
This does not work And I have no clue what to do here..
How can I use the variables sent with the action?
In the end I want to use $woocommerce_checkout->posted['createprofessional'] to get the value that should be the value of my checkbox.
Other details
This checkbox was made with the following code:
add_action('woocommerce_before_checkout_registration_form' , 'define_telesales_fields', 3);
<?php function define_telesales_fields() { ?>
<p class="form-row form-row-wide create-professional">
<div class="create-account">
<input class="input-checkbox" id="createprofessional" type="checkbox" name="createprofessional" value="1" />
<label for="createprofessional" class="checkbox"><?php _e( 'Create a professional', 'woocommerce' ); ?></label>
</div>
</p>
<?php }?>
Solved
A comma was missing in the add_action
add_action('woocommerce_after_checkout_validation', 'validate_professional_field', 10,1);

Just use $woocommerce_checkout as the parameter name in the function declaration; if you're passing the whole object into the function, you can then use $woocommerce_checkout->posted within the function itself.
eg:
function validate_professional_field( $woocommerce_checkout ) {
//$woocommerce_checkout->posted is valid here
}
//and you'd call it like this:
validate_professional_field( $woocommerce_checkout );
Alternatively, if you know you only want to use posted in the function, you could limit the argument to just that, which seems to be what you want to do. In this case, give it a valid variable name in the function declaration, like so:
function validate_professional_field( $posted ) {
//$posted is valid here, and will be contain the data from $woocommerce_checkout->posted that you're passing into the function.
}
//and you'd call it like this:
validate_professional_field( $woocommerce_checkout->posted );

Related

Custom "Post Author" Input Instead of Dropdown

I have a site with over 20,000 users. Occasionally I need to update the author of a post. However, the sheer amount of users makes the "Author" metabox on the edit post screen unusable. I'm trying to make a custom box where I can input the desired author's ID and change the post author to that ID. Ideally, I would like to do this within the box itself, rather than by way of saving/updating the post.
Here's my custom meta box code:
//Get the post data
$id = get_the_ID();
$author_id= $post->post_author;
<div class="update-author">
<p><strong>Current Author ID:</strong> <?php echo $author_id;?></p>
<p><strong>CHANGE AUTHOR ID TO:</strong></p>
<form id="update-author-form" method="post" action="<?php echo esc_url( admin_url('admin-post.php') ); ?>" >
<input type="hidden" name="action" value="update_author_form">
<input type="hidden" name="post-id" value="<?php echo $id; ?>">
<input type="number" id="update-author-id" name="update-author-id" value="" />
<button id="update-author-button" class="button button-primary button-large">Update Author ID</button>
</form>
</div>
Next, I have my form function built as follows:
function handle_update_author_form() {
$post_id = $_POST['post-id'];
$update_id = $_POST['update-author-id'];
$my_post = array(
'ID' => $post_id,
'post_author' => $update)_id,
);
wp_update_post( $my_post );
}
At this stage, my form button does nothing but refresh the page and send it to the posts screen (I know, I need to change the redirect URL).
Like in comments - I would go for a another approach of removing the original meta_box and replacing it with a new one - or alternatively just use a JS to turn the dropdown list into a searchable field ( for example the excellent select2 plugins - but have others - and also pure JS is quite easy - see example below )
Anyhow - in your code that you posted you are missing the hook where you can apply and invoke your code, for example:
'add_action( 'save_post', 'handle_update_author_form', 10, 1 ); '
Have a look at wp filters and actions.
The suggested (simple) JS solution :
Now, for the simple approach of just using JS to pseudo-search inside the dropdown and therefor there is no real need to interfere with the query or post injections.....
myPlugin.php / myTHeme,php
function admin_enqueue_scripts_callback(){
// We are using select2.js from CDN here ..
//This will add Select2 CSS
wp_enqueue_style( 'select2-css', 'https://cdn.jsdelivr.net/npm/select2#4.1.0-rc.0/dist/css/select2.min.css', array(), '4.1.0-rc.0');
////This will add Select2 JS
wp_enqueue_script( 'select2-js', 'https://cdn.jsdelivr.net/npm/select2#4.1.0-rc.0/dist/js/select2.min.js', 'jquery', '4.1.0-rc.0');
// Now we need a JavaScript file to initialize the Select2 elements
// here it is staged as a plugin - but a theme would be the same .
wp_enqueue_script( 'select2-init', '/wp-content/plugins/select2-init.js', 'jquery', '4.1.0-rc.0');
}
add_action( 'admin_enqueue_scripts', 'admin_enqueue_scripts_callback' );
select2-init.js
// initialize select2 on author dropdown field with jQuery
jQuery(document).ready(function($) {
$('#post_author_override').select2();
});
voilà !
At this point you will have the pseudo-search implemented that would resolve your problem in a practical way without any new ->queries or $objects and with minimum coding.
Possible / potential caveats
I am not sure what would be the efficiency of filtering 20,000 items.
It would be interesting to know how the select2 JS would perform with such a long list...
But if it is already loaded to the DOM i guess it would be ok ( might take a few seconds to react though )
Please let me know how it performing if you implement the solution.

How to send form data to woocommerce add_to_cart from custom template?

I have a created a new template inside theme's folder named Pre-Checkout Customer Details where there is a form. and the page looks like:
<?php /* Template Name: Pre-Checkout Customer Details */ ?>
<?php
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
get_header(); ?>
<form action="/checkout/?">
<input type="name" name="name">
<input type="date" name="start_date">
<input type="submit" name="Next">
</form>
<?php get_footer(); ?>
Along with that, this page's URL will always contain some parameters such as
?add-to-cart=608&subscribe='weight_loss_plan'
which will look somewhat:
https://challengecenter-q8.com/pre-checkout-customer-details/?add-to-cart=608&subscribe=%D8%A8%D9%86%D8%A7%D8%A1%20%D8%B9%D8%B6%D9%84%20%D8%A3%D8%B4%D8%AA%D8%B1%D8%A7%D9%83%20%D8%A7%D8%B3%D8%A8%D9%88%D8%B9%D9%8A%D9%86%20%D9%88%D8%AC%D8%A8%D8%AA%D9%8A%D9%86
Now when I am clicking on submit, it is showing page not found instead of moving to the cart page. Also, I want the form details to show on the checkout page like: https://challengecenter-q8.com/checkout/?name='value 1'&date='04-04-2021'
How can I achieve that?
Thank you in advance!
Note: “Enable AJAX add to cart buttons on archives” is enabled and “Redirect to the cart page after successful addition”. is disabled.
I would look into using actions to accomplish what you're trying to do. You can use the template_redirect action to check for your URL parameter and programmatically add that item to the cart then redirect to which ever page you would like.
You can simply create an anchor link for the page you're currently on that has the parameter you're needing (in my case 'atc').
Here's a piece of code I use to do this.
add_action('template_redirect', 'mks_add_to_cart');
function mks_add_to_cart(){
$pid = filter_input( INPUT_GET, 'atc', FILTER_VALIDATE_INT );
if( !empty( $pid ) ) {
global $woocommerce;
$woocommerce->cart->add_to_cart( $pid );
wp_redirect( site_url() . '/cart' );
exit;
}}
Use another action for your second part to display on the checkout page. I use Business Bloomer Visual Hook Guide often to reference where I want information to show.

What hook do I need to save a setting?

I've added a new field onto the discussion's section on the /wp-admin/options-discussion.php page that outputs along with this:
<?php do_settings_sections('discussion'); ?>
How can I hook the Save Changes button so that I can handle saving my new setting's fields?
I've tried updated_option like so:
add_action('updated_option', [__CLASS__, 'sanitize_settings'], 11, 3);
But I don't think this is what I need.
for saving data in wp_options you should set the name and value together
for example first we can add new options with add_option function and see this link
add_option( 'nameOfYourOption', 'value', '', 'yes' );
then you can easily access your data with the get_option function and see this link
$yourOption = get_option( 'nameOfYourOption' );
var_dump($yourOption)
and if you want to change the value you can do that with update_option function and see this link
update_option( 'nameOfYourOption', 'newValue' );
With these three functions, you can manage your option
but if you try just using the hook for update_option see this link
do_action( 'update_option', string $option, mixed $old_value, mixed $value )
Updated
When you try to click on a Save button to using those functions, you can handle that with a form or with WordPress ajax
<form method="post">
<button name="uniqName" type="submit">Save Changes</button>
</form>
in wordpress/php
<?PHP
if(isset($_POST['uniqName'])){
//do something
}
and if you try to send data with ajax, just see this link

Saving data to WooCommerce session

I'm attempting to save a simple text input to the WooCommerce session. The session is created when a user adds something to their cart.
My input field exists in custom page template that will be placed in the user flow after the cart but before the checkout: cart > my template > checkout.
So far
Simple form to capture data (custom template file)
<form name="group" method="post" class="checkout woocommerce-checkout" action="http://localhost:/site.dev/my-template">
<div class="group-order">
<p class="form-row form-row woocommerce-validated" id="create_new_group_field">
<label for="create_new_group" class="">Join an existing group</label>
<input type="text" class="input-text " name="create_new_group" id="create_new_group">
</p>
</div>
</form>
Receiving and setting data (I'm having trouble figuring out when/how to run this. in my custom page)
UPDATE
I've added the code below to the top of my page template so the page processes itself and then re-directs to the checkout.
function set_and_save_input_to_session() {
if( !is_admin( ) ) {
// User input
if( ! empty( $_POST['create_new_group'] ) ) {
$group_input_value = $_POST['create_new_group'];
// Set session and save data
WC()->session->set( 'group_order_data', $group_input_value );
wp_redirect( 'http://localhost:28/site.dev/checkout' );
exit();
}
}
get_header();
add_action('woocommerce_checkout_process', 'set_and_save_input_to_session');
Retrieving and saving data
function retrieve_and_save_group_input_value_to_order_meta() {
$retrived_group_input_value = WC()->session->get( 'group_order_data' );
update_post_meta( $order_id, '_create_new_group', $retrived_group_input_value );
}
add_action('woocommerce_checkout_update_order_meta', 'retrieve_and_save_group_input_value_to_order_meta');
I'm currently working my way through what are to me, more complex solutions and therefore I'd appreciate if anyone could point out any major flaws with my process so far.
UPDATE
I can confirm that the form is receiving data and that the WC()->session->set is setting data. (Thanks to #Firefog for suggesting the use the $_SESSION global)
After further investigation and finding the right place to var_dump the session data I found that the data was being set to the session with my original method.
The data is set, but I can't see why the data won't save to the order.
It's more saying Thank you for solving my problem. But here is an answer, too:
The post meta could not been updated because there is no $order_id parameter in your callback function. This should do the trick:
function retrieve_and_save_group_input_value_to_order_meta( $order_id ) {
$retrived_group_input_value = WC()->session->get( 'group_order_data' );
update_post_meta( $order_id, '_create_new_group', $retrived_group_input_value );
}
add_action('woocommerce_checkout_update_order_meta', 'retrieve_and_save_group_input_value_to_order_meta');
Here is another approach.
1st page:
session_start();//place this at the top of all code
$data = $_POST['create_new_group'];
$_SESSION['custom_create_new_group']=$data;
Now in another page write the following to receive the value:
session_start(); //optional
$retrive_price = $_SESSION['custom_create_new_group'];

Access function argument in different function?

I have this function:
<?php myWidget() { ?>
<div id="<?php echo $args['widget_id']; ?>">
<p>Something</p>
</div>
<?php } ?>
(widget_id is Wordpress core function so I have no direct access to that, it just simply generates widgets name)
I wanted to add my widget as a shortcode so needed to create another function:
function myWidget_shortcode( $atts ) {
extract( shortcode_atts( array(
/* attributes here */
), $atts ) );
ob_start();
the_widget(myWidget);
return ob_get_clean();
}
the_widget just simply calls widget called myWidget.
The point is, everything works good, but id=" " is always empty when I use the second code.
I know it's a Wordpress question, but I believe this has more to do with my PHP code.
Any ideas?
Judging from your last comment the problem is that $args is not set and since the ID is set from $args it will "".
You have to find out where $args is set and either make sure that part is run or set it your self.
$args in this case is not arguments to myWidget method but a global array.
Check if it exists at all
isset($args)
My guess is its a scope issue. $args isnt inside the function. Try passing it to the function

Categories