Adding ACF to CUSTOM wp api endpoints - php

I'm writing a custom endpoint for WP API, to retrieve posts from wordpress that for example are from the 'real_estate' post_type and capacity for '5 or more' persons.
I've built a new custom endpoint:
// permite que meta_key e meta_value
// sejam filtrados pela api
function filtros( $valid_vars ) {
$valid_vars = array_merge(
$valid_vars,
array(
'meta_key',
'meta_value' ) );
return $valid_vars;
}
add_filter( 'rest_query_vars', 'filtros' );
// funcção que retorna posts do autor
function busca( $data ) {
$posts = get_posts(array(
'post_type' => 'imoveis',
'posts_per_page' => '1000',
'meta_query' => array(
'relation' => 'AND',
array(
'key' => 'transacao',
'value' => $data['tipo']
),
array(
'key' => 'quartos',
'value' => $data['quartos'],
'compare' => '>'
)
)
));
if ( empty( $posts ) ) {
return new WP_Error( 'sem resultados', 'quartos: ' . $data['quartos'] . ' transacao: '. $data['tipo'], array( 'status' => 404 ) );
}
return $posts;
}
// cria o endpoint que ira receber a função acima
add_action( 'rest_api_init', function () {
register_rest_route( 'busca/v2', '/resultado/(?P<tipo>.+)/(?P<quartos>\d+)',
array(
'methods' => 'GET',
'callback' => 'busca',
)
);
});
The search is fine, it's working, i'm filtering by transaction type (sale or rent) and number of rooms in each real estate.
But my JSON response is missing a lot of fields, including ACF.
EX:
{
"ID":149,
"post_author":"2",
"post_date":"2016-03-03 23:53:39",
"post_date_gmt":"2016-03-03 23:53:39",
"post_content":"",
"post_title":"Oportunidade do Ano",
"post_excerpt":"",
"post_status":"publish",
"comment_status":"closed",
"ping_status":"closed",
"post_password":"",
"post_name":"oportunidade-do-ano",
"to_ping":"",
"pinged":"",
"post_modified":"2016-03-03 23:53:39",
"post_modified_gmt":"2016-03-03 23:53:39",
"post_content_filtered":"",
"post_parent":0,
"guid":"http://raphaelk.co/api/?post_type=imoveis&p=149",
"menu_order":0,
"post_type":"imoveis",
"post_mime_type":"",
"comment_count":"0",
"filter":"raw"
},
Do you guys have any idea how can i change that response? And include ACF to it.
Thank you

Did you try to simply use the ACF function get_fields ?
In your "busca" function, after get_posts(), if $posts isn't empty, retrieve acf fields for each posts like this :
if ( empty( $posts ) ) {
return new WP_Error( 'sem resultados', 'quartos: ' . $data['quartos'] . ' transacao: '. $data['tipo'], array( 'status' => 404 ) );
} else {
foreach ($posts as $key => $post) {
$posts[$key]->acf = get_fields($post->ID);
}
}
Hopefully that'll do it !

Related

How do I query related product post title instead of whole post object array the WordPress query?

How do I query related product post title instead of the whole post object array in my WordPress query below?
$product_search = $_GET['s'];
$related_product = get_field( 'related_products' ); // This is an ACF relationship field so I can link products to articles and display teh related article in search.php from the product page
$knowledge_args = array(
'post_type' => 'knowledge_hub',
'fields' => 'ids',
'posts_per_page' => -1,
'meta_query' => array(
'key' => $related_product, // How do I query related product post title instead of whole post object array?
'value' => $product_search,
'compare' => 'LIKE'
)
);
$relatedProductArticles = new WP_Query($knowledge_args);
You could do that by manipulating the sql "WHERE" clause.
Create a custom function that does the filtering for you!
Add the argument that our custom function is looking for
Add the filter right before the custom WP_Query
Remove the filter after WP_Query
So you could write a the custom function in your functions.php like so:
function related_products_title_filter($where, $wp_query)
{
global $wpdb;
if ($searched_term = $wp_query->get('my_custom_search_filter_title')) {
$where .= ' AND ' . $wpdb->posts . '.post_title LIKE \'%' . esc_sql(like_escape($searched_term)) . '%\'';
}
return $where;
}
Add a custom argument to the arguments:
$knowledge_args = array(
'my_custom_search_filter_title' => $product_search, // This is the custom argument that our function is looking for
'post_type' => 'knowledge_hub',
'fields' => 'ids',
'posts_per_page' => -1,
'meta_query' => array(
array(
'key' => $related_product,
'value' => $product_search,
'compare' => 'LIKE'
)
)
);
Add the filter right before the custom WP_Query:
add_filter('posts_where', 'related_products_title_filter', 10, 2);
Remove the filter after WP_Query
remove_filter('posts_where', 'related_products_title_filter', 10, 2);
So your entire code would be something like this:
function related_products_title_filter($where, $wp_query)
{
global $wpdb;
if ($searched_term = $wp_query->get('my_custom_search_filter_title')) {
$where .= ' AND ' . $wpdb->posts . '.post_title LIKE \'%' . esc_sql(like_escape($searched_term)) . '%\'';
}
return $where;
}
$product_search = sanitize_text_field($_GET['s']);
$related_product = get_field( 'related_products' );
$knowledge_args = array(
'my_custom_search_filter_title' => $product_search,
'post_type' => 'knowledge_hub',
'fields' => 'ids',
'posts_per_page' => -1,
'meta_query' => array(
array(
'key' => $related_product,
'value' => $product_search,
'compare' => 'LIKE'
)
)
);
add_filter('posts_where', 'related_products_title_filter', 10, 2);
$relatedProductArticles = new WP_Query($knowledge_args);
remove_filter('posts_where', 'related_products_title_filter', 10, 2);
Let me know if you were able to get it to work!

WooCommerce using meta_query to get products where custom checkbox option is NOT checked

I have built a WooCommerce website for a client with a "Latest Products" page. Due to the competitive nature of the client's industry, the client wants to be able to select certain products to NOT appear amongst the Latest Products.
For this, I have added a custom "Hide from Latest Products" checkbox to the product editor with this code:
add_action('add_meta_boxes', 'gd_add_product_extra_options_metabox');
function gd_add_product_extra_options_metabox(){
add_meta_box("product_extra_options_meta", "Extra Options", "gd_product_extra_options_metabox", "product", "side", "high");
}
// ADD CUSTOM FIELDS //
function gd_product_extra_options_metabox(){
global $post;
// Nonce field to validate form request came from current site
wp_nonce_field( basename( __FILE__ ), 'product_fields' );
// Get the field data if it's already been entered
$hide_from_latest = get_post_meta( $post->ID, 'hide_from_latest', true );
if($hide_from_latest == '1'){$checked = ' checked';}else{$checked = '';}
// Output the field
echo '<p><input type="checkbox" name="hide_from_latest" value="1"' . $checked . '> Hide from Latest Products</p>';
}
And so on and so forth with the saving code, etc. The checkbox appears to work perfectly.
The problem though, is in writing a custom product query to fetch all of the latest products for which this checkbox is NOT checked.
For testing, I have checked and saved the "Hide" option for only 1 product.
I have my query as follows:
$products = new WP_Query( array (
'post_type' => 'product',
'post_status' => 'publish',
'posts_per_page' => '100',
'order_by' => 'date',
'order' => 'ASC',
'meta_query' => array(
array(
'key' => 'hide_from_latest',
'value' => '1',
'compare' => 'NOT LIKE'
),
)
This gives me a very empty screen with "There is no results."
If, however, I change the meta_query to:
'meta_query' => array(
array(
'key' => 'hide_from_latest',
'value' => '1',
'compare' => 'LIKE'
),
)
Then it fetches and displays the 1 single product that I have checked and saved the option for.
I have tried various other options such as using "=" and "!=" for 'compare', I've tried changing the value of the checkbox to "on" and then having 'value' => 'on' in the meta_query, etc. The results are always the same.
Where have I gone wrong?
EDIT:
Here is my full code:
// ADD CUSTOM OPTIONS TO WOOCOMMERCE PRODUCTS //
add_action('add_meta_boxes', 'gd_add_product_extra_options_metabox');
function gd_add_product_extra_options_metabox(){
add_meta_box("product_extra_options_meta", "Extra Options", "gd_product_extra_options_metabox", "product", "side", "high");
}
// ADD CUSTOM FIELDS //
function gd_product_extra_options_metabox(){
global $post;
// Nonce field to validate form request came from current site
wp_nonce_field( basename( __FILE__ ), 'notice_fields' );
// Get the field data if it's already been entered
$hide_from_latest = get_post_meta( $post->ID, 'hide_from_latest', true );
if($hide_from_latest == '1'){$checked = ' checked';}else{$checked = '';}
// Output the field
echo '<p><input type="checkbox" name="hide_from_latest" value="1"' . $checked . '> Hide from Latest Products</p>';
}
// SAVE METABOX DATA //
function gd_save_product_extra_options_metabox( $post_id, $post ) {
// Return if the user doesn't have edit permissions.
if ( ! current_user_can( 'edit_post', $post_id ) ) {
return $post_id;
}
// Verify this came from the our screen and with proper authorization,
// because save_post can be triggered at other times.
if ( !wp_verify_nonce($_POST['notice_fields'], basename(__FILE__)) ) {
return $post_id;
}
// Now that we're authenticated, time to save the data.
// This sanitizes the data from the field and saves it into an array $product_meta.
$product_meta['hide_from_latest'] = esc_textarea( $_POST['hide_from_latest'] );
// Cycle through the $notice_meta array.
foreach ( $product_meta as $key => $value ) :
// Don't store custom data twice
if ( 'revision' === $post->post_type ) {
return;
}
if ( get_post_meta( $post_id, $key, false ) ) {
// If the custom field already has a value, update it.
update_post_meta( $post_id, $key, $value );
} else {
// If the custom field doesn't have a value, add it.
add_post_meta( $post_id, $key, $value);
}
if ( ! $value ) {
// Delete the meta key if there's no value
delete_post_meta( $post_id, $key );
}
endforeach;
}
add_action( 'save_post', 'gd_save_product_extra_options_metabox', 1, 2 );
if( ! function_exists('latest_products_censored') ) {
// Add Shortcode
function latest_products_censored( $atts ) {
global $woocommerce_loop;
// Attributes
$atts = shortcode_atts(
array(
'columns' => '4',
'limit' => '100'
),
$atts, 'products_test'
);
$woocommerce_loop['columns'] = $atts['columns'];
// The WP_Query
$products = new WP_Query( array (
'post_type' => 'product',
'post_status' => 'publish',
'posts_per_page' => $atts['limit'],
'order_by' => 'date',
'order' => 'ASC',
'meta_query' => array(
array(
'key' => 'hide_from_latest',
'value' => '1',
'compare' => 'NOT LIKE'
),
)
));
ob_start();
if ( $products->have_posts() ) { ?>
<?php woocommerce_product_loop_start(); ?>
<?php while ( $products->have_posts() ) : $products->the_post(); ?>
<?php wc_get_template_part( 'content', 'product' ); ?>
<?php endwhile; // end of the loop. ?>
<?php woocommerce_product_loop_end(); ?>
<?php
} else {
do_action( "woocommerce_shortcode_products_loop_no_results", $atts );
echo "<p>There is no results.</p>";
}
woocommerce_reset_loop();
wp_reset_postdata();
return '<div class="woocommerce columns-' . $atts['columns'] . '">' . ob_get_clean() . '</div>';
}
add_shortcode( 'latest_products_censored', 'latest_products_censored' );
}
After a bit more digging in the Wordpress Codex, I have found the answer!
The meta_query needs to be:
'meta_query' => array(
array(
'key' => 'hide_from_latest',
'value' => '1',
'compare' => 'NOT EXISTS'
),
)
I have just given that a go and it is now working perfectly! :-)

Trying show list of cities

First of all, sorry my horrible English =)
I'll try to explain how works everything:
I use this to create 'agreement' to be searched on my website, só the basic is the name, and where that 'agreement' works, for example, states and cities... but I have a problem when I try to select the 'states' and after show the cities to select where my 'agreement' can be used and save to show on the site.
But when I select the states, the WordPress just don't show the cities, and this problem happened after some att in WordPress plugins (exemple: Advanced custom field)
And know I have no idea how I can fix this.
Here is my code:
//Load cities - Convenio
function ag_apcef_load_cities_field_choices( $field ) {
// get selected
$selected = get_field( 'ag-estado-convenio', $post->ID );
// reset choices
$field['choices'] = array();
if($selected) {
$args = array(
'post_type' => 'cities',
'orderby' => 'title',
'order' => 'ASC',
'posts_per_page' => -1,
'meta_query' => array(
array(
'key' => 'city_meta_box_state',
'value' => $selected->ID
)
)
);
$posts = get_posts( $args );
foreach($posts as $post) {
$field['choices'][$post->ID] = $post->post_title;
}
}
return $field;
}
add_filter('acf/load_field/name=ag-cidade-convenio', 'ag_apcef_load_cities_field_choices');
// Admin enqueue - Convenio
function ag_apcef_admin_convenio_enqueue( $hook ) {
// Allowed post types
$types = array( 'convenio' );
if( !in_array( get_post_type(), $types ) )
return;
wp_enqueue_script( 'populate-area', get_stylesheet_directory_uri() . '/js/autopopulate-admin.js' );
wp_localize_script( 'populate-area', 'populate_vars',
array(
'populate_nonce' => wp_create_nonce( 'populate_nonce' ), // Create nonce
)
);
}
add_action( 'admin_enqueue_scripts', 'ag_apcef_admin_convenio_enqueue' );
//Enqueue - Convenio
function ag_apcef_convenio_enqueue() {
if ( is_page( 'portal-de-vantagens' ) || is_page( 'bem-estar' )) {
wp_enqueue_script( 'populate-area', get_stylesheet_directory_uri() . '/js/autopopulate.js' );
wp_localize_script( 'populate-area', 'populate_vars',
array(
'populate_nonce' => wp_create_nonce( 'populate_nonce' ), // Create nonce
'ajaxurl' => admin_url( 'admin-ajax.php' )
)
);
}
}
add_action( 'wp_enqueue_scripts', 'ag_apcef_convenio_enqueue' );
// Load cities by state
function ag_apcef_city_by_state( $selected_state ) {
// Verify nonce
if( !isset( $_POST['populate_nonce'] ) || !wp_verify_nonce( $_POST['populate_nonce'], 'populate_nonce' ) )
die('Permission denied');
// Get selected state
$selected_state = $_POST['state'];
// Populate arr_data
$arr_data = array();
if(!empty($selected_state)) {
$args = array(
'post_type' => 'cities',
'orderby' => 'title',
'order' => 'ASC',
'posts_per_page' => -1,
'meta_query' => array(
array(
'key' => 'city_meta_box_state',
'value' => $selected_state
)
)
);
$posts = get_posts( $args );
foreach($posts as $post) {
$arr_data[] = [
'key' => $post->ID,
'value' => $post->post_title
];
}
}
return wp_send_json($arr_data);
die();
}
add_action('wp_ajax_apcef_city_by_state', 'ag_apcef_city_by_state');
add_action('wp_ajax_nopriv_apcef_city_by_state', 'ag_apcef_city_by_state');

Get Custom Posts and put into option array - wordpress plugin

Trying to write a piece of code to expand a theme that I am using in Wordpress.
Basically, I want to get all custom post types and put it into an array for a select - the issue I am having is that I need to add the option values in the array and I cannot put a foreach loop in the array so not sure how to do this.
In the code below you will see the code:
'options' => array(),
This is where the custom posts need to be in the format:
'PostID' => esc_html__( 'Post Name', 'builder' ),
Here is my code:
function get_fields() {
$fields = array(
'get_post_names' => array(
'label' => esc_html__( 'Url Opens', 'builder' ),
'type' => 'select',
'option_category' => 'configuration',
'options' => array(),
'toggle_slug' => 'post_names',
'description' => esc_html__( 'Here you can choose whether or not your link opens in a new window', 'et_builder' ),
),
);
global $wpdb;
$custom_post_type = 'custom_post_name';
$results = $wpdb->get_results( $wpdb->prepare( "SELECT ID, post_title FROM {$wpdb->posts} WHERE post_type = %s and post_status = 'publish'", $custom_post_type ), ARRAY_A );
if ( ! $results )
return;
foreach( $results as $index => $post ) {
$fields['options'][] = array (
$post['ID'] => esc_html__( $post['post_title'], 'builder' ),
);
}
return $fields;
}
Any help would be much appreciated.
Thanks
Hopefully this may work
function generate_post_select($select_id, $post_type, $selected = 0) {
$post_type_object = get_post_type_object($post_type);
$label = $post_type_object->label;
$posts = get_posts(array('post_type'=> $post_type, 'post_status'=> 'publish', 'suppress_filters' => false, 'posts_per_page'=>-1));
foreach ($posts as $post) {
echo $post->post_title;
}
}
$select_id is used as the name and id of the select, $post_type is the type you want to be made into the select and $selected is the post id you want selected in the select box.
Found a solution if anyone wants to know.
Changed the 'option' to be the following and removed the code from global $wpdb; down.
'options' => array_reduce( get_posts( 'post_type=custom_post&posts_per_page=-1' ), function( $result, $item ) {
$result[$item->ID] = $item->post_title;
return $result;
}),

Custom post type not showing posts inserted from frontend

Hey everyone,
I have a post type called `index`, and i'm trying to build a form for users to insert posts from the frontend.
i created a page and a template for it with a form and an ajax function which insert the content to the DB using `wp_insert_post`. the function works generally, i can see the new posts added to the wp_post db in phpmyadmin. the problem is that i can't see the new posts in the admin panel. the post are counted (i can see the number goes up everytime i try the form), but not shown.
this is the functions.php ajax code (some $_get vars are to be used for meta data inserting):
add_action('wp_ajax_addtoindex', 'addtoindex');
add_action('wp_ajax_nopriv_addtoindex', 'addtoindex');
function addtoindex(){
$title = $_GET["title"];
$slug = sanitize_title_with_dashes($title,'','save');
$group = $_GET["group"];
$inst = $_GET["inst"];
$location = $_GET["location"];
$address = $_GET["address"];
$content = $_GET["content"];
$website = $_GET["website"];
$year = $_GET["year"];
$educ = $_GET["educ"];
$aud = $_GET["aud"];
$teaching = $_GET["teaching"];
$teachers = $_GET["teachers"];
$contact1 = $_GET["contact1"];
$email1 = $_GET["email1"];
$phone1 = $_GET["phone1"];
$contact2 = $_GET["contact2"];
$email2 = $_GET["email2"];
$phone2 = $_GET["phone2"];
$user = get_user_by("login",$authorid);
$authorid = $user->ID;
// Check if the group exists
$group_term = term_exists( $group, 'group', 0 );
// Create group if it doesn't exist
if ( !$group_term ) {
$group_term = wp_insert_term( $group, 'group', array( 'parent' => 0 ) );
}
// Check if the inst exists
$inst_term = term_exists( $inst, 'inst', 0 );
// Create inst if it doesn't exist
if ( !$inst_term ) {
$inst_term = wp_insert_term( $inst, 'inst', array( 'parent' => 0 ) );
}
// Check if the location exists
$location_term = term_exists( $location, 'location', 0 );
// Create location if it doesn't exist
if ( !$location_term ) {
$location_term = wp_insert_term( $location, 'location', array( 'parent' => 0 ) );
}
$custom_tax = array(
'group' => $group_term,
'inst' => $group_inst,
'location' => $group_location
);
//Post Properties
$new_post = array(
'post_title' => $title,
'post_name' => $slug,
'post_content' => $content,
'post_status' => 'pending',
'post_type' => 'index',
'post_author' => $authorid,
'comment_status' => 'closed',
'ping_status' => 'closed',
'tax_input' => $custom_tax
);
//save the new post
if ( post_type_exists( 'index' ) ) {
$pid = wp_insert_post($new_post, true);
echo 'good';
}
else{
echo "bad";
}
// Reset Post Data
wp_reset_postdata();
exit;
}
and this is the index post type code:
function post_type_index() {
register_post_type( 'index',
array(
'label' => __('Index'),
'labels' => array('name' => 'אינדקס האנתרופוסופיה','singular_name' => __('פריט לאינדקס','ohav'),'edit_item' => __('עריכת פריט אינדקס','ohav'),'add_new' => __('הוספת פריט לאינדקס','ohav'),'add_new_item' => __('הוספת פריט לאינדקס','ohav'),'all_items' => __('לכל פריטי האינדקס','ohav')),
'public' => true,
//'publicly_queryable' => true,
//'query_var' => true,
//'capability_type' => 'post',
'has_archive' => true,
'show_ui' => true,
'show_in_nav_menus' => true,
'rewrite' =>array(
'slug' => __('index','ohav'),
'with_front' => true
),
'hierarchical' => true,
'supports' => array(
'title',
'boxplace',
'editor',
'thumbnail'
)
)
);
}
add_action('init', 'post_type_index');
okay i found it!
the problem was i already had a pre_get_posts hook that changes the order of the index archive according to the post meta.
add_action( 'pre_get_posts', 'change_order_for_index' );
function change_order_for_index( $query ) {
if ( is_post_type_archive('index') ) {
$query->set( 'meta_key', '_index_featured' );
$query->set( 'orderby', 'meta_value' );
}
}
i added && !is_admin() to the if and it turned okay.
thank you Arif, your answer helped me find it.
you can add an action hook 'pre_get_posts' to include/exclude your custom post type to/from the admin post list or any for any other listing like archives.
add_filter( 'pre_get_posts', 'include_custom_type_index' );
function include_custom_type_index( $query ) {
$query->set( 'post_type', array(
'post', 'index'
));
return $query;
}

Categories