Example #1
0
 public static function exception_scripts()
 {
     if (!current_user_can('pp_assign_roles') && !pp_bulk_roles_enabled()) {
         return array();
     }
     $vars = array('addExceptions' => __('Add Exceptions', 'pp'), 'clearException' => __('clear', 'pp'), 'pleaseReview' => __('Review selection(s) below, then click Save.', 'pp'), 'alreadyException' => __('Exception already selected!', 'pp'), 'noAction' => __('No Action selected!', 'pp'), 'submissionMsg' => __('Exception submission in progress...', 'pp'), 'reloadRequired' => __('Reload form for further changes to this exception', 'pp'), 'noMode' => __('No Assignment Mode selected!', 'pp'), 'ajaxurl' => admin_url(''));
     $vars['agentType'] = isset($_REQUEST['agent_type']) ? pp_sanitize_key($_REQUEST['agent_type']) : 'pp_group';
     $vars['agentID'] = isset($_REQUEST['agent_id']) ? (int) $_REQUEST['agent_id'] : 0;
     //$vars['agentID'] = ( isset($_REQUEST['group_id']) ) ? $_REQUEST['group_id'] : 0;
     // Simulate Nav Menu setup
     require_once dirname(__FILE__) . '/includes/item-menu_pp.php';
     /*
     if ( ! pp_wp_ver( '3.3' ) ) {
     	global $wp_styles;
     	$wp_styles->add( 'nav-menu', "/wp-admin/css/nav-menu.css" );
     	wp_admin_css( 'nav-menu' );
     }
     */
     $vars['noItems'] = __('No items selected!', 'pp');
     $suffix = defined('SCRIPT_DEBUG') && SCRIPT_DEBUG ? '.dev' : '';
     //wp_enqueue_script( 'nav-menu' );
     wp_enqueue_script('pp-item-menu', PP_URLPATH . "/admin/js/pp-item-menu{$suffix}.js", array('jquery', 'jquery-form'), PPC_VERSION);
     wp_localize_script('pp-item-menu', 'ppItems', array('ajaxurl' => admin_url(''), 'noResultsFound' => __('No results found.', 'pp')));
     wp_enqueue_script('pp_exception_edit', PP_URLPATH . "/admin/js/pp_exception_edit{$suffix}.js", array('jquery', 'jquery-form'), PPC_VERSION);
     wp_localize_script('pp_exception_edit', 'ppRestrict', $vars);
     wp_enqueue_script('common');
     wp_enqueue_script('postbox');
     return $vars;
 }
Example #2
0
 public static function display_ui_user_roles($user)
 {
     $roles = array();
     $post_types = pp_get_enabled_post_types(array(), 'object');
     $taxonomies = pp_get_enabled_taxonomies(array(), 'object');
     $is_administrator = pp_bulk_roles_enabled() && current_user_can('pp_manage_groups');
     $edit_url = $is_administrator ? "admin.php?page=pp-edit-permissions&action=edit&agent_id={$user->ID}&agent_type=user" : '';
     $user->retrieve_extra_groups();
     foreach (array_keys($user->groups) as $agent_type) {
         foreach (array_keys($user->groups[$agent_type]) as $agent_id) {
             $roles = array_merge($roles, ppc_get_roles($agent_type, $agent_id, array('post_types' => $post_types, 'taxonomies' => $taxonomies, 'query_agent_ids' => array_keys($user->groups[$agent_type]))));
         }
     }
     $link = current_user_can('pp_assign_roles') ? "admin.php?page=pp-edit-permissions&action=edit&agent_type=user&agent_id={$user->ID}" : '';
     PP_GroupsUI::_current_roles_ui($roles, array('read_only' => true, 'link' => '', 'caption' => sprintf(__('Supplemental Roles %1$s(from primary role or group membership)%2$s', 'pp'), '<small>', '</small>')));
     self::abbreviated_exceptions_ui('user', $user->ID, array('edit_url' => '', 'class' => 'pp-group-roles', 'caption' => __('Exceptions (from primary role or group membership)', 'pp'), 'join_groups' => 'groups_only', 'display_limit' => 12));
 }
        printf(__('%1$sUsers who have Exceptions assigned directly%2$s', 'pp'), "<a href='{$url}?pp_user_exceptions=1'>", '</a>');
        ?>
</li>
		<li><?php 
        printf(__('%1$sUsers who have Supplemental Roles or Exceptions directly%2$s', 'pp'), "<a href='{$url}?pp_user_perms=1'>", '</a>');
        ?>
</li>
		</ul>
		<?php 
    }
    // endif ($agent_id)
    ?>
	</div>
<?php 
}
if (pp_bulk_roles_enabled()) {
    echo '<div class="pp_exceptions_notes">';
    echo '<div><strong>' . __('Exceptions Explained:', 'pp') . '</strong>';
    echo "<ul>";
    echo "<li>" . __('Not These : Specified items are not accessible unless an "Also These" exception is also stored.', 'pp') . '</li>';
    echo "<li>" . __('Only These : Item access as defined by user / group role(s) is further limited by these selections. Users will still need sufficient capabilities in their primary or supplemental roles.', 'pp') . '</li>';
    echo "<li>" . __('Also These : Specified items are accessible regardless of role(s) and other exceptions.', 'pp') . '</li>';
    echo "</ul>";
    echo '</div>';
    echo '<div>';
    _e('Keep in mind that roles and exceptions can be assigned to WP Roles, BuddyPress Groups, Custom Groups and/or individual Users.  "Not These" and "Only These" exceptions are unavailable for groups in some contexts.', 'pp');
    echo '</div>';
    echo '</div>';
}
?>
Example #4
0
         require_once dirname(__FILE__) . '/role_assigner_pp.php';
         $results = $wpdb->get_results("SELECT agent_type, agent_id, role_name FROM {$wpdb->ppc_roles} WHERE {$agent_clause} assignment_id IN ('" . implode("','", $deleted_ass_ids) . "')");
         foreach ($results as $row) {
             $this_group_clase = $agent_clause ? $agent_clause : "agent_type = '{$row->agent_type}' AND agent_id = '{$row->agent_id}' AND";
             if ($_ass_ids = $wpdb->get_col("SELECT assignment_id FROM {$wpdb->ppc_roles} WHERE {$this_group_clase} role_name='{$row->role_name}'")) {
                 PP_RoleAssigner::remove_roles_by_id($_ass_ids);
             }
         }
     }
     echo '<!--ppResponse-->' . implode('|', $input_vals) . '<--ppResponse-->';
     break;
 case 'exceptions_remove':
     if (empty($_GET['pp_eitem_ids'])) {
         exit;
     }
     if (!current_user_can('pp_assign_roles') || !pp_bulk_roles_enabled()) {
         exit;
     }
     $deleted_eitem_ids = array();
     $input_vals = explode('|', pp_sanitize_csv($_GET['pp_eitem_ids']));
     foreach ($input_vals as $id_csv) {
         $eitem_ids = _pp_editable_eitem_ids(explode(',', $id_csv));
         $deleted_eitem_ids = array_merge($deleted_eitem_ids, $eitem_ids);
         // possible TODO: remove elem from $input_vals if content-specific assign_roles authentication fails
     }
     if ($deleted_eitem_ids) {
         require_once dirname(__FILE__) . '/role_assigner_pp.php';
         $exc_clause = $agent_clause ? "exception_id IN ( SELECT exception_id FROM {$wpdb->ppc_exceptions} WHERE {$agent_clause} 1=1 ) AND" : '';
         $results = $wpdb->get_results("SELECT exception_id, item_id FROM {$wpdb->ppc_exception_items} WHERE {$exc_clause} eitem_id IN ('" . implode("','", $deleted_eitem_ids) . "')");
         // safeguard against accidental deletion of a different agent's exceptions
         foreach ($results as $row) {
Example #5
0
 function ui_user()
 {
     global $profileuser, $pp_current_user;
     $pp_profile_user = $profileuser->ID == $pp_current_user->ID ? $pp_current_user : new PP_User($profileuser->ID);
     $is_administrator = pp_is_user_administrator() && pp_bulk_roles_enabled() && current_user_can('list_users');
     if ($is_administrator || pp_get_option('display_user_profile_roles') || pp_get_option('display_user_profile_groups')) {
         require_once dirname(__FILE__) . '/profile_ui_pp.php';
         require_once dirname(__FILE__) . '/permissions-ui_pp.php';
     }
     if ($is_administrator || pp_get_option('display_user_profile_roles')) {
         PP_ProfileUI::display_ui_user_assigned_roles($pp_profile_user);
     }
     if ($is_administrator || pp_get_option('display_user_profile_groups')) {
         PP_ProfileUI::display_ui_user_groups();
     }
     if ($is_administrator || pp_get_option('display_user_profile_roles')) {
         PP_ProfileUI::display_ui_user_roles($pp_profile_user);
     }
 }
function _pp_edit_agent_exceptions($agent_id, $agent_type)
{
    if (!current_user_can('pp_assign_roles') || !pp_bulk_roles_enabled()) {
        return;
    }
    $type_objs = array();
    if (isset($_POST['pp_add_exception'])) {
        // note: group editing capability already verified at this point
        foreach ($_POST['pp_add_exception'] as $exception) {
            $exception = apply_filters('pp_add_exception', $exception);
            extract($exception);
            $args = compact('mod_type', 'item_id', 'operation');
            $args['for_item_status'] = $attrib_cond;
            if (taxonomy_exists($via_type)) {
                $args['via_item_source'] = 'term';
                $args['via_item_type'] = $via_type;
                $args['item_id'] = pp_termid_to_ttid($item_id, $via_type);
            } elseif (!$via_type || post_type_exists($via_type)) {
                $args['via_item_source'] = 'post';
                $args['via_item_type'] = '';
            } else {
                $args['via_item_source'] = $via_type;
                $args['via_item_type'] = '';
            }
            if (taxonomy_exists($for_type)) {
                $args['for_item_source'] = 'term';
            } elseif (!$for_type || post_type_exists($for_type) || '(all)' == $for_type) {
                $args['for_item_source'] = 'post';
            } else {
                $args['for_item_source'] = $for_type;
            }
            $args['for_item_type'] = '(all)' == $for_type ? '' : $for_type;
            $agents = array();
            // also support bulk-assignment of user exceptions
            $agent_ids = 'user' == $agent_type && !$agent_id && isset($_REQUEST['member_csv']) ? explode(',', $_REQUEST['member_csv']) : array($agent_id);
            foreach ($agent_ids as $_agent_id) {
                if ($_agent_id) {
                    foreach (array('item' => $for_item, 'children' => $for_children) as $assign_for => $is_assigned) {
                        if ($is_assigned) {
                            $agents[$assign_for][$_agent_id] = true;
                        }
                    }
                }
            }
            ppc_assign_exceptions($agents, $agent_type, $args);
        }
    }
}
Example #7
0
    public static function _current_exceptions_ui($exc_results, $args = array())
    {
        global $pp_admin, $pp_role_defs, $pp_data_sources;
        $defaults = array('read_only' => false, 'class' => 'pp-group-roles', 'item_links' => false, 'caption' => '', 'link' => '', 'agent_type' => '');
        $args = array_merge($defaults, $args);
        extract($args);
        if (!$exc_results) {
            return;
        }
        if (!$caption) {
            $caption = 'user' == $agent_type ? sprintf(__('Exceptions %1$s(for user)%2$s', 'pp'), '<small>', '</small>') : __('Exceptions', 'pp');
        }
        require_once PPC_ABSPATH . '/lib/ancestry_lib_pp.php';
        $can_assign = current_user_can('pp_assign_roles') && pp_bulk_roles_enabled();
        $exceptions = array_fill_keys(array_merge(array('term', 'post'), pp_get_group_types()), array());
        $item_paths = array_fill_keys(array_keys($exceptions), array(__('(none)', 'pp')));
        // support imported include exception with no items included
        $post_types = pp_get_enabled_post_types(array(), 'names');
        $taxonomies = pp_get_enabled_taxonomies(array('object_type' => false), 'names');
        foreach ($exc_results as $row) {
            // object_type not strictly necessary here, included for consistency with term role array
            switch ($row->via_item_source) {
                case 'term':
                    if ($row->item_id) {
                        $taxonomy = '';
                        $term_id = (int) pp_ttid_to_termid($row->item_id, $taxonomy);
                        if ($row->item_id) {
                            $item_paths['term'][$row->item_id] = PP_Ancestry::get_term_path($term_id, $taxonomy);
                        }
                        $via_type = $taxonomy;
                    } else {
                        $via_type = $row->via_item_type;
                    }
                    break;
                case 'post':
                    if ($row->item_id) {
                        $item_paths['post'][$row->item_id] = PP_Ancestry::get_post_path($row->item_id);
                    }
                    // no break
                // no break
                default:
                    if (pp_group_type_exists($row->via_item_source)) {
                        static $groups_by_id;
                        if (!isset($groups_by_id)) {
                            $groups_by_id = array();
                        }
                        if (!isset($groups_by_id[$row->via_item_source])) {
                            $groups_by_id[$row->via_item_source] = array();
                            foreach (pp_get_groups($row->via_item_source, array('skip_meta_types' => 'wp_role')) as $group) {
                                $groups_by_id[$row->via_item_source][$group->ID] = $group->name;
                            }
                        }
                        if (isset($groups_by_id[$row->via_item_source][$row->item_id])) {
                            $item_paths[$row->via_item_source][$row->item_id] = $groups_by_id[$row->via_item_source][$row->item_id];
                        }
                        $via_type = $row->via_item_source;
                    } else {
                        $via_type = $row->via_item_type ? $row->via_item_type : $row->for_item_type;
                    }
            }
            if (!isset($exceptions[$row->via_item_source][$via_type])) {
                $exceptions[$row->via_item_source][$via_type] = array();
            }
            if (!isset($exceptions[$row->via_item_source][$via_type][$row->for_item_type])) {
                $exceptions[$row->via_item_source][$via_type][$row->for_item_type] = array();
            }
            if (!isset($exceptions[$row->via_item_source][$via_type][$row->for_item_type][$row->operation])) {
                $exceptions[$row->via_item_source][$via_type][$row->for_item_type][$row->operation] = array();
            }
            if (!isset($exceptions[$row->via_item_source][$via_type][$row->for_item_type][$row->operation][$row->mod_type])) {
                $exceptions[$row->via_item_source][$via_type][$row->for_item_type][$row->operation][$row->mod_type] = array();
            }
            if (!isset($exceptions[$row->via_item_source][$via_type][$row->for_item_type][$row->operation][$row->mod_type][$row->for_item_status])) {
                $exceptions[$row->via_item_source][$via_type][$row->for_item_type][$row->operation][$row->mod_type][$row->for_item_status] = array();
            }
            if (!isset($exceptions[$row->via_item_source][$via_type][$row->for_item_type][$row->operation][$row->mod_type][$row->for_item_status][$row->item_id])) {
                $exceptions[$row->via_item_source][$via_type][$row->for_item_type][$row->operation][$row->mod_type][$row->for_item_status][$row->item_id] = array();
            }
            $exceptions[$row->via_item_source][$via_type][$row->for_item_type][$row->operation][$row->mod_type][$row->for_item_status][$row->item_id][$row->assign_for] = $row->eitem_id;
            if (!empty($row->inherited_from)) {
                $exceptions[$row->via_item_source][$via_type][$row->for_item_type][$row->operation][$row->mod_type][$row->for_item_status][$row->item_id]['inherited_from'] = $row->inherited_from;
            }
        }
        echo '<div style="clear:both;"></div>' . "<div id='pp_current_exceptions' class='pp-group-box {$class}'>" . '<h3>';
        if ($link) {
            echo "<a href='{$link}'>{$caption}</a>";
        } else {
            echo $caption;
        }
        echo '</h3>';
        echo '<div>';
        echo '<div id="pp_current_exceptions_inner">';
        //ksort( $type_roles );
        if (empty($_REQUEST['all_types']) && !empty($exceptions['post'])) {
            $all_types = array_fill_keys(array_merge($post_types, $taxonomies, array('')), true);
            $all_types = array_diff_key($all_types, array('topic' => true, 'reply' => true));
            // hide topic, reply assignments even if they are somehow saved/imported without inherited_from value
            $exceptions['post'] = array_intersect_key($exceptions['post'], $all_types);
            foreach (array_keys($exceptions['post']) as $key) {
                $exceptions['post'][$key] = array_intersect_key($exceptions['post'][$key], $all_types);
            }
        }
        foreach (array_keys($exceptions) as $via_src) {
            ksort($exceptions[$via_src]);
            foreach (array_keys($exceptions[$via_src]) as $via_type) {
                if ($via_type_obj = pp_get_type_object($via_src, $via_type)) {
                    $via_type_caption = $via_type_obj->labels->singular_name;
                } else {
                    continue;
                }
                $any_redundant = false;
                echo "<div id='pp_current_{$via_src}_{$via_type}_roles' class='pp-current-exceptions'>";
                /*
                if ( 'term' == $via_src )
                	echo '<h4>' . __( 'Per-Term:', 'pp' ) . '</h4>';
                else {
                	if ( $object_type )
                		echo '<h4>' . sprintf( __( 'Per-%s:', 'pp' ), $type_caption ) . '</h4>';
                	else
                		echo '<h4>' . sprintf( __( 'Per-object:', 'pp' ), $type_caption ) . '</h4>';
                }
                
                echo '<h4>' . sprintf( __( '%s Exceptions', 'pp' ), $via_type_caption ) . '</h4>';
                */
                ksort($exceptions[$via_src][$via_type]);
                foreach (array_keys($exceptions[$via_src][$via_type]) as $for_type) {
                    if (pp_group_type_exists($for_type)) {
                        $for_src = $for_type;
                    } else {
                        $for_src = taxonomy_exists($for_type) || !$for_type ? 'term' : 'post';
                    }
                    if (!$for_type) {
                        $for_type_obj = (object) array('labels' => (object) array('singular_name' => __('(all post types)', 'pp')));
                    } elseif (!($for_type_obj = pp_get_type_object($for_src, $for_type))) {
                        continue;
                    }
                    foreach (array_keys($exceptions[$via_src][$via_type][$for_type]) as $operation) {
                        if (!($operation_obj = pp_get_op_object($operation, $for_type))) {
                            continue;
                        }
                        if ('assign' == $operation) {
                            $op_caption = $for_type ? sprintf(__('%1$s (%2$s: %3$s)', 'pp'), $operation_obj->label, $for_type_obj->labels->singular_name, $via_type_caption) : sprintf(__('%1$s %2$s %3$s', 'pp'), $operation_obj->label, $via_type_caption, $for_type_obj->labels->singular_name);
                        } elseif (in_array($operation, array('manage', 'associate'))) {
                            $op_caption = sprintf(__('%1$s %2$s', 'pp'), $operation_obj->label, $via_type_caption);
                        } else {
                            $op_caption = sprintf(__('%1$s %2$s', 'pp'), $operation_obj->label, $for_type_obj->labels->singular_name);
                        }
                        echo "<div class='type-roles-wrapper'>";
                        echo '<h4>' . $op_caption . '</h4>';
                        echo "<div class='pp-current-type-roles'>";
                        echo '<div class="pp-current-roles-tbl-wrapper"><table>';
                        // fill table body (item assignments for each role)
                        echo '<tbody>';
                        foreach (array_keys($exceptions[$via_src][$via_type][$for_type][$operation]) as $mod_type) {
                            if (!($mod_type_obj = pp_get_mod_object($mod_type))) {
                                continue;
                            }
                            foreach (array_keys($exceptions[$via_src][$via_type][$for_type][$operation][$mod_type]) as $status) {
                                if ($status) {
                                    $_status = explode(':', $status);
                                    if (count($_status) > 1) {
                                        $attrib = $_status[0];
                                        $_status = $_status[1];
                                    } else {
                                        $attrib = 'post_status';
                                        $_status = $status;
                                    }
                                    if ('post_status' == $attrib) {
                                        if ($status_obj = get_post_status_object($_status)) {
                                            $status_label = $status_obj->label;
                                        } elseif ('{unpublished}' == $_status) {
                                            // @todo: API
                                            $status_label = __('unpublished', 'pp');
                                        } else {
                                            $status_label = $status;
                                        }
                                    } else {
                                        $status_label = $status;
                                    }
                                    $mod_caption = sprintf(__('%1$s (%2$s)', 'pp'), $mod_type_obj->label, $status_label);
                                } else {
                                    $mod_caption = $mod_type_obj->label;
                                }
                                if ('exclude' == $mod_type && !empty($exceptions[$via_src][$via_type][$for_type][$operation]['include'])) {
                                    $tr_class = ' class="pp_faded"';
                                    $mod_caption = sprintf(__('* %s', 'pp'), $mod_caption);
                                    $any_faded = true;
                                } else {
                                    $tr_class = '';
                                }
                                echo "<tr{$tr_class}><td class='pp_item_role_caption'>{$mod_caption}</td>";
                                echo '<td>';
                                //if ( $item_links ) {
                                //	if ( 'term' != $scope )
                                //		$edit_url_base = $pp_data_sources->member_property( $item_source, '_edit_link' );
                                //}
                                echo "<div class='pp-role-terms-wrapper pp-role-terms-{$via_type}'>";
                                if ('term' == $via_src && !in_array($operation, array('manage', 'associate'))) {
                                    if (taxonomy_exists($via_type)) {
                                        // "Categories:"
                                        $tx_obj = get_taxonomy($via_type);
                                        $tx_caption = $tx_obj->labels->name;
                                    } else {
                                        $tx_caption = '';
                                    }
                                    echo '<div class="pp-taxonomy-caption">' . sprintf(__('%s:', 'pp'), $tx_caption) . '</div>';
                                    //$edit_url_base = ( isset($tx_obj->_edit_link) ) ? $tx_obj->_edit_link : '';
                                }
                                echo '<div class="pp-role-terms">';
                                $tx_item_paths = array_intersect_key($item_paths[$via_src], $exceptions[$via_src][$via_type][$for_type][$operation][$mod_type][$status]);
                                uasort($tx_item_paths, 'strnatcasecmp');
                                // sort by array values, but maintain keys );
                                foreach ($tx_item_paths as $item_id => $item_path) {
                                    //$assignment = $roles[$scope][$role_name][$item_source][$item_type][$item_id];
                                    $assignment = $exceptions[$via_src][$via_type][$for_type][$operation][$mod_type][$status][$item_id];
                                    $classes = array();
                                    if (isset($assignment['children'])) {
                                        if (isset($assignment['item'])) {
                                            $ass_id = $assignment['item'] . ',' . $assignment['children'];
                                            $classes[] = 'role_both';
                                            $any_both = true;
                                        } else {
                                            $ass_id = '0,' . $assignment['children'];
                                            $classes[] = 'role_ch';
                                            $any_child_only = true;
                                        }
                                    } else {
                                        $ass_id = $assignment['item'];
                                    }
                                    $class = $classes ? "class='" . implode(' ', $classes) . "'" : '';
                                    if ($read_only) {
                                        if ($item_links) {
                                            //$item_edit_url = sprintf($edit_url_base, $item_id);
                                            $item_edit_url = '';
                                            echo "<div><a href='{$item_edit_url}' {$class}>{$item_path}</a></div>";
                                        } else {
                                            echo "<div><span {$class}>{$item_path}</span></div>";
                                        }
                                    } else {
                                        $cb_id = 'pp_edit_exception_' . str_replace(',', '_', $ass_id);
                                        if (!empty($assignment['inherited_from'])) {
                                            $classes[] = 'inherited';
                                            $classes[] = "from_{$assignment['inherited_from']}";
                                        }
                                        if ($tr_class) {
                                            // apply fading for redundantly stored exclusions
                                            $classes[] = $tr_class;
                                        }
                                        $lbl_class = $classes ? "class='" . implode(' ', $classes) . "'" : '';
                                        if ('term' == $via_src) {
                                            $edit_url = admin_url("edit-tags.php?taxonomy={$via_type}&action=edit&tag_ID=" . pp_ttid_to_termid($item_id, $via_type) . "&post_type={$for_type}");
                                        } else {
                                            $edit_url = admin_url("post.php?post={$item_id}&action=edit");
                                        }
                                        echo "<div><label for='{$cb_id}' {$lbl_class}><input id='{$cb_id}' type='checkbox' name='pp_edit_exception[]' value='{$ass_id}' {$class}> " . $item_path . '</label><a href="' . $edit_url . '">' . __('edit') . '</a></div>';
                                    }
                                }
                                // end foreach item
                                if (count($tx_item_paths) > 3 && !$read_only) {
                                    $cb_id = "pp_check_all_{$via_src}_{$via_type}_{$for_type}_{$operation}_{$status}";
                                    echo "<div><label for='{$cb_id}'><input type='checkbox' id='{$cb_id}' class='pp_check_all'> " . __('(all)', 'pp') . '</label></div>';
                                }
                                echo '</div></div>';
                                // pp-role-terms, pp-role-terms-wrapper
                                echo '</td></tr>';
                            }
                            // end foreach status
                        }
                        // end foreach mod_type
                        echo '</tbody>';
                        echo '</table></div>';
                        // pp-current-roles-tbl-wrapper
                        echo '<div class="pp-exception-bulk-edit" style="display:none">';
                        echo "<select><option value=''>" . __ppw('Bulk Actions', 'pp') . "</option><option value='remove'>" . __ppw('Remove', 'pp') . '</option>';
                        if ('post' == $via_src && (!$via_type || $via_type_obj->hierarchical)) {
                            echo "<option value='propagate'>" . sprintf(__('Assign for selected and sub-%s', 'pp'), $via_type_obj->labels->name) . '</option>';
                            echo "<option value='unpropagate'>" . sprintf(__('Assign for selected %s only', 'pp'), $via_type_obj->labels->singular_name) . '</option>';
                            echo "<option value='children_only'>" . sprintf(__('Assign for sub-%s only', 'pp'), $via_type_obj->labels->name) . '</option>';
                        } elseif ('term' == $via_src && $via_type_obj->hierarchical) {
                            echo "<option value='propagate'>" . __('Assign for selected and sub-terms', 'pp') . '</option>';
                            echo "<option value='unpropagate'>" . __('Assign for selected term only', 'pp') . '</option>';
                            echo "<option value='children_only'>" . __('Assign for sub-terms only', 'pp') . '</option>';
                        }
                        echo '</select>';
                        //submit_button( __ppw('Apply'), 'button-secondary submit-edit-item-exception', '', false );
                        ?>
						<input type="submit" name="" class="button submit-edit-item-exception" value="<?php 
                        _e('Apply', 'pp');
                        ?>
" />
						<?php 
                        echo '<img class="waiting" style="display:none;" src="' . esc_url(admin_url('images/wpspin_light.gif')) . '" alt="" />';
                        echo '</div>';
                        // pp-exception-bulk-edit
                        echo '</div></div>';
                        // type-roles-wrapper, pp-current-type-roles
                    }
                    // end foreach operation
                }
                // end foreach for_type
                if ($any_redundant) {
                    echo '<div class="pp-current-roles-note">' . __('* = exceptions redundant due to a corresponding &quot;only these&quot; entry', 'pp') . '</div>';
                }
                if (!empty($via_type_obj->hierarchical)) {
                    $_caption = strtolower($via_type_obj->labels->name);
                    if (!empty($any_both) || !empty($any_child_only)) {
                        ?>
						<div class="pp-current-roles-note">

						<?php 
                        if (!empty($any_both)) {
                            echo '<span class="role_both" style="padding-right:20px">' . sprintf(__('... = assigned for %1$s and sub-%1$s', 'pp'), $_caption) . '</span>';
                        }
                        if (!empty($any_child_only)) {
                            echo '<span>' . sprintf(__('* = assigned for sub-%s only', 'pp'), $_caption) . '</span>';
                        }
                        ?>
						</div>
					<?php 
                    }
                    $show_all_url = esc_url(add_query_arg('show_propagated', '1', $_SERVER['REQUEST_URI']));
                    $show_all_link = "&nbsp;&nbsp;<a href='{$show_all_url}'>";
                    if (empty($_REQUEST['show_propagated'])) {
                        if ('term' == $via_src) {
                            echo '<div class="pp-current-roles-note">' . sprintf(__('note: Exceptions inherited from parent %1$s are not displayed. %2$sshow all%3$s', 'pp'), $_caption, $show_all_link, '</a>') . '</div>';
                        } else {
                            echo '<div class="pp-current-roles-note">' . sprintf(__('note: Exceptions inherited from parent %1$s or terms are not displayed. %2$sshow all%3$s', 'pp'), $_caption, $show_all_link, '</a>') . '</div>';
                        }
                    }
                }
                echo '</div>';
                // pp-current-exceptions
            }
            // end foreach via_type
        }
        // end foreach via_src
        echo '</div>';
        // pp_current_exceptions_inner
        echo '</div>';
        // no class
        echo '</div>';
        // pp_current_exceptions
    }