WP tends to load a lot of things with ajax admin, but what I need is to only load it to use basic ajax with my own calls and functions.
This posts says:
<?php
//mimic the actuall admin-ajax
define('DOING_AJAX', true);
if (!isset( $_POST['action']))
die('-1');
//make sure you update this line
//to the relative location of the wp-load.php
require_once('../../../../../wp-load.php');
//Typical headers
header('Content-Type: text/html');
send_nosniff_header();
//Disable caching
header('Cache-Control: no-cache');
header('Pragma: no-cache');
$action = esc_attr(trim($_POST['action']));
//A bit of security
$allowed_actions = array(
'my_allow_action_1',
'my_allow_action_2',
'my_allow_action_3',
'my_allow_action_4',
'my_allow_action_5'
);
if(in_array($action, $allowed_actions)){
if(is_user_logged_in())
do_action('MY_AJAX_HANDLER_'.$action);
else
do_action('MY_AJAX_HANDLER_nopriv_'.$action);
}
else{
die('-1');
}
And it says:
Next we Only need to hook our callbacks to this handler like so:
//For logged in users
add_action('MY_AJAX_HANDLER_{$action_name}','function_callback_name');
//For logged out users
add_action('MY_AJAX_HANDLER_nopriv_{$action_name}','function_callback_name');
Finally says :
jQuery(document).ready(function($){
var data={
action:'action_name',
otherData: 'otherValue'
};
$.post('http://url/to/your/MY_CUSTOM_AJAX.php', data, function(response){
alert(response);
});
});
But I got confused, as I don't know what it means with SOME CUSTOM TEXT or how it is handling the variables etc, this is how I currently do:
function.php
add_action( 'wp_ajax_nopriv_data_fetch', 'data_fetch' );
add_action('wp_ajax_data_fetch' , 'data_fetch');
function data_fetch(){
$dates = $_POST['dates'];
$dates = explode(',', $dates);
$args = array(
'meta_query' => array(
array(
'key' => 'anno',
'value' => array($dates[0], $dates[1]),
'compare' => 'BETWEEN',
'no_found_rows' => true,
'update_post_meta_cache' => false,
'update_post_term_cache' => false,
'type' => 'NUMERIC'
),
)
);
$query = new WP_Query( $args );
if( $query->have_posts() ):
$coordinates = [];
$links = [];
while( $query->have_posts() ) : $query->the_post();
$id = get_the_ID();
$location = get_field('location');
$lat = $location['lat'];
$lng = $location['lng'];
$title = get_the_title($id);
if ( ! add_post_meta( $id, 'latitude', $lat, true) ) {
delete_post_meta($id, 'latitude');
update_post_meta($id, 'latitude', $lat, true);
}
if ( ! add_post_meta( $id, 'longitude', $lng, true) ) {
delete_post_meta($id, 'longitude');
update_post_meta($id, 'longitude', $lng, true);
}
$latitude = get_field('latitude');
$longitude = get_field('longitude');
$coordinates[] = $latitude.", ".$longitude;
$links[] = get_permalink();
$anno = get_field('anno');
$site[] = get_field("site_name", "option", true);
$contentProprierty[] = array("links"=>$links, "coordinates"=>$coordinates, "anno"=>$anno, "ids"=>$id, "site"=>$site, "title"=>$title);
endwhile;
echo json_encode($contentProprierty);
die;
endif;
wp_die();
}
JS in front end:
var ajax_url = '<?php echo admin_url( 'admin-ajax.php' ); ?>';
$.ajax({
url : ajax_url,
type: 'post',
dataType: 'json',
data: {
action: 'data_fetch', dates: datesSearch
},
success: function(data) {
for (var i = 0; i < data.length; i++) {
coords.push(data[i].coordinates[i]);
links.push(data[i].links[i]);
years.push([data[i].anno]);
ids.push(data[i].ids);
titles.push(data[i].title);
currentSite.push("curr");
site.push(thisSiteName);
};
}
});
How would I implement the custom ajax in order not to load the whole thing wp does with its own ajax admin?
add_action('MY_AJAX_HANDLER_{$action_name}','function_callback_name');
//For logged out users
add_action('MY_AJAX_HANDLER_nopriv_{$action_name}','function_callback_name');
These action hooks only call data related to your current ajax function nothing else you can use wp_nonce_field to secure your function from hacking and securing the site. inside the function.
Related
I need to show a counter within my single page post (I use it as a shortcode).
I have a custom post type (slug = 'portfolio') that has different categories.
When I am in the single post, I want to display a counter such as "n/tot" where
n = number of post (first post within the category = 1; second post= 2 etc)
tot = total number of posts within that category
I found the way to show the total number of posts, but not within a category
add_shortcode( 'tot_posts', 'number_factsheets' );
function number_factsheets () {
$total = wp_count_posts('portfolio')->publish;
$output = '<div class="count">';
$output .= $total;
$output .='</div>';
return $output;
}
Is it possible to obtain the data above when I am in single page post? And how?
WORKING CODE FOR RETRIEVING NUMBER OF SINGLE CUSTOM POST TYPE OVER TOTAL NUMBER OF CPT WITHIN A SPECIFIC CATEGORY
add_shortcode('post-counter', 'get_current_post_num');
function get_current_post_num() {
$url = $_SERVER['REQUEST_URI'];
$curr_post_id = url_to_postid( "https://sharkrayareas.org".$url ); //Too early for $post object
$taxonomy = 'portfolio_entries';
$term_objs = get_the_terms( $curr_post_id->ID, $taxonomy );
foreach ($term_objs as $term_obj)
$term_ids = $term_obj->term_id; // get the id from the WP_Term object
$args = array(
'post_type' => 'portfolio',
'post_status' => 'publish',
'tax_query' => array(
array(
'taxonomy' => 'portfolio_entries',
'terms' => $term_ids,
),
),
'order'=> 'ASC',
'posts_per_page' => -1
);
$portfolio_posts = new WP_Query($args);
if ($portfolio_posts->have_posts()):
echo 'true';
$total_posts = $portfolio_posts->found_posts;
$num = 1;
while ($portfolio_posts->have_posts()) : $portfolio_posts->the_post();
$post_id = get_the_ID();
if ($post_id === $curr_post_id) {
$output= '<div class="count">'. $num . '/' . $total_posts .'</div>';
} else {
$num++;
}
endwhile;
endif;
return $output;
}
I recommend going about that by looping through the posts and checking whether the the page you are on is that point in the loop. I'm including an example that prints it on-page.
add_action('init', 'get_current_post_num');
function get_current_post_num() {
$url = $_SERVER['SERVER_NAME'].$_SERVER['REQUEST_URI'];
$curr_post_id = url_to_postid( "https://".$url ); //Too early for $post object so get $curr_post_id from url_to_postid
$args = array(
'post_type' => 'portfolio',
'post_status' => 'publish',
'posts_per_page' => -1
);
$portfolio_posts = new WP_Query($args);
if ($portfolio_posts->have_posts()):
$total_posts = $portfolio_posts->found_posts;
$num = 1;
while ($portfolio_posts->have_posts()) : $portfolio_posts->the_post();
$post_id = get_the_ID();
if ($post_id === $curr_post_id) {
echo $num . '/' . $total_posts;
} else {
$num++;
}
endwhile;
endif;
}
My custom post type "references" has a custom field called "references_count". It has a numeric value.
I have an custom taxonomy called "country" with a custom field called "country_count" for the terms.
Background:
The custom post type "references" saves cities with a number of clients in this city. This value is saved in the field "references_count". In the custom taxonomy there are countries. For each country, there is a total number of references.
Example:
In the city of "Berlin" there are 3 clients. In the city of "Munich" there are 2 clients. The taxonomy term "Germany" includes the sum of all cities in this country. So the value of "country_count" in this example for the taxonomy term "Germany" is 5, being the sum of the references of each city.
I wrote this code which is working, if I'm saving each individual taxonomy term.
add_action( 'edited_country', 'update_counter_for_countries', 10, 2 );
function update_counter_for_countries( $term_id ) {
// Get posts with term
$args = array(
'post_type' => 'reference',
'posts_per_page' => -1,
'tax_query' => array(
array(
'taxonomy' => 'country',
'field' => 'term_id',
'terms' => $term_id
)
)
);
$the_query = new WP_Query( $args );
// sum values in posts
$sumTerm = 0;
if ( $the_query->have_posts() ) {
while ( $the_query->have_posts() ) {
$the_query->the_post();
$number = get_field( 'references_count', get_the_ID() );
$sumTerm = $sumTerm + $number;
}
}
wp_reset_postdata();
// update field in term
update_field( 'country_count', $sumTerm, 'country'.'_'.$term_id );
}
Problem:
I have more than 100 countries (taxonomy terms), so I have to save each term individually to get things going.
What I am looking for: Is there a way to update / save all custom taxonomy terms at once, so I don't have to update each term seperately? I checked out a lot of plugins, but couldn't find any plugin which gives the possibility of "bulk edit" or "bulk save" taxonomy terms. I would prefer a solution without plugin if possible. I am very grateful for any hint, thank you very much.
You can use this code to update all terms in one go.
Just make sure to backup your database in case needed.
This code will loop through all the terms and will only run once. after that you can remove this code.
Just to make this code run only on your IP, change 111.111.111.111 to your IP ADDRESS.
if($_SERVER["REMOTE_ADDR"]=='111.111.111.111'){
//run only my ip
add_action("init","update_all_terms_in_one_go");
}
function update_all_terms_in_one_go(){
session_start();
if(isset($_SESSION['all_terms_updated']) && $_SESSION['all_terms_updated'] == "done"){
return;
}
$taxonomy = "country";
$terms = get_terms([
'taxonomy' => $taxonomy,
'hide_empty' => false,
]);
foreach ($terms as $term) {
update_counter_for_countries( $term->term_id );
}
$_SESSION['all_terms_updated'] = "done";
echo "ALL TAXONOMY TERMS UPDATED";
die();
}
function update_counter_for_countries( $term_id ) {
// Get posts with term
$args = array(
'post_type' => 'reference',
'posts_per_page' => -1,
'tax_query' => array(
array(
'taxonomy' => 'country',
'field' => 'term_id',
'terms' => $term_id
)
)
);
$the_query = new WP_Query( $args );
// sum values in posts
$sumTerm = 0;
if ( $the_query->have_posts() ) {
while ( $the_query->have_posts() ) {
$the_query->the_post();
$number = get_field( 'references_count', get_the_ID() );
$sumTerm = $sumTerm + $number;
}
}
wp_reset_postdata();
// update field in term
update_field( 'country_count', $sumTerm, 'country'.'_'.$term_id );
}
I wanted to have a neat admin page with a button to bulk update all my taxonomy terms. The process should work using AJAX so it can take a while without confusing the user. There should be status messages.
So in the first step I added a new admin page to the wordpress backend.
add_action( 'admin_menu', array( $this, 'my_admin_page' ) );
function my_admin_page() {
add_menu_page(
__('Bulk Terms'), // page title
__('Bulk Terms'), // menu title
'manage_options', // user capabilities
'options-page', // menu slug
'my_output_function', // output function
'dashicons-admin-generic', // menu icon
77 // menu position
);
}
In the output function I put a form with a button to bulk update terms. And some status messages.
function my_output_function() {
echo '<div class="wrap">';
echo '<form action="admin.php?page=options-page" method="post">';
wp_nonce_field( 'ajax_validation', 'nonce' ); // security feature
submit_button('Update Terms', 'primary', 'submitOptions', false);
echo '</form>';
echo '<div id="processing" style="display:none;">Please wait</div>';
echo '<div id="error" style="display:none;">Something went wrong</div>';
echo '<div id="success" style="display:none;">Done!</div>';
echo '</div>';
}
In the second step I had to enqueue script file for ajax calls:
add_action( 'admin_enqueue_scripts', 'my_ajax_scripts' );
function my_ajax_scripts() {
// Check if on specific admin page
global $pagenow;
if (( $pagenow == 'admin.php' ) && ($_GET['page'] == 'options-page')):
wp_enqueue_script( 'ajaxcalls', plugin_dir_url( __FILE__ ).'/js/ajax-calls.js', array('jquery'), '1.0.0', true );
wp_localize_script( 'ajaxcalls', 'ajax_object', array(
'ajaxurl' => admin_url( 'admin-ajax.php' ),
'ajaxnonce' => wp_create_nonce( 'ajax_validation' )
) );
endif;
}
And create the function to bulk update all my taxnomy terms:
function options_page_action() {
$taxonomy = "country";
$terms = get_terms([
'taxonomy' => $taxonomy,
'hide_empty' => false,
]);
foreach ($terms as $term) {
$term_id = $term->term_id;
// Get posts with term
$args = array(
'post_type' => 'reference',
'posts_per_page' => -1,
'tax_query' => array(
array(
'taxonomy' => 'country',
'field' => 'term_id',
'terms' => $term_id
)
)
);
$the_query = new WP_Query( $args );
// sum values in posts
$sumTerm = 0;
if ( $the_query->have_posts() ) {
while ( $the_query->have_posts() ) {
$the_query->the_post();
$number = get_field( 'references_count', get_the_ID() );
$sumTerm = $sumTerm + $number;
}
}
wp_reset_postdata();
// update field in term
update_field( 'country_count', $sumTerm, 'country'.'_'.$term_id );
}
$result = array( 'status' => 'success' ); // create response
wp_send_json_success( $result ); // send response
wp_die(); // close ajax request
}
As the third step, in my ajax_calls.js file I take the click event to call the function for updating the taxonomy terms using ajax.
$( '#submitOptions' ).click( function(event) {
event.preventDefault();
$('#submitOptions').css('cssText','display:none;');
$('#processing').css('cssText','display: block;');
$.ajax({
type: 'POST',
url: ajax_object.ajaxurl,
data: {
action: 'options_page_action',
nonce: ajax_object.ajaxnonce
},
success: function( response ) {
if( response['data']['status'] == 'success' ) {
$('#processing').css('cssText','display:none;');
$('#success').css('cssText','display:block;');
}
},
error: function() {
$('#processing').css('cssText','display:none;');
$('#error').css('cssText','display:block;');
}
});
});
There are messages indicating that the function is running and it show messages when it's done or has an error. This way the user will always know what's going on when bulk updating terms.
Some people suggested using /posts?tags=tag_id_1,tag_id_2 or /posts?tags[]=tag_id_1&tags[]=tag_id_2
but wordpress seems to be returning posts that are tagged either with tag1 OR tag2. What I actually need is posts tagged with tag1 AND tag2.
Anyone has an idea?
I will share with you what I have done.
I created a new endpoint for my custom needs,
which ends like myapi/v1/posts/tag1/tag2
add_action('rest_api_init', function () {
register_rest_route( 'myapi/v1', 'posts/(?P<tag_1>[-\w]+)/(?P<tag_2>[-\w]+)',array(
'methods' => 'GET',
'callback' => 'get_posts_set'
));
});
Then, created
function get_posts_set($request) {
$args = array(
'category_name' => $request['category_name'],
'tag_slug__and' => array( $request['tag_1'],$request['tag_2'] ),
);
$posts = get_posts($args);
if (empty($posts)) {
return new WP_Error( 'empty_category', 'there is no post in this category', array('status' => 404) );
}
// Following code is my processing of output. Customize it to suit your needs
$post_data = array();
$i = 0;
foreach( $posts as $post) {
$post_id = $post->ID;
$post_title = remove_html_comments($post->post_title);
$post_content = remove_html_comments($post->post_content);
$post_data[ $i ][ 'id' ] = $post_id;
$post_data[ $i ][ 'title' ] = $post_title;
$post_data[ $i ][ 'content' ] = $post_content;
$i++;
}
$response = new WP_REST_Response($post_data);
$response->set_status(200);
return $response;
}
function remove_html_comments($content = '') {
return preg_replace('/<!--(.|\s)*?-->/', '', $content);
}
This will return only the PostID, Post Title and Post Content with HTML formatting for direcr reuse. Hope this solves your question.
I wrote a plugin, which reads csv files and create new products. The plugin works when I create only one product but when I add while in Insert() the plugin doesn't work. I want to create all products first off. Maybe it's something related to the add_action... Please help.
define( 'PLUGIN_DIR', dirname(__FILE__).'/' );
function CreateProduct($line) {
$data = explode('";"', $line);
define(POST_NAME, $data[2]);
define(cena_netto_pw, $data[5]);
$post = get_page_by_title( POST_NAME, 'OBJECT', 'product' );
$product_ID = $post->ID;
$post_data = get_post($product_ID);
function hbt_create_post() {
$my_post = array(
'post_title' => POST_NAME,
'post_content' => '',
'post_status' => 'publish',
'post_author' => 1,
'post_type' =>'product'
);
$product_ID = wp_insert_post( $my_post );
}
if(!isset($post))
hbt_create_post();
return $error_obj;
}
function Import() {
$file = PLUGIN_DIR.'test.csv';
$open = fopen($file, 'r');
while (!feof($open)) {
$line = fgets($open);
CreateProduct($line);
}
fclose($open);
}
add_action('admin_init', 'Import' );
?>
While loop code
while (!feof($open)) { $line = fgets($open); CreateProduct($line); }
This code doesn't work. It works when there is only
$line = fgets($open); CreateProduct($line);
try
fgetcsv($open)
instead
fgets($open)
I'm displaying the userpicture on a node with this code here:
<?php
$user_load = user_load($node->uid);
$imgtag = theme('imagecache', 'avatar_node', $user_load->picture, $user_load->name, $user_load->name);
$attributes = array('attributes' => array('title' => t('View user profile.')), 'html' => TRUE);
print l($imgtag, 'u/'.$user_load->name, $attributes);
?>
This works great, except if the user doesn't have a picture, in which case it looks strange.
How do I load the default picture if the user doesn't have a picture.
I don't believe I have access to $picture in this block.
Thanks in advance.
$user_load = user_load($node->uid);
$picture = $user_load->picture ? $user_load->picture : variable_get('user_picture_default', ''); //
$imgtag = theme('imagecache', 'avatar_node', $picture, $user_load->name, $user_load->name);
$attributes = array('attributes' => array('title' => t('View user profile.')), 'html' => TRUE);
print l($imgtag, 'u/'.$user_load->name, $attributes);
if you copy default picture to files directory, you can determine it via http://api.drupal.org/api/function/file_directory_path/6
This is what I'm using for a similar situation:
if (!empty($user->picture) && file_exists($user->picture)) {
$picture = file_create_url($user->picture);
}
else if (variable_get('user_picture_default', '')) {
$picture = variable_get('user_picture_default', '');
}
if (isset($picture)) {
$alt = t("#user's picture", array('#user' => $user->name ? $user->name : variable_get('anonymous', t('Anonymous'))));
$picture = theme('image', $picture, $alt, $alt, '', FALSE);
if (!empty($user->uid) && user_access('access user profiles')) {
$attributes = array(
'attributes' => array('title' => t('View user profile.')),
'html' => TRUE,
);
echo l($picture, "user/$user->uid", $attributes);
}
}
It is adapted from http://api.drupal.org/api/drupal/modules%21user%21user.module/function/template_preprocess_user_picture/6
In Drupal 7 I use:
global $user;
file_create_url( file_load($user->picture)->uri)