Wordpress custom metabox input value with AJAX - wordpress

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');
});
});

Related

Add different WordPress excerpt formats to different templates

I added the following code to my functions.php file in WordPress 6.1.1 to display excerpts.
function new_excerpt_length($length) {
return 100;
}
add_filter('excerpt_length', 'new_excerpt_length');
function new_excerpt_more($more) {
return '...';
}
add_filter('excerpt_more', 'new_excerpt_more');
...but I also have a use case to show the full excerpt without a read more link.
On page template 1 I add the below code to display the excerpt:
<?php echo the_excerpt(); ?>
...and it displays the excerpt as per the functions.php file but how do I create a 2nd excerpt without the read more link and apply it to page template 2?
Is there a parameter I can use within the_excerpt(parameter); or can I use something like wp_trim_excerpt https://developer.wordpress.org/reference/functions/wp_trim_excerpt/ maybe?
I came across the below code that is supposed to do what I want
function wpex_get_excerpt( $args = array() ) {
// Default arguments.
$defaults = array(
'post' => '',
'length' => 40,
'readmore' => false,
'readmore_text' => esc_html__( 'read more', 'text-domain' ),
'readmore_after' => '',
'custom_excerpts' => true,
'disable_more' => false,
);
// Apply filters to allow child themes mods.
$args = apply_filters( 'wpex_excerpt_defaults', $defaults );
// Parse arguments, takes the function arguments and combines them with the defaults.
$args = wp_parse_args( $args, $defaults );
// Apply filters to allow child themes mods.
$args = apply_filters( 'wpex_excerpt_args', $args );
// Extract arguments to make it easier to use below.
extract( $args );
// Get the current post.
$post = get_post( $post );
// Get the current post id.
$post_id = $post->ID;
// Check for custom excerpts.
if ( $custom_excerpts && has_excerpt( $post_id ) ) {
$output = $post->post_excerpt;
}
// No custom excerpt...so lets generate one.
else {
// Create the readmore link.
$readmore_link = '' . $readmore_text . $readmore_after . '';
// Check for more tag and return content if it exists.
if ( ! $disable_more && strpos( $post->post_content, '<!--more-->' ) ) {
$output = apply_filters( 'the_content', get_the_content( $readmore_text . $readmore_after ) );
}
// No more tag defined so generate excerpt using wp_trim_words.
else {
// Generate an excerpt from the post content.
$output = wp_trim_words( strip_shortcodes( $post->post_content ), $length );
// Add the readmore text to the excerpt if enabled.
if ( $readmore ) {
$output .= apply_filters( 'wpex_readmore_link', $readmore_link );
}
}
}
// Apply filters and return the excerpt.
return apply_filters( 'wpex_excerpt', $output );
}
Output using:
<?php echo wpex_get_excerpt ( $defaults = array(
'length' => 40,
'readmore' => true,
'readmore_text' => esc_html__( 'read more', 'wpex-boutique' ),
'custom_excerpts' => true,
) ); ?>
...but doesn't seem to workas intended. Outputs the excerpt with no link but the args don't see to work when changed. Would be perfect for my use otherwise. Maybe someone sees how to fix this code?
Thanks

Pods Custom Post types use Tags with Check Boxes like Categories

I have been using pods to create various custom post types .. I was able to find some code to do what I want for the Standard wordpress post type .. How can I modify this code to work with my pods post types ?
I wan to Change from having to type the tags to pulling in the tags with check boxes
Like this here
Here is the code `/*
* Meta Box Removal
*/
function rudr_post_tags_meta_box_remove() {
$id = 'tagsdiv-post_tag'; // you can find it in a page source code (Ctrl+U)
$post_type = 'post'; // remove only from post edit screen
$position = 'side';
remove_meta_box( $id, $post_type, $position );
}
add_action( 'admin_menu', 'rudr_post_tags_meta_box_remove');
/*
* Add
*/
function rudr_add_new_tags_metabox(){
$id = 'rudrtagsdiv-post_tag'; // it should be unique
$heading = 'Tags'; // meta box heading
$callback = 'rudr_metabox_content'; // the name of the callback function
$post_type = 'post';
$position = 'side';
$pri = 'default'; // priority, 'default' is good for us
add_meta_box( $id, $heading, $callback, $post_type, $position, $pri );
}
add_action( 'admin_menu', 'rudr_add_new_tags_metabox');
/*
* Fill
*/
function rudr_metabox_content($post) {
// get all blog post tags as an array of objects
$all_tags = get_terms( array('taxonomy' => 'post_tag', 'hide_empty' => 0) );
// get all tags assigned to a post
$all_tags_of_post = get_the_terms( $post->ID, 'post_tag' );
// create an array of post tags ids
$ids = array();
if ( $all_tags_of_post ) {
foreach ($all_tags_of_post as $tag ) {
$ids[] = $tag->term_id;
}
}
// HTML
echo '<div id="taxonomy-post_tag" class="categorydiv">';
echo '<input type="hidden" name="tax_input[post_tag][]" value="0" />';
echo '<ul>';
foreach( $all_tags as $tag ){
// unchecked by default
$checked = "";
// if an ID of a tag in the loop is in the array of assigned post tags - then check the checkbox
if ( in_array( $tag->term_id, $ids ) ) {
$checked = " checked='checked'";
}
$id = 'post_tag-' . $tag->term_id;
echo "<li id='{$id}'>";
echo "<label><input type='checkbox' name='tax_input[post_tag][]' id='in-$id'". $checked ." value='$tag->slug' /> $tag->name</label><br />";
echo "</li>";
}
echo '</ul></div>'; // end HTML
}
`

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.

Multiple select product using select2 for wordpress plugin option page

I am trying to implement multiple select product using select2 . the list come up using getproductsearch this ajax action i did earlier but i failed to save it. I did this feature before for post-meta and product-category but failed for plugin option page. I am not sure what i am doing wrong.
please help.
class FeatureSale {
private $feature_sale_options;
public function __construct() {
add_action( 'admin_menu', array( $this, 'feature_sale_add_plugin_page' ) );
add_action( 'admin_init', array( $this, 'feature_sale_page_init' ) );
}
public function feature_sale_add_plugin_page() {
add_submenu_page(
'exclutips-settings',
'Feature & Sale', // page_title
'Feature & Sale', // menu_title
'manage_options', // capability
'feature-sale', // menu_slug
array( $this, 'feature_sale_create_admin_page' ) // function
);
}
public function feature_sale_create_admin_page() {
$this->feature_sale_options = get_option( 'feature_sale_option_name' ); ?>
<div class="wrap">
<div class="catbox-area-admin" style="width: 500px;background: #fff;padding: 27px 50px;">
<h2>Feature & Sale</h2>
<p></p>
<?php settings_errors(); ?>
<form method="post" action="options.php">
<?php
settings_fields( 'feature_sale_option_group' );
do_settings_sections( 'feature-sale-admin' );
submit_button();
?>
</form>
</div>
</div>
<?php }
public function feature_sale_page_init() {
register_setting(
'feature_sale_option_group', // option_group
'feature_sale_option_name', // option_name
array( $this, 'feature_sale_sanitize' ) // sanitize_callback
);
add_settings_section(
'feature_sale_setting_section', // id
'', // title
array( $this, 'feature_sale_section_info' ), // callback
'feature-sale-admin' // page
);
add_settings_field(
'vpm_sale_product', // id
'VPM Sale Product', // title
array( $this, 'vpm_sale_product_callback' ), // callback
'feature-sale-admin', // page
'feature_sale_setting_section' // section
);
add_settings_field(
'vpm_featured_product', // id
'VPM Featured Product', // title
array( $this, 'vpm_featured_product_callback' ), // callback
'feature-sale-admin', // page
'feature_sale_setting_section' // section
);
}
public function feature_sale_sanitize($input) {
$sanitary_values = array();
if ( isset( $input['vpm_sale_product'] ) ) {
$sanitary_values['vpm_sale_product'] = $input['vpm_sale_product'];
}
if ( isset( $input['vpm_featured_product'] ) ) {
$sanitary_values['vpm_featured_product'] = $input['vpm_featured_product'];
}
return $sanitary_values;
}
public function feature_sale_section_info() {
}
//Output the HTML for the metabox.
public function vpm_sale_product_callback() {
global $post;
// Nonce field to validate form request came from current site
wp_nonce_field( basename( __FILE__ ), 'vpm_sale_product_nonce' );
$html = '';
// always array because we have added [] to our <select> name attribute
$feature_sale_options = get_option( 'feature_sale_option_name' ); // Array of All Options
$vpm_sale_product = $feature_sale_options['vpm_sale_product'];
$html .= '<p><select id="vpm_sale_product" name="vpm_sale_product[]" multiple="multiple" style="width:99%;max-width:25em;">';
if( $vpm_sale_product ) {
foreach( $vpm_sale_product as $post_id ) {
$title = get_the_title( $post_id );
// if the post title is too long, truncate it and add "..." at the end
$title = ( mb_strlen( $title ) > 50 ) ? mb_substr( $title, 0, 49 ) . '...' : $title;
$html .= '<option value="' . $post_id . '" selected="selected">' . $title . '</option>';
}
}
$html .= '</select></p>';
echo $html;
//==========================================
}
//* Output the HTML for the metabox.
public function vpm_featured_product_callback() {
global $post;
// Nonce field to validate form request came from current site
wp_nonce_field( basename( __FILE__ ), 'vpm_featured_product_nonce' );
$html = '';
// always array because we have added [] to our <select> name attribute
$feature_sale_options = get_option( 'feature_sale_option_name' ); // Array of All Options
$vpm_featured_product = $feature_sale_options['vpm_featured_product'];
$html .= '<p><select id="vpm_featured_product" name="vpm_featured_product[]" multiple="multiple" style="width:99%;max-width:25em;">';
if( $vpm_featured_product ) {
foreach( $vpm_featured_product as $post_id ) {
$title = get_the_title( $post_id );
// if the post title is too long, truncate it and add "..." at the end
$title = ( mb_strlen( $title ) > 50 ) ? mb_substr( $title, 0, 49 ) . '...' : $title;
$html .= '<option value="' . $post_id . '" selected="selected">' . $title . '</option>';
}
}
$html .= '</select></p>';
echo $html;
echo $vpm_featured_product;
//==========================================
?>
<script>
(function ($) {
'use strict';
$(function () {
//--------------------------------------------------------------------------
// multiple select with AJAX search
$('#vpm_featured_product,#vpm_sale_product').select2({
ajax: {
url: ajaxurl, // AJAX URL is predefined in WordPress admin
dataType: 'json',
delay: 250, // delay in ms while typing when to perform a AJAX search
data: function (params) {
return {
q: params.term, // search query
action: 'getproductsearch' // AJAX action for admin-ajax.php
};
},
processResults: function( data ) {
var options = [];
if ( data ) {
// data is the array of arrays, and each of them contains ID and the Label of the option
$.each( data, function( index, text ) { // do not forget that "index" is just auto incremented value
options.push( { id: text[0], text: text[1] } );
});
}
return {
results: options
};
},
cache: true
},
minimumInputLength: 3 // the minimum of symbols to input before perform a search
});
//----------------------------------------------------------------------------------------
});
})(jQuery);
</script>
<?php
}
}
if ( is_admin() )
$feature_sale = new FeatureSale();
The problem is that these select tags are not using the correct name value:
<select id="vpm_sale_product" name="vpm_sale_product[]"...>
<select id="vpm_featured_product" name="vpm_featured_product[]"...>
And the proper name values are: (based on your register_setting() call)
<select id="vpm_sale_product" name="feature_sale_option_name[vpm_sale_product][]"...>
<select id="vpm_featured_product" name="feature_sale_option_name[vpm_featured_product][]"...>
And although after correcting the above issue, the form data would be saved properly, the fifth parameter (i.e. the menu/page slug) passed to add_submenu_page() should match the fourth parameter passed to add_settings_section() and add_settings_field(), and also the one passed to do_settings_sections(). In your add_submenu_page() call, the menu/page slug is feature-sale, but with the other three functions, you set it to feature-sale-admin.
And using wp_nonce_field() is recommended, but in your case, it's not necessary since you're submitting to wp-admin/options.php. Unless of course, you want to check that prior to WordPress saving the options. But even so, I believe one nonce field is good. :)

Move custom column admin links from below "post title"

It seems I can't figure out how to add the edit, remove, view, etc... to one of my custom columns in the backend of wordpress. The idea is to get the links that are attached to title when one hovers over the title, to be attached to a different column.
This is what the below code outputs.
This is what I want the link in the authors column have when mouse is hovered over the authors, just like when you hover over the title in this screenshot; all the edit links.
This is what I have so far:
add_filter( 'manage_edit-testimonial-quotes_columns', 'view_columns' ) ;
function view_columns( $columns ) {
$columns = array(
'cb' => '',
'date' => __( 'Date' ),
'tq_author' => __( 'Author' ),
'tq_quote' => __( 'Testimonial' ),
);
return $columns;
}
add_action('manage_testimonial-quotes_posts_custom_column', 'custom_view_columns', 10, 2);
function custom_view_columns($column, $post_id){
global $post;
switch ($column){
case 'tq_author':
echo '<a href="post.php?post=' . $post->ID . '&action=edit">';
$column_content = the_field('tq_author');
echo $column_content;
echo '</a>';
break;
case 'tq_quote':
$column_content = the_field('tq_quote');
echo $column_content;
break;
default:
break;
}
}
The best way of doing this since WP 4.3.0 is using
add_filter( 'list_table_primary_column', [ $this, 'list_table_primary_column' ], 10, 2 );
public function list_table_primary_column( $default, $screen ) {
if ( 'edit-yourpostype' === $screen ) {
$default = 'yourcolumn';
}
return $default;
}
I really doubt that there's a hook to deal with that. So, I'll not even check the core and go straight to the dirty solution:
add_action( 'admin_head-edit.php', 'so_13418722_move_quick_edit_links' );
function so_13418722_move_quick_edit_links()
{
global $current_screen;
if( 'post' != $current_screen->post_type )
return;
if( current_user_can( 'delete_plugins' ) )
{
?>
<script type="text/javascript">
function so_13418722_doMove()
{
jQuery('td.post-title.page-title.column-title div.row-actions').each(function() {
var $list = jQuery(this);
var $firstChecked = $list.parent().parent().find('td.author.column-author');
if ( !$firstChecked.html() )
return;
$list.appendTo($firstChecked);
});
}
jQuery(document).ready(function ($){
so_13418722_doMove();
});
</script>
<?php
}
}
Result:
Notes:
adjust your post_type: 'post' != $current_screen->post_type
adjust your column classes: find('td.author.column-author')
Bug and solution:
You'll note that, after updating, the quick-edit menu goes back to its original position. The following AJAX interception deals with it. Refer to this WordPress Developers answer for more details.
add_action( 'wp_ajax_inline-save', 'so_13418722_ajax_inline_save' , 0 );
/**
Copy of the function wp_ajax_inline_save()
http://core.trac.wordpress.org/browser/tags/3.4.2/wp-admin/includes/ajax-actions.php#L1315
Only Modification marked at the end of the function with INTERCEPT
*/
function so_13418722_ajax_inline_save()
{
global $wp_list_table;
check_ajax_referer( 'inlineeditnonce', '_inline_edit' );
if ( ! isset($_POST['post_ID']) || ! ( $post_ID = (int) $_POST['post_ID'] ) )
wp_die();
if ( 'page' == $_POST['post_type'] ) {
if ( ! current_user_can( 'edit_page', $post_ID ) )
wp_die( __( 'You are not allowed to edit this page.' ) );
} else {
if ( ! current_user_can( 'edit_post', $post_ID ) )
wp_die( __( 'You are not allowed to edit this post.' ) );
}
set_current_screen( $_POST['screen'] );
if ( $last = wp_check_post_lock( $post_ID ) ) {
$last_user = get_userdata( $last );
$last_user_name = $last_user ? $last_user->display_name : __( 'Someone' );
printf( $_POST['post_type'] == 'page' ? __( 'Saving is disabled: %s is currently editing this page.' ) : __( 'Saving is disabled: %s is currently editing this post.' ), esc_html( $last_user_name ) );
wp_die();
}
$data = &$_POST;
$post = get_post( $post_ID, ARRAY_A );
$post = add_magic_quotes($post); //since it is from db
$data['content'] = $post['post_content'];
$data['excerpt'] = $post['post_excerpt'];
// rename
$data['user_ID'] = $GLOBALS['user_ID'];
if ( isset($data['post_parent']) )
$data['parent_id'] = $data['post_parent'];
// status
if ( isset($data['keep_private']) && 'private' == $data['keep_private'] )
$data['post_status'] = 'private';
else
$data['post_status'] = $data['_status'];
if ( empty($data['comment_status']) )
$data['comment_status'] = 'closed';
if ( empty($data['ping_status']) )
$data['ping_status'] = 'closed';
// update the post
edit_post();
$wp_list_table = _get_list_table('WP_Posts_List_Table');
$mode = $_POST['post_view'];
$wp_list_table->display_rows( array( get_post( $_POST['post_ID'] ) ) );
// INTERCEPT: Check if it is our post_type, if not, do nothing
if( 'post' == $_POST['post_type'] )
{
?>
<script type="text/javascript">so_13418722_doMove();</script>
<?php
}
// end INTERCEPT
wp_die();
}
I had the same need.
Nicola's solution worked for me except I was getting an "Undefined variable" notice/error. Then I realized that the parameter has to be without the "[$this ... ]" part.
I guess that was a copy/paste from the documentation.
So this worked:
add_filter( 'list_table_primary_column', 'list_table_primary_column', 10, 2 );
function list_table_primary_column( $default, $screen ) {
if ( 'edit-your_post_type' === $screen ) {
// Set default columns to Minutes Spent.
$default = 'your_column';
}
return $default;
}
If you don't know what your_column is, just inspect the title of that column and get the ID.
You can't move the actions per se without resorting to JS, as the accepted answer does. However, you can very easily build your own version of the actions popup with php and inbuilt Wordpress functions. This version will work even if the user has JS turned off.
Presuming you use a switch to populate your custom columns, do something likes this, if not adapt to your own function:
switch ( $column ) {
case 'your_column_name':
echo "Your custom content here";
my_custom_column_actions($post_id);
break;
}
Then have a separate function that recreates the actions popup.
function my_custom_column_actions($post_id) {
if($_GET['post_status']!='trash') :
$bare_url = "/wp-admin/post.php?post=$post_id&action=trash";
$nonce_url = wp_nonce_url( $bare_url, 'trash-post_'.$post_id );
echo " <div class='row-actions'>
<span class='edit'>
<a href='/wp-admin/post.php?post=$post_id&action=edit'>Edit</a> |
</span>
<span class='trash'>
<a href='$nonce_url' class='submitdelete'>Trash</a>
</span>
<span class='edit'>
<a href='".get_the_permalink($post_id)."'>View</a> |
</span>
</div>";
else:
$bare_url = "/wp-admin/post.php?post=$post_id&action=untrash";
$nonce_url = wp_nonce_url( $bare_url, 'untrash-post_'.$post_id );
$delete_url = "/wp-admin/post.php?post=$post_id&action=delete";
$nonce_delete_url = wp_nonce_url( $delete_url, 'delete-post_'.$post_id );
echo " <div class='row-actions'>
<span class='untrash'>
<a href='$nonce_url' class='untrash'>Restore</a> |
</span>
<span class='delete'>
<a href='$nonce_delete_url' class='submitdelete'>Delete Permanently</a>
</span>
</div>";
endif;
}
All the business with nonce_urls is important for trashing, restoring or deleting; these actions won't work without it.
If you want to include this on a column that would normally appear, e.g. author or date published, you'll need to not include the standard column when you're declaring your custom columns and instead include a custom column that gets the same data (plus a call to the function above).
The same goes for if you want to include the title but not have the actions appear under it - otherwise they'll appear twice. Don't include the title column and instead include your own custom column that grabs the title but not the new function.
You can also very easily add your own actions by just editing the content that the function echoes.

Resources