Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

Bare with me as I explain this. I'm adding an Assistant Editor feature to my multiple author platform. In the box that appears in post-edit page, the Editors can tick which task that they have done (for instance proofread the article) and then check their username (so that they will be credited on the front post page). The box looks something like this:

enter image description here

The code for the box:

// author checkboxes
add_action( 'add_meta_boxes', 'assisting_editor' );
function assisting_editor() {
    add_meta_box(
        'assisting_editor', // id, used as the html id att
        __( 'Editorial Tasks' ), // meta box title
        'editor_tasks', // callback function, spits out the content
        'post', // post type or page. This adds to posts only
        'side', // context, where on the screen
        'low' // priority, where should this go in the context
    );

}

function editor_tasks( $post ) {
    global $wpdb;
    $value = get_post_meta($post->ID, 'ratings', true);

    echo '<div class="misc-pub-section misc-pub-section-last"><span id="timestamp"><label>Editorial tasks: </label>';

    $ratings = array(
        1 => ' Proofread ',
        2 => ' Graphics Added ',
        3 => ' SEO Fixed ',
        4 => ' Ready for Publish '
    );

    foreach ($ratings as $id => $text) {
    $checked = (in_array($id,(array)$value)) ? ' checked="checked"' : '';
    echo '<input type="checkbox" name="ratings[]" value="' . $id . '"'.  $checked . '/><label for="ratings[]">'.$text.'</label>';
    }

    $qry['relation'] = 'OR';
    $qry[] = array(
      'key' => $wpdb->prefix.'capabilities',
      'value' => 'editor',
      'compare' => 'like'
    );
    $qry[] = array(
      'key' => $wpdb->prefix.'capabilities',
      'value' => 'administrator',
      'compare' => 'like'
    );
    $qry = array('fields' => 'all_with_meta','meta_query'=>$qry);

    $alleds = get_users($qry);

    $currenteds = get_post_meta($post->ID, 'currenteds', true);

    foreach ($alleds as $ed) {
    $checked = (in_array($ed->ID,(array)$currenteds)) ? ' checked="checked"' : '';
    echo '<input type="checkbox" name="currenteds[]" value="' . $ed->ID . '"' .$checked . '"/><label for="ratings[]">'.$ed->user_nicename.'</label>';
    }
    echo '</span></div>';
}

add_action( 'save_post', 'save_metadata');

function save_metadata($postid)
{   
    if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) return false;
    if ( !current_user_can( 'edit_page', $postid ) ) return false;
    if( empty($postid) ) return false;

    if ( is_null($_REQUEST["ratings"]) ) {
        delete_post_meta($postid, 'ratings');
    } else {
        update_post_meta($postid, 'ratings', $_REQUEST['ratings']);
    }

    if ( is_null($_REQUEST["currenteds"]) ) {
    delete_post_meta($postid, 'currenteds');
    } else {
    update_post_meta($postid, 'currenteds', $_REQUEST['currenteds']);
    }
}

function display_current_eds($ID = '') {
  if (empty($ID)) {
    global $post;
    if (!empty($post)) {
      $ID = $post->ID;
    }
  }
  if (empty($ID)) return false;
  $eds = get_post_meta($post->ID,'currenteds',true);
  if (!empty($eds)) {
    foreach ($eds as $e) {
      $edu = get_userdata($e);
      $edusers[] = sprintf(
        '<a href="%1$s" title="%2$s" rel="author">%3$s</a>',
        get_author_posts_url( $edu->ID, $edu->user_nicename ),
        esc_attr( sprintf( __( 'Posts by %s' ), $edu->user_nicename ) ),
        $edu->user_nicename
      );
    }
    return $edusers;
  }
  return false;
}

function authors_content_filter($content) {
  $authors = display_current_eds();
  if (false !== $authors) {
    $content .= implode(', ',$authors);
  }
  return $content;
}
add_filter('the_content','authors_content_filter');

    // add author checkboxes

Now, the problem is that the user can tick his own name and any of the other editors. This means that the user can as well untick any of the names too. That is not good.

My question is, how do I make it so that the user can only tick his own name and the other names are greyed out?

share|improve this question
add comment

2 Answers

up vote 2 down vote accepted

Use the same technique as $checked:

$disabled = ( $ed->ID != get_current_user_id() ) ? ' disabled="disabled"' : '';

your code:

foreach ($alleds as $ed) {
    $checked = (in_array($ed->ID,(array)$currenteds)) ? ' checked="checked"' : '';
    $disabled = ( $ed->ID != get_current_user_id() ) ? ' disabled="disabled"' : '';
    echo '<input type="checkbox" name="currenteds[]" value="' . $ed->ID . '"' . $checked . $disabled . '"/><label for="ratings[]">'.$ed->user_nicename.'</label>';
}
share|improve this answer
    
Can you please elaborate where exactly I would add that code? –  Christine Cooper Jan 14 '13 at 15:34
    
And what about if I want to display the full list for Admins? –  Christine Cooper Jan 14 '13 at 15:36
    
I updated my answer. To keep all things checkable for admins, try: $disabled = ( current_user_can( 'manage_options' ) ) ? '' : ( $ed->ID != get_current_user_id() ) ? ' disabled="disabled"' : ''; –  diggy Jan 14 '13 at 15:45
    
Please update your answer with that solution. Also, can you please elaborate how this will work? Will it grey out the list or simply not display the other usernames? –  Christine Cooper Jan 14 '13 at 15:50
1  
There appears to be one serious problem with this code. If a list item is already checked but visually disabled when the user loads it up, when that user updates the post, the disabled list item will be unchecked. Diggy, is there any way to prevent that problem? Please let me know if I did not explain this good. –  Christine Cooper Jan 18 '13 at 19:09
add comment

Check the editor IDs against the current user ID and add disabled="disabled" if they don't match.

$current_user = get_currentuseinfo();
foreach ($alleds as $ed) {
    $checked = (in_array($ed->ID,(array)$currenteds)) ? ' checked="checked"' : '';
    $disabled = (!current_user_can('administrator') && $current_user->ID !== $ed->ID) ? ' disabled="disabled" : '';
    echo '<input type="checkbox" name="currenteds[]" value="' . $ed->ID . '"' .$checked . '" '.$disabled.' /><label for="ratings[]">'.$ed->user_nicename.'</label>';
}

Be aware that this is not foolproof. I can bypass that in under 10 seconds. Consider that a visual convenience only. You'd want to do the same thing when you save the data. That is trickier. I think I would change this:

if ( is_null($_REQUEST["currenteds"]) ) {
    delete_post_meta($postid, 'currenteds');
} else {
    update_post_meta($postid, 'currenteds', $_REQUEST['currenteds']);
}

To something more like:

// admins have full capabilities
if (current_user_can('administrator')) {
    if ( is_null($_REQUEST["currenteds"]) ) {
        delete_post_meta($postid, 'currenteds');
    } else {
        update_post_meta($postid, 'currenteds', $_REQUEST['currenteds']);
    }
} else {
   $meta_values = get_post_meta($postid, 'currenteds', true);
   // I don't remember what the relevant arrays look like
   // even though I wrote much of that code :)
   // Here is the idea
   // Check the IDs in $meta_values against the IDs in $_REQUEST['currenteds']
   // and only allow manipulation of IDs that match get_currentuserinfo()->ID
   // I'll have to install the code to do better but if you can't get it I will.
}

Two modified methods, lightly tested.

function editor_tasks( $post ) {
    global $wpdb;
    $value = get_post_meta($post->ID, 'ratings', true);

    echo '<div class="misc-pub-section misc-pub-section-last"><span id="timestamp"><label>Editorial tasks: </label>';

    $ratings = array(
        1 => ' Proofread ',
        2 => ' Graphics Added ',
        3 => ' SEO Fixed ',
        4 => ' Ready for Publish '
    );

    foreach ($ratings as $id => $text) {
    $checked = (in_array($id,(array)$value)) ? ' checked="checked"' : '';
    echo '<input type="checkbox" name="ratings[]" value="' . $id . '"'.  $checked . '/><label for="ratings[]">'.$text.'</label>';
    }

    $qry['relation'] = 'OR';
    $qry[] = array(
      'key' => $wpdb->prefix.'capabilities',
      'value' => 'editor',
      'compare' => 'like'
    );
    $qry[] = array(
      'key' => $wpdb->prefix.'capabilities',
      'value' => 'administrator',
      'compare' => 'like'
    );
    $qry = array('fields' => 'all_with_meta','meta_query'=>$qry);

    $alleds = get_users($qry);

    $currenteds = get_post_meta($post->ID, 'currenteds', true);

    global $current_user;
    get_currentuserinfo();
    foreach ($alleds as $ed) {
    $checked = (in_array($ed->ID,(array)$currenteds)) ? ' checked="checked"' : '';
    $disabled = (!current_user_can('administrator') && $current_user->ID !== $ed->ID) ? ' disabled="disabled"' : '';
    echo '<input type="checkbox" name="currenteds[]" value="' . $ed->ID . '" ' .$checked . ' '.$disabled.' /><label for="ratings[]">'.$ed->user_nicename.'</label>';
    }
    echo '</span></div>';
}

And...

function save_metadata($postid)
{
    $rid = wp_is_post_revision($postid);
    if ($postid !== $rid) $postid = $rid;

    if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) return false;
    if ( !current_user_can( 'edit_page', $postid ) ) return false;
    if( empty($postid) ) return false;

    if (!empty($_REQUEST['ratings'])) {
      if ( is_null($_REQUEST["ratings"]) ) {
      delete_post_meta($postid, 'ratings');
      } else {
      update_post_meta($postid, 'ratings', $_REQUEST['ratings']);
      }
    }

    // admins have full capabilities
    if (current_user_can('administrator')) {
    if ( is_null($_REQUEST["currenteds"]) ) {
        delete_post_meta($postid, 'currenteds');
    } else {
        update_post_meta($postid, 'currenteds', $_REQUEST['currenteds']);
    }
    } else {
      global $current_user;
      get_currentuserinfo();
      $meta_values = get_post_meta($postid, 'currenteds', true);
      if (!empty($_REQUEST["currenteds"]) && in_array($current_user->ID,$_REQUEST["currenteds"])) {
    $meta_values[] = "$current_user->ID";
      } else {
    $u = array_search($current_user->ID,$meta_values);
    var_dump($u);
    if (false !== $u) {
      unset($meta_values[$u]);
    }
      }
      $meta_values = array_unique($meta_values);
      update_post_meta($postid, 'currenteds', $meta_values);
    }
}
share|improve this answer
1  
Yes, it is easy to bypass it with Firebug or similar. Great to have the original coder of this feature here! Is there any chance that you can do a testrun of the data save solution to confirm if it does work as proposed? –  Christine Cooper Jan 14 '13 at 15:59
    
I can test it but I can't promise when. I have a busy morning. –  s_ha_dum Jan 14 '13 at 16:02
    
Take your time and please keep me updated. Thank you. I will leave this question open until then. –  Christine Cooper Jan 14 '13 at 16:15
    
I have another question for you if you don't mind. It appears that authors_content_filter displays the Editors after the content no matter where I execute it. How can I display it elsewhere (within the loop though). I want to place it where I have the meta info (where I list date of post etc). –  Christine Cooper Jan 14 '13 at 17:48
    
That last question is easy. I have time for that. :) Just call display_current_eds() directly and echo the output. Skip the filter. –  s_ha_dum Jan 14 '13 at 17:57
show 11 more comments

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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