I just found this code in pods/includes/general.php:
if ( ! current_user_can( 'publish_post', $check_post_id ) && ! pods_is_admin() ) {
return empty( $tags['field'] ) ? pods_get_access_user_notice( $info, true, esc_html__( 'You do not have the capability to preview this Pods embed.', 'pods' ) ) : '';
}
So, I guess contributors aren’t allowed to preview any pods data. But why? Is there no way at all (or workarounds) for people who have no ‘publish_post’ capability to preview pods data? What’s the logic behind preventing users without ‘publish_post’ to preview the post?
ACF has this as well as other custom field plugins. This prevents a contributor from being able to preview the shortcode.
I’ll review this now that the dust has settled from the Pods 3.1 release. I’m open to adding a filter for this to make it optional.
Hmmmm… I see. I guess in most other cases, people don’t want contributors to see them.
Looking forward to a filter…
current_user_can()
is a proxy to WP_User::has_hap()
, which is filterable with user_has_cap
with inline documentation at wp-includes/class-wp-user.php
lines 790 to 808
.
The filter takes 4 arguments:
- An array of all capabilities, where the keys are the capability name such as
publish_post
and the value is boolean true
or false
. Modifying this will grant or reject the capability.
- An array of strings representing capabilities required for the requested capability. I have never used this; seems like it has to do with capability dependencies.
- An array of arguments, where the first value is the requested capability as a string e.g.,
publish_post
, the second value is the user_id as an integer, and the third value is usually a contextual object ID, in this case it would be $check_post_id
— the ID of the post for which a preview is being requested in a preview context, or the ID of a post being requested for publishing when publish_post
is used in core.
- The
WP_User
object… All the IDs and roles and capabilities and methods associated with the currently logged in user.
The key here is to modify the behavior when content is being previewed, but not when content is being published or when a user is logged out or is at a lower role, such as Subscriber, since ?preview=1
can be added to any URL, possibly causing unexpected results.
The filter use would likely look like below (I am writing based on the spec and verifying there are no fatal errors, but do not have time this evening to configure a user permissions structure and test preview scenarios, so please test and consider versus expected results).
This code is written in the form of a plugin. It can be put as a single file such as wp-content/plugins/contributor-preview/contributor-preview.php
or in any theme functions.php or Snippets plugin or wp-content/mu-plugins/contributor-preview.php
.
<?php
/**
* Plugin Name: Contributor Preview
* Description: Allow contributor user role to preview content from Pods.
* Version: 1
* Plugin URL: https://wordpress.org/support/topic/contributors-cannot-preview-data-from-pods-but-authors-and-editors-can/
*
* @see https://github.com/WordPress/wordpress-develop/blob/02fb53498f1ce7e63d807b9bafc47a7dba19d169/src/wp-includes/class-wp-user.php#L790-L808
* @see https://github.com/pods-framework/pods/blob/e571552e7724b8dacb2b5ef272c9344fd0f7695f/includes/general.php#L1809-L1812
*/
add_action(
'init',
function() {
if (
// The user is logged in.
is_user_logged_in()
// A preview is being requested.
&& is_preview()
// The user has the role "Contributor"
&& in_array( 'contributor', (array) wp_get_current_user()->roles )
// This is not an attempt to publish.
&& (
empty( $_POST )
&& ! wp_is_json_request()
)
) {
add_filter(
'user_has_cap',
function( $permissions, $caps, $args, $user ) {
/**
* At this point we know the context is a preview, not a publish,
* and the user is a Contributor, so grant
publish_post
.
*
* For more control, the specific post ID is stored in $args[2].
*/
return array_merge(
$permissions,
[
'publish_post' => true,
]
);
},
PHP_INT_MAX,
4
);
}
}
);