/**
 * Overwrites capabilities in certain scenarios.
 *
 * @since  1.0.0
 * @access public
 * @param  array   $caps
 * @param  string  $cap
 * @param  int     $user_id
 * @param  array   $args
 * @return array
 */
function mb_reply_map_meta_cap($caps, $cap, $user_id, $args)
{
    /* Checks if a user can read a specific reply. */
    if ('read_post' === $cap && mb_is_reply($args[0])) {
        $post = get_post($args[0]);
        /* Only run our code if the user isn't the post author. */
        if ($user_id != $post->post_author) {
            $topic_id = $post->post_parent;
            /* If we have a topic and the user can't read it, don't allow reading the reply. */
            if (0 < $topic_id && !user_can($user_id, 'read_post', $topic_id)) {
                $caps = array('do_not_allow');
                /* If the user can read the topic, check if they can read the reply. */
            } else {
                $post_type = get_post_type_object($post->post_type);
                if ($post_type->cap->read !== $post_type->cap->read_others_replies) {
                    $caps[] = $post_type->cap->read_others_replies;
                } else {
                    $caps = array();
                }
            }
        } else {
            $caps = array();
        }
        /* Meta cap for editing a single reply. */
    } elseif ('edit_post' === $cap && mb_is_reply($args[0])) {
        $post = get_post($args[0]);
        $reply_obj = get_post_type_object(mb_get_reply_post_type());
        // Spam topics
        if (mb_is_reply_spam($args[0])) {
            $caps[] = $reply_obj->cap->edit_spam_replies;
        }
        /* Meta cap for spamming a single reply. */
    } elseif ('spam_reply' === $cap) {
        $caps = array();
        $caps[] = user_can($user_id, 'edit_reply', $args[0]) ? 'spam_replies' : 'do_not_allow';
        /* Meta cap check for accessing the reply form. */
    } elseif ('access_reply_form' === $cap) {
        $caps = array('create_replies');
        if (mb_is_single_topic()) {
            $topic_id = mb_get_topic_id();
            $topic_status = mb_get_topic_status($topic_id);
            $topic_type = mb_get_topic_type($topic_id);
            if (!current_user_can('read_topic', $topic_id)) {
                $caps[] = 'do_not_allow';
            } elseif (!mb_topic_allows_replies($topic_id)) {
                $caps[] = 'do_not_allow';
            }
        } elseif (mb_is_reply_edit() && !user_can($user_id, 'edit_post', mb_get_reply_id())) {
            $caps[] = 'do_not_allow';
        }
    }
    return $caps;
}
/**
 * Helper function for checking if a user can read forums, topics, or replies. We need this to handle 
 * users who are not logged in but should have permission to read (e.g, non-private forums).  This 
 * function is meant to be used in conjunction with a filter on `map_meta_cap`.
 *
 * @since  1.0.0
 * @access public
 * @param  int     $user_id
 * @param  string  $cap
 * @param  int     $post_id
 * @return bool
 */
function mb_user_can($user_id, $cap, $post_id)
{
    // @todo Check hierarchy.
    if (in_array($cap, array('read_forum', 'read_topic', 'read_reply'))) {
        if ('read_forum' === $cap) {
            $status_obj = get_post_status_object(mb_get_forum_status($post_id));
        } elseif ('read_topic' === $cap) {
            $status_obj = get_post_status_object(mb_get_topic_status($post_id));
        } elseif ('read_forum' === $cap) {
            $status_obj = get_post_status_object(mb_get_reply_status($post_id));
        }
        if (false === $status_obj->private && false === $status_obj->protected) {
            return true;
        }
    }
    return user_can($user_id, $cap, $post_id);
}
/**
 * Overwrites capabilities in certain scenarios.
 *
 * @since  1.0.0
 * @access public
 * @param  array   $caps
 * @param  string  $cap
 * @param  int     $user_id
 * @param  array   $args
 * @return array
 */
function mb_topic_map_meta_cap($caps, $cap, $user_id, $args)
{
    /* Checks if a user can read a specific topic. */
    if ('read_post' === $cap && mb_is_topic($args[0])) {
        $post = get_post($args[0]);
        /* Only run our code if the user isn't the post author. */
        if ($user_id != $post->post_author) {
            $forum_id = $post->post_parent;
            /* If we have a forum and the user can't read it, don't allow reading the topic. */
            if (0 < $forum_id && !mb_user_can($user_id, 'read_forum', $forum_id)) {
                $caps = array('do_not_allow');
                /* If the user can read the forum, check if they can read the topic. */
            } else {
                $post_type = get_post_type_object($post->post_type);
                $post_status = mb_get_topic_status($post->ID);
                $status_obj = get_post_status_object($post_status);
                if (mb_get_hidden_post_status() === $status_obj->name) {
                    $caps[] = $post_type->cap->read_hidden_topics;
                } elseif (mb_get_private_post_status() === $status_obj->name) {
                    $caps[] = $post_type->cap->read_private_posts;
                } elseif ($post_type->cap->read !== $post_type->cap->read_others_topics) {
                    $caps[] = $post_type->cap->read_others_topics;
                } else {
                    $caps = array();
                }
                //$caps[] = $post_type->cap->read;
            }
        } else {
            $caps = array();
        }
        /* Meta cap for editing a single topic. */
    } elseif ('edit_post' === $cap && mb_is_topic($args[0])) {
        $post = get_post($args[0]);
        $topic_obj = get_post_type_object(mb_get_topic_post_type());
        if ($user_id != $post->post_author) {
            // Open topics.
            if (mb_is_topic_open($args[0])) {
                $caps[] = $topic_obj->cap->edit_open_topics;
            } elseif (mb_is_topic_closed($args[0])) {
                $caps[] = $topic_obj->cap->edit_closed_topics;
            } elseif (mb_is_topic_hidden($args[0])) {
                $caps[] = $topic_obj->cap->edit_hidden_topics;
            }
        }
        // Spam topics
        if (mb_is_topic_spam($args[0])) {
            $caps[] = $topic_obj->cap->edit_spam_topics;
        } elseif (mb_is_topic_orphan($args[0])) {
            $caps[] = $topic_obj->cap->edit_orphan_topics;
        }
        /* Meta cap for opening a single topic. */
    } elseif ('open_topic' === $cap) {
        $caps = array();
        $caps[] = user_can($user_id, 'edit_topic', $args[0]) ? 'open_topics' : 'do_not_allow';
        /* Meta cap for closing a single topic. */
    } elseif ('close_topic' === $cap) {
        $caps = array();
        $caps[] = user_can($user_id, 'edit_topic', $args[0]) ? 'close_topics' : 'do_not_allow';
        /* Meta cap for privatizing a single topic. */
    } elseif ('privatize_topic' === $cap) {
        $caps = array();
        $caps[] = user_can($user_id, 'edit_topic', $args[0]) ? 'privatize_topics' : 'do_not_allow';
        /* Meta cap for hiding a single topic. */
    } elseif ('hide_topic' === $cap) {
        $caps = array();
        $caps[] = user_can($user_id, 'edit_topic', $args[0]) ? 'hide_topics' : 'do_not_allow';
        /* Meta cap for spamming a single topic. */
    } elseif ('spam_topic' === $cap) {
        $caps = array();
        $caps[] = user_can($user_id, 'edit_topic', $args[0]) ? 'spam_topics' : 'do_not_allow';
        /* Meta cap for spamming a single topic. */
    } elseif ('super_topic' === $cap) {
        $caps = array();
        $caps[] = user_can($user_id, 'edit_topic', $args[0]) ? 'super_topics' : 'do_not_allow';
        /* Meta cap for spamming a single topic. */
    } elseif ('stick_topic' === $cap) {
        $caps = array();
        $caps[] = user_can($user_id, 'edit_topic', $args[0]) ? 'stick_topics' : 'do_not_allow';
        /* Meta cap check for accessing the topic form. */
    } elseif ('access_topic_form' === $cap) {
        $caps = array('create_topics');
        if (mb_is_single_forum()) {
            $forum_id = mb_get_forum_id();
            if (!current_user_can('read_forum', $forum_id)) {
                $caps[] = 'do_not_allow';
            } elseif (!mb_forum_allows_topics($forum_id)) {
                $caps[] = 'do_not_allow';
            }
        } elseif (mb_is_topic_edit() && !user_can($user_id, 'edit_post', mb_get_topic_id())) {
            $caps[] = 'do_not_allow';
        }
    }
    return $caps;
}
 /**
  * Custom row actions below the post title.
  *
  * @since  1.0.0
  * @access public
  * @param  array   $actions
  * @param  object  $post
  * @return array
  */
 function row_actions($actions, $post)
 {
     $topic_id = mb_get_topic_id($post->ID);
     /* Remove quick edit. */
     if (isset($actions['inline hide-if-no-js'])) {
         unset($actions['inline hide-if-no-js']);
     }
     /* Add delete link for spam and orphan replies. */
     if ((mb_is_topic_spam($topic_id) || mb_is_topic_orphan($topic_id)) && current_user_can('delete_post', $topic_id) && EMPTY_TRASH_DAYS) {
         $actions['delete'] = sprintf('<a class="submitdelete" href="%s">%s</a>', get_delete_post_link($topic_id, '', true), __('Delete Permanently', 'message-board'));
     }
     /* Add spam toggle link if user has permission. */
     if (current_user_can('spam_topic', $topic_id) && !mb_is_topic_orphan($topic_id)) {
         /* Get post status objects. */
         $spam_object = get_post_status_object(mb_get_spam_post_status());
         /* Get spam link text. */
         $spam_text = mb_is_topic_spam($topic_id) ? __('Not Spam', 'message-board') : $spam_object->mb_label_verb;
         /* Build spam toggle URL. */
         $spam_url = remove_query_arg(array('topic_id', 'mb_topic_notice'));
         $spam_url = add_query_arg(array('topic_id' => $topic_id, 'mb_toggle_status' => 'spam'), $spam_url);
         $spam_url = wp_nonce_url($spam_url, "spam_topic_{$topic_id}");
         /* Add toggle spam action link. */
         $actions['mb_toggle_spam'] = sprintf('<a href="%s" class="%s">%s</a>', esc_url($spam_url), mb_is_topic_spam() ? 'restore' : 'spam', $spam_text);
     }
     /* Add open/close toggle link if user has permission and topic is not spam. */
     if (current_user_can('open_topic', $topic_id) && !mb_is_topic_open($topic_id) && !mb_is_topic_spam($topic_id) && !mb_is_topic_orphan($topic_id)) {
         /* Get post status objects. */
         $open_object = get_post_status_object(mb_get_open_post_status());
         /* Build open/close toggle URL. */
         $open_url = remove_query_arg(array('topic_id', 'mb_topic_notice'));
         $open_url = add_query_arg(array('topic_id' => $topic_id, 'mb_toggle_status' => 'open'), $open_url);
         $open_url = wp_nonce_url($open_url, "open_topic_{$topic_id}");
         /* Add toggle open/close action link. */
         $actions['mb_toggle_open'] = sprintf('<a href="%s" class="%s">%s</a>', esc_url($open_url), 'open', $open_object->mb_label_verb);
     }
     /* Add open/close toggle link if user has permission and topic is not spam. */
     if (current_user_can('close_topic', $topic_id) && !mb_is_topic_closed($topic_id) && !mb_is_topic_spam($topic_id) && !mb_is_topic_orphan($topic_id)) {
         /* Get post status objects. */
         $close_object = get_post_status_object(mb_get_close_post_status());
         /* Build open/close toggle URL. */
         $close_url = remove_query_arg(array('topic_id', 'mb_topic_notice'));
         $close_url = add_query_arg(array('topic_id' => $topic_id, 'mb_toggle_status' => 'close'), $close_url);
         $close_url = wp_nonce_url($close_url, "close_topic_{$topic_id}");
         /* Add toggle open/close action link. */
         $actions['mb_toggle_close'] = sprintf('<a href="%s" class="%s">%s</a>', esc_url($close_url), 'close', $close_object->mb_label_verb);
     }
     /* Don't allow stickies for these topic statuses. */
     $icky_sticky = array(mb_get_orphan_post_status(), mb_get_spam_post_status(), mb_get_trash_post_status());
     $topic_status = mb_get_topic_status($topic_id);
     /* Add super toggle link if user has permission and topic has a public status. */
     if (current_user_can('super_topic', $topic_id) && !in_array($topic_status, $icky_sticky)) {
         $current_url = remove_query_arg(array('topic_id', 'mb_topic_notice'));
         /* Build sticky text. */
         $super_text = mb_is_topic_super($topic_id) ? __('Unsuper', 'message-board') : __('Super', 'message-board');
         /* Build super toggle URL. */
         $super_url = add_query_arg(array('topic_id' => $topic_id, 'action' => 'mb_toggle_super'), $current_url);
         $super_url = wp_nonce_url($super_url, "super_topic_{$topic_id}");
         $actions['mb_toggle_super'] = sprintf('<a href="%s" class="%s">%s</a>', esc_url($super_url), 'super', $super_text);
     }
     /* Add sticky toggle link if user has permission and topic has a public status. */
     if (current_user_can('stick_topic', $topic_id) && !in_array($topic_status, $icky_sticky)) {
         $current_url = remove_query_arg(array('topic_id', 'mb_topic_notice'));
         /* Build sticky text. */
         $sticky_text = mb_is_topic_sticky($topic_id) ? __('Unstick', 'message-board') : __('Stick', 'message-board');
         /* Build sticky toggle URL. */
         $sticky_url = add_query_arg(array('topic_id' => $topic_id, 'action' => 'mb_toggle_sticky'), $current_url);
         $sticky_url = wp_nonce_url($sticky_url, "sticky_topic_{$topic_id}");
         $actions['mb_toggle_sticky'] = sprintf('<a href="%s" class="%s">%s</a>', esc_url($sticky_url), 'sticky', $sticky_text);
     }
     /* Move view action to the end. */
     if (isset($actions['view'])) {
         $view_action = $actions['view'];
         unset($actions['view']);
         if (mb_get_spam_post_status() !== get_query_var('post_status')) {
             $actions['view'] = $view_action;
         }
     }
     return $actions;
 }
			<label for="mb_topic_type"><?php 
mb_topic_label('mb_form_type');
?>
</label>
			<?php 
mb_dropdown_topic_type();
?>
		</p><!-- .mb-form-type -->

		<p class="mb-form-status">
			<label for="mb_post_status"><?php 
mb_topic_label('mb_form_status');
?>
</label>
			<?php 
mb_dropdown_topic_status(array('name' => 'mb_post_status', 'id' => 'mb_post_status', 'selected' => mb_get_topic_status()));
?>
		</p><!-- .mb-form-status -->

		<div class="mb-form-content">
			<label class="screen-reader-text" for="mb_topic_content"><?php 
mb_topic_label('mb_form_content');
?>
</label>
			<?php 
mb_topic_editor();
?>
		</div><!-- .mb-form-content -->

		<p class="mb-form-submit">
			<input type="submit" value="<?php 
/**
 * Conditional check to see whether a topic has the "orphan" post status.
 *
 * @since  1.0.0
 * @access public
 * @return bool
 */
function mb_is_topic_orphan($topic_id = 0)
{
    $reply_id = mb_get_topic_id($topic_id);
    $status = mb_get_topic_status($topic_id);
    return apply_filters('mb_is_topic_orphan', mb_get_orphan_post_status() === $status ? true : false, $topic_id);
}