4

For users with the Contributor user role, I want to restrict the total amount of images that they are allowed to upload. I found this code posted on an answer here:

add_filter( 'wp_handle_upload', 'wpse47580_update_upload_stats' );
function wpse47580_update_upload_stats( $args ) {

    $user_id = get_current_user_id();

    $upload_count = get_user_meta( $user_id, 'upload_count', $single = true );

    update_user_meta( $user_id, 'upload_count', $upload_count + 1 );
}

add_filter( 'wp_handle_upload_prefilter', 'wpse47580_check_upload_limits' );
function wpse47580_check_upload_limits( $file ) {
    $user_id = get_current_user_id();

    $upload_count = get_user_meta( $user_id, 'upload_count', $single = true );

    $upload_count_limit_reached = apply_filters( 'wpse47580_upload_count_limit_reached', 10 ) > ( $upload_count + 1 );

    if ( $upload_count_limit_reached  )
        $file['error'] = 'Upload limit has been reached for this account!';

    return $file;
}

There are two problems. Firstly, the above code does not function properly, it is supposed to allow 10 uploads but the upload limit message is displayed no matter what. Secondly, it applies to all user roles.

Upon further research, I found this working answer, but the solution applies for total uploads per post, not user.

How can I set an upload count limit for users on a specific user role? Ideally with a solution that deducts the count if user permanently removes an uploaded image.

5

I'm not really sure which is the real problem with code you posted, however I cant understand why use 2 functions when one is enough...

add_filter( 'wp_handle_upload_prefilter', 'limit_uploads_for_user_roles' );

function limit_uploads_for_user_roles( $file ) {
  $user = wp_get_current_user();
  // add the role you want to limit in the array
  $limit_roles = array('contributor');
  $filtered = apply_filters( 'limit_uploads_for_roles', $limit_roles, $user );
  if ( array_intersect( $limit_roles, $user->roles ) ) {
    $upload_count = get_user_meta( $user->ID, 'upload_count', true ) ? : 0;
    $limit = apply_filters( 'limit_uploads_for_user_roles_limit', 10, $user, $upload_count, $file );
    if ( ( $upload_count + 1 ) > $limit ) {
      $file['error'] = __('Upload limit has been reached for this account!', 'yourtxtdomain');
    } else {
      update_user_meta( $user->ID, 'upload_count', $upload_count + 1 );
    }
  }
  return $file;
}

Note that the count start when you add the function and the filter: all previous uploaded files are not counted.

The roles to limit can be altered also via filter.

The limit can be changed via filter (default 10 in my code) and I also pass to filter the user object and the current number of user uploads, in this way the filter can take into accounts more informations...

Edit

To decrease the count when a contributor delete an attachment hook delete_attachment and do some logic:

add_action('delete_attachment', 'decrease_limit_uploads_for_user');

function decrease_limit_uploads_for_user( $id ) {
   $user = wp_get_current_user();
   // add the role you want to limit in the array
   $limit_roles = array('contributor');
   $filtered = apply_filters( 'limit_uploads_for_roles', $limit_roles, $user );
   if ( array_intersect( $limit_roles, $user->roles ) ) {
     $post = get_post( $id);
     if ( $post->post_author != $user->ID ) return;
     $count = get_user_meta( $user->ID, 'upload_count', true ) ? : 0;
     if ( $count ) update_user_meta( $user->ID, 'upload_count', $count - 1 );
   }
}

Note that previous code do not prevent attachment being deleted was uploaded by other users, because this should be handled by the functions/plugin/code that allow contributors to upload files (once by default they can't do that) and because the 'delete_attachment' hook happens after the attachment was already deleted. However if the attachment was not uploaded by current user the decrease isn't performed, just for sure...

  • Works great Giuseppe! One concern, is it possible to deduct the upload count if the user permanently removes an image? – Christine Cooper Oct 25 '13 at 15:48
  • Unfortunately, the delete_attachment hook does not seem to function. The upload limit count never decreases when image is deleted. Also, wp_debug does not show any issues, what are we missing? – Christine Cooper Oct 25 '13 at 18:08
  • 1
    @ChristineCooper the hook is fired, problem was get_post_field that doesn't return post author. Now I've replaced it with get_post and then checking for $post->post_author and now it works. – gmazzap Oct 26 '13 at 1:26
  • Maybe you will use the plugin or contribute to more functionality github.com/bueltge/Limit-Upload – bueltge Mar 17 '14 at 5:53
  • Just a note: When the media/attachment is deleted by a different user, the account will not decrease as well. This might lead to some strange results when users with "higher" roles (read: admin for e.g.) deletes attachments. – kaiser Jul 20 '15 at 13:25
1

Instead of managing an extra meta field in the database per user, you could just keep things simple and count the number of uploads on the fly, like so:

add_filter( 'wp_handle_upload_prefilter', 'limit_user_uploads' );

function limit_user_uploads( $file ) {
    global $wpdb;
    $user = wp_get_current_user();
    $roles = array( 'contributor' ); // Roles to limit
    if ( array_intersect( $roles, $user->roles ) ) { // User has a restricted role
        // Count user's uploads
        $count = $wpdb->get_var( "SELECT COUNT(*) FROM $wpdb->posts WHERE post_type = 'attachment' AND post_author = " . $user->ID );
        if ( 10 <= $count ) {
            $file['error'] = 'Upload limit has been reached for this account!';
        }
    }
    return $file;
}

This could be less practical for very large databases, but in many instances it will do just fine. It works out-of-the-box for existing databases and always ensures that the count is correct. It only counts uploads if the user matches a restricted role, so it doesn't affect unrestricted users.

0

I have adjusted the later answer to check for the user role, I haven't tested it but this should work

The filter wp_handle_upload_prefilter provides you with an opportunity to examine or alter the filename before the file is moved to its final location. so here we would check for the role and upload count.

add_filter( 'wp_handle_upload_prefilter', 'wp_check_upload_limits' );
function wp_check_upload_limits( $file ) {
    $current_user = wp_get_current_user();
    $current_user_role = $current_user->roles[0];

    if ( $current_user_role != "contributor" )
        return false;

    $upload_count = get_user_meta( $current_user->ID, 'upload_count', true );
    $upload_count_limit_reached = apply_filters( 'wpse47580_upload_count_limit_reached', 100 ) > ( $upload_count + 1 );

    if ( $upload_count_limit_reached )
        $file['error'] = 'Upload limit has been reached for this user!';

    return $file;
}
  • Just tested this, unfortunately it has the same problem as the original code, it displays the error message whenever user uploads a file, so the count does not work. Do you by any chance have a fix for this issue? – Christine Cooper Oct 24 '13 at 21:07
  • Did you check the upload count, if the user's upload count has exceeded the maximum, here in my code it is 100 try and check it by echoing $upload_count = get_user_meta( $current_user->ID, 'upload_count', true ); – Maruti Mohanty Oct 25 '13 at 6:26

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.