15

In my WordPress installation (4.9.8.) the editor role isn't allowed to edit the privacy page.

It would work with following in my functions.php:

$role_object = get_role( 'editor' );
$role_object->add_cap( 'manage_privacy_options', true );
$role_object->add_cap( 'manage_options' ); // this needs to be active in order that before cap works

But now the editor has lot more rights than just editing the privacy page.

Is there another way to grant access to the editor user role with some lines of PHP code?


As a workaround I make usage of this Plugin now: https://wordpress.org/plugins/manage-privacy-options/

Another kind of workaround is just to choose no privacy page in the privacy settings.

2

3 Answers 3

21

Editing the privacy policy page is restricted to manage_privacy_options as pointed out in a comment in the WordPress core file wp-includes/capabilities.php:

/*
 * Setting the privacy policy page requires `manage_privacy_options`,
 * so editing it should require that too.
 */
if ( (int) get_option( 'wp_page_for_privacy_policy' ) === $post->ID ) {
  $caps = array_merge( $caps, map_meta_cap( 'manage_privacy_options', $user_id ) );
}

To allow users with the roles editor and administrator who can edit pages (in single and also multisite instances) to edit and delete the privacy policy page one has to overwrite the $caps array:

add_action('map_meta_cap', 'custom_manage_privacy_options', 1, 4);
function custom_manage_privacy_options($caps, $cap, $user_id, $args)
{
  if (!is_user_logged_in()) return $caps;

  if ('manage_privacy_options' === $cap) {
    $manage_name = is_multisite() ? 'manage_network' : 'manage_options';
    $caps = array_diff($caps, [ $manage_name ]);
  }
  return $caps;
}

Update: Allow users with the role editor or administrator to edit and delete the privacy policy page (which is not possible per default in multisite instances):

add_action('map_meta_cap', 'custom_manage_privacy_options', 1, 4);
function custom_manage_privacy_options($caps, $cap, $user_id, $args)
{
  if (!is_user_logged_in()) return $caps;

  $user_meta = get_userdata($user_id);
  if (array_intersect(['editor', 'administrator'], $user_meta->roles)) {
    if ('manage_privacy_options' === $cap) {
      $manage_name = is_multisite() ? 'manage_network' : 'manage_options';
      $caps = array_diff($caps, [ $manage_name ]);
    }
  }
  return $caps;
}
11
  • 1
    no sorry, couldn't find the time to check this. will do immediately! Mar 4, 2019 at 14:16
  • 1
    @GDY Good point. I assumed that only editors and administrators can edit pages. I added the check of the user role to my answer.
    – Sven
    Dec 12, 2019 at 10:06
  • 1
    Actually the question asks for the editor role (which cant edit the privacy page in regular installations) so it should cover editors and admins.
    – GDY
    Dec 12, 2019 at 14:25
  • 1
    Many thanks for the solution. For those wanting to enable WooCommerce Shop Managers to the list allowed to edit privacy add "shop_manager" to the array_intersect in the second example.
    – Andrew
    Nov 23, 2020 at 23:07
  • 1
    I know add_action is an alias for the add_filter, but since the map_meta_cap filter is defined using apply_filters, I think you should replace add_action() with add_filter() for brevity Sep 2, 2022 at 0:16
2

Thanks @Sven for the nice workaround, it works well but I had an issue when the user is not yet logged_in, the map_meta_cap action is fired anyway, which resulted on a "502 bad getaway" error. I added a is_user_logged_in() test before like so :

if (is_user_logged_in()){
    add_action('map_meta_cap', 'custom_manage_privacy_options', 1, 4);
}

Maybe it's my server configuration (nginx) that results on this bug, but if someone get the same error, here is a solution.

0

The provided answer did the trick. However, this line:

if (array_intersect(['editor', 'administrator'], $user_meta->roles)) {

Was generating this error:

array_intersect(): Expected parameter 2 to be an array, null given in

So I tweaked the code a bit to ensure that both values were valid arrays (full code):

add_action('map_meta_cap', 'custom_manage_privacy_options', 1, 4);
function custom_manage_privacy_options($caps, $cap, $user_id, $args) {
    if ( !is_user_logged_in() ) return $caps;

$target_roles = array('editor', 'administrator');
$user_meta = get_userdata($user_id);
$user_roles = ( array ) $user_meta->roles;

if ( array_intersect($target_roles, $user_roles) ) {
    if ('manage_privacy_options' === $cap) {
        $manage_name = is_multisite() ? 'manage_network' : 'manage_options';
        $caps = array_diff($caps, [ $manage_name ]);
    }
}

return $caps;
}
3
  • I don't see what you've changed. If $user_meta->roles is null you're still passing null to array_intersect here.
    – Rup
    Apr 21, 2021 at 9:35
  • As we're making sure that the user is logged in first, the $user_meta->roles could never null? I thought that the problem was due to using $user_meta->roles directly on the array_intersect, so I saved that as a variable first. I'm no longer getting any error messages so it seems like that fixed the issue.
    – Preguntón
    Apr 21, 2021 at 10:51
  • Casting $user_meta->roles as an array is definitely not the best way. Just check if $user_meta is set.
    – Gavin
    Jul 9, 2021 at 11:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.