0

I finally managed to update an old WP 3.3.1 site to WP 4.1 with few issues, but one unexpected change seems to have come about with relation to file uploads.

In the WP 3.3.1 version of the plugin, I enabled uploads for a custom Role via 'read' and 'upload_files'.

NOTE: This is for content that is NOT post driven. It's just the editor I want to grab things for some custom db tables. The wp_editor call has content explicitly set to ''. I'm using a buffering hack to reposition the editor, which is detailed at: https://wordpress.stackexchange.com/a/66345

// capture the editor for later use...
// HACK: https://wordpress.stackexchange.com/a/66345
ob_start();

wp_editor(
    '',
    'xyz-note-editor',
    array(
        'textarea_rows' => '10',
    )
);

$editor = ob_get_clean();

// ...

$edit_form_template = str_replace('{{NotesEditor}}', $editor, $edit_form_template);

After the update to WP 4.1, everything works for Editors and Administrators.

It fails for Authors, Contributors and my custom role with the error: "You don't have permission to attach files to this post."

(The "post" appears to be an unrelated custom post type instance, which the uploaded media gets assigned to, when successfully uploading as an Editor or Administrator.)

Short of rebuilding things, or hunting down some plugin (like Members by Justin Tadlock, recommended elsewhere on StackExchange), I'm stuck.

Why can Editors circumvent upload restrictions in this case?

I've tried assigning edit/publish/read permissons for Editors (and below) to the custom Role with no success - based on http://codex.wordpress.org/Roles_and_Capabilities.

add_role(
    XxYyConfig::USER_ROLE(), 
    'Custom Data Manager', 
    array(
        'read' => true,

        // ADDED: to address changes in how WordPress "Add Media" works - re: "You don't have permission to attach files to this post." error
        // NOTE: Custom Data Managers, Contributors and Authors CANNOT add media -- BUT Editors/Administrators can. Trying to add to {custom_post_type} post (for reasons unknown). Content for editor set to ''...
        'edit_files' => true,
        'edit_others_pages' => true,
        'edit_others_posts' => true,
        'edit_pages' => true,
        'edit_posts' => true,
        'edit_private_pages' => true,
        'edit_private_posts' => true,
        'edit_published_pages' => true,
        'edit_published_posts' => true,
        'publish_pages' => true,
        'publish_posts' => true,
        'read_private_pages' => true,
        'read_private_posts' => true,
        // ADDED: END

        'upload_files' => true,
    )
);

I know I'm out in left field a bit here, but this feels inconsistent (even if something from ages long since gone has been "fixed").

map_meta_cap looks like it might apply here, but no custom post type makes me think that's the wrong solution.

Ideally, I'd like to know why the custom post type gets tagged during this whole thing, but I'm sticking to what permissions/capability handling needs to be set up to allow uploading through the WYSIWYG editor?

EDIT: Since my role is set up during plugin activation, I've been sure to deactivate and reactivate the plugin to ensure nothing unusual is happening there.

3

Found the basic problem! Although a different context than the one you described, the root cause is probably the same. I was trying to allow users to setup a personal page and upload an image to display there. I kept getting the dreaded "You don't have permission to attach files to this post".

The message itself comes from wp_ajax_upload_attachment() in /wp-admin/includes/ajax-actions.php, even though the user is working on the front-page, not the dashboard, because the plugin I'm using (Advanced Custom Fields -- recommended!) makes use of wordpress library routines (thankfully it restricts access to library). The error occurs if current_user_can() fails to give permission. (You can prove the message is in this routine by changing the message statement to something else.)

In turn, current_user_can() calls $current_user->has_cap() to get current capabilities.

has_cap() offers a nice filter that we can make use of, but it kept failing anyway. The reason was that it first calls map_meta_cap() which builds a large array of possible capabilities for this instance. If any one of those possible capabilities is left 'empty' then has_cap returns false.

That means any custom filter that is determined to give permission must loop through the array and set everything true. Seems to me that a better permanent solution would be for Wordpress to ignore any cap that is not explicitly set to allow or disallow.

For now, here's a sample filter function that works for me:

// allow users to add images to their home page
function allow_own_attachments( $user_caps, $req_caps, $args, $UserObj ) {
   if ( empty($args[2]) ) {
      return $user_caps;  // nothing to check
   }
   $post = get_post( $args[2] );  // post_id was passed here
   if ( $post->post_author == $UserObj->ID ) {  // this is my post
      foreach ( (array) $req_caps as $cap ) {
         if ( empty( $user_caps[ $cap ] ) )
            $user_caps[ $cap ] = true;
      }
   }
   $user_caps['edit_post'] = true; // tested by wp_ajax_upload_attachment()
   return $user_caps;
}
add_filter( 'user_has_cap', 'allow_own_attachments', 10, 4 );
0

The code in the previous answer worked for me, but I was getting this notice when in debug mode: "Trying to get property 'post_author' of non-object". I added a check to see if $post returns an object (if (is_object($post)). This gets rid of the notice.

function allow_own_attachments( $user_caps, $req_caps, $args, $UserObj ) {
if ( empty($args[2]) ) {
   return $user_caps;  // nothing to check
}
$post = get_post( $args[2] );  // post_id was passed here

if (is_object($post)){  //check if $post is an object. If it is't checked the code throws this Notice: Trying to get property 'post_author' of non-object 
    if ( $post->post_author == $UserObj->ID ) {  // this is my post
        foreach ( (array) $req_caps as $cap ) {
            if ( empty( $user_caps[ $cap ] ) )
                $user_caps[ $cap ] = true;
        }
    }
}
$user_caps['edit_post'] = true; // tested by wp_ajax_upload_attachment()
return $user_caps;
}

add_filter( 'user_has_cap', 'allow_own_attachments', 10, 4 );

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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