WordPress Update custom post status by clicking custom link in admin - wordpress

i have a site where i get posts from users, those posts save in WP as a custom post with status pending,
Admin have custom link in that custom post type page Approve | Reject
Approve should change post status to Public
Reject Should change post status to trash/del
can anyone tell any hook to anything which i can run to change post status from backend by clicking these custom links
the code of approve | reject button if anyone want to see
add_filter( 'manage_dream_posts_columns', 'smashing_filter_posts_columns' );
function smashing_filter_posts_columns( $columns ) {
$columns['decision'] = __( 'Decision Pending', 'rima' );
return $columns;
}
add_action( 'manage_dream_posts_custom_column', 'smashing_dream_column', 10, 2);
function smashing_dream_column( $column, $post_id ) {
if ( 'decision' === $column ) {
if (get_post_status ( $post_id ) == 'pending') {
echo '<div class="decision">ApproveReject</div>';
}
else {
echo '<div class="decision"><span class="dapprove">Approved</span></div>';
}
}
}

You could do something like this - it's a bit hacky and uses jQuery but is a quick fix for your issue using an Ajax method so it all works realtime with your admin screen. You can approve/reject multiple posts without any page reloads, including some colour feedback to let you know what's happening.
You need to add 2 new actions:
add_action( 'wp_ajax_set_post_status', 'set_post_status_ajax_handler' );
add_action( 'admin_footer', 'set_post_status_js' );
Then add these functions:
function set_post_status_js()
{
$nonce = wp_create_nonce('set_post_status');
$ajax_url = admin_url('admin-ajax.php'); ?>
<script type="text/javascript">
(function($){
$(document).ready(function(){
$('.decision a').click(function(event){
event.preventDefault();
$.post( "<?= $ajax_url; ?>", {
nonce: "<?= $nonce; ?>",
action: 'set_post_status',
post_id: $(this).data('post_id'),
status: $(this).data('status'),
}, function(data){
if (data.ok) {
var postStateLabel = (data.status === 'publish') ? '<span style="color: #009900;">Approved</span>' : '<span style="color: #990000;">Rejected</span>';
$('#post-' + data.id)
.css('background', data.status === 'publish' ? '#EEFFEE' : '#FFEEEE')
.find('.post-state').html( postStateLabel );
}
});
});
});
})(jQuery)
</script>
<?php
}
And
function set_post_status_ajax_handler()
{
$nonce = $_POST['nonce'];
if ( ! wp_verify_nonce( $nonce, 'set_post_status' ) )
die ( 'Not permitted');
// Extract the vars from the Ajax request
$post_id = $_POST['post_id'];
$status = $_POST['status'];
// Now update the relevant post
$post_id = wp_update_post([
'ID' => $post_id,
'post_status' => $status,
], true);
// make sure it all went OK
if (is_wp_error($post_id))
{
$response = [
'ok' => false,
];
} else
{
$response = [
'ok' => true,
'id' => $post_id,
'status' => $status,
];
}
// Return the response
wp_send_json( $response );
}
Finally, you need to change your Approve / Reject links to this HTML:
echo '
<div class="decision">
Approve
Reject
</div>';
Hopefully that will get you sorted. Cheers.

Related

How can get the checkout field value and hidden order button in woocommerce?

I have payment needed to wait for JS callback token, so on the checkout page, the flow will have the customer check the token button, then click and get the token will apply to the custom field,
in the end, if the custom field is not empty show the order button.
custom field
function techiepress_payleo_description_fields( $description, $payment_id ) {
if( 'payleos' !== $payment_id) {
return $description;
};
// $json = json_encode(WC()->cart);
ob_start();
echo '<div id="Payment">'; // it will create get token button
echo '</div>';
woocommerce_form_field( 'payment_number', array(
'type' => 'text',
'label' => __("credit card", "payleo_payment_plus"),
'required' => true,
),'');
$description .= ob_get_clean();
return $description;
}
hidden order button
add_filter('woocommerce_order_button_html', 'remove_place_order_button_for_specific_payments' );
function remove_place_order_button_for_specific_payments( $button ) {
// HERE define your targeted payment(s) method(s) in the array
$targeted_payments_methods = array('payleos');
$chosen_payment_method = WC()->session->get('chosen_payment_method'); // The chosen payment
// For matched payment(s) method(s), we remove place order button (on checkout page)
if( in_array( $chosen_payment_method, $targeted_payments_methods ) && ! is_wc_endpoint_url() ) {
$button = '';
}
return $button;
}
// jQuery - Update checkout on payment method change
add_action( 'wp_footer', 'custom_checkout_jquery_script' );
function custom_checkout_jquery_script() {
if ( is_checkout() && ! is_wc_endpoint_url() ) :
?>
<script type="text/javascript">
jQuery( function($){
$('form.checkout').on('change', 'input[name="payment_method"]', function(){
$(document.body).trigger('update_checkout');
});
});
</script>
<?php
endif;
}
I would like to know how can show the place order button when the custom field has value?

Woocommerce - Validation on cart page

I have a custom filed for specific shipping methods (see screenshot).
Is there a hook/action to validate this field before proceeding the checkout. When I set the field to required the validation will fire at the checkout page but I want it at the cart page.
Validation:
//Validate the custom selection field
add_action('woocommerce_checkout_process', 'carrier_company_checkout_validation');
function carrier_company_checkout_validation() {
Load settings and convert them in variables
extract( custom_field_settings() );
if( isset( $_POST[$field_id] ) && empty( $_POST[$field_id] ) )
wc_add_notice(
sprintf( __("Please select a %s as it is a required field.","woocommerce"),
'<strong>' . $label_name . '</strong>'
), "error" );
}
** UPDATE: **
like #LoicTheAztec mentioned here the complete code.
Everything is working fine. The custom input value from cart will be shown on checkout and saved in the DB after order confirmation. But I don't know where I have to put the validation on the cart page when the custom input is empty because everything on cart is on ajax.
// ##########################################
// Add custom fields to a specific selected shipping method
// ##########################################
// Custom function that handle your settings
function delivery_date_settings(){
return array(
'field_id' => 'delivery_date', // Field Id
'field_type' => 'text', // Field type
'field_label' => 'label text', // Leave empty value if the first option has a text (see below).
'label_name' => __("Lieferdatum","woocommerce"), // for validation and as meta key for orders
);
}
// Display the custom checkout field
add_action( 'woocommerce_after_shipping_rate', 'carrier_company_custom_select_field', 20, 2 );
function carrier_company_custom_select_field( $method, $index ) {
if( $method->id == 'flat_rate:2' || $method->id == 'free_shipping:1') {
extract( delivery_date_settings() ); // Load settings and convert them in variables
$chosen = WC()->session->get('chosen_shipping_methods'); // The chosen methods
$value = WC()->session->get($field_id);
$value = WC()->session->__isset($field_id) ? $value : WC()->checkout->get_value('_'.$field_id);
$options = array(); // Initializing
$chosen_method_id = WC()->session->chosen_shipping_methods[ $index ];
if($chosen_method_id == 'flat_rate:2' || $method->id == 'free_shipping:1' ){
echo '<div class="custom-date-field">';
woocommerce_form_field( $field_id, array(
'type' => $field_type,
'label' => $field_label, // Not required if the first option has a text.
'class' => array('form-row-wide datepicker ' . $field_id . '-' . $field_type ),
'required' => false,
), $value );
echo '</div>';
// Jquery: Enable the Datepicker
?>
<script language="javascript">
jQuery( function($){
$('.datepicker input').datepicker({
dateFormat: 'dd.mm.yy', // ISO formatting date
});
});
</script>
<?php
}
}
}
// jQuery code (client side) - Ajax sender
add_action( 'wp_footer', 'carrier_company_script_js' );
function carrier_company_script_js() {
// Only cart & checkout pages
if( is_cart() || ( is_checkout() && ! is_wc_endpoint_url() ) ):
// Load settings and convert them in variables
extract( lieferdatum_settings() );
$js_variable = is_cart() ? 'wc_cart_params' : 'wc_checkout_params';
// jQuery Ajax code
?>
<script type="text/javascript">
jQuery( function($){
if (typeof <?php echo $js_variable; ?> === 'undefined')
return false;
$(document.body).on( 'change', 'input#<?php echo $field_id; ?>', function(){
var value = $(this).val();
$.ajax({
type: 'POST',
url: <?php echo $js_variable; ?>.ajax_url,
data: {
'action': 'delivery_date',
'value': value
},
success: function (result) {
console.log(result); // Only for testing (to be removed)
}
});
});
});
</script>
<?php
endif;
}
// The Wordpress Ajax PHP receiver
add_action( 'wp_ajax_delivery_date', 'set_carrier_company_name' );
add_action( 'wp_ajax_nopriv_delivery_date', 'set_carrier_company_name' );
function set_carrier_company_name() {
if ( isset($_POST['value']) ){
// Load settings and convert them in variables
extract( delivery_date_settings() );
if( empty($_POST['value']) ) {
$value = 0;
$label = 'Empty';
} else {
$value = $label = esc_attr( $_POST['value'] );
}
// Update session variable
WC()->session->set( $field_id, $value );
// Send back the data to javascript (json encoded)
echo $label;
die();
}
}
// Save custom field as order meta data
add_action( 'woocommerce_checkout_create_order', 'save_carrier_company_as_order_meta', 30, 1 );
function save_carrier_company_as_order_meta( $order ) {
// Load settings and convert them in variables
extract( delivery_date_settings() );
if( isset( $_POST[$field_id] ) && ! empty( $_POST[$field_id] ) ) {
$order->update_meta_data( '_'.$field_id, esc_attr($_POST[$field_id]) );
WC()->session->__unset( $field_id ); // remove session variable
}
}
// Display custom field in admin order pages
add_action( 'woocommerce_admin_order_data_after_shipping_address', 'admin_order_display_carrier_company', 30, 1 );
function admin_order_display_carrier_company( $order ) {
// Load settings and convert them in variables
extract( delivery_date_settings() );
$carrier = $order->get_meta( '_'.$field_id ); // Get carrier company
if( ! empty($carrier) ) {
// Display
echo '<p><strong>' . $label_name . '</strong>: ' . $carrier . '</p>';
}
}
// Display carrier company after shipping line everywhere (orders and emails)
add_filter( 'woocommerce_get_order_item_totals', 'display_carrier_company_on_order_item_totals', 1000, 3 );
function display_carrier_company_on_order_item_totals( $total_rows, $order, $tax_display ){
// Load settings and convert them in variables
extract( delivery_date_settings() );
$carrier = $order->get_meta( '_'.$field_id ); // Get carrier company
if( ! empty($carrier) ) {
$new_total_rows = [];
// Loop through order total rows
foreach( $total_rows as $key => $values ) {
$new_total_rows[$key] = $values;
// Inserting the carrier company under shipping method
if( $key === 'shipping' ) {
$new_total_rows[$field_id] = array(
'label' => $label_name,
'value' => $carrier,
);
}
}
return $new_total_rows;
}
return $total_rows;
}
I think the hook you're looking for is woocommerce_check_cart_items, that's the one that validates the cart items before proceeding to checkout.
I'm not 100% sure whether you'll be able to get the field in the same way using $_POST but it's worth a go.

Woocommerce ajax call on single product page

I get all my products from an API and those who are variations to each other all share a custom meta key called "api_product_family". The products with the same api_product_family are variants to each other, so on the single page I have a hook where I display the other variants with image and anchor to it's variants.
My code:
function mv_variations() {
global $post;
global $wpdb;
$product_id = $post->ID;
$product_family = get_post_meta( $post->ID, 'api_product_family', true );
if(!empty($product_family)) {
$query = "
SELECT post_id
FROM " . $wpdb->prefix . "postmeta
WHERE meta_value = '" . $product_family . "'
";
$products = $wpdb->get_col($query);
if(count($products) > 0) {
for($i=0; $i<count($products); $i++) {
if($products[$i] == $product_id) {
unset($products[$i]);
}
}
if(count($products) > 0) {
print '<h3>Choose other variants: </h3>';
foreach($products as $product) {
$image = wp_get_attachment_image_src(get_post_thumbnail_id($product));
print '<img src="' . $image[0] . '" alt="img"/> ';
}
}
}
}
}
add_action( 'woocommerce_single_product_summary', 'mv_variations' );
The problem:
I have a LOT of posts, and a lot of post_meta's, so it's taking an eternity to load so I was thinking to move this whole function inside and AJAX call so it's doesn't slow down the initial load. The problem is that I have no idea how to do that with wordpress
Are you simply looking to run a WP function via AJAX?
1) Add ajax actions
This needs to run inside the main plugin file. If you run this only on the public code, it will not work. WP is a little weird and all ajax uses admin-ajax.php
if ( wp_doing_ajax() ){
add_action( 'wp_ajax_yourcustomfunction', array($this, 'yourcustomfunction') );
add_action( 'wp_ajax_nopriv_yourcustomfunction', array($this, 'yourcustomfunction') );
}
function yourcustomfunction(){
echo 'success';
exit();
}
2) In JavaScript
in the backend, you have the global: ajaxurl for the ajax url
BUT in the front end you need to pass this as a variable via wp_localize_script
$datatoBePassed = array(
'ajaxurl' => admin_url( 'admin-ajax.php' ),
);
wp_localize_script( 'your_javascript_script', 'plugin_display_settings', $datatoBePassed );
In JS:
var datavar = {
action: 'yourcustomfunction',
};
$.post(plugin_display_settings.ajaxurl, datavar, function(response){
//response received here. It will be 'success' which is echoed in PHP
});
3)
If you also want to run a security nonce check (to check the request truly originates from the WP website, prevents some attacks), it gets a little more complicated:
$datatoBePassed should also include 'security' => wp_create_nonce( 'yourplugin_security_nonce' ),
datavar in JS includes security: plugin_display_settings.security,
Finally, your PHP custom function begins with:
// Check security nonce.
if ( ! check_ajax_referer( 'yourplugin_security_nonce', 'security' ) ) {
wp_send_json_error( 'Invalid security token sent.' );
wp_die();
}
// If security check passed, run further
So I think you might get better performance using WP_Query. Below I converted what you have into a custom WP_Query. May need some slight adjustment but should be the right direction.
function mv_variations() {
global $post_id;
// get current post "product family"
$product_family = get_post_meta( $post_id, 'api_product_family', true );
// build related "product family" products query
$products_query_args = array(
'post_type' => 'product', // may need to update this for your case
'posts_per_page' => -1, // return all found
'post__not_in' => array($post_id), // exclude current post
'post_status' => 'publish',
// use a meta query to pull only posts with same "product family" as current post
'meta_query' => array(
array(
'key' => 'api_product_family',
'value' => $product_family,
'compare' => '='
)
)
);
$products_query = new WP_Query($products_query);
// use "the loop" to display your products
if ( $products_query->have_posts() ) :
print '<h3>Choose other variants: </h3>';
while ( $products_query->have_posts() ) : $products_query->the_post();
print ''. wp_get_attachment_image() .'';
endwhile;
// restore global post
wp_reset_postdata();
endif;
}
add_action( 'woocommerce_single_product_summary', 'mv_variations' );

Redirect To URL when a comment is approved in WordPress

I am working on a custom post type, where the post content is updated with the comment content that is approved.
My code is:-
add_action('comment_unapproved_to_approved', 'hgkb_update_post_content_on_comment_approval');
function hgkb_update_post_content_on_comment_approval($comment)
{
$post_id = $comment->comment_post_ID;
$comment = $comment->comment_content;
$post_type=array('hgkb','hg-questions');
if (in_array(get_post_type( $post_id ),$post_type))
{
$update_answer=wp_update_post( array('ID' => $post_id, 'post_content' => $comment) );
if($update_answer)
{
//How to reload the page or redirect to another url?
}
}
}
Once the post content is updated, I want the content to be reflected in the content editor immediately or reload the page, so that the user can see the changes has been made.
Thanks in advance.
I have done it using another hook. So the code becomes:-
add_action('comment_unapproved_to_approved', 'hgkb_update_post_content_on_comment_approval');
function hgkb_update_post_content_on_comment_approval($comment)
{
$post_id = $comment->comment_post_ID;
$comment = $comment->comment_content;
$post_type=array('hgkb','hg-questions');
if (in_array(get_post_type( $post_id ),$post_type))
{
$update_answer=wp_update_post( array('ID' => $post_id, 'post_content' => $comment) );
if($update_answer)
{
//How to reload the page or redirect to another url?
}
}
}
and then:-
add_action('admin_footer-post.php', 'hgkb_reload_after_approval');
function hgkb_reload_after_approval()
{
global $post;
$post_type=array('hgkb','hg-questions');
if (stristr( $_SERVER['REQUEST_URI'], 'post.php' ) !== false && is_object( $post ) && in_array(get_post_type( $post->ID ),$post_type) )
{
?>
<script>
jQuery(document).ready(function(){
// Reload after 1 second when a comment approved
jQuery(document).on('click', '.vim-a', function (e) {
alert("Answer Updated!! The page will be reloaded after you click on OK. ");
setTimeout(function() {
window.location.href = "<?php echo site_url(); ?>/wp-admin/post.php?post=<?php echo $post->ID; ?>&action=edit"
}, 1000);
});
// END Reload after 1 second when a comment approved and Reload the Page when a comment approved
});
</script>
<?php
}
}

Wordpress custom metabox input value with AJAX

I am using Wordpress 3.5, I have a custom post (sp_product) with a metabox and some input field. One of those input (sp_title).
I want to Search by the custom post title name by typing in my input (sp_title) field and when i press add button (that also in my custom meta box), It will find that post by that Title name and bring some post meta data into this Meta box and show into other field.
Here in this picture (Example)
Search
Click Button
Get some value by AJAX from a custom post.
Please give me a example code (just simple)
I will search a simple custom post Title,
Click a button
Get the Title of that post (that i search or match) with any other post meta value, By AJAX (jQuery-AJAX).
Please Help me.
I was able to find the lead because one of my plugins uses something similar to Re-attach images.
So, the relevant Javascript function is findPosts.open('action','find_posts').
It doesn't seem well documented, and I could only found two articles about it:
Find Posts Dialog Box
Using Built-in Post Finder in Plugins
Tried to implement both code samples, the modal window opens but dumps a -1 error. And that's because the Ajax call is not passing the check_ajax_referer in the function wp_ajax_find_posts.
So, the following works and it's based on the second article. But it has a security breach that has to be tackled, which is wp_nonce_field --> check_ajax_referer. It is indicated in the code comments.
To open the Post Selector, double click the text field.
The jQuery Select needs to be worked out.
Plugin file
add_action( 'load-post.php', 'enqueue_scripts_so_14416409' );
add_action( 'add_meta_boxes', 'add_custom_box_so_14416409' );
add_action( 'wp_ajax_find_posts', 'replace_default_ajax_so_14416409', 1 );
/* Scripts */
function enqueue_scripts_so_14416409() {
# Enqueue scripts
wp_enqueue_script( 'open-posts-scripts', plugins_url('open-posts.js', __FILE__), array('media', 'wp-ajax-response'), '0.1', true );
# Add the finder dialog box
add_action( 'admin_footer', 'find_posts_div', 99 );
}
/* Meta box create */
function add_custom_box_so_14416409()
{
add_meta_box(
'sectionid_so_14416409',
__( 'Select a Post' ),
'inner_custom_box_so_14416409',
'post'
);
}
/* Meta box content */
function inner_custom_box_so_14416409( $post )
{
?>
<form id="emc2pdc_form" method="post" action="">
<?php wp_nonce_field( 'find-posts', '_ajax_nonce', false); ?>
<input type="text" name="kc-find-post" id="kc-find-post" class="kc-find-post">
</form>
<?php
}
/* Ajax replacement - Verbatim copy from wp_ajax_find_posts() */
function replace_default_ajax_so_14416409()
{
global $wpdb;
// SECURITY BREACH
// check_ajax_referer( '_ajax_nonce' );
$post_types = get_post_types( array( 'public' => true ), 'objects' );
unset( $post_types['attachment'] );
$s = stripslashes( $_POST['ps'] );
$searchand = $search = '';
$args = array(
'post_type' => array_keys( $post_types ),
'post_status' => 'any',
'posts_per_page' => 50,
);
if ( '' !== $s )
$args['s'] = $s;
$posts = get_posts( $args );
if ( ! $posts )
wp_die( __('No items found.') );
$html = '<table class="widefat" cellspacing="0"><thead><tr><th class="found-radio"><br /></th><th>'.__('Title').'</th><th class="no-break">'.__('Type').'</th><th class="no-break">'.__('Date').'</th><th class="no-break">'.__('Status').'</th></tr></thead><tbody>';
foreach ( $posts as $post ) {
$title = trim( $post->post_title ) ? $post->post_title : __( '(no title)' );
switch ( $post->post_status ) {
case 'publish' :
case 'private' :
$stat = __('Published');
break;
case 'future' :
$stat = __('Scheduled');
break;
case 'pending' :
$stat = __('Pending Review');
break;
case 'draft' :
$stat = __('Draft');
break;
}
if ( '0000-00-00 00:00:00' == $post->post_date ) {
$time = '';
} else {
/* translators: date format in table columns, see http://php.net/date */
$time = mysql2date(__('Y/m/d'), $post->post_date);
}
$html .= '<tr class="found-posts"><td class="found-radio"><input type="radio" id="found-'.$post->ID.'" name="found_post_id" value="' . esc_attr($post->ID) . '"></td>';
$html .= '<td><label for="found-'.$post->ID.'">' . esc_html( $title ) . '</label></td><td class="no-break">' . esc_html( $post_types[$post->post_type]->labels->singular_name ) . '</td><td class="no-break">'.esc_html( $time ) . '</td><td class="no-break">' . esc_html( $stat ). ' </td></tr>' . "\n\n";
}
$html .= '</tbody></table>';
$x = new WP_Ajax_Response();
$x->add( array(
'data' => $html
));
$x->send();
}
Javascript file open-posts.js
jQuery(document).ready(function($) {
// Find posts
var $findBox = $('#find-posts'),
$found = $('#find-posts-response'),
$findBoxSubmit = $('#find-posts-submit');
// Open
$('input.kc-find-post').live('dblclick', function() {
$findBox.data('kcTarget', $(this));
findPosts.open();
});
// Insert
$findBoxSubmit.click(function(e) {
e.preventDefault();
// Be nice!
if ( !$findBox.data('kcTarget') )
return;
var $selected = $found.find('input:checked');
if ( !$selected.length )
return false;
var $target = $findBox.data('kcTarget'),
current = $target.val(),
current = current === '' ? [] : current.split(','),
newID = $selected.val();
if ( $.inArray(newID, current) < 0 ) {
current.push(newID);
$target.val( current.join(',') );
}
});
// Double click on the radios
$('input[name="found_post_id"]', $findBox).live('dblclick', function() {
$findBoxSubmit.trigger('click');
});
// Close
$( '#find-posts-close' ).click(function() {
$findBox.removeData('kcTarget');
});
});

Resources