WP, pass several id's to query - php

function my_relationship_query( $args, $field, $post_id ) {
// only show children of the current post being edited
$args['post_parent'] = $post_id;
// return
return $args;
}
How for example I could pass two parameters as post_id ? Is the only way of doing that includes writing some meta queries ?

Pass an array of post IDs to post_parent__in, per WP_Query (assuming $args is representative of WP_Query params):
$post_id_array = array( $id1, $id2 );
function my_relationship_query( $args, $field, $post_id_array ) {
// only show children of the current post being edited
$args['post_parent__in'] = $post_id_array;
// return
return $args;
}

Related

Custom map_meta_cap filter does not return ['do_not_allow']

I have created a custom role that only has access to certain pages and their children/parents. I have used map_meta_cap filter to solve this. However even though it goes through my function correctly it will not function properly, return ['do_not_allow']; is not working as intended and I don't know why, it seemingly does not do anything.
//Role cap for different pages
function staby_map_meta_cap( $caps, $cap, $user_id, $args ) {
// // If the capability being filtered isn't of our interest, just return current value
if ( in_array($cap, ['edit_pages']) ) {
// First item in $args array should be page ID
if (!staby_role_can_edit( $user_id, $args[0] ) ) {
// User is not allowed, let's tell that to WP
return ['do_not_allow'];
}
}
// Otherwise just return current value
return $caps;
}
add_filter( 'map_meta_cap', 'staby_map_meta_cap', 10, 4 );
//See if role can edit correspondent page
function staby_role_can_edit( $user_id, $page_id) {
$page = get_post( $page_id );
// let's find the topmost page in the hierarchy
while( $page && (int) $page->parent ) {
$page = get_post( $page->parent );
}
if ( ! $page ) {
return false;
}
$user = new WP_User($user_id);
if ($user->allcaps['pages_id']) {
$user_pages = $user->allcaps['pages_id'];
if (!in_array($page->ID, $user_pages)) {
return false;
}
}
return true;
}
The only thing I have noticed is that the map_meta_cap filter runs multiple times, and the $args variable is always empty but it somehow still retrieves the $args[0] (page id) in my custom function staby_role_can_edit( $user_id, $page_id ) (but when I call it in that function it's null?). I have no idea why it's not working at all.
Any help is very appreciated! Thanks.

How to alter Wordpress global post title using php

I know i can use:
global $wp_query;
$wp_query->is_page = true;
For example to set the global is_page conditional to true.
Can i change the global post title in a similar way so it would effect the the_title() returned value?
To clarify things:
I need for a use of a "virtual page" case, where no post is actually loaded and i don't want to use any existing post title. just inject some custom title to the current globals so i will get it when using the_title on the current page.
To modify the title you can use a build in hook of wordpress:
function suppress_if_blurb( $title, $id = null ) {
if ( in_category(' blurb', $id ) ) {
return '';
}
return $title;
}
add_filter( 'the_title', 'suppress_if_blurb', 10, 2 );
https://codex.wordpress.org/Plugin_API/Filter_Reference/the_title
Finally found it. gladly it's very simple :) but this piece of code will also create all other post vars for a "fake post/page":
$post_id = -99; // negative ID, to avoid clash with a valid post
$post = new stdClass();
$post->ID = $post_id;
$post->post_title = 'Some title or other';
$wp_post = new WP_Post( $post );
wp_cache_add( $post_id, $wp_post, 'posts' );
global $wp, $wp_query;
$wp_query->post = $wp_post;
$wp_query->posts = array( $wp_post );
$wp_query->queried_object = $wp_post;
$wp_query->queried_object_id = $post_id;
$wp_query->is_404=false;
$wp_query->is_page=true;
$GLOBALS['wp_query'] = $wp_query;
$wp->register_globals();
More details here!

Which WordPress hook fires after save all post data and post meta?

I have a custom post type crm, and i need to send a mail after each crm saved or updated. i user cmb2 for some custom meta like subject, to users etc. I know the save_post hook fires after post save (according to WordPress codex) in my case when i call save_post with two parameters (id and post) the post does not contains update values. here is my code :
function send_mail_to_user($id, $post){
$crm = $post;
$user_email = array();
if($crm->vc_all_vc == 'on'){
$args = array('orderby' => 'display_name');
$wp_user_query = new WP_User_Query($args);
$authors = $wp_user_query->get_results();
if (!empty($authors)) {
foreach ($authors as $author) {
array_push($user_email , $author->user_email );
}
}
}
else{
$to_users = $crm->vc_users;
$to_program = $crm->vc_program;
$to_group = $crm->vc_group;
$to_excode = $crm->vc_ex_code;
foreach ($to_users as $key => $value) {
$user_data = get_userdata($value);
array_push($user_email, $user_data->user_email);
}
foreach ($to_program as $key => $value) {
$users = get_users( array('meta_key' => 'programs' ) );
if($users){
foreach ($users as $index => $data) {
if(in_array($value , explode('#', $data->programs))){
if(! in_array($data->user_email, $user_email) )
{
array_push($user_email, $data->user_email);
}
}
}
}
}
foreach($to_group as $group) {
$term = get_term_by('slug', esc_attr($group), 'user-group');
$user_ids = get_objects_in_term($term->term_id, 'user-group');
foreach($user_ids as $user_id){
$fc_user = get_userdata($user_id);
if(! in_array($fc_user->user_email, $user_email) )
{
array_push($user_email, $fc_user->user_email);
}
}
}
foreach($to_excode as $codes) {
$value = explode('*',$codes)[1];
$users = get_users( array('meta_key' => 'programs' ) );
if($users){
foreach ($users as $index => $data) {
if(in_array($value , explode('#', $data->programs))){
if(! in_array($data->user_email, $user_email) )
{
array_push($user_email, $data->user_email);
}
}
}
}
}
}
foreach($user_email as $index => $email){
$to = $email;
$subject = $crm->vc_subject;
$body = $crm->post_content;
$headers = array(
'Content-Type: text/html; charset=UTF-8'
);
wp_mail($to, $subject, $body, $headers);
}
}
add_action( 'save_post', 'send_mail_to_user', 10, 2 );
And i also try publish_post hook , that works fine when new post created but when updated it works same. I have tried edit_post and post_updated hook also, but i never be able to retrieve my update data.
So how can i solve it? which action hook will give me all the new data?
thanks in advance.
You can use something like this,
function your_custom_function($meta_id, $post_id, $meta_key='', $meta_value='') {
if($meta_key=='_edit_lock') {
// if post meta is updated
}
}
add_action('updated_post_meta', 'your_custom_function', 10, 4);
Try with post_updated and use $post_after object.
https://codex.wordpress.org/Plugin_API/Action_Reference/post_updated
you can use this save_post hook with your function. change your hook priority to 100 it will give you updated post
add_action( 'save_post', 'send_mail_to_user', 100, 2 );
This might be a bit old but just wanted to give an update since from version 5.6.0 a new hook is available. The hook is wp_after_insert_post and you can find more information here . This hook is triggered after a post is created or updated and all of its terms and meta are updated. You can find an example below:
add_action( 'wp_after_insert_post', 'send_mail_to_user', 90, 4 );
/**
* Callback to: 'wp_after_insert_post'
* Fires once a post, its terms and meta data has been saved
* #param int $post_id Post ID.
* #param WP_Post $post Post object.
* #param bool $update Whether this is an existing post being updated.
* #param null|WP_Post $post_before Null for new posts, the WP_Post object prior to the update for updated posts.
*
*/
public static function sync_product_registrations_on_update( $post_id, $post, $update, $post_before ) {
if ( 'post' !== $post->post_type ) {
//Only to process the below when post type is 'post' else return
return;
}
if ( ! in_array( $post->post_status, [ 'private', 'publish' ] ) ) {
//To only process when status is private or publish
return;
}
//The rest of your code goes here
}
You can use the rest_after_insert_{$this->post_type} hook (where $this->post_type is replaced with the post type, eg 'post' or 'myposttype').
Thanks to Florian Brinkmann for this link.
add_action('rest_after_insert_myposttype', 'myfunction', 10, 3);
function myfunction($post, $request, $creating) {
// $creating is TRUE if the post is created for the first time,
// false if it's an update
// ...
}
See also here.
Some workaround is to use $_POST['meta_field'] with sanitation:
$to_users = $_POST['vc_users'];
$to_program = $_POST['vc_program'];
$to_group = $_POST['vc_group'];
$to_excode = $_POST['vc_ex_code'];
$to_users = sanitize_text_field($to_users);
$to_program = sanitize_text_field($to_program);
$to_group = sanitize_text_field($to_group);
$to_excode = sanitize_text_field($to_excode);
Pay attention to the field names, using ACF will make you use the field key.
This problem is more complicated than seems on first sight:
Our 'post_updated' hook is running before post is updated, so every attempt for getting meta data will result with the previous data. Also, Wordpress (v5.7.2) doesn't seem to have a hook for after a post was saved.
Also, 'save_post' hook is very complicated because it runs for every post saved or created including revisions and the $update boolean is still not reliable enough.
The correct and simpler answer is to use the wp_insert_post action.
https://developer.wordpress.org/reference/hooks/wp_insert_post/
An important distinction of wp_insert_post action is that it is fired
after update_post_meta has been called.
There are 3 parameters available - the $update flag tells you if this is a new or updated post.
do_action( 'wp_insert_post', int $post_ID, WP_Post $post, bool $update )
So - to implement your code after all post meta has been updated, use something like this:
add_action('wp_insert_post', 'run_after_post_updated', 10, 3);
function run_after_post_updated($post_ID, $post, $update ) {
// ...
}
You can use the save_post action wih a higher priority so that your function is called afer all meta data has been saved.
add_action( 'save_post', 'action_woocommerce_update_product', 20, 3 );
Here I have used higher priority 20

WordPress get current post id of custom post type in functions.php function

I have a function in my functions.php file and I need the current post ID.
I have tried getting it like this:
global $wp_query;
$currentID = $wp_query->post->ID;
echo '<pre>';
print_r($currentID);
echo '</pre>';
but doesn't seem to work since it says:
Trying to get property of non-object
EDIT: Entire function in functions.php
add_filter( 'gform_pre_render_1', 'populate_posts' );
add_filter( 'gform_pre_validation_1', 'populate_posts' );
add_filter( 'gform_pre_submission_filter_1', 'populate_posts' );
add_filter( 'gform_admin_pre_render_1', 'populate_posts' );
function populate_posts( $form ) {
global $wp_query;
foreach ( $form['fields'] as &$field ) {
if ( $field->type != 'select' || strpos($field['cssClass'], 'booking-option') === false ) {
continue;
}
$currentID = $wp_query->post->ID;
var_dump($wp_query->post);
$choices[] = array( 'text' => $price, 'value' => $price );
$field->placeholder = '0';
$field->choices = $choices;
}
return $form;
}
Anyone can help me out please
Thanks a lot!
In your function add
global $post;
echo $post->ID;
To have access to the post id you must be within the loop
Otherwise , you must modify your function to accept the post id as a parameter , and hook where is safe to get post id, like so:
add_action('template_redirect', function() {
if (is_single())
your_function(get_queried_object_id());
}
});
function your_function($id){
//Do what you want
}
Some references:
https://wordpress.stackexchange.com/questions/177262/cant-get-post-id-in-functions-php?rq=1
https://wordpress.stackexchange.com/questions/140753/get-current-post-id-in-functions-php
As a note, for the future i think is more appropriate if you post these questions to the http://wordpress.stackexchange.com community
EDIT:
now that you posted the entire code i see that you are using gravity forms (which you didn't mentioned before).
This is a completely different question then.
You must obtain the post_id from the Entry object that gravity forms will pass to your function
https://www.gravityhelp.com/documentation/article/entry-object/
if you want to print the ID then use
the_ID();
if you want to store it then use
$postId = get_the_ID();
Use it in the loop
Hope this helps
Take Care and Happy coding
Getting the current post ID
The ID can be stored as a variable using
<?php $postid = get_the_ID(); ?>
To print
<?php echo $postid; ?>
By function
function get_the_ID() {
$post = get_post();
return ! empty( $post ) ? $post->ID : false;
}
For Reference : click here

Customize the auto generation of Post Slug in Wordpress

When we add new post in wordpress, after supplying the post title, the slug is generated automatically. I need to edit that auto generation module so that i can add some arbitrary number in the end of the slug automatically. How to do it?
Don't use the hard-coded version that the OP used here. When he did that, there was not a filter available. More recently, since 3.3, a filter was added.
add_filter( 'wp_unique_post_slug', 'custom_unique_post_slug', 10, 4 );
function custom_unique_post_slug( $slug, $post_ID, $post_status, $post_type ) {
if ( $custom_post_type == $post_type ) {
$slug = md5( time() );
}
return $slug;
}
However this method will change the slug every time you save the post... Which was what I was hoping for...
EDIT:
This kind of works for limiting the generation to just once. The only drawback is that it creates one version when ajax runs after creating the title, then it creates another, permanent slug when the post is saved.
function custom_unique_post_slug( $slug, $post_ID, $post_status, $post_type ) {
if ( $custom_post_type == $post_type ) {
$post = get_post($post_ID);
if ( empty($post->post_name) || $slug != $post->post_name ) {
$slug = md5( time() );
}
}
return $slug;
}
Write a plugin to hook into the wp_insert_post_data filter so you can update the slug before the post is sent for insertion into the database:
function append_slug($data) {
global $post_ID;
if (empty($data['post_name'])) {
$data['post_name'] = sanitize_title($data['post_title'], $post_ID);
$data['post_name'] .= '-' . generate_arbitrary_number_here();
}
return $data;
}
add_filter('wp_insert_post_data', 'append_slug', 10);
Note that this function requires that you allow WordPress to auto-generate the slug first, meaning you must not enter your own slug before generating, and it cannot update existing posts with the number.
Test this : (paste it into functions.php)
function append_slug($data) {
global $post_ID;
if (!empty($data['post_name']) && $data['post_status'] == "publish" && $data['post_type'] == "post") {
if( !is_numeric(substr($data['post_name'], -4)) ) {
$random = rand(1111,9999);
$data['post_name'] = sanitize_title($data['post_title'], $post_ID);
$data['post_name'] .= '-' . $random;
}
}
return $data; } add_filter('wp_insert_post_data', 'append_slug', 10);
add_filter('post_link','postLinkFilter', 10, 3);
/**
* Manipulates the permalink
*
* #param string $permalink
* #param stdClass $post
* #return string
*/
function postLinkFilter($permalink,stdClass $post){
return $permalink.'?12345';
}
Untested in that scenario, but I have already used it, should work with a minimum of changes, but try and test it REALLY Carefully .
In any Case, don't use rand() here or something alike, since the function must return the same link for the same post every time, otherwise you will have some serious problems.
Have fun!
You should operate with wp_ajax_sample-permalink action and name_save_pre filter.
More examples here: https://wordpress.stackexchange.com/a/190314/42702

Categories