Wordpress JSON api fetch selected items - wordpress

How can I fetch only post title, excerpt of all the posts of my WordPress blog using JSON api.
Currently, I am using https://www.example.com/wp-json/wp/v2/posts, which returns a lot of data that slows down the whole process. Is there any url where I can fetch only selected fields?

Have you considered writing your own API endpoints? https://developer.wordpress.org/rest-api/extending-the-rest-api/adding-custom-endpoints/
Something like this would probably work for you where your endpoint becomes http://example.com/wp-json/myplugin/v1/post-titles:
function my_awesome_func( $data ) {
$args = array(
'post_type' => 'post',
);
$query = new WP_Query( $args );
$arr = array();
while ( $query->have_posts() ) {
$query->the_post();
$titles = get_the_title();
array_push($arr, $titles);
}
return $arr;
}
add_action( 'rest_api_init', function () {
register_rest_route( 'myplugin/v1', '/post-titles', array(
'methods' => 'GET',
'callback' => 'my_awesome_func',
) );
} );

Related

WordPress XMLRPC - Search Post by Slug and Update

Is there anyway to search posts by slug through XMLRPC
https://codex.wordpress.org/XML-RPC_WordPress_API/Posts#wp.getPosts
getPosts() doesn't seem to return using "name"..
$args = array(
'name' => 'my-slug',
'number' => 1
);
$post = $wpClient->getPosts( $args );
Please let me know if there is a workaround for this, I need to search by slug and then update those slugs remotely via XMLRPC. cheers
I ended up using Methods, this may help someone and save time.. paste the following code in functions.php of the domain you are fetching data from
add_filter('xmlrpc_methods', 'clx_xmlrpc_methods');
function clx_xmlrpc_methods($methods) {
$methods['getPostBySlug'] = 'clx_getpost';
return $methods;
}
function clx_getpost($args) {
global $wp_xmlrpc_server;
$slug = $args["slug"];
$pargs = array(
'name' => $slug,
'post_type' => 'post',
'numberposts' => 1
);
$my_posts = get_posts($pargs);
if( $my_posts ) :
return $my_posts; //echo $my_posts[0]->ID;
endif;
}
from your XMLRPC code use the following to get POST array from slug
$args = array(
'slug' => 'your-post-slug'
);
$postArray = $wpClient->callCustomMethod( 'getPostBySlug', $args );

Bulk update all taxonomy terms in wordpress

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.

Wordpress REST API: How to retrieve posts tagged by multiple tags?

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.

wordpress expose menus to the rest api

Hi I'm trying to expose the WordPress menus to the rest api, but I want to make it generic, so I can crate expose any menus with the same code, but something is wrong with my code, t always show Json.pase error, I don't know how to solve this.
here is my code.
//define all the menu positions I need
$menus = array(
'main-menu' => __( 'Main Menu' ),
'other-menu' => __( 'Other Menu' )
);
function register_menus() {
//register the menus in the backend
global $menus;
register_nav_menus($menus);
}
add_action( 'init', 'register_menus' );
add_action( 'rest_api_init', function () {
// create custom route to expose the menus
register_rest_route( 'wp_ang/v1', '/menu', array(
'methods' => 'GET',
'callback' => 'get_menu_items',
)
);
}
);
function get_menu_items() {
// callback to get menus and its items
global $menus;
$rest_menu = [];
foreach ($menus as $key => $value){
$menu_name = $key;
$menu_location = get_nav_menu_locations( );
$menu = wp_get_nav_menu_object( $menu_location[$menu_name] );
$menu_items = wp_get_nav_menu_items( $menu->term_id );
}
return $menus;
}
Then I have this error as a result:
SyntaxError: JSON.parse: unexpected character at line 1 column 1 of
the JSON data

$wp_query and WP_QUERY - same arguments, different results

I spend this whole day trying to figure out a problem with a combination of a custom query and custom post types. This is my last resort...
The setting
I wrote a plugin that introduces some custom post types to my WordPress. To display them in the main query I hooked them into the query like this:
function add_cpt_to_query( $query ) {
*some code...*
// add custom post types to query
if ( !( is_admin() || is_post_type_archive() || is_page() ) && $query->is_main_query() ) {
$query->set('post_type', array_merge( array('post'), $cpt ) );
}
}
add_action('pre_get_posts','add_cpt_to_query');
In my theme on the other hand I setup ajax pagination like this:
function setup_pagination() {
global $wp_query;
$max_pages = $wp_query->max_num_pages;
$current_page = ( $wp_query->paged > 1 ) ? $wp_query->paged : 1;
$ajaxurl = admin_url( 'admin-ajax.php' );
wp_register_script( 'ajax-pagination', get_template_directory_uri() .'/js/dummy.js', array('jquery'), '', true);
wp_localize_script( 'ajax-pagination', 'ajaxpagination', array(
'max_pages' => $max_pages,
'current_page' => $current_page,
'ajaxurl' => $ajaxurl,
'query_vars' => $wp_query->query_vars
));
wp_enqueue_script( 'ajax-pagination' );
}
add_action( 'wp_enqueue_scripts', 'setup_pagination' );
function pagination() {
$query = $_POST['query_vars'];
$query['paged'] = $_POST['next_page'];
/*
$query = array(
'paged' => 2,
'post_type' => array('post', 'custom_post_type_1', 'custom_post_type_2' )
);
*/
$posts = new WP_Query( $query );
$GLOBALS['wp_query'] = $posts;
// Start the loop.
while ( have_posts() ) : the_post();
?>
*some code...*
<?php endwhile;
die();
}
add_action( 'wp_ajax_nopriv_ajax_pagination', 'pagination' );
add_action( 'wp_ajax_ajax_pagination', 'pagination' );
and the script part:
$.ajax({
url: ajaxpagination.ajaxurl,
type: 'post',
data: {
action: 'ajax_pagination',
query_vars: ajaxpagination.query_vars,
next_page: parseInt(ajaxpagination.current_page) + 1
}
});
The problem
If I pass the query_vars array I get from $wp_query with the altered 'paged' value back to WP_QUERY, it returns the wrong set of posts. It looks like, that WP_QUERY does not account for the cpts in the loop. Though these cpts are mentioned in the 'post_type' of the query_vars array and thereby passed along to the new WP_QUERY.
When I manually set 'post_type' and only pass this argument, it works as intended. The aspect that blows my mind is, that the resulting query_vars used in the ajax call to WP_QUERY are exactly the same, but only when I manually set 'post_type' the pagination works as it should.
I dont know if this was a somewhat understandable explanation, but I'm thankful for every idea that could help me out. Big THX!
Ok... I got it now.
I made a mistake in wp_localize_script(). The query_vars should be a json-string, I on the other hand just passed the array itself. My code above has to be altered in two lines:
function mk_setup_pagination() {
...
wp_localize_script( 'ajax-pagination', 'ajaxpagination', array(
...
'query_vars' => json_encode($wp_query->query_vars) <- convert to json-string
));
...
}
function mk_pagination() {
$query = json_decode( stripslashes( $_POST['query_vars'] ) , true); <- convert json-string to array
...
Works like a charm now. :)
btw: the code is based on a tutorial by wpmudev.org: Loading WordPress Posts Dynamically With AJAX

Resources